summaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/client/crypto.go235
-rw-r--r--internal/client/email.go28
-rw-r--r--internal/client/telegram.go28
-rw-r--r--internal/formatter/crypto.go39
-rw-r--r--internal/formatter/email.go103
-rw-r--r--internal/formatter/telegram.go34
-rw-r--r--internal/models/admin.go19
-rw-r--r--internal/models/crypto.go12
-rw-r--r--internal/models/email.go21
-rw-r--r--internal/models/github.go1
-rw-r--r--internal/models/telegram.go12
11 files changed, 523 insertions, 9 deletions
diff --git a/internal/client/crypto.go b/internal/client/crypto.go
new file mode 100644
index 0000000..ee145f9
--- /dev/null
+++ b/internal/client/crypto.go
@@ -0,0 +1,235 @@
+package client
+
+import (
+ "encoding/json"
+ "fmt"
+ "git.db.org.ai/dborg/internal/models"
+ "strings"
+)
+
+func (c *Client) GetBundleDetection(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/bundle-detection/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetCrossTraders(addresses string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/cross-traders/%s", addresses)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetEarlyAdopters(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/early-adopters/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetFloorHolders(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/floor-holders/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetFreshAccounts(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/fresh-accounts/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetFundingSource(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/funding-source/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetGraduationStats() (*models.CryptoResponse, error) {
+ data, err := c.Get("/crypto/graduation-stats", nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetLaunchParticipants(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/launch-participants/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetLiquidity(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/liquidity/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetOwnerIntel(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/owner-intel/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetOwnershipDistribution(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/ownership-distribution/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetPortfolio(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/portfolio/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetTopOwners(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/top-owners/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func (c *Client) GetWhaleIntel(address string) (*models.CryptoResponse, error) {
+ path := fmt.Sprintf("/crypto/whale-intel/%s", address)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.CryptoResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse crypto response: %w", err)
+ }
+
+ return &response, nil
+}
+
+func ValidateCryptoAddress(address string) error {
+ if len(address) == 0 {
+ return fmt.Errorf("address cannot be empty")
+ }
+ return nil
+}
+
+func ValidateCryptoAddresses(addresses string) error {
+ if len(addresses) == 0 {
+ return fmt.Errorf("addresses cannot be empty")
+ }
+ parts := strings.Split(addresses, ",")
+ if len(parts) < 2 {
+ return fmt.Errorf("at least 2 addresses required for cross-trader analysis")
+ }
+ return nil
+}
diff --git a/internal/client/email.go b/internal/client/email.go
new file mode 100644
index 0000000..a7000fe
--- /dev/null
+++ b/internal/client/email.go
@@ -0,0 +1,28 @@
+package client
+
+import (
+ "encoding/json"
+ "fmt"
+ "git.db.org.ai/dborg/internal/models"
+ "strings"
+)
+
+func (c *Client) VerifyEmail(email string) (*models.EmailVerifyResponse, error) {
+ email = strings.TrimSpace(email)
+ if email == "" {
+ return nil, fmt.Errorf("email address cannot be empty")
+ }
+
+ path := fmt.Sprintf("/email/verify/%s", email)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.EmailVerifyResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse email verification response: %w", err)
+ }
+
+ return &response, nil
+}
diff --git a/internal/client/telegram.go b/internal/client/telegram.go
new file mode 100644
index 0000000..33b4ac2
--- /dev/null
+++ b/internal/client/telegram.go
@@ -0,0 +1,28 @@
+package client
+
+import (
+ "encoding/json"
+ "fmt"
+ "git.db.org.ai/dborg/internal/models"
+ "strings"
+)
+
+func (c *Client) GetTelegramPhone(identifier string) (*models.TelegramPhoneResponse, error) {
+ identifier = strings.TrimSpace(identifier)
+ if identifier == "" {
+ return nil, fmt.Errorf("identifier cannot be empty")
+ }
+
+ path := fmt.Sprintf("/telegram/phone/%s", identifier)
+ data, err := c.Get(path, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var response models.TelegramPhoneResponse
+ if err := json.Unmarshal(data, &response); err != nil {
+ return nil, fmt.Errorf("failed to parse telegram response: %w", err)
+ }
+
+ return &response, nil
+}
diff --git a/internal/formatter/crypto.go b/internal/formatter/crypto.go
new file mode 100644
index 0000000..70ef29b
--- /dev/null
+++ b/internal/formatter/crypto.go
@@ -0,0 +1,39 @@
+package formatter
+
+import (
+ "fmt"
+ "git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
+ "strings"
+)
+
+func FormatCryptoResults(response *models.CryptoResponse, asJSON bool) error {
+ if asJSON {
+ return utils.PrintJSON(response)
+ }
+
+ PrintSection(fmt.Sprintf("📊 Crypto Analysis Results"))
+
+ if response.Query != "" {
+ fmt.Printf("%s: %s\n\n", Cyan("Query"), response.Query)
+ }
+
+ if response.Response != "" {
+ fmt.Println(response.Response)
+ fmt.Println()
+ }
+
+ PrintDivider()
+ fmt.Printf("%s: ", Cyan("Credits Remaining"))
+ if response.Credits.Unlimited {
+ fmt.Printf("%s\n", Green("Unlimited"))
+ } else {
+ fmt.Printf("%s\n", FormatCredits(int64(response.Credits.Remaining)))
+ }
+
+ if response.Message != "" && !strings.Contains(strings.ToLower(response.Message), "success") {
+ fmt.Printf("\n%s: %s\n", Yellow("Message"), response.Message)
+ }
+
+ return nil
+}
diff --git a/internal/formatter/email.go b/internal/formatter/email.go
new file mode 100644
index 0000000..80f590c
--- /dev/null
+++ b/internal/formatter/email.go
@@ -0,0 +1,103 @@
+package formatter
+
+import (
+ "fmt"
+ "git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
+)
+
+func FormatEmailResults(response *models.EmailVerifyResponse, asJSON bool) error {
+ if asJSON {
+ return utils.PrintJSON(response)
+ }
+
+ PrintSection(fmt.Sprintf("📧 Email Verification: %s", Bold(response.Email)))
+
+ statusColor := ColorGreen
+ switch response.Status {
+ case "valid":
+ statusColor = ColorGreen
+ case "invalid":
+ statusColor = ColorRed
+ case "risky", "accept_all":
+ statusColor = ColorYellow
+ default:
+ statusColor = ColorGray
+ }
+
+ fmt.Printf("%s: %s", Cyan("Status"), Colorize(response.Status, statusColor))
+ if response.Score > 0 {
+ scoreColor := ColorGreen
+ if response.Score < 50 {
+ scoreColor = ColorRed
+ } else if response.Score < 75 {
+ scoreColor = ColorYellow
+ }
+ fmt.Printf(" (Score: %s)", Colorize(fmt.Sprintf("%d/100", response.Score), scoreColor))
+ }
+ fmt.Println()
+
+ fmt.Println()
+ fmt.Printf("%s\n", Bold("Validation Checks"))
+
+ checks := []struct {
+ name string
+ passed bool
+ }{
+ {"Format Valid", response.Regexp},
+ {"MX Records Found", response.MXRecords},
+ {"SMTP Server Reachable", response.SMTPServer},
+ {"Mailbox Verified", response.SMTPCheck},
+ }
+
+ for _, check := range checks {
+ status := StatusError
+ if check.passed {
+ status = StatusSuccess
+ }
+ fmt.Printf(" %s %s\n", status.String(), check.name)
+ }
+
+ if response.MXServer != "" {
+ fmt.Printf("\n%s: %s\n", Cyan("MX Server"), response.MXServer)
+ }
+
+ fmt.Println()
+ fmt.Printf("%s\n", Bold("Risk Indicators"))
+
+ risks := []struct {
+ name string
+ present bool
+ }{
+ {"Disposable Email", response.Disposable},
+ {"Webmail Service", response.Webmail},
+ {"Blocked Domain", response.Block},
+ {"Gibberish Detected", response.Gibberish},
+ }
+
+ hasRisks := false
+ for _, risk := range risks {
+ if risk.present {
+ hasRisks = true
+ fmt.Printf(" %s %s\n", StatusWarning.String(), risk.name)
+ }
+ }
+
+ if !hasRisks {
+ fmt.Printf(" %s %s\n", StatusSuccess.String(), "No risk indicators found")
+ }
+
+ if response.ResponseTimeMs > 0 {
+ fmt.Printf("\n%s: %dms\n", Dim("Response Time"), response.ResponseTimeMs)
+ }
+
+ if response.ErrorMessage != "" {
+ fmt.Printf("\n%s: %s\n", Red("Error"), response.ErrorMessage)
+ }
+
+ if response.VerifiedAt != "" {
+ fmt.Printf("%s: %s\n", Dim("Verified At"), response.VerifiedAt)
+ }
+
+ return nil
+}
diff --git a/internal/formatter/telegram.go b/internal/formatter/telegram.go
new file mode 100644
index 0000000..7491c66
--- /dev/null
+++ b/internal/formatter/telegram.go
@@ -0,0 +1,34 @@
+package formatter
+
+import (
+ "fmt"
+ "git.db.org.ai/dborg/internal/models"
+ "git.db.org.ai/dborg/internal/utils"
+)
+
+func FormatTelegramResults(response *models.TelegramPhoneResponse, asJSON bool) error {
+ if asJSON {
+ return utils.PrintJSON(response)
+ }
+
+ PrintSection(fmt.Sprintf("📱 Telegram Phone Lookup"))
+
+ fmt.Printf("%s: %s\n", Cyan("Identifier"), response.Identifier)
+
+ if response.PhoneNumber != "" {
+ fmt.Printf("%s: %s\n", Cyan("Phone Number"), Green(response.PhoneNumber))
+ } else {
+ fmt.Printf("%s: %s\n", Cyan("Phone Number"), Red("Not found"))
+ }
+
+ fmt.Println()
+ PrintDivider()
+ fmt.Printf("%s: ", Cyan("Credits Remaining"))
+ if response.Credits.Unlimited {
+ fmt.Printf("%s\n", Green("Unlimited"))
+ } else {
+ fmt.Printf("%s\n", FormatCredits(int64(response.Credits.Remaining)))
+ }
+
+ return nil
+}
diff --git a/internal/models/admin.go b/internal/models/admin.go
index 852e80f..ee551f3 100644
--- a/internal/models/admin.go
+++ b/internal/models/admin.go
@@ -1,15 +1,16 @@
package models
type Account struct {
- ID int `json:"id"`
- APIKey string `json:"api_key"`
- Name string `json:"name"`
- Credits int `json:"credits"`
- Unlimited bool `json:"unlimited"`
- Disabled bool `json:"disabled"`
- IsPremium bool `json:"is_premium"`
- IsAdmin bool `json:"is_admin"`
- CreatedAt interface{} `json:"created_at,omitempty"`
+ ID int `json:"id"`
+ APIKey string `json:"api_key"`
+ Name string `json:"name"`
+ Credits int `json:"credits"`
+ Unlimited bool `json:"unlimited"`
+ Disabled bool `json:"disabled"`
+ IsPremium bool `json:"is_premium"`
+ IsAdmin bool `json:"is_admin"`
+ PremiumDiscountPct int `json:"premium_discount_pct,omitempty"`
+ CreatedAt interface{} `json:"created_at,omitempty"`
}
type AccountCreateRequest struct {
diff --git a/internal/models/crypto.go b/internal/models/crypto.go
new file mode 100644
index 0000000..1900037
--- /dev/null
+++ b/internal/models/crypto.go
@@ -0,0 +1,12 @@
+package models
+
+type CryptoResponse struct {
+ Query string `json:"query"`
+ Response string `json:"response"`
+ Credits struct {
+ Remaining int `json:"remaining"`
+ Unlimited bool `json:"unlimited"`
+ } `json:"credits"`
+ Message string `json:"message,omitempty"`
+ Error string `json:"error,omitempty"`
+}
diff --git a/internal/models/email.go b/internal/models/email.go
new file mode 100644
index 0000000..0b95e85
--- /dev/null
+++ b/internal/models/email.go
@@ -0,0 +1,21 @@
+package models
+
+type EmailVerifyResponse struct {
+ Email string `json:"email"`
+ Status string `json:"status"`
+ Score int `json:"score"`
+ Regexp bool `json:"regexp"`
+ MXRecords bool `json:"mx_records"`
+ MXServer string `json:"mx_server,omitempty"`
+ SMTPServer bool `json:"smtp_server"`
+ SMTPCheck bool `json:"smtp_check"`
+ Disposable bool `json:"disposable"`
+ Webmail bool `json:"webmail"`
+ Block bool `json:"block"`
+ Gibberish bool `json:"gibberish"`
+ ErrorMessage string `json:"error_message,omitempty"`
+ VerifiedAt string `json:"verified_at,omitempty"`
+ ResponseTimeMs int `json:"response_time_ms"`
+ Message string `json:"message,omitempty"`
+ Error string `json:"error,omitempty"`
+}
diff --git a/internal/models/github.go b/internal/models/github.go
index fc1c9c3..3b7fc73 100644
--- a/internal/models/github.go
+++ b/internal/models/github.go
@@ -9,4 +9,5 @@ type GitHubLead struct {
Website string `json:"website,omitempty"`
Twitter string `json:"twitter,omitempty"`
PFP string `json:"pfp,omitempty"`
+ Bio string `json:"bio,omitempty"`
}
diff --git a/internal/models/telegram.go b/internal/models/telegram.go
new file mode 100644
index 0000000..05900cb
--- /dev/null
+++ b/internal/models/telegram.go
@@ -0,0 +1,12 @@
+package models
+
+type TelegramPhoneResponse struct {
+ Identifier string `json:"identifier"`
+ PhoneNumber string `json:"phone_number"`
+ Credits struct {
+ Remaining int `json:"remaining"`
+ Unlimited bool `json:"unlimited"`
+ } `json:"credits"`
+ Message string `json:"message,omitempty"`
+ Error string `json:"error,omitempty"`
+}