mirror of
https://github.com/Vyntral/god-eye.git
synced 2026-02-12 16:52:45 +00:00
## AI & CVE Improvements - Fix AI report to display actual subdomain names instead of generic placeholders - Add 10-year CVE filter to reduce false positives from outdated vulnerabilities - Integrate CISA KEV (Known Exploited Vulnerabilities) database support - Improve AI analysis prompt for more accurate security findings ## New Security Modules - Add wildcard DNS detection with multi-phase validation (DNS + HTTP) - Add TLS certificate analyzer for certificate chain inspection - Add comprehensive rate limiting module for API requests - Add retry mechanism with exponential backoff - Add stealth mode for reduced detection during scans - Add progress tracking module for better UX ## Code Refactoring - Extract scanner output logic to dedicated module - Add base source interface for consistent passive source implementation - Reduce admin panel paths to common generic patterns only - Improve HTTP client with connection pooling - Add JSON output formatter ## Documentation Updates - Correct passive source count to 20 (was incorrectly stated as 34) - Fix AI model names: deepseek-r1:1.5b (fast) + qwen2.5-coder:7b (deep) - Update all markdown files for consistency - Relocate demo GIFs to assets/ directory - Add benchmark disclaimer for test variability ## Files Changed - 4 documentation files updated (README, AI_SETUP, BENCHMARK, EXAMPLES) - 11 new source files added - 12 existing files modified
198 lines
4.0 KiB
Go
198 lines
4.0 KiB
Go
package progress
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"god-eye/internal/output"
|
|
)
|
|
|
|
// Bar represents a progress bar
|
|
type Bar struct {
|
|
total int64
|
|
current int64
|
|
width int
|
|
prefix string
|
|
startTime time.Time
|
|
lastUpdate time.Time
|
|
mu sync.Mutex
|
|
done bool
|
|
silent bool
|
|
}
|
|
|
|
// New creates a new progress bar
|
|
func New(total int, prefix string, silent bool) *Bar {
|
|
return &Bar{
|
|
total: int64(total),
|
|
current: 0,
|
|
width: 40,
|
|
prefix: prefix,
|
|
startTime: time.Now(),
|
|
silent: silent,
|
|
}
|
|
}
|
|
|
|
// Increment increases the progress by 1
|
|
func (b *Bar) Increment() {
|
|
atomic.AddInt64(&b.current, 1)
|
|
b.render()
|
|
}
|
|
|
|
// Add increases the progress by n
|
|
func (b *Bar) Add(n int) {
|
|
atomic.AddInt64(&b.current, int64(n))
|
|
b.render()
|
|
}
|
|
|
|
// SetCurrent sets the current progress value
|
|
func (b *Bar) SetCurrent(n int) {
|
|
atomic.StoreInt64(&b.current, int64(n))
|
|
b.render()
|
|
}
|
|
|
|
// render displays the progress bar
|
|
func (b *Bar) render() {
|
|
if b.silent {
|
|
return
|
|
}
|
|
|
|
b.mu.Lock()
|
|
defer b.mu.Unlock()
|
|
|
|
// Throttle updates to avoid flickering (max 10 updates/sec)
|
|
if time.Since(b.lastUpdate) < 100*time.Millisecond && !b.done {
|
|
return
|
|
}
|
|
b.lastUpdate = time.Now()
|
|
|
|
current := atomic.LoadInt64(&b.current)
|
|
total := b.total
|
|
|
|
// Calculate percentage
|
|
var percent float64
|
|
if total > 0 {
|
|
percent = float64(current) / float64(total) * 100
|
|
}
|
|
|
|
// Calculate filled width
|
|
filled := int(float64(b.width) * percent / 100)
|
|
if filled > b.width {
|
|
filled = b.width
|
|
}
|
|
|
|
// Build progress bar
|
|
bar := strings.Repeat("█", filled) + strings.Repeat("░", b.width-filled)
|
|
|
|
// Calculate ETA
|
|
elapsed := time.Since(b.startTime)
|
|
var eta string
|
|
if current > 0 && current < total {
|
|
remaining := time.Duration(float64(elapsed) / float64(current) * float64(total-current))
|
|
eta = formatDuration(remaining)
|
|
} else if current >= total {
|
|
eta = "done"
|
|
} else {
|
|
eta = "..."
|
|
}
|
|
|
|
// Calculate speed
|
|
var speed float64
|
|
if elapsed.Seconds() > 0 {
|
|
speed = float64(current) / elapsed.Seconds()
|
|
}
|
|
|
|
// Print progress bar (overwrite line with \r) - clean style without box characters
|
|
fmt.Printf("\r %s [%s] %s/%s %.0f%% %s ETA %s ",
|
|
b.prefix,
|
|
output.Green(bar),
|
|
output.BoldWhite(fmt.Sprintf("%d", current)),
|
|
output.Dim(fmt.Sprintf("%d", total)),
|
|
percent,
|
|
output.Dim(fmt.Sprintf("%.0f/s", speed)),
|
|
output.Dim(eta),
|
|
)
|
|
}
|
|
|
|
// Finish completes the progress bar
|
|
func (b *Bar) Finish() {
|
|
if b.silent {
|
|
return
|
|
}
|
|
|
|
b.mu.Lock()
|
|
b.done = true
|
|
b.mu.Unlock()
|
|
|
|
current := atomic.LoadInt64(&b.current)
|
|
elapsed := time.Since(b.startTime)
|
|
|
|
// Clear the line and print final status - clean style
|
|
fmt.Printf("\r %s %s %s completed in %s \n",
|
|
output.Green("✓"),
|
|
output.BoldWhite(fmt.Sprintf("%d", current)),
|
|
b.prefix,
|
|
output.Green(formatDuration(elapsed)),
|
|
)
|
|
}
|
|
|
|
// FinishWithMessage completes with a custom message
|
|
func (b *Bar) FinishWithMessage(msg string) {
|
|
if b.silent {
|
|
return
|
|
}
|
|
|
|
b.mu.Lock()
|
|
b.done = true
|
|
b.mu.Unlock()
|
|
|
|
// Clear the line and print message - clean style
|
|
fmt.Printf("\r %s %s \n",
|
|
output.Green("✓"),
|
|
msg,
|
|
)
|
|
}
|
|
|
|
// formatDuration formats a duration nicely
|
|
func formatDuration(d time.Duration) string {
|
|
if d < time.Second {
|
|
return "<1s"
|
|
} else if d < time.Minute {
|
|
return fmt.Sprintf("%ds", int(d.Seconds()))
|
|
} else if d < time.Hour {
|
|
mins := int(d.Minutes())
|
|
secs := int(d.Seconds()) % 60
|
|
return fmt.Sprintf("%dm%ds", mins, secs)
|
|
}
|
|
hours := int(d.Hours())
|
|
mins := int(d.Minutes()) % 60
|
|
return fmt.Sprintf("%dh%dm", hours, mins)
|
|
}
|
|
|
|
// MultiBar manages multiple progress bars
|
|
type MultiBar struct {
|
|
bars []*Bar
|
|
mu sync.Mutex
|
|
silent bool
|
|
}
|
|
|
|
// NewMulti creates a new multi-bar manager
|
|
func NewMulti(silent bool) *MultiBar {
|
|
return &MultiBar{
|
|
bars: make([]*Bar, 0),
|
|
silent: silent,
|
|
}
|
|
}
|
|
|
|
// AddBar adds a new progress bar
|
|
func (m *MultiBar) AddBar(total int, prefix string) *Bar {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
bar := New(total, prefix, m.silent)
|
|
m.bars = append(m.bars, bar)
|
|
return bar
|
|
}
|