mirror of
https://github.com/Vyntral/god-eye.git
synced 2026-02-12 16:52:45 +00:00
- Fix confidence always showing 0% (use coordinator confidence) - Simplify AI report prompt to prevent hallucinated subdomain names - Update slogan to reflect AI-powered capabilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
148 lines
5.0 KiB
Go
148 lines
5.0 KiB
Go
package output
|
|
|
|
import (
|
|
"encoding/csv"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/fatih/color"
|
|
|
|
"god-eye/internal/config"
|
|
)
|
|
|
|
var (
|
|
// Basic colors
|
|
Green = color.New(color.FgGreen).SprintFunc()
|
|
Red = color.New(color.FgRed).SprintFunc()
|
|
Blue = color.New(color.FgBlue).SprintFunc()
|
|
Yellow = color.New(color.FgYellow).SprintFunc()
|
|
Cyan = color.New(color.FgCyan).SprintFunc()
|
|
Magenta = color.New(color.FgMagenta).SprintFunc()
|
|
White = color.New(color.FgWhite).SprintFunc()
|
|
|
|
// Bold variants
|
|
BoldGreen = color.New(color.FgGreen, color.Bold).SprintFunc()
|
|
BoldRed = color.New(color.FgRed, color.Bold).SprintFunc()
|
|
BoldCyan = color.New(color.FgCyan, color.Bold).SprintFunc()
|
|
BoldYellow = color.New(color.FgYellow, color.Bold).SprintFunc()
|
|
BoldMagenta = color.New(color.FgMagenta, color.Bold).SprintFunc()
|
|
BoldWhite = color.New(color.FgWhite, color.Bold).SprintFunc()
|
|
|
|
// Dim/faint
|
|
Dim = color.New(color.Faint).SprintFunc()
|
|
|
|
// Background highlights
|
|
BgRed = color.New(color.BgRed, color.FgWhite, color.Bold).SprintFunc()
|
|
BgGreen = color.New(color.BgGreen, color.FgBlack, color.Bold).SprintFunc()
|
|
BgYellow = color.New(color.BgYellow, color.FgBlack, color.Bold).SprintFunc()
|
|
)
|
|
|
|
func PrintBanner() {
|
|
fmt.Println()
|
|
fmt.Println(BoldWhite(" ██████╗ ██████╗ ██████╗ ") + BoldGreen("███████╗") + BoldWhite(" ███████╗██╗ ██╗███████╗"))
|
|
fmt.Println(BoldWhite(" ██╔════╝ ██╔═══██╗██╔══██╗") + BoldGreen("██╔════╝") + BoldWhite(" ██╔════╝╚██╗ ██╔╝██╔════╝"))
|
|
fmt.Println(BoldWhite(" ██║ ███╗██║ ██║██║ ██║") + BoldGreen("███████╗") + BoldWhite(" █████╗ ╚████╔╝ █████╗ "))
|
|
fmt.Println(BoldWhite(" ██║ ██║██║ ██║██║ ██║") + BoldGreen("╚════██║") + BoldWhite(" ██╔══╝ ╚██╔╝ ██╔══╝ "))
|
|
fmt.Println(BoldWhite(" ╚██████╔╝╚██████╔╝██████╔╝") + BoldGreen("███████║") + BoldWhite(" ███████╗ ██║ ███████╗"))
|
|
fmt.Println(BoldWhite(" ╚═════╝ ╚═════╝ ╚═════╝ ") + BoldGreen("╚══════╝") + BoldWhite(" ╚══════╝ ╚═╝ ╚══════╝"))
|
|
fmt.Println()
|
|
fmt.Printf(" %s %s\n", BoldGreen("⚡"), Dim("AI-powered attack surface discovery & security analysis"))
|
|
fmt.Printf(" %s %s %s %s %s %s\n",
|
|
Dim("Version:"), BoldGreen("0.1"),
|
|
Dim("By:"), White("github.com/Vyntral"),
|
|
Dim("For:"), Yellow("github.com/Orizon-eu"))
|
|
fmt.Println()
|
|
}
|
|
|
|
func PrintSection(icon, title string) {
|
|
fmt.Println()
|
|
fmt.Printf(" %s %s\n", icon, BoldWhite(title))
|
|
fmt.Printf(" %s\n", Dim(strings.Repeat("─", 50)))
|
|
}
|
|
|
|
func PrintSubSection(text string) {
|
|
fmt.Printf(" %s\n", text)
|
|
}
|
|
|
|
func PrintEndSection() {
|
|
// No more lines, just spacing
|
|
}
|
|
|
|
func PrintProgress(current, total int, label string) {
|
|
width := 30
|
|
filled := int(float64(current) / float64(total) * float64(width))
|
|
if filled > width {
|
|
filled = width
|
|
}
|
|
bar := strings.Repeat("█", filled) + strings.Repeat("░", width-filled)
|
|
percent := float64(current) / float64(total) * 100
|
|
fmt.Printf("\r %s %s %s %.0f%% ", label, Green(bar), Dim(fmt.Sprintf("(%d/%d)", current, total)), percent)
|
|
}
|
|
|
|
func ClearLine() {
|
|
fmt.Print("\r\033[K")
|
|
}
|
|
|
|
func SaveOutput(path string, format string, results map[string]*config.SubdomainResult) {
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
fmt.Printf("%s Failed to create output file: %v\n", Red("[-]"), err)
|
|
return
|
|
}
|
|
defer file.Close()
|
|
|
|
// Sort subdomains for consistent output
|
|
var sortedSubs []string
|
|
for sub := range results {
|
|
sortedSubs = append(sortedSubs, sub)
|
|
}
|
|
sort.Strings(sortedSubs)
|
|
|
|
switch format {
|
|
case "json":
|
|
var resultList []*config.SubdomainResult
|
|
for _, sub := range sortedSubs {
|
|
resultList = append(resultList, results[sub])
|
|
}
|
|
encoder := json.NewEncoder(file)
|
|
encoder.SetIndent("", " ")
|
|
encoder.Encode(resultList)
|
|
|
|
case "csv":
|
|
writer := csv.NewWriter(file)
|
|
// Header
|
|
writer.Write([]string{"subdomain", "ips", "status_code", "title", "server", "technologies", "ports", "takeover", "response_ms"})
|
|
|
|
for _, sub := range sortedSubs {
|
|
r := results[sub]
|
|
var portStrs []string
|
|
for _, p := range r.Ports {
|
|
portStrs = append(portStrs, strconv.Itoa(p))
|
|
}
|
|
writer.Write([]string{
|
|
r.Subdomain,
|
|
strings.Join(r.IPs, ";"),
|
|
strconv.Itoa(r.StatusCode),
|
|
r.Title,
|
|
r.Server,
|
|
strings.Join(r.Tech, ";"),
|
|
strings.Join(portStrs, ";"),
|
|
r.Takeover,
|
|
strconv.FormatInt(r.ResponseMs, 10),
|
|
})
|
|
}
|
|
writer.Flush()
|
|
|
|
default: // txt
|
|
for _, sub := range sortedSubs {
|
|
file.WriteString(sub + "\n")
|
|
}
|
|
}
|
|
|
|
fmt.Printf("\n %s Results saved to %s\n", Green("✓"), path)
|
|
}
|