Files
god-eye/internal/progress/progress.go
Vyntral b1bf119c82 v0.1.1: Major AI improvements, new security modules, and documentation fixes
## 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
2025-11-21 12:00:58 +01:00

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
}