package formatter import ( "encoding/json" "fmt" "strings" "git.db.org.ai/dborg/internal/models" ) func FormatSLResults(resp *models.SLResponse, asJSON bool) (string, error) { if asJSON { data, err := json.MarshalIndent(resp.Results, "", " ") if err != nil { return "", fmt.Errorf("failed to marshal JSON: %w", err) } return string(data), nil } var sb strings.Builder if resp.Results == nil { sb.WriteString(fmt.Sprintf("\n%s\n\n", Gray("No results found"))) return sb.String(), nil } resultsMap, ok := resp.Results.(map[string]interface{}) if !ok { resultsJSON, err := json.MarshalIndent(resp.Results, "", " ") if err != nil { return "", fmt.Errorf("failed to format results: %w", err) } return string(resultsJSON), nil } hits, ok := resultsMap["hits"].([]interface{}) if !ok || len(hits) == 0 { sb.WriteString(fmt.Sprintf("\n%s\n\n", Gray("No results found"))) return sb.String(), nil } numHits, _ := resultsMap["num_hits"].(float64) elapsed, _ := resultsMap["elapsed_time_micros"].(float64) sb.WriteString(fmt.Sprintf("%s %s %s\n", Cyan("Found"), Bold(Yellow(fmt.Sprintf("%d", int(numHits)))), Cyan(fmt.Sprintf("credentials (%.2fms)", elapsed/1000)))) sb.WriteString("\n") for i, hit := range hits { hitMap, ok := hit.(map[string]interface{}) if !ok { continue } if i > 0 { sb.WriteString(Dim("───")) sb.WriteString("\n") } username, _ := hitMap["username"].(string) password, _ := hitMap["password"].(string) url, _ := hitMap["url"].(string) filename, _ := hitMap["filename"].(string) sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Username:"), Bold(username))) if password != "" { sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Password:"), Yellow(password))) } if url != "" { sb.WriteString(fmt.Sprintf("%s %s\n", Dim("URL:"), Blue(url))) } if filename != "" { sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Source:"), Magenta(filename))) } sb.WriteString("\n") } if resp.Credits.Unlimited { sb.WriteString(fmt.Sprintf("%s: %s\n", Dim("Credits"), Green("Unlimited"))) } else { sb.WriteString(fmt.Sprintf("%s: %s\n", Dim("Credits Remaining"), FormatCredits(int64(resp.Credits.Remaining)))) } return sb.String(), nil } func formatSLResultsData(sb *strings.Builder, data map[string]interface{}) { sb.WriteString(fmt.Sprintf("%s\n", Bold("Stealer Log Entries:"))) for key, value := range data { sb.WriteString(fmt.Sprintf("\n %s:\n", Cyan(key))) if valueMap, ok := value.(map[string]interface{}); ok { for k, v := range valueMap { sb.WriteString(fmt.Sprintf(" %s %v\n", Dim(fmt.Sprintf("%s:", k)), v)) } } else if valueArray, ok := value.([]interface{}); ok { for i, item := range valueArray { sb.WriteString(fmt.Sprintf(" %s %v\n", Dim(fmt.Sprintf("[%d]:", i)), item)) } } else { sb.WriteString(fmt.Sprintf(" %v\n", value)) } } } func formatSLResultsArray(sb *strings.Builder, data []interface{}) { sb.WriteString(fmt.Sprintf("%s\n", Bold("Stealer Log Entries:"))) for i, entry := range data { sb.WriteString(fmt.Sprintf("\n %s:\n", Blue(fmt.Sprintf("Entry %d", i+1)))) if entryMap, ok := entry.(map[string]interface{}); ok { for key, value := range entryMap { sb.WriteString(fmt.Sprintf(" %s %v\n", Dim(fmt.Sprintf("%s:", key)), value)) } } else { sb.WriteString(fmt.Sprintf(" %v\n", entry)) } } }