summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors <[email protected]>2025-11-07 11:50:47 -0500
committers <[email protected]>2025-11-07 11:50:47 -0500
commit7d63867f365163f149db5d768c71f518f9eaf711 (patch)
treef3f4856cf82f57286dee5bec23fae0c5f70bd1ee
parent5821aaa32e7ff2a2b2935bee712c2684907a3451 (diff)
downloaddborg-7d63867f365163f149db5d768c71f518f9eaf711.tar.gz
dborg-7d63867f365163f149db5d768c71f518f9eaf711.zip
refactor: extract json output formatting to utils.PrintJSON and add colorized json output with new dns tld command
-rw-r--r--cmd/admin.go10
-rw-r--r--cmd/dns.go57
-rw-r--r--cmd/npd.go10
-rw-r--r--cmd/osint.go17
-rw-r--r--cmd/reddit.go42
-rw-r--r--cmd/skiptrace.go26
-rw-r--r--cmd/sl.go10
-rw-r--r--cmd/x.go13
-rw-r--r--internal/client/dns.go51
-rw-r--r--internal/models/dns.go12
-rw-r--r--internal/utils/output.go113
11 files changed, 258 insertions, 103 deletions
diff --git a/cmd/admin.go b/cmd/admin.go
index 5637724..e0f0653 100644
--- a/cmd/admin.go
+++ b/cmd/admin.go
@@ -1,11 +1,11 @@
package cmd
import (
- "encoding/json"
"fmt"
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
"git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
"strconv"
"github.com/spf13/cobra"
@@ -94,13 +94,7 @@ func runAdminList(cmd *cobra.Command, args []string) 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
+ return utils.PrintJSON(response.Accounts)
}
func runAdminCreate(cmd *cobra.Command, args []string) error {
diff --git a/cmd/dns.go b/cmd/dns.go
new file mode 100644
index 0000000..71a0d83
--- /dev/null
+++ b/cmd/dns.go
@@ -0,0 +1,57 @@
+package cmd
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "git.db.org.ai/dborg/internal/client"
+ "git.db.org.ai/dborg/internal/config"
+ "git.db.org.ai/dborg/internal/models"
+ "github.com/spf13/cobra"
+)
+
+var dnsCmd = &cobra.Command{
+ Use: "dns",
+ Short: "DNS operations",
+ Long: "DNS-related operations for domain checking",
+}
+
+var dnsTLDCmd = &cobra.Command{
+ Use: "tld [term]",
+ Short: "Check NXDOMAIN for custom term against all TLDs",
+ Long: "Streams NDJSON results checking each TLD. For NXDOMAIN domains, returns status. For existing domains, runs httpx to get page title and tech stack.",
+ Args: cobra.ExactArgs(1),
+ RunE: runDNSTLDCheck,
+}
+
+func runDNSTLDCheck(cmd *cobra.Command, args []string) error {
+ term := args[0]
+
+ cfg := config.New()
+ c, err := client.New(cfg)
+ if err != nil {
+ return fmt.Errorf("failed to create client: %w", err)
+ }
+
+ params := &models.DNSTLDParams{
+ Term: term,
+ }
+
+ fmt.Printf("Checking TLDs for term: %s\n\n", term)
+
+ err = c.CheckDNSTLDStream(params, func(result json.RawMessage) error {
+ fmt.Println(string(result))
+ return nil
+ })
+
+ if err != nil {
+ return fmt.Errorf("TLD check failed: %w", err)
+ }
+
+ return nil
+}
+
+func init() {
+ rootCmd.AddCommand(dnsCmd)
+ dnsCmd.AddCommand(dnsTLDCmd)
+}
diff --git a/cmd/npd.go b/cmd/npd.go
index 6e7ed4b..a6bd7b2 100644
--- a/cmd/npd.go
+++ b/cmd/npd.go
@@ -1,11 +1,11 @@
package cmd
import (
- "encoding/json"
"fmt"
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
"git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
"github.com/spf13/cobra"
)
@@ -85,11 +85,5 @@ func runNPDSearch(cmd *cobra.Command, args []string) 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
+ return utils.PrintJSON(response.Results.Hits)
}
diff --git a/cmd/osint.go b/cmd/osint.go
index 49b94ab..5aa8799 100644
--- a/cmd/osint.go
+++ b/cmd/osint.go
@@ -6,6 +6,7 @@ import (
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
"git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
"github.com/spf13/cobra"
)
@@ -106,13 +107,7 @@ func runOsintBSSIDLookup(cmd *cobra.Command, args []string) error {
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
+ return utils.PrintJSON(response)
}
func runOsintBreachForumSearch(cmd *cobra.Command, args []string) error {
@@ -134,11 +129,5 @@ func runOsintBreachForumSearch(cmd *cobra.Command, args []string) error {
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
+ return utils.PrintJSON(response)
}
diff --git a/cmd/reddit.go b/cmd/reddit.go
index 2341322..1096a23 100644
--- a/cmd/reddit.go
+++ b/cmd/reddit.go
@@ -1,12 +1,12 @@
package cmd
import (
- "encoding/json"
"fmt"
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
"git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
"github.com/spf13/cobra"
)
@@ -103,13 +103,7 @@ func runRedditSubredditPosts(cmd *cobra.Command, args []string) error {
return fmt.Errorf("API error: %s", response.Error)
}
- output, err := json.MarshalIndent(response, "", " ")
- if err != nil {
- return fmt.Errorf("failed to format response: %w", err)
- }
-
- fmt.Println(string(output))
- return nil
+ return utils.PrintJSON(response)
}
func runRedditSubredditComments(cmd *cobra.Command, args []string) error {
@@ -134,13 +128,7 @@ func runRedditSubredditComments(cmd *cobra.Command, args []string) error {
return fmt.Errorf("API error: %s", response.Error)
}
- output, err := json.MarshalIndent(response, "", " ")
- if err != nil {
- return fmt.Errorf("failed to format response: %w", err)
- }
-
- fmt.Println(string(output))
- return nil
+ return utils.PrintJSON(response)
}
func runRedditUserPosts(cmd *cobra.Command, args []string) error {
@@ -165,13 +153,7 @@ func runRedditUserPosts(cmd *cobra.Command, args []string) error {
return fmt.Errorf("API error: %s", response.Error)
}
- output, err := json.MarshalIndent(response, "", " ")
- if err != nil {
- return fmt.Errorf("failed to format response: %w", err)
- }
-
- fmt.Println(string(output))
- return nil
+ return utils.PrintJSON(response)
}
func runRedditUserComments(cmd *cobra.Command, args []string) error {
@@ -196,13 +178,7 @@ func runRedditUserComments(cmd *cobra.Command, args []string) error {
return fmt.Errorf("API error: %s", response.Error)
}
- output, err := json.MarshalIndent(response, "", " ")
- if err != nil {
- return fmt.Errorf("failed to format response: %w", err)
- }
-
- fmt.Println(string(output))
- return nil
+ return utils.PrintJSON(response)
}
func runRedditUserAbout(cmd *cobra.Command, args []string) error {
@@ -227,11 +203,5 @@ func runRedditUserAbout(cmd *cobra.Command, args []string) error {
return fmt.Errorf("API error: %s", response.Error)
}
- output, err := json.MarshalIndent(response, "", " ")
- if err != nil {
- return fmt.Errorf("failed to format response: %w", err)
- }
-
- fmt.Println(string(output))
- return nil
+ return utils.PrintJSON(response)
}
diff --git a/cmd/skiptrace.go b/cmd/skiptrace.go
index 6b0ad0b..a9ab862 100644
--- a/cmd/skiptrace.go
+++ b/cmd/skiptrace.go
@@ -1,11 +1,11 @@
package cmd
import (
- "encoding/json"
"fmt"
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
"git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
"strconv"
"github.com/spf13/cobra"
@@ -92,11 +92,7 @@ func runSkiptracePeople(cmd *cobra.Command, args []string) 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))
+ return utils.PrintJSON(response.Data)
}
return nil
@@ -124,11 +120,9 @@ func runSkiptraceReport(cmd *cobra.Command, args []string) 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)
+ if err := utils.PrintJSON(response.Data); err != nil {
+ return err
}
- fmt.Println(string(output))
}
if response.Message != "" {
@@ -154,11 +148,9 @@ func runSkiptracePhone(cmd *cobra.Command, args []string) 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)
+ if err := utils.PrintJSON(response.Data); err != nil {
+ return err
}
- fmt.Println(string(output))
}
if response.Message != "" {
@@ -184,11 +176,9 @@ func runSkiptraceEmail(cmd *cobra.Command, args []string) 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)
+ if err := utils.PrintJSON(response.Data); err != nil {
+ return err
}
- fmt.Println(string(output))
}
if response.Message != "" {
diff --git a/cmd/sl.go b/cmd/sl.go
index 82adfdf..cabd4ce 100644
--- a/cmd/sl.go
+++ b/cmd/sl.go
@@ -1,11 +1,11 @@
package cmd
import (
- "encoding/json"
"fmt"
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
"git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
"github.com/spf13/cobra"
)
@@ -63,11 +63,5 @@ func runSLSearch(cmd *cobra.Command, args []string) error {
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
+ return utils.PrintJSON(response.Results)
}
diff --git a/cmd/x.go b/cmd/x.go
index b933e3d..c88243b 100644
--- a/cmd/x.go
+++ b/cmd/x.go
@@ -5,6 +5,7 @@ import (
"fmt"
"git.db.org.ai/dborg/internal/client"
"git.db.org.ai/dborg/internal/config"
+ "git.db.org.ai/dborg/internal/utils"
"github.com/spf13/cobra"
)
@@ -56,19 +57,11 @@ func runXHistorySearch(cmd *cobra.Command, args []string) 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))
+ return utils.PrintJSON(response.PreviousUsernames)
} 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))
+ return utils.PrintJSON(response.Data)
} else {
fmt.Println("No username history found")
}
diff --git a/internal/client/dns.go b/internal/client/dns.go
new file mode 100644
index 0000000..08449e0
--- /dev/null
+++ b/internal/client/dns.go
@@ -0,0 +1,51 @@
+package client
+
+import (
+ "bufio"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+
+ "git.db.org.ai/dborg/internal/models"
+)
+
+func (c *Client) CheckDNSTLDStream(params *models.DNSTLDParams, callback func(result json.RawMessage) error) error {
+ term := url.PathEscape(params.Term)
+ fullURL := c.config.BaseURL + "/dns/tld/" + term
+
+ req, err := http.NewRequest(http.MethodGet, fullURL, nil)
+ if err != nil {
+ return fmt.Errorf("failed to create request: %w", err)
+ }
+
+ req.Header.Set("User-Agent", c.config.UserAgent)
+
+ resp, err := c.httpClient.Do(req)
+ if err != nil {
+ return fmt.Errorf("request failed: %w", err)
+ }
+ defer resp.Body.Close()
+
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("API request failed with status %d", resp.StatusCode)
+ }
+
+ scanner := bufio.NewScanner(resp.Body)
+ for scanner.Scan() {
+ line := scanner.Bytes()
+ if len(line) == 0 {
+ continue
+ }
+
+ if err := callback(json.RawMessage(line)); err != nil {
+ return fmt.Errorf("callback failed: %w", err)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return fmt.Errorf("failed to read response: %w", err)
+ }
+
+ return nil
+}
diff --git a/internal/models/dns.go b/internal/models/dns.go
new file mode 100644
index 0000000..b08d8ba
--- /dev/null
+++ b/internal/models/dns.go
@@ -0,0 +1,12 @@
+package models
+
+type DNSTLDParams struct {
+ Term string
+}
+
+type DomainResult struct {
+ Domain string `json:"domain"`
+ Status string `json:"status"`
+ Title string `json:"title,omitempty"`
+ Tech []string `json:"tech,omitempty"`
+}
diff --git a/internal/utils/output.go b/internal/utils/output.go
index 3f2347c..e8e97bc 100644
--- a/internal/utils/output.go
+++ b/internal/utils/output.go
@@ -1,18 +1,129 @@
package utils
import (
+ "bytes"
"encoding/json"
"fmt"
"os"
"text/tabwriter"
)
+const (
+ colorReset = "\033[0m"
+ colorKey = "\033[36m"
+ colorString = "\033[32m"
+ colorNumber = "\033[33m"
+ colorBool = "\033[35m"
+ colorNull = "\033[90m"
+ colorBrace = "\033[37m"
+)
+
+func colorizeJSON(data []byte) string {
+ if !isTerminal() {
+ return string(data)
+ }
+
+ var result bytes.Buffer
+ var inString bool
+ var isKey bool
+ var depth int
+
+ for i := 0; i < len(data); i++ {
+ c := data[i]
+
+ switch c {
+ case '"':
+ if i > 0 && data[i-1] != '\\' {
+ inString = !inString
+ if inString {
+ if i > 0 && (data[i-1] == '{' || data[i-1] == ',' || data[i-1] == '[' || data[i-1] == '\n' || data[i-1] == ' ') {
+ isKey = true
+ result.WriteString(colorKey)
+ } else {
+ result.WriteString(colorString)
+ }
+ } else {
+ result.WriteByte(c)
+ result.WriteString(colorReset)
+ if isKey && i+1 < len(data) && data[i+1] == ':' {
+ isKey = false
+ }
+ continue
+ }
+ }
+ result.WriteByte(c)
+
+ case '{', '}', '[', ']':
+ if !inString {
+ result.WriteString(colorBrace)
+ result.WriteByte(c)
+ result.WriteString(colorReset)
+ if c == '{' || c == '[' {
+ depth++
+ } else {
+ depth--
+ }
+ } else {
+ result.WriteByte(c)
+ }
+
+ case 't', 'f':
+ if !inString && i+3 < len(data) {
+ word := string(data[i:min(i+5, len(data))])
+ if word[:4] == "true" || word[:5] == "false" {
+ result.WriteString(colorBool)
+ if word[:4] == "true" {
+ result.WriteString("true")
+ i += 3
+ } else {
+ result.WriteString("false")
+ i += 4
+ }
+ result.WriteString(colorReset)
+ } else {
+ result.WriteByte(c)
+ }
+ } else {
+ result.WriteByte(c)
+ }
+
+ case 'n':
+ if !inString && i+3 < len(data) && string(data[i:i+4]) == "null" {
+ result.WriteString(colorNull)
+ result.WriteString("null")
+ result.WriteString(colorReset)
+ i += 3
+ } else {
+ result.WriteByte(c)
+ }
+
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
+ if !inString {
+ result.WriteString(colorNumber)
+ for i < len(data) && (data[i] >= '0' && data[i] <= '9' || data[i] == '.' || data[i] == '-' || data[i] == 'e' || data[i] == 'E' || data[i] == '+') {
+ result.WriteByte(data[i])
+ i++
+ }
+ i--
+ result.WriteString(colorReset)
+ } else {
+ result.WriteByte(c)
+ }
+
+ default:
+ result.WriteByte(c)
+ }
+ }
+
+ return result.String()
+}
+
func PrintJSON(data any) error {
output, err := json.MarshalIndent(data, "", " ")
if err != nil {
return fmt.Errorf("failed to format JSON: %w", err)
}
- fmt.Println(string(output))
+ fmt.Println(colorizeJSON(output))
return nil
}