package cmd import ( "context" "fmt" "github.com/salvacybersec/keyhunter/pkg/recon" "github.com/spf13/cobra" ) var ( reconStealth bool reconRespectRobots bool reconQuery string ) var reconCmd = &cobra.Command{ Use: "recon", Short: "Run OSINT recon across internet sources", Long: "Run OSINT recon sweeps across registered sources. Phase 9 ships with an ExampleSource stub; real sources land in Phases 10-16.", } var reconFullCmd = &cobra.Command{ Use: "full", Short: "Sweep all enabled sources in parallel and deduplicate findings", RunE: func(cmd *cobra.Command, args []string) error { eng := buildReconEngine() cfg := recon.Config{ Stealth: reconStealth, RespectRobots: reconRespectRobots, Query: reconQuery, } ctx := context.Background() all, err := eng.SweepAll(ctx, cfg) if err != nil { return fmt.Errorf("recon sweep: %w", err) } deduped := recon.Dedup(all) fmt.Printf("recon: swept %d sources, %d findings (%d after dedup)\n", len(eng.List()), len(all), len(deduped)) for _, f := range deduped { fmt.Printf(" [%s] %s %s %s\n", f.SourceType, f.ProviderName, f.KeyMasked, f.Source) } return nil }, } var reconListCmd = &cobra.Command{ Use: "list", Short: "List registered recon sources", RunE: func(cmd *cobra.Command, args []string) error { eng := buildReconEngine() for _, name := range eng.List() { fmt.Println(name) } return nil }, } // buildReconEngine constructs the recon Engine with all sources registered. // Phase 9 ships ExampleSource only; Phases 10-16 will add real sources here // (or via a registration side-effect in their packages). func buildReconEngine() *recon.Engine { e := recon.NewEngine() e.Register(recon.ExampleSource{}) return e } func init() { reconFullCmd.Flags().BoolVar(&reconStealth, "stealth", false, "enable UA rotation and jitter delays") reconFullCmd.Flags().BoolVar(&reconRespectRobots, "respect-robots", true, "respect robots.txt for web-scraping sources") reconFullCmd.Flags().StringVar(&reconQuery, "query", "", "override query sent to each source") reconCmd.AddCommand(reconFullCmd) reconCmd.AddCommand(reconListCmd) }