package cmd import ( "context" "fmt" "os" "os/signal" "syscall" "github.com/salvacybersec/keyhunter/pkg/bot" "github.com/salvacybersec/keyhunter/pkg/providers" "github.com/salvacybersec/keyhunter/pkg/recon" "github.com/spf13/cobra" "github.com/spf13/viper" ) var ( servePort int serveTelegram bool ) var serveCmd = &cobra.Command{ Use: "serve", Short: "Start KeyHunter server (Telegram bot + scheduler)", RunE: func(cmd *cobra.Command, args []string) error { ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer cancel() if serveTelegram { token := viper.GetString("telegram.token") if token == "" { token = os.Getenv("TELEGRAM_BOT_TOKEN") } if token == "" { return fmt.Errorf("telegram token required: set telegram.token in config or TELEGRAM_BOT_TOKEN env var") } reg, err := providers.NewRegistry() if err != nil { return fmt.Errorf("loading providers: %w", err) } db, encKey, err := openDBWithKey() if err != nil { return fmt.Errorf("opening database: %w", err) } defer db.Close() reconEng := recon.NewEngine() b, err := bot.New(bot.Config{ Token: token, DB: db, ScanEngine: nil, // TODO: wire scan engine ReconEngine: reconEng, ProviderRegistry: reg, EncKey: encKey, }) if err != nil { return fmt.Errorf("creating bot: %w", err) } go b.Start(ctx) fmt.Println("Telegram bot started.") } fmt.Printf("KeyHunter server running on port %d. Press Ctrl+C to stop.\n", servePort) <-ctx.Done() fmt.Println("\nShutting down.") return nil }, } func init() { serveCmd.Flags().IntVar(&servePort, "port", 8080, "HTTP server port") serveCmd.Flags().BoolVar(&serveTelegram, "telegram", false, "enable Telegram bot") }