summaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/admin.go238
-rw-r--r--cmd/npd.go95
-rw-r--r--cmd/osint.go103
-rw-r--r--cmd/root.go25
-rw-r--r--cmd/skiptrace.go199
-rw-r--r--cmd/sl.go73
-rw-r--r--cmd/x.go61
7 files changed, 794 insertions, 0 deletions
diff --git a/cmd/admin.go b/cmd/admin.go
new file mode 100644
index 0000000..3c43e20
--- /dev/null
+++ b/cmd/admin.go
@@ -0,0 +1,238 @@
+package cmd
+
+import (
+ "dborg/internal/client"
+ "dborg/internal/config"
+ "dborg/internal/models"
+ "encoding/json"
+ "fmt"
+ "strconv"
+
+ "github.com/spf13/cobra"
+)
+
+var adminCmd = &cobra.Command{
+ Use: "admin",
+ Short: "Admin operations",
+ Long: `Administrative operations for managing accounts`,
+}
+
+var adminListCmd = &cobra.Command{
+ Use: "list",
+ Short: "List all accounts",
+ RunE: runAdminList,
+}
+
+var adminCreateCmd = &cobra.Command{
+ Use: "create [name]",
+ Short: "Create new account",
+ Args: cobra.ExactArgs(1),
+ RunE: runAdminCreate,
+}
+
+var adminDeleteCmd = &cobra.Command{
+ Use: "delete [api_key]",
+ Short: "Delete account",
+ Args: cobra.ExactArgs(1),
+ RunE: runAdminDelete,
+}
+
+var adminCreditsCmd = &cobra.Command{
+ Use: "credits [api_key] [amount]",
+ Short: "Add credits to account",
+ Args: cobra.ExactArgs(2),
+ RunE: runAdminCredits,
+}
+
+var adminSetCreditsCmd = &cobra.Command{
+ Use: "set-credits [api_key] [amount]",
+ Short: "Set account credits to specific amount",
+ Args: cobra.ExactArgs(2),
+ RunE: runAdminSetCredits,
+}
+
+var adminDisableCmd = &cobra.Command{
+ Use: "disable [api_key]",
+ Short: "Disable/enable account",
+ Args: cobra.ExactArgs(1),
+ RunE: runAdminDisable,
+}
+
+func init() {
+ rootCmd.AddCommand(adminCmd)
+ adminCmd.AddCommand(adminListCmd)
+ adminCmd.AddCommand(adminCreateCmd)
+ adminCmd.AddCommand(adminDeleteCmd)
+ adminCmd.AddCommand(adminCreditsCmd)
+ adminCmd.AddCommand(adminSetCreditsCmd)
+ adminCmd.AddCommand(adminDisableCmd)
+
+ adminCreateCmd.Flags().IntP("credits", "c", 0, "Initial credits")
+ adminCreateCmd.Flags().BoolP("unlimited", "u", false, "Unlimited credits")
+ adminCreateCmd.Flags().BoolP("premium", "p", false, "Premium account (enables skiptrace access)")
+ adminDisableCmd.Flags().BoolP("enable", "e", false, "Enable account instead of disable")
+}
+
+func getAdminClient(cmd *cobra.Command) (*client.Client, error) {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+ return client.New(cfg)
+}
+
+func runAdminList(cmd *cobra.Command, args []string) error {
+ c, err := getAdminClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ response, err := c.ListAccounts()
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ output, err := json.MarshalIndent(response.Accounts, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+
+ fmt.Println(string(output))
+ return nil
+}
+
+func runAdminCreate(cmd *cobra.Command, args []string) error {
+ c, err := getAdminClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ credits, _ := cmd.Flags().GetInt("credits")
+ unlimited, _ := cmd.Flags().GetBool("unlimited")
+ premium, _ := cmd.Flags().GetBool("premium")
+
+ req := &models.AccountCreateRequest{
+ Name: args[0],
+ Credits: credits,
+ Unlimited: unlimited,
+ IsPremium: premium,
+ }
+
+ response, err := c.CreateAccount(req)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if response.Account != nil {
+ fmt.Printf("Account created successfully!\n")
+ fmt.Printf("Name: %s\n", response.Account.Name)
+ fmt.Printf("API Key: %s\n", response.Account.APIKey)
+ fmt.Printf("Credits: %d\n", response.Account.Credits)
+ fmt.Printf("Unlimited: %v\n", response.Account.Unlimited)
+ fmt.Printf("Premium: %v\n", response.Account.IsPremium)
+ fmt.Printf("Disabled: %v\n", response.Account.Disabled)
+ } else {
+ fmt.Println(response.Message)
+ }
+ return nil
+}
+
+func runAdminDelete(cmd *cobra.Command, args []string) error {
+ c, err := getAdminClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ response, err := c.DeleteAccount(args[0])
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ fmt.Println(response.Message)
+ return nil
+}
+
+func runAdminCredits(cmd *cobra.Command, args []string) error {
+ c, err := getAdminClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ credits, err := strconv.Atoi(args[1])
+ if err != nil {
+ return fmt.Errorf("invalid credits amount: %s", args[1])
+ }
+
+ response, err := c.UpdateCredits(args[0], credits)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ fmt.Println(response.Message)
+ return nil
+}
+
+func runAdminSetCredits(cmd *cobra.Command, args []string) error {
+ c, err := getAdminClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ credits, err := strconv.Atoi(args[1])
+ if err != nil {
+ return fmt.Errorf("invalid credits amount: %s", args[1])
+ }
+
+ response, err := c.SetCredits(args[0], credits)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if response.Account != nil {
+ fmt.Printf("Credits set successfully!\n")
+ fmt.Printf("Account: %s\n", response.Account.Name)
+ fmt.Printf("API Key: %s\n", response.Account.APIKey)
+ fmt.Printf("Credits: %d\n", response.Account.Credits)
+ } else if response.Message != "" {
+ fmt.Println(response.Message)
+ }
+ return nil
+}
+
+func runAdminDisable(cmd *cobra.Command, args []string) error {
+ c, err := getAdminClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ enable, _ := cmd.Flags().GetBool("enable")
+ response, err := c.ToggleAccount(args[0], enable)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ fmt.Println(response.Message)
+ return nil
+}
diff --git a/cmd/npd.go b/cmd/npd.go
new file mode 100644
index 0000000..0df627f
--- /dev/null
+++ b/cmd/npd.go
@@ -0,0 +1,95 @@
+package cmd
+
+import (
+ "dborg/internal/client"
+ "dborg/internal/config"
+ "dborg/internal/models"
+ "encoding/json"
+ "fmt"
+
+ "github.com/spf13/cobra"
+)
+
+var npdCmd = &cobra.Command{
+ Use: "npd",
+ Short: "Search NPD breach data",
+ Long: `Search NPD breach data by various fields`,
+ RunE: runNPDSearch,
+}
+
+func init() {
+ rootCmd.AddCommand(npdCmd)
+ npdCmd.Flags().StringP("id", "i", "", "ID")
+ npdCmd.Flags().StringP("firstname", "f", "", "First name")
+ npdCmd.Flags().StringP("lastname", "l", "", "Last name")
+ npdCmd.Flags().StringP("middlename", "m", "", "Middle name")
+ npdCmd.Flags().StringP("dob", "d", "", "Date of birth")
+ npdCmd.Flags().StringP("ssn", "s", "", "Social security number")
+ npdCmd.Flags().StringP("phone1", "p", "", "Phone number")
+ npdCmd.Flags().StringP("address", "a", "", "Address")
+ npdCmd.Flags().StringP("city", "c", "", "City")
+ npdCmd.Flags().StringP("st", "t", "", "State")
+ npdCmd.Flags().StringP("zip", "z", "", "ZIP code")
+ npdCmd.Flags().StringP("county_name", "y", "", "County name")
+ npdCmd.Flags().StringP("name_suff", "x", "", "Name suffix")
+ npdCmd.Flags().StringP("aka1fullname", "1", "", "AKA 1 full name")
+ npdCmd.Flags().StringP("aka2fullname", "2", "", "AKA 2 full name")
+ npdCmd.Flags().StringP("aka3fullname", "3", "", "AKA 3 full name")
+ npdCmd.Flags().StringP("alt1dob", "4", "", "Alternate DOB 1")
+ npdCmd.Flags().StringP("alt2dob", "5", "", "Alternate DOB 2")
+ npdCmd.Flags().StringP("alt3dob", "6", "", "Alternate DOB 3")
+ npdCmd.Flags().StringP("startdat", "r", "", "Start date")
+ npdCmd.Flags().IntP("max_hits", "n", 10, "Maximum number of hits to return")
+ npdCmd.Flags().StringP("sort_by", "o", "", "Sort by field")
+}
+
+func runNPDSearch(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.NPDParams{}
+ params.ID, _ = cmd.Flags().GetString("id")
+ params.FirstName, _ = cmd.Flags().GetString("firstname")
+ params.LastName, _ = cmd.Flags().GetString("lastname")
+ params.MiddleName, _ = cmd.Flags().GetString("middlename")
+ params.DOB, _ = cmd.Flags().GetString("dob")
+ params.SSN, _ = cmd.Flags().GetString("ssn")
+ params.Phone1, _ = cmd.Flags().GetString("phone1")
+ params.Address, _ = cmd.Flags().GetString("address")
+ params.City, _ = cmd.Flags().GetString("city")
+ params.State, _ = cmd.Flags().GetString("st")
+ params.Zip, _ = cmd.Flags().GetString("zip")
+ params.CountyName, _ = cmd.Flags().GetString("county_name")
+ params.NameSuffix, _ = cmd.Flags().GetString("name_suff")
+ params.AKA1FullName, _ = cmd.Flags().GetString("aka1fullname")
+ params.AKA2FullName, _ = cmd.Flags().GetString("aka2fullname")
+ params.AKA3FullName, _ = cmd.Flags().GetString("aka3fullname")
+ params.Alt1DOB, _ = cmd.Flags().GetString("alt1dob")
+ params.Alt2DOB, _ = cmd.Flags().GetString("alt2dob")
+ params.Alt3DOB, _ = cmd.Flags().GetString("alt3dob")
+ params.StartDate, _ = cmd.Flags().GetString("startdat")
+ params.MaxHits, _ = cmd.Flags().GetInt("max_hits")
+ params.SortBy, _ = cmd.Flags().GetString("sort_by")
+
+ response, err := c.SearchNPD(params)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ output, err := json.MarshalIndent(response.Results.Hits, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+
+ fmt.Println(string(output))
+ return nil
+}
diff --git a/cmd/osint.go b/cmd/osint.go
new file mode 100644
index 0000000..2f1f427
--- /dev/null
+++ b/cmd/osint.go
@@ -0,0 +1,103 @@
+package cmd
+
+import (
+ "dborg/internal/client"
+ "dborg/internal/config"
+ "dborg/internal/models"
+ "encoding/json"
+ "fmt"
+
+ "github.com/spf13/cobra"
+)
+
+var osintCmd = &cobra.Command{
+ Use: "osint",
+ Short: "OSINT tools and searches",
+ Long: `Open Source Intelligence tools for username, email, and other searches`,
+}
+
+var osintUsernameCmd = &cobra.Command{
+ Use: "username [username]",
+ Short: "Check username availability across websites",
+ Long: `Check username availability across hundreds of websites using WhatsMyName dataset`,
+ Args: cobra.ExactArgs(1),
+ RunE: runOsintUsernameCheck,
+}
+
+var osintBSSIDCmd = &cobra.Command{
+ Use: "bssid [bssid]",
+ Short: "Lookup WiFi access point location by BSSID",
+ Long: `Lookup geographic location of a WiFi access point by its BSSID (MAC address) using Apple's location services`,
+ Args: cobra.ExactArgs(1),
+ RunE: runOsintBSSIDLookup,
+}
+
+func init() {
+ rootCmd.AddCommand(osintCmd)
+ osintCmd.AddCommand(osintUsernameCmd)
+ osintCmd.AddCommand(osintBSSIDCmd)
+
+ osintUsernameCmd.Flags().StringSliceP("sites", "s", []string{}, "Specific sites to check (comma-separated)")
+ osintUsernameCmd.Flags().BoolP("fuzzy", "f", false, "Enable fuzzy validation mode")
+ osintUsernameCmd.Flags().IntP("max_tasks", "m", 50, "Maximum concurrent tasks")
+
+ osintBSSIDCmd.Flags().BoolP("all", "a", false, "Show all related results instead of exact match only")
+ osintBSSIDCmd.Flags().BoolP("map", "m", false, "Include Google Maps URL for the location")
+}
+
+func runOsintUsernameCheck(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.USRSXParams{
+ Username: args[0],
+ }
+ params.Sites, _ = cmd.Flags().GetStringSlice("sites")
+ params.Fuzzy, _ = cmd.Flags().GetBool("fuzzy")
+ params.MaxTasks, _ = cmd.Flags().GetInt("max_tasks")
+
+ err = c.CheckUsernameStream(params, func(result json.RawMessage) error {
+ fmt.Println(string(result))
+ return nil
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func runOsintBSSIDLookup(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.BSSIDParams{
+ BSSID: args[0],
+ }
+ params.All, _ = cmd.Flags().GetBool("all")
+ params.Map, _ = cmd.Flags().GetBool("map")
+
+ response, err := c.LookupBSSID(params)
+ if err != nil {
+ return err
+ }
+
+ output, err := json.MarshalIndent(response, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+
+ fmt.Println(string(output))
+ return nil
+}
diff --git a/cmd/root.go b/cmd/root.go
new file mode 100644
index 0000000..b8ab9e4
--- /dev/null
+++ b/cmd/root.go
@@ -0,0 +1,25 @@
+package cmd
+
+import (
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+)
+
+var rootCmd = &cobra.Command{
+ Use: "dborg",
+ Short: "DB.org.ai CLI client",
+ Long: `Query db.org.ai API`,
+}
+
+func Execute() {
+ if err := rootCmd.Execute(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}
+
+func init() {
+ rootCmd.PersistentFlags().StringP("api-key", "k", os.Getenv("DBORG_API_KEY"), "API key for authentication")
+}
diff --git a/cmd/skiptrace.go b/cmd/skiptrace.go
new file mode 100644
index 0000000..68fb832
--- /dev/null
+++ b/cmd/skiptrace.go
@@ -0,0 +1,199 @@
+package cmd
+
+import (
+ "dborg/internal/client"
+ "dborg/internal/config"
+ "dborg/internal/models"
+ "encoding/json"
+ "fmt"
+ "strconv"
+
+ "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 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 skiptraceReportCmd = &cobra.Command{
+ Use: "report [sx_key] [selection]",
+ Short: "Get detailed report for selected person",
+ Long: `Retrieve detailed report for a person from previous search results using sx_key and selection number`,
+ Args: cobra.ExactArgs(2),
+ RunE: runSkiptraceReport,
+}
+
+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,
+}
+
+func init() {
+ rootCmd.AddCommand(skiptraceCmd)
+ skiptraceCmd.AddCommand(skiptracePeopleCmd)
+ skiptraceCmd.AddCommand(skiptraceReportCmd)
+ skiptraceCmd.AddCommand(skiptracePhoneCmd)
+ skiptraceCmd.AddCommand(skiptraceEmailCmd)
+
+ 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")
+}
+
+func getSkiptraceClient(cmd *cobra.Command) (*client.Client, error) {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+ return client.New(cfg)
+}
+
+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 response.Data != nil && len(response.Data) > 0 {
+ output, err := json.MarshalIndent(response.Data, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+ fmt.Println(string(output))
+ }
+
+ return nil
+}
+
+func runSkiptraceReport(cmd *cobra.Command, args []string) error {
+ c, err := getSkiptraceClient(cmd)
+ if err != nil {
+ return err
+ }
+
+ sxKey := args[0]
+ selection, err := strconv.Atoi(args[1])
+ if err != nil {
+ return fmt.Errorf("invalid selection number: %s", args[1])
+ }
+
+ response, err := c.GetPersonReport(sxKey, selection)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if response.Data != nil && len(response.Data) > 0 {
+ output, err := json.MarshalIndent(response.Data, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+ fmt.Println(string(output))
+ }
+
+ if response.Message != "" {
+ fmt.Println(response.Message)
+ }
+
+ 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 response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if response.Data != nil && len(response.Data) > 0 {
+ output, err := json.MarshalIndent(response.Data, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+ fmt.Println(string(output))
+ }
+
+ if response.Message != "" {
+ fmt.Println(response.Message)
+ }
+
+ 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 response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if response.Data != nil && len(response.Data) > 0 {
+ output, err := json.MarshalIndent(response.Data, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+ fmt.Println(string(output))
+ }
+
+ if response.Message != "" {
+ fmt.Println(response.Message)
+ }
+
+ return nil
+}
diff --git a/cmd/sl.go b/cmd/sl.go
new file mode 100644
index 0000000..1551681
--- /dev/null
+++ b/cmd/sl.go
@@ -0,0 +1,73 @@
+package cmd
+
+import (
+ "dborg/internal/client"
+ "dborg/internal/config"
+ "dborg/internal/models"
+ "encoding/json"
+ "fmt"
+
+ "github.com/spf13/cobra"
+)
+
+var slCmd = &cobra.Command{
+ Use: "sl [query]",
+ Short: "Search stealer logs",
+ Long: `Search stealer logs with various filters`,
+ Args: cobra.ExactArgs(1),
+ RunE: runSLSearch,
+}
+
+func init() {
+ rootCmd.AddCommand(slCmd)
+ slCmd.Flags().IntP("max_hits", "n", 10, "Maximum number of hits to return")
+ slCmd.Flags().StringP("sort_by", "s", "", "Sort by field (ingest_timestamp or date_posted)")
+ slCmd.Flags().StringP("ingest_start_date", "i", "", "Ingest timestamp start date")
+ slCmd.Flags().StringP("ingest_end_date", "e", "", "Ingest timestamp end date")
+ slCmd.Flags().StringP("posted_start_date", "p", "", "Date posted start date")
+ slCmd.Flags().StringP("posted_end_date", "d", "", "Date posted end date")
+ slCmd.Flags().StringP("format", "f", "json", "Response format")
+}
+
+func runSLSearch(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ params := &models.SLParams{
+ Query: args[0],
+ }
+ params.MaxHits, _ = cmd.Flags().GetInt("max_hits")
+ params.SortBy, _ = cmd.Flags().GetString("sort_by")
+ params.IngestStartDate, _ = cmd.Flags().GetString("ingest_start_date")
+ params.IngestEndDate, _ = cmd.Flags().GetString("ingest_end_date")
+ params.PostedStartDate, _ = cmd.Flags().GetString("posted_start_date")
+ params.PostedEndDate, _ = cmd.Flags().GetString("posted_end_date")
+ params.Format, _ = cmd.Flags().GetString("format")
+
+ response, err := c.SearchStealerLogs(params)
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if params.Format != "json" {
+ fmt.Println(response.Message)
+ return nil
+ }
+
+ output, err := json.MarshalIndent(response.Results, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+
+ fmt.Println(string(output))
+ return nil
+}
diff --git a/cmd/x.go b/cmd/x.go
new file mode 100644
index 0000000..b4114b5
--- /dev/null
+++ b/cmd/x.go
@@ -0,0 +1,61 @@
+package cmd
+
+import (
+ "dborg/internal/client"
+ "dborg/internal/config"
+ "encoding/json"
+ "fmt"
+
+ "github.com/spf13/cobra"
+)
+
+var xCmd = &cobra.Command{
+ Use: "x [username]",
+ Short: "Search Twitter/X username history",
+ Long: `Search for Twitter/X username history and previous usernames`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXSearch,
+}
+
+func init() {
+ rootCmd.AddCommand(xCmd)
+}
+
+func runXSearch(cmd *cobra.Command, args []string) error {
+ apiKey, _ := cmd.Flags().GetString("api-key")
+ cfg := config.New().WithAPIKey(apiKey)
+
+ c, err := client.New(cfg)
+ if err != nil {
+ return err
+ }
+
+ response, err := c.SearchTwitterHistory(args[0])
+ if err != nil {
+ return err
+ }
+
+ if response.Error != "" {
+ return fmt.Errorf("API error: %s", response.Error)
+ }
+
+ if len(response.PreviousUsernames) > 0 {
+ output, err := json.MarshalIndent(response.PreviousUsernames, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+ fmt.Println(string(output))
+ } else if response.Response != "" {
+ fmt.Println(response.Response)
+ } else if response.Data != nil {
+ output, err := json.MarshalIndent(response.Data, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to format response: %w", err)
+ }
+ fmt.Println(string(output))
+ } else {
+ fmt.Println("No username history found")
+ }
+
+ return nil
+}