package cmd import ( "fmt" "git.db.org.ai/dborg/internal/client" "git.db.org.ai/dborg/internal/formatter" "git.db.org.ai/dborg/internal/models" "git.db.org.ai/dborg/internal/tui" "github.com/spf13/cobra" ) var skiptraceCmd = &cobra.Command{ Use: "skiptrace", Short: "Premium skiptrace operations (requires premium API access)", Long: `Search for people, phone numbers, and email addresses using premium skiptrace data. Note: All skiptrace commands require a premium API key. If you receive a 403 error, contact support to upgrade your account for premium access.`, } var skiptraceWizardCmd = &cobra.Command{ Use: "wizard", Short: "Interactive wizard to search for a person and generate a report", Long: `Launch an interactive wizard with a form to enter search criteria, then select from results in a table view to generate a detailed report.`, RunE: runSkiptraceWizard, } var skiptracePeopleCmd = &cobra.Command{ Use: "people", Short: "Search for people by name", Long: `Search for people by first name, last name, and optional location/age filters`, RunE: runSkiptracePeople, } var skiptracePhoneCmd = &cobra.Command{ Use: "phone [phone_number]", Short: "Search for phone number", Long: `Look up information about a phone number (10 digits, no +1 prefix)`, Args: cobra.ExactArgs(1), RunE: runSkiptracePhone, } var skiptraceEmailCmd = &cobra.Command{ Use: "email [email_address]", Short: "Search for email address", Long: `Look up information about an email address`, Args: cobra.ExactArgs(1), RunE: runSkiptraceEmail, } var skiptraceReportCmd = &cobra.Command{ Use: "report [sx_key] [selection]", Short: "Get a person report by sx_key and selection number", Long: `Generate a detailed report for a person using the sx_key from a people search and selection number`, Args: cobra.ExactArgs(2), RunE: runSkiptraceReport, } func init() { rootCmd.AddCommand(skiptraceCmd) skiptraceCmd.AddCommand(skiptracePeopleCmd) skiptraceCmd.AddCommand(skiptracePhoneCmd) skiptraceCmd.AddCommand(skiptraceEmailCmd) skiptraceCmd.AddCommand(skiptraceWizardCmd) skiptraceCmd.AddCommand(skiptraceReportCmd) skiptracePeopleCmd.Flags().StringP("first-name", "f", "", "First name (required)") skiptracePeopleCmd.Flags().StringP("last-name", "l", "", "Last name (required)") skiptracePeopleCmd.Flags().StringP("city", "c", "", "City") skiptracePeopleCmd.Flags().StringP("state", "s", "", "State (2-letter code)") skiptracePeopleCmd.Flags().StringP("age", "a", "", "Age") skiptracePeopleCmd.MarkFlagRequired("first-name") skiptracePeopleCmd.MarkFlagRequired("last-name") skiptraceWizardCmd.Flags().BoolP("json", "j", false, "Output raw JSON instead of formatted display") } func getSkiptraceClient(cmd *cobra.Command) (*client.Client, error) { return newClient() } func runSkiptracePeople(cmd *cobra.Command, args []string) error { c, err := getSkiptraceClient(cmd) if err != nil { return err } params := &models.SkiptraceParams{} params.FirstName, _ = cmd.Flags().GetString("first-name") params.LastName, _ = cmd.Flags().GetString("last-name") params.City, _ = cmd.Flags().GetString("city") params.State, _ = cmd.Flags().GetString("state") params.Age, _ = cmd.Flags().GetString("age") response, err := c.SearchPeople(params) if err != nil { return err } if err := checkError(response.Error); err != nil { return err } output, err := formatter.FormatSkiptraceResults(response, IsJSONOutput()) if err != nil { return err } printOutput(output) return nil } func runSkiptracePhone(cmd *cobra.Command, args []string) error { c, err := getSkiptraceClient(cmd) if err != nil { return err } response, err := c.SearchPhone(args[0]) if err != nil { return err } if err := checkError(response.Error); err != nil { return err } output, err := formatter.FormatSkiptraceResults(response, IsJSONOutput()) if err != nil { return err } printOutput(output) return nil } func runSkiptraceEmail(cmd *cobra.Command, args []string) error { c, err := getSkiptraceClient(cmd) if err != nil { return err } response, err := c.SearchEmail(args[0]) if err != nil { return err } if err := checkError(response.Error); err != nil { return err } output, err := formatter.FormatSkiptraceResults(response, IsJSONOutput()) if err != nil { return err } printOutput(output) return nil } func runSkiptraceReport(cmd *cobra.Command, args []string) error { c, err := getSkiptraceClient(cmd) if err != nil { return err } sxKey := args[0] selection := 0 if _, err := fmt.Sscanf(args[1], "%d", &selection); err != nil { return fmt.Errorf("invalid selection number: %s", args[1]) } if selection <= 0 { return fmt.Errorf("selection must be a positive integer") } response, err := c.GetPersonReport(sxKey, selection) if err != nil { return err } if err := checkError(response.Error); err != nil { return err } output, err := formatter.FormatSkiptraceResults(response, IsJSONOutput()) if err != nil { return err } printOutput(output) return nil } func runSkiptraceWizard(cmd *cobra.Command, args []string) error { c, err := getSkiptraceClient(cmd) if err != nil { return err } jsonOutput, _ := cmd.Flags().GetBool("json") searchFn := func(firstName, lastName, city, state, age string) (map[string]interface{}, string, error) { params := &models.SkiptraceParams{ FirstName: firstName, LastName: lastName, City: city, State: state, Age: age, } response, err := c.SearchPeople(params) if err != nil { return nil, "", err } if response.Error != "" { return nil, "", fmt.Errorf("%s", response.Error) } sxKey := response.SXKey if sxKey == "" { if key, ok := response.Data["sx_key"].(string); ok { sxKey = key } } return response.Data, sxKey, nil } reportFn := func(sxKey string, selection int) (map[string]interface{}, error) { response, err := c.GetPersonReport(sxKey, selection) if err != nil { return nil, err } if response.Error != "" { return nil, fmt.Errorf("%s", response.Error) } return response.Data, nil } return tui.RunSkiptraceWizard(searchFn, reportFn, jsonOutput) }