summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.python-version1
-rw-r--r--cmd/breachforum.go11
-rw-r--r--cmd/bssid.go11
-rw-r--r--cmd/buckets.go18
-rw-r--r--cmd/crawl.go11
-rw-r--r--cmd/crypto.go161
-rw-r--r--cmd/dns.go22
-rw-r--r--cmd/email.go18
-rw-r--r--cmd/files.go11
-rw-r--r--cmd/geo.go9
-rw-r--r--cmd/github.go18
-rw-r--r--cmd/moon.go11
-rw-r--r--cmd/reddit.go76
-rw-r--r--cmd/shortlinks.go9
-rw-r--r--cmd/skiptrace.go52
-rw-r--r--cmd/telegram.go18
-rw-r--r--cmd/username.go11
-rw-r--r--cmd/x.go110
-rw-r--r--internal/formatter/sl.go86
-rw-r--r--internal/models/sl.go18
-rw-r--r--resume.cfg2
-rw-r--r--sl_bot.py281
22 files changed, 628 insertions, 337 deletions
diff --git a/.python-version b/.python-version
new file mode 100644
index 0000000..2c07333
--- /dev/null
+++ b/.python-version
@@ -0,0 +1 @@
+3.11
diff --git a/cmd/breachforum.go b/cmd/breachforum.go
index 366092c..63254c1 100644
--- a/cmd/breachforum.go
+++ b/cmd/breachforum.go
@@ -7,11 +7,12 @@ import (
)
var breachforumCmd = &cobra.Command{
- Use: "breachforum [search]",
- Short: "Search BreachForum data",
- Long: `Search breachdetect index for BreachForum messages and detections`,
- Args: cobra.ExactArgs(1),
- RunE: runBreachForumSearch,
+ Use: "breachforum [search]",
+ Aliases: []string{"brf"},
+ Short: "Search BreachForum data",
+ Long: `Search breachdetect index for BreachForum messages and detections`,
+ Args: cobra.ExactArgs(1),
+ RunE: runBreachForumSearch,
}
func init() {
diff --git a/cmd/bssid.go b/cmd/bssid.go
index 7a9e4c0..0cf751f 100644
--- a/cmd/bssid.go
+++ b/cmd/bssid.go
@@ -7,11 +7,12 @@ import (
)
var bssidCmd = &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: runBSSIDLookup,
+ Use: "bssid [bssid]",
+ Aliases: []string{"bs"},
+ 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: runBSSIDLookup,
}
func init() {
diff --git a/cmd/buckets.go b/cmd/buckets.go
index fcb292d..74e0e3b 100644
--- a/cmd/buckets.go
+++ b/cmd/buckets.go
@@ -7,17 +7,19 @@ import (
)
var bucketsCmd = &cobra.Command{
- Use: "buckets",
- Short: "List public buckets",
- Long: `List public S3, Azure, GCP, and DigitalOcean buckets with file counts`,
- RunE: runBucketsSearch,
+ Use: "buckets",
+ Aliases: []string{"b"},
+ Short: "List public buckets",
+ Long: `List public S3, Azure, GCP, and DigitalOcean buckets with file counts`,
+ RunE: runBucketsSearch,
}
var bucketFilesCmd = &cobra.Command{
- Use: "bucket-files",
- Short: "Search public bucket files",
- Long: `Search public S3, Azure, GCP, and DigitalOcean buckets for exposed files`,
- RunE: runBucketFilesSearch,
+ Use: "bucket-files",
+ Aliases: []string{"bf"},
+ Short: "Search public bucket files",
+ Long: `Search public S3, Azure, GCP, and DigitalOcean buckets for exposed files`,
+ RunE: runBucketFilesSearch,
}
func init() {
diff --git a/cmd/crawl.go b/cmd/crawl.go
index d889e1d..2c9b719 100644
--- a/cmd/crawl.go
+++ b/cmd/crawl.go
@@ -7,11 +7,12 @@ import (
)
var crawlCmd = &cobra.Command{
- Use: "crawl [domain]",
- Short: "Crawl domain",
- Long: `Resolves a domain using httpx and crawls it using katana. Returns discovered links as plain text, one per line, streamed in real-time. Supports both http:// and https:// URLs.`,
- Args: cobra.ExactArgs(1),
- RunE: runCrawl,
+ Use: "crawl [domain]",
+ Aliases: []string{"cw"},
+ Short: "Crawl domain",
+ Long: `Resolves a domain using httpx and crawls it using katana. Returns discovered links as plain text, one per line, streamed in real-time. Supports both http:// and https:// URLs.`,
+ Args: cobra.ExactArgs(1),
+ RunE: runCrawl,
}
func init() {
diff --git a/cmd/crypto.go b/cmd/crypto.go
index 02b39b1..829a54d 100644
--- a/cmd/crypto.go
+++ b/cmd/crypto.go
@@ -7,121 +7,136 @@ import (
)
var cryptoCmd = &cobra.Command{
- Use: "crypto",
- Short: "Crypto analysis commands",
- Long: `Analyze cryptocurrency tokens, wallets, and trading activity`,
+ Use: "crypto",
+ Aliases: []string{"cr"},
+ Short: "Crypto analysis commands",
+ Long: `Analyze cryptocurrency tokens, wallets, and trading activity`,
}
var bundleDetectionCmd = &cobra.Command{
- Use: "bundle-detection [address]",
- Short: "Detect bundled launches",
- Long: `Analyzes whether a token contract was bundled during launch`,
- Args: cobra.ExactArgs(1),
- RunE: runBundleDetection,
+ Use: "bundle-detection [address]",
+ Aliases: []string{"bd"},
+ Short: "Detect bundled launches",
+ Long: `Analyzes whether a token contract was bundled during launch`,
+ Args: cobra.ExactArgs(1),
+ RunE: runBundleDetection,
}
var crossTradersCmd = &cobra.Command{
- Use: "cross-traders [addresses]",
- Short: "Find cross-token traders",
- Long: `Filters common traders active across multiple token contracts (comma-separated addresses)`,
- Args: cobra.ExactArgs(1),
- RunE: runCrossTraders,
+ Use: "cross-traders [addresses]",
+ Aliases: []string{"ct"},
+ Short: "Find cross-token traders",
+ Long: `Filters common traders active across multiple token contracts (comma-separated addresses)`,
+ Args: cobra.ExactArgs(1),
+ RunE: runCrossTraders,
}
var earlyAdoptersCmd = &cobra.Command{
- Use: "early-adopters [address]",
- Short: "Analyze early adopters",
- Long: `Analyzes early buyers and their trading activity for a token`,
- Args: cobra.ExactArgs(1),
- RunE: runEarlyAdopters,
+ Use: "early-adopters [address]",
+ Aliases: []string{"ea"},
+ Short: "Analyze early adopters",
+ Long: `Analyzes early buyers and their trading activity for a token`,
+ Args: cobra.ExactArgs(1),
+ RunE: runEarlyAdopters,
}
var floorHoldersCmd = &cobra.Command{
- Use: "floor-holders [address]",
- Short: "Analyze floor price holders",
- Long: `Analyzes top holders who bought at floor prices`,
- Args: cobra.ExactArgs(1),
- RunE: runFloorHolders,
+ Use: "floor-holders [address]",
+ Aliases: []string{"fh"},
+ Short: "Analyze floor price holders",
+ Long: `Analyzes top holders who bought at floor prices`,
+ Args: cobra.ExactArgs(1),
+ RunE: runFloorHolders,
}
var freshAccountsCmd = &cobra.Command{
- Use: "fresh-accounts [address]",
- Short: "Analyze fresh accounts",
- Long: `Analyzes top holder fresh wallets to detect potential sybil attacks`,
- Args: cobra.ExactArgs(1),
- RunE: runFreshAccounts,
+ Use: "fresh-accounts [address]",
+ Aliases: []string{"fa"},
+ Short: "Analyze fresh accounts",
+ Long: `Analyzes top holder fresh wallets to detect potential sybil attacks`,
+ Args: cobra.ExactArgs(1),
+ RunE: runFreshAccounts,
}
var fundingSourceCmd = &cobra.Command{
- Use: "funding-source [address]",
- Short: "Analyze funding source",
- Long: `Determines how and when a wallet address was funded`,
- Args: cobra.ExactArgs(1),
- RunE: runFundingSource,
+ Use: "funding-source [address]",
+ Aliases: []string{"fs"},
+ Short: "Analyze funding source",
+ Long: `Determines how and when a wallet address was funded`,
+ Args: cobra.ExactArgs(1),
+ RunE: runFundingSource,
}
var graduationStatsCmd = &cobra.Command{
- Use: "graduation-stats",
- Short: "Get graduation statistics",
- Long: `Retrieves statistics for recently graduated token launches`,
- Args: cobra.NoArgs,
- RunE: runGraduationStats,
+ Use: "graduation-stats",
+ Aliases: []string{"gs"},
+ Short: "Get graduation statistics",
+ Long: `Retrieves statistics for recently graduated token launches`,
+ Args: cobra.NoArgs,
+ RunE: runGraduationStats,
}
var launchParticipantsCmd = &cobra.Command{
- Use: "launch-participants [address]",
- Short: "Get launch participants",
- Long: `Retrieves list of early participants in token launch`,
- Args: cobra.ExactArgs(1),
- RunE: runLaunchParticipants,
+ Use: "launch-participants [address]",
+ Aliases: []string{"lp"},
+ Short: "Get launch participants",
+ Long: `Retrieves list of early participants in token launch`,
+ Args: cobra.ExactArgs(1),
+ RunE: runLaunchParticipants,
}
var liquidityCmd = &cobra.Command{
- Use: "liquidity [address]",
- Short: "Check liquidity status",
- Long: `Checks if liquidity has been added or updated on DEX for a token`,
- Args: cobra.ExactArgs(1),
- RunE: runLiquidity,
+ Use: "liquidity [address]",
+ Aliases: []string{"liq"},
+ Short: "Check liquidity status",
+ Long: `Checks if liquidity has been added or updated on DEX for a token`,
+ Args: cobra.ExactArgs(1),
+ RunE: runLiquidity,
}
var ownerIntelCmd = &cobra.Command{
- Use: "owner-intel [address]",
- Short: "Get owner intelligence",
- Long: `Retrieves detailed intelligence and analysis on token holders`,
- Args: cobra.ExactArgs(1),
- RunE: runOwnerIntel,
+ Use: "owner-intel [address]",
+ Aliases: []string{"oi"},
+ Short: "Get owner intelligence",
+ Long: `Retrieves detailed intelligence and analysis on token holders`,
+ Args: cobra.ExactArgs(1),
+ RunE: runOwnerIntel,
}
var ownershipDistributionCmd = &cobra.Command{
- Use: "ownership-distribution [address]",
- Short: "Analyze ownership distribution",
- Long: `Visualizes token holder ownership distribution and concentration`,
- Args: cobra.ExactArgs(1),
- RunE: runOwnershipDistribution,
+ Use: "ownership-distribution [address]",
+ Aliases: []string{"od"},
+ Short: "Analyze ownership distribution",
+ Long: `Visualizes token holder ownership distribution and concentration`,
+ Args: cobra.ExactArgs(1),
+ RunE: runOwnershipDistribution,
}
var portfolioCmd = &cobra.Command{
- Use: "portfolio [address]",
- Short: "Analyze portfolio",
- Long: `Analyzes profit and loss for recently traded tokens in a wallet`,
- Args: cobra.ExactArgs(1),
- RunE: runPortfolio,
+ Use: "portfolio [address]",
+ Aliases: []string{"pf"},
+ Short: "Analyze portfolio",
+ Long: `Analyzes profit and loss for recently traded tokens in a wallet`,
+ Args: cobra.ExactArgs(1),
+ RunE: runPortfolio,
}
var topOwnersCmd = &cobra.Command{
- Use: "top-owners [address]",
- Short: "Analyze top owners",
- Long: `Analyzes the top holders and their positions for a token`,
- Args: cobra.ExactArgs(1),
- RunE: runTopOwners,
+ Use: "top-owners [address]",
+ Aliases: []string{"to"},
+ Short: "Analyze top owners",
+ Long: `Analyzes the top holders and their positions for a token`,
+ Args: cobra.ExactArgs(1),
+ RunE: runTopOwners,
}
var whaleIntelCmd = &cobra.Command{
- Use: "whale-intel [address]",
- Short: "Analyze whale holdings",
- Long: `Analyzes net worth and positions of top 50 whale holders`,
- Args: cobra.ExactArgs(1),
- RunE: runWhaleIntel,
+ Use: "whale-intel [address]",
+ Aliases: []string{"wi"},
+ Short: "Analyze whale holdings",
+ Long: `Analyzes net worth and positions of top 50 whale holders`,
+ Args: cobra.ExactArgs(1),
+ RunE: runWhaleIntel,
}
func init() {
diff --git a/cmd/dns.go b/cmd/dns.go
index 30757c9..dda2ddd 100644
--- a/cmd/dns.go
+++ b/cmd/dns.go
@@ -16,19 +16,21 @@ var dnsCmd = &cobra.Command{
}
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,
+ Use: "tld [term]",
+ Aliases: []string{"t"},
+ 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,
}
var dnsSiteCmd = &cobra.Command{
- Use: "site [url]",
- Short: "Check if a website URL has been reused",
- Long: "Checks if a website URL has been reused across different domains",
- Args: cobra.ExactArgs(1),
- RunE: runDNSSiteCheck,
+ Use: "site [url]",
+ Aliases: []string{"s"},
+ Short: "Check if a website URL has been reused",
+ Long: "Checks if a website URL has been reused across different domains",
+ Args: cobra.ExactArgs(1),
+ RunE: runDNSSiteCheck,
}
func runDNSTLDCheck(cmd *cobra.Command, args []string) error {
diff --git a/cmd/email.go b/cmd/email.go
index f4306ec..85cc686 100644
--- a/cmd/email.go
+++ b/cmd/email.go
@@ -6,17 +6,19 @@ import (
)
var emailCmd = &cobra.Command{
- Use: "email",
- Short: "Email verification commands",
- Long: `Verify email addresses and check deliverability`,
+ Use: "email",
+ Aliases: []string{"e"},
+ Short: "Email verification commands",
+ Long: `Verify email addresses and check deliverability`,
}
var verifyEmailCmd = &cobra.Command{
- Use: "verify [email]",
- Short: "Verify email address",
- Long: `Performs comprehensive email verification including format validation, MX records check, SMTP verification, and disposable/webmail detection`,
- Args: cobra.ExactArgs(1),
- RunE: runVerifyEmail,
+ Use: "verify [email]",
+ Aliases: []string{"v"},
+ Short: "Verify email address",
+ Long: `Performs comprehensive email verification including format validation, MX records check, SMTP verification, and disposable/webmail detection`,
+ Args: cobra.ExactArgs(1),
+ RunE: runVerifyEmail,
}
func init() {
diff --git a/cmd/files.go b/cmd/files.go
index 6ce818c..aee7d14 100644
--- a/cmd/files.go
+++ b/cmd/files.go
@@ -7,11 +7,12 @@ import (
)
var filesCmd = &cobra.Command{
- Use: "files [url]",
- Short: "Search open directory files",
- Long: `Search for files in open directories using various filters (free OSINT endpoint)`,
- Args: cobra.ExactArgs(1),
- RunE: runFilesSearch,
+ Use: "files [url]",
+ Aliases: []string{"f"},
+ Short: "Search open directory files",
+ Long: `Search for files in open directories using various filters (free OSINT endpoint)`,
+ Args: cobra.ExactArgs(1),
+ RunE: runFilesSearch,
}
func init() {
diff --git a/cmd/geo.go b/cmd/geo.go
index 6c7caf9..cea7a75 100644
--- a/cmd/geo.go
+++ b/cmd/geo.go
@@ -7,10 +7,11 @@ import (
)
var geoCmd = &cobra.Command{
- Use: "geo",
- Short: "Search for address information",
- Long: `Returns address information including residents, property details, and demographics (costs 1 credit)`,
- RunE: runGeoSearch,
+ Use: "geo",
+ Aliases: []string{"g"},
+ Short: "Search for address information",
+ Long: `Returns address information including residents, property details, and demographics (costs 1 credit)`,
+ RunE: runGeoSearch,
}
func init() {
diff --git a/cmd/github.go b/cmd/github.go
index f38e5fe..73fe2a9 100644
--- a/cmd/github.go
+++ b/cmd/github.go
@@ -9,17 +9,19 @@ import (
)
var githubCmd = &cobra.Command{
- Use: "github",
- Short: "GitHub leads scanner",
- Long: `Scans GitHub repositories for commit author information based on search query`,
+ Use: "github",
+ Aliases: []string{"gh"},
+ Short: "GitHub leads scanner",
+ Long: `Scans GitHub repositories for commit author information based on search query`,
}
var githubLeadsCmd = &cobra.Command{
- Use: "leads [query]",
- Short: "Search GitHub repositories for commit authors",
- Long: `Scans GitHub repositories for commit author information based on search query and streams results as NDJSON. If no query is provided, returns random leads.`,
- Args: cobra.MaximumNArgs(1),
- RunE: runGitHubLeads,
+ Use: "leads [query]",
+ Aliases: []string{"l"},
+ Short: "Search GitHub repositories for commit authors",
+ Long: `Scans GitHub repositories for commit author information based on search query and streams results as NDJSON. If no query is provided, returns random leads.`,
+ Args: cobra.MaximumNArgs(1),
+ RunE: runGitHubLeads,
}
func init() {
diff --git a/cmd/moon.go b/cmd/moon.go
index 512fb7e..931f64c 100644
--- a/cmd/moon.go
+++ b/cmd/moon.go
@@ -9,11 +9,12 @@ import (
)
var moonCmd = &cobra.Command{
- Use: "moon [query]",
- Short: "Search moon logs",
- Long: `Search moon logs with various filters. Requires admin API key.`,
- Args: cobra.ExactArgs(1),
- RunE: runMoon,
+ Use: "moon [query]",
+ Aliases: []string{"mn"},
+ Short: "Search moon logs",
+ Long: `Search moon logs with various filters. Requires admin API key.`,
+ Args: cobra.ExactArgs(1),
+ RunE: runMoon,
}
func init() {
diff --git a/cmd/reddit.go b/cmd/reddit.go
index bb31336..7a5da71 100644
--- a/cmd/reddit.go
+++ b/cmd/reddit.go
@@ -7,61 +7,69 @@ import (
)
var redditCmd = &cobra.Command{
- Use: "reddit",
- Short: "Reddit data retrieval tools",
- Long: `Retrieve posts, comments, and user information from Reddit`,
+ Use: "reddit",
+ Aliases: []string{"rd"},
+ Short: "Reddit data retrieval tools",
+ Long: `Retrieve posts, comments, and user information from Reddit`,
}
var redditSubredditCmd = &cobra.Command{
- Use: "subreddit",
- Short: "Get subreddit data",
- Long: `Retrieve posts or comments from a subreddit`,
+ Use: "subreddit",
+ Aliases: []string{"sr"},
+ Short: "Get subreddit data",
+ Long: `Retrieve posts or comments from a subreddit`,
}
var redditUserCmd = &cobra.Command{
- Use: "user",
- Short: "Get Reddit user data",
- Long: `Retrieve posts, comments, or profile information for a Reddit user`,
+ Use: "user",
+ Aliases: []string{"u"},
+ Short: "Get Reddit user data",
+ Long: `Retrieve posts, comments, or profile information for a Reddit user`,
}
var redditSubredditPostsCmd = &cobra.Command{
- Use: "posts [subreddit]",
- Short: "Get subreddit posts",
- Long: `Get up to 1000 recent posts from a subreddit`,
- Args: cobra.ExactArgs(1),
- RunE: runRedditSubredditPosts,
+ Use: "posts [subreddit]",
+ Aliases: []string{"p"},
+ Short: "Get subreddit posts",
+ Long: `Get up to 1000 recent posts from a subreddit`,
+ Args: cobra.ExactArgs(1),
+ RunE: runRedditSubredditPosts,
}
var redditSubredditCommentsCmd = &cobra.Command{
- Use: "comments [subreddit]",
- Short: "Get subreddit comments",
- Long: `Get up to 1000 recent comments from a subreddit`,
- Args: cobra.ExactArgs(1),
- RunE: runRedditSubredditComments,
+ Use: "comments [subreddit]",
+ Aliases: []string{"c"},
+ Short: "Get subreddit comments",
+ Long: `Get up to 1000 recent comments from a subreddit`,
+ Args: cobra.ExactArgs(1),
+ RunE: runRedditSubredditComments,
}
var redditUserPostsCmd = &cobra.Command{
- Use: "posts [username]",
- Short: "Get user posts",
- Long: `Get up to 1000 recent posts from a Reddit user`,
- Args: cobra.ExactArgs(1),
- RunE: runRedditUserPosts,
+ Use: "posts [username]",
+ Aliases: []string{"p"},
+ Short: "Get user posts",
+ Long: `Get up to 1000 recent posts from a Reddit user`,
+ Args: cobra.ExactArgs(1),
+ RunE: runRedditUserPosts,
}
var redditUserCommentsCmd = &cobra.Command{
- Use: "comments [username]",
- Short: "Get user comments",
- Long: `Get up to 1000 recent comments from a Reddit user`,
- Args: cobra.ExactArgs(1),
- RunE: runRedditUserComments,
+ Use: "comments [username]",
+ Aliases: []string{"c"},
+ Short: "Get user comments",
+ Long: `Get up to 1000 recent comments from a Reddit user`,
+ Args: cobra.ExactArgs(1),
+ RunE: runRedditUserComments,
}
var redditUserAboutCmd = &cobra.Command{
- Use: "about [username]",
- Short: "Get user profile",
- Long: `Get profile information for a Reddit user`,
- Args: cobra.ExactArgs(1),
- RunE: runRedditUserAbout,
+ Use: "about [username]",
+ Aliases: []string{"a"},
+ Short: "Get user profile",
+ Long: `Get profile information for a Reddit user`,
+ Args: cobra.ExactArgs(1),
+ RunE: runRedditUserAbout,
}
func init() {
diff --git a/cmd/shortlinks.go b/cmd/shortlinks.go
index 0621da6..4824b81 100644
--- a/cmd/shortlinks.go
+++ b/cmd/shortlinks.go
@@ -7,10 +7,11 @@ import (
)
var shortlinksCmd = &cobra.Command{
- Use: "shortlinks",
- Short: "Search brute forced short links",
- Long: `Search for exposed URLs discovered through brute forcing URL shortener services`,
- RunE: runShortlinksSearch,
+ Use: "shortlinks",
+ Aliases: []string{"shl"},
+ Short: "Search brute forced short links",
+ Long: `Search for exposed URLs discovered through brute forcing URL shortener services`,
+ RunE: runShortlinksSearch,
}
func init() {
diff --git a/cmd/skiptrace.go b/cmd/skiptrace.go
index d8c439a..5b9ed35 100644
--- a/cmd/skiptrace.go
+++ b/cmd/skiptrace.go
@@ -11,8 +11,9 @@ import (
)
var skiptraceCmd = &cobra.Command{
- Use: "skiptrace",
- Short: "Premium skiptrace operations (requires premium API access)",
+ Use: "skiptrace",
+ Aliases: []string{"st"},
+ 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,
@@ -20,42 +21,47 @@ 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",
+ Use: "wizard",
+ Aliases: []string{"w"},
+ 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,
+ Use: "people",
+ Aliases: []string{"ppl"},
+ 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,
+ Use: "phone [phone_number]",
+ Aliases: []string{"ph"},
+ 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,
+ Use: "email [email_address]",
+ Aliases: []string{"em"},
+ 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,
+ Use: "report [sx_key] [selection]",
+ Aliases: []string{"rpt"},
+ 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() {
diff --git a/cmd/telegram.go b/cmd/telegram.go
index 1c650b7..98092a6 100644
--- a/cmd/telegram.go
+++ b/cmd/telegram.go
@@ -6,17 +6,19 @@ import (
)
var telegramCmd = &cobra.Command{
- Use: "telegram",
- Short: "Telegram lookup commands",
- Long: `Lookup phone numbers associated with Telegram accounts`,
+ Use: "telegram",
+ Aliases: []string{"tg"},
+ Short: "Telegram lookup commands",
+ Long: `Lookup phone numbers associated with Telegram accounts`,
}
var phoneCmd = &cobra.Command{
- Use: "phone [identifier]",
- Short: "Get phone number for Telegram user",
- Long: `Retrieves the phone number associated with a Telegram username (with @ prefix) or user ID`,
- Args: cobra.ExactArgs(1),
- RunE: runTelegramPhone,
+ Use: "phone [identifier]",
+ Aliases: []string{"p"},
+ Short: "Get phone number for Telegram user",
+ Long: `Retrieves the phone number associated with a Telegram username (with @ prefix) or user ID`,
+ Args: cobra.ExactArgs(1),
+ RunE: runTelegramPhone,
}
func init() {
diff --git a/cmd/username.go b/cmd/username.go
index f67890b..ed51d2e 100644
--- a/cmd/username.go
+++ b/cmd/username.go
@@ -10,11 +10,12 @@ import (
)
var usernameCmd = &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: runUsernameCheck,
+ Use: "username [username]",
+ Aliases: []string{"un"},
+ Short: "Check username availability across websites",
+ Long: `Check username availability across hundreds of websites using WhatsMyName dataset`,
+ Args: cobra.ExactArgs(1),
+ RunE: runUsernameCheck,
}
func init() {
diff --git a/cmd/x.go b/cmd/x.go
index d8198ac..04ea964 100644
--- a/cmd/x.go
+++ b/cmd/x.go
@@ -15,27 +15,30 @@ var xCmd = &cobra.Command{
}
var xHistoryCmd = &cobra.Command{
- Use: "history [username]",
- Short: "Search Twitter/X username history",
- Long: `Search for Twitter/X username history and previous usernames`,
- Args: cobra.ExactArgs(1),
- RunE: runXHistorySearch,
+ Use: "history [username]",
+ Aliases: []string{"h"},
+ Short: "Search Twitter/X username history",
+ Long: `Search for Twitter/X username history and previous usernames`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXHistorySearch,
}
var xTweetsCmd = &cobra.Command{
- Use: "tweets [username]",
- Short: "Scrape tweets by username (Free OSINT)",
- Long: `Discovers tweet IDs from Internet Archive and fetches tweet content. Free and unauthenticated endpoint.`,
- Args: cobra.ExactArgs(1),
- RunE: runXTweetsSearch,
+ Use: "tweets [username]",
+ Aliases: []string{"tw"},
+ Short: "Scrape tweets by username (Free OSINT)",
+ Long: `Discovers tweet IDs from Internet Archive and fetches tweet content. Free and unauthenticated endpoint.`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXTweetsSearch,
}
var xFirstCmd = &cobra.Command{
- Use: "first [username]",
- Short: "Get first 20 followers of a Twitter/X account",
- Long: `Retrieves the first 20 followers of a Twitter/X account`,
- Args: cobra.ExactArgs(1),
- RunE: runXFirstFollowers,
+ Use: "first [username]",
+ Aliases: []string{"f"},
+ Short: "Get first 20 followers of a Twitter/X account",
+ Long: `Retrieves the first 20 followers of a Twitter/X account`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXFirstFollowers,
}
var xNFLCmd = &cobra.Command{
@@ -47,19 +50,21 @@ var xNFLCmd = &cobra.Command{
}
var xRepliesCmd = &cobra.Command{
- Use: "replies [tweet_id]",
- Short: "Fetch all replies for a tweet",
- Long: `Fetches all replies for a given tweet ID and streams results as NDJSON`,
- Args: cobra.ExactArgs(1),
- RunE: runXReplies,
+ Use: "replies [tweet_id]",
+ Aliases: []string{"r"},
+ Short: "Fetch all replies for a tweet",
+ Long: `Fetches all replies for a given tweet ID and streams results as NDJSON`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXReplies,
}
var xSearchCmd = &cobra.Command{
- Use: "search [query]",
- Short: "Search for tweets matching a term",
- Long: `Searches Twitter/X for tweets matching the given search term and streams results as NDJSON`,
- Args: cobra.ExactArgs(1),
- RunE: runXSearch,
+ Use: "search [query]",
+ Aliases: []string{"s"},
+ Short: "Search for tweets matching a term",
+ Long: `Searches Twitter/X for tweets matching the given search term and streams results as NDJSON`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXSearch,
}
func init() {
@@ -233,27 +238,30 @@ func runXSearch(cmd *cobra.Command, args []string) error {
}
var xDeletedTweetsCmd = &cobra.Command{
- Use: "deleted-tweets [handle]",
- Short: "Check deleted tweets for a Twitter/X account",
- Long: `Checks deleted token-related tweets from a Twitter account`,
- Args: cobra.ExactArgs(1),
- RunE: runXDeletedTweets,
+ Use: "deleted-tweets [handle]",
+ Aliases: []string{"dt"},
+ Short: "Check deleted tweets for a Twitter/X account",
+ Long: `Checks deleted token-related tweets from a Twitter account`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXDeletedTweets,
}
var xDomainCmd = &cobra.Command{
- Use: "domain [domain]",
- Short: "Check domain/website age",
- Long: `Checks the age of a domain/website`,
- Args: cobra.ExactArgs(1),
- RunE: runXDomain,
+ Use: "domain [domain]",
+ Aliases: []string{"dom"},
+ Short: "Check domain/website age",
+ Long: `Checks the age of a domain/website`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXDomain,
}
var xHoldersMapCmd = &cobra.Command{
- Use: "holders-map [address]",
- Short: "Analyze holder trading behavior for a token",
- Long: `Analyzes trading behavior of top 50 holders for a token`,
- Args: cobra.ExactArgs(1),
- RunE: runXHoldersMap,
+ Use: "holders-map [address]",
+ Aliases: []string{"hm"},
+ Short: "Analyze holder trading behavior for a token",
+ Long: `Analyzes trading behavior of top 50 holders for a token`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXHoldersMap,
}
var xIDCmd = &cobra.Command{
@@ -265,19 +273,21 @@ var xIDCmd = &cobra.Command{
}
var xImageCmd = &cobra.Command{
- Use: "image [address]",
- Short: "Reverse image search for a token",
- Long: `Performs reverse image search for a token (SOL/TRON)`,
- Args: cobra.ExactArgs(1),
- RunE: runXImage,
+ Use: "image [address]",
+ Aliases: []string{"img"},
+ Short: "Reverse image search for a token",
+ Long: `Performs reverse image search for a token (SOL/TRON)`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXImage,
}
var xUserIDCmd = &cobra.Command{
- Use: "user-id [handle]",
- Short: "Get Twitter user ID for a handle",
- Long: `Retrieves the Twitter user ID for a given handle`,
- Args: cobra.ExactArgs(1),
- RunE: runXUserID,
+ Use: "user-id [handle]",
+ Aliases: []string{"uid"},
+ Short: "Get Twitter user ID for a handle",
+ Long: `Retrieves the Twitter user ID for a given handle`,
+ Args: cobra.ExactArgs(1),
+ RunE: runXUserID,
}
func runXDeletedTweets(cmd *cobra.Command, args []string) error {
diff --git a/internal/formatter/sl.go b/internal/formatter/sl.go
index d7d293f..33f4ac0 100644
--- a/internal/formatter/sl.go
+++ b/internal/formatter/sl.go
@@ -10,7 +10,7 @@ import (
func FormatSLResults(resp *models.SLResponse, asJSON bool) (string, error) {
if asJSON {
- data, err := json.MarshalIndent(resp.Results, "", " ")
+ data, err := json.MarshalIndent(resp.Hits, "", " ")
if err != nil {
return "", fmt.Errorf("failed to marshal JSON: %w", err)
}
@@ -19,63 +19,35 @@ func FormatSLResults(resp *models.SLResponse, asJSON bool) (string, error) {
var sb strings.Builder
- if resp.Results == nil {
+ if len(resp.Hits) == 0 {
sb.WriteString(fmt.Sprintf("\n%s\n\n", Gray("No results found")))
return sb.String(), nil
}
- resultsMap, ok := resp.Results.(map[string]interface{})
- if !ok {
- resultsJSON, err := json.MarshalIndent(resp.Results, "", " ")
- if err != nil {
- return "", fmt.Errorf("failed to format results: %w", err)
- }
- return string(resultsJSON), nil
- }
-
- hits, ok := resultsMap["hits"].([]interface{})
- if !ok || len(hits) == 0 {
- sb.WriteString(fmt.Sprintf("\n%s\n\n", Gray("No results found")))
- return sb.String(), nil
- }
-
- numHits, _ := resultsMap["num_hits"].(float64)
- elapsed, _ := resultsMap["elapsed_time_micros"].(float64)
-
sb.WriteString(fmt.Sprintf("%s %s %s\n",
Cyan("Found"),
- Bold(Yellow(fmt.Sprintf("%d", int(numHits)))),
- Cyan(fmt.Sprintf("credentials (%.2fms)", elapsed/1000))))
+ Bold(Yellow(fmt.Sprintf("%d", resp.NumHits))),
+ Cyan("credentials")))
sb.WriteString("\n")
- for i, hit := range hits {
- hitMap, ok := hit.(map[string]interface{})
- if !ok {
- continue
- }
-
+ for i, hit := range resp.Hits {
if i > 0 {
sb.WriteString(Dim("───"))
sb.WriteString("\n")
}
- username, _ := hitMap["username"].(string)
- password, _ := hitMap["password"].(string)
- url, _ := hitMap["url"].(string)
- filename, _ := hitMap["filename"].(string)
+ sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Username:"), Bold(hit.Username)))
- sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Username:"), Bold(username)))
-
- if password != "" {
- sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Password:"), Yellow(password)))
+ if hit.Password != "" {
+ sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Password:"), Yellow(hit.Password)))
}
- if url != "" {
- sb.WriteString(fmt.Sprintf("%s %s\n", Dim("URL:"), Blue(url)))
+ if hit.URL != "" {
+ sb.WriteString(fmt.Sprintf("%s %s\n", Dim("URL:"), Blue(hit.URL)))
}
- if filename != "" {
- sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Source:"), Magenta(filename)))
+ if hit.Filename != "" {
+ sb.WriteString(fmt.Sprintf("%s %s\n", Dim("Source:"), Magenta(hit.Filename)))
}
sb.WriteString("\n")
@@ -89,37 +61,3 @@ func FormatSLResults(resp *models.SLResponse, asJSON bool) (string, error) {
return sb.String(), nil
}
-
-func formatSLResultsData(sb *strings.Builder, data map[string]interface{}) {
- sb.WriteString(fmt.Sprintf("%s\n", Bold("Stealer Log Entries:")))
-
- for key, value := range data {
- sb.WriteString(fmt.Sprintf("\n %s:\n", Cyan(key)))
- if valueMap, ok := value.(map[string]interface{}); ok {
- for k, v := range valueMap {
- sb.WriteString(fmt.Sprintf(" %s %v\n", Dim(fmt.Sprintf("%s:", k)), v))
- }
- } else if valueArray, ok := value.([]interface{}); ok {
- for i, item := range valueArray {
- sb.WriteString(fmt.Sprintf(" %s %v\n", Dim(fmt.Sprintf("[%d]:", i)), item))
- }
- } else {
- sb.WriteString(fmt.Sprintf(" %v\n", value))
- }
- }
-}
-
-func formatSLResultsArray(sb *strings.Builder, data []interface{}) {
- sb.WriteString(fmt.Sprintf("%s\n", Bold("Stealer Log Entries:")))
-
- for i, entry := range data {
- sb.WriteString(fmt.Sprintf("\n %s:\n", Blue(fmt.Sprintf("Entry %d", i+1))))
- if entryMap, ok := entry.(map[string]interface{}); ok {
- for key, value := range entryMap {
- sb.WriteString(fmt.Sprintf(" %s %v\n", Dim(fmt.Sprintf("%s:", key)), value))
- }
- } else {
- sb.WriteString(fmt.Sprintf(" %v\n", entry))
- }
- }
-}
diff --git a/internal/models/sl.go b/internal/models/sl.go
index f520450..845c022 100644
--- a/internal/models/sl.go
+++ b/internal/models/sl.go
@@ -13,12 +13,24 @@ type SLParams struct {
}
type SLResponse struct {
- MaxHits int `json:"max_hits"`
- Results interface{} `json:"results"`
- Credits struct {
+ MaxHits int `json:"max_hits"`
+ TotalScanned int `json:"total_scanned"`
+ TotalDedupe int `json:"total_dedupe"`
+ NumHits int `json:"num_hits"`
+ Hits []SLHit `json:"hits"`
+ Credits struct {
Remaining int `json:"remaining"`
Unlimited bool `json:"unlimited"`
} `json:"credits"`
Message string `json:"message,omitempty"`
Error string `json:"error,omitempty"`
}
+
+type SLHit struct {
+ IngestTimestamp string `json:"_ingest_timestamp"`
+ DocID string `json:"doc_id"`
+ Filename string `json:"filename"`
+ Password string `json:"password"`
+ URL string `json:"url"`
+ Username string `json:"username"`
+}
diff --git a/resume.cfg b/resume.cfg
new file mode 100644
index 0000000..e427045
--- /dev/null
+++ b/resume.cfg
@@ -0,0 +1,2 @@
+resume_from=https://wishlist.fullstory-marketing-dev.com/phpmyadmin/
+index=99
diff --git a/sl_bot.py b/sl_bot.py
new file mode 100644
index 0000000..1fe5294
--- /dev/null
+++ b/sl_bot.py
@@ -0,0 +1,281 @@
+#!/usr/bin/env python3
+import os, httpx, json, hashlib, logging
+from datetime import datetime
+from telegram import (
+ Update,
+ InlineQueryResultArticle,
+ InputTextMessageContent,
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ LinkPreviewOptions,
+)
+from telegram.ext import (
+ Application,
+ InlineQueryHandler,
+ ChosenInlineResultHandler,
+ MessageHandler,
+ CallbackQueryHandler,
+ filters,
+)
+import io
+
+logging.basicConfig(
+ format="%(asctime)s | %(message)s",
+ datefmt="%Y-%m-%d %H:%M:%S",
+ level=logging.INFO,
+)
+log = logging.getLogger(__name__)
+
+API_KEY = "dc56cf41ff66114030f7766e547f1d64d99356982093bb4b74506e88281ce198"
+ALLOWED = {8066036773, 8546929916, 8303244085, 7661900680, 7316173289, 7838198850}
+PROXY = "http://MW1BWBJK28_US_5_LOHMZVIP:[email protected]:8080"
+
+
+import re
+
+
+def process_response(text, fmt):
+ if fmt == "json":
+ try:
+ data = json.loads(text)
+ results = data.get("results", [])
+ return json.dumps(results, indent=2)
+ except:
+ return text
+ return text
+
+
+def safe_filename(query):
+ name = re.sub(r'[<>:"/\\|?*]', "_", query)
+ name = re.sub(r"https?://", "", name)
+ name = name.strip("._")[:50]
+ return name or "results"
+
+
+async def inline(update: Update, _):
+ user = update.inline_query.from_user
+ log.info(
+ f"INLINE | user={user.id} ({user.username}) | query='{update.inline_query.query}'"
+ )
+ if user.id not in ALLOWED:
+ return
+ if not (query := update.inline_query.query.strip()):
+ return
+ formats = [
+ ("ulp", "ULP", "URL:Login:Password format"),
+ ("lp", "LP", "Login:Password format"),
+ ("u", "URL", "URL only"),
+ ("l", "Login", "Login only"),
+ ("p", "Password", "Password only"),
+ ("json", "JSON", "Full JSON format"),
+ ]
+ await update.inline_query.answer(
+ [
+ InlineQueryResultArticle(
+ id=fmt_id,
+ title=f"Search: {query} ({fmt_name})",
+ description=fmt_desc,
+ input_message_content=InputTextMessageContent(f"Searching: {query}..."),
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("Loading...", callback_data="noop")]]
+ ),
+ )
+ for fmt_id, fmt_name, fmt_desc in formats
+ ],
+ cache_time=0,
+ )
+
+
+async def chosen(update: Update, context):
+ user = update.chosen_inline_result.from_user
+ result_id = update.chosen_inline_result.result_id
+ log.info(
+ f"CHOSEN | user={user.id} ({user.username}) | query='{update.chosen_inline_result.query}' | format={result_id}"
+ )
+ if user.id not in ALLOWED:
+ return
+ query = update.chosen_inline_result.query.strip()
+ if not query:
+ return
+ try:
+ inline_message_id = update.chosen_inline_result.inline_message_id
+ result_id = update.chosen_inline_result.result_id
+ fmt = result_id if result_id in ("ulp", "lp", "u", "l", "p", "json") else "ulp"
+ loading_markup = InlineKeyboardMarkup(
+ [[InlineKeyboardButton("⏳ Searching...", callback_data="noop")]]
+ )
+ if inline_message_id:
+ await context.bot.edit_message_text(
+ inline_message_id=inline_message_id,
+ text=f"Searching: {query}...",
+ reply_markup=loading_markup,
+ )
+ log.info(f"API | fetching format={fmt}")
+ async with httpx.AsyncClient(proxy=PROXY, timeout=120) as client:
+ resp = await client.get(
+ "https://db.org.ai/sl/search",
+ params={"query": query, "max_hits": 10000, "format": fmt},
+ headers={"X-API-Key": API_KEY},
+ )
+ txt = (
+ process_response(resp.text, fmt)
+ if resp.status_code == 200
+ else "No results"
+ )
+ lines = len(txt.splitlines())
+ log.info(f"API | status={resp.status_code} | lines={lines}")
+
+ if lines == 0:
+ if inline_message_id:
+ await context.bot.edit_message_text(
+ inline_message_id=inline_message_id,
+ text=f"❌ No results found for: {query}",
+ )
+ return
+
+ uploading_markup = InlineKeyboardMarkup(
+ [[InlineKeyboardButton("⏳ Uploading...", callback_data="noop")]]
+ )
+ if inline_message_id:
+ await context.bot.edit_message_text(
+ inline_message_id=inline_message_id,
+ text=f"Uploading {lines} lines...",
+ reply_markup=uploading_markup,
+ )
+ upload_headers = {"User-Agent": "curl/8.0.1"}
+ try:
+ upload = await client.post(
+ "https://0x.at",
+ files={"file": (f"{safe_filename(query)}.txt", txt.encode())},
+ headers=upload_headers,
+ )
+ url = upload.text.strip()
+ except Exception:
+ async with httpx.AsyncClient(timeout=30, verify=False) as upload_client:
+ upload = await upload_client.post(
+ "https://0x.at",
+ files={"file": (f"{safe_filename(query)}.txt", txt.encode())},
+ headers=upload_headers,
+ )
+ url = upload.text.strip()
+ log.info(f"UPLOAD | url={url}")
+
+ if inline_message_id:
+ await context.bot.edit_message_text(
+ inline_message_id=inline_message_id,
+ text=f"🔗 {query} - {lines} lines ({fmt.upper()})",
+ reply_markup=InlineKeyboardMarkup(
+ [[InlineKeyboardButton("📥 Download", url=url)]]
+ ),
+ )
+ log.info(
+ f"DONE | user={user.id} | query='{query}' | lines={lines} | url={url}"
+ )
+ except httpx.TimeoutException:
+ log.error(f"TIMEOUT | user={user.id} | query='{query}'")
+ if inline_message_id:
+ await context.bot.edit_message_text(
+ inline_message_id=inline_message_id,
+ text=f"⏱️ Request timed out for: {query}",
+ )
+ except Exception as e:
+ log.error(f"ERROR | user={user.id} | query='{query}' | error={e}")
+
+
+async def dm(update: Update, context):
+ user = update.message.from_user
+ if user.id not in ALLOWED:
+ return
+ query = update.message.text.strip()
+ if not query:
+ return
+ log.info(f"DM | user={user.id} ({user.username}) | query='{query}'")
+
+ format_buttons = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton("ULP", callback_data=f"dm:ulp:{query}"),
+ InlineKeyboardButton("LP", callback_data=f"dm:lp:{query}"),
+ InlineKeyboardButton("JSON", callback_data=f"dm:json:{query}"),
+ ],
+ [
+ InlineKeyboardButton("URL", callback_data=f"dm:u:{query}"),
+ InlineKeyboardButton("Login", callback_data=f"dm:l:{query}"),
+ InlineKeyboardButton("Password", callback_data=f"dm:p:{query}"),
+ ],
+ ]
+ )
+ await update.message.reply_text(
+ f"Select format for: {query}",
+ reply_markup=format_buttons,
+ )
+
+
+async def dm_callback(update: Update, context):
+ query_obj = update.callback_query
+ await query_obj.answer()
+
+ user = query_obj.from_user
+ if user.id not in ALLOWED:
+ return
+
+ data = query_obj.data
+ if not data.startswith("dm:"):
+ return
+
+ parts = data.split(":", 2)
+ if len(parts) != 3:
+ return
+
+ _, fmt, query = parts
+ log.info(
+ f"DM_CALLBACK | user={user.id} ({user.username}) | query='{query}' | format={fmt}"
+ )
+
+ await query_obj.edit_message_text(f"⏳ Searching: {query}...")
+
+ try:
+ async with httpx.AsyncClient(proxy=PROXY, timeout=120) as client:
+ resp = await client.get(
+ "https://db.org.ai/sl/search",
+ params={"query": query, "max_hits": 10000, "format": fmt},
+ headers={"X-API-Key": API_KEY},
+ )
+ txt = process_response(resp.text, fmt) if resp.status_code == 200 else ""
+ lines = len(txt.splitlines())
+ log.info(f"API | status={resp.status_code} | lines={lines}")
+
+ if lines == 0:
+ await query_obj.edit_message_text(f"❌ No results found for: {query}")
+ log.info(f"DONE | user={user.id} | query='{query}' | no results")
+ return
+
+ await query_obj.edit_message_text(f"⏳ Uploading {lines} lines...")
+
+ await query_obj.message.reply_document(
+ document=io.BytesIO(txt.encode()),
+ filename=f"{safe_filename(query)}.txt",
+ caption=f"🔗 {query} - {lines} lines ({fmt.upper()})",
+ )
+ await query_obj.delete_message()
+ log.info(
+ f"DONE | user={user.id} | query='{query}' | lines={lines} | sent document"
+ )
+ except httpx.TimeoutException:
+ log.error(f"TIMEOUT | user={user.id} | query='{query}'")
+ await query_obj.edit_message_text(f"⏱️ Request timed out for: {query}")
+ except Exception as e:
+ log.error(f"ERROR | user={user.id} | query='{query}' | error={e}")
+ await query_obj.edit_message_text(f"❌ Error: {e}")
+
+
+app = (
+ Application.builder()
+ .token("8511396304:AAHn0da5vx7bLoMED7THD8on0mXNvNjY3Ks")
+ .build()
+)
+app.add_handler(InlineQueryHandler(inline))
+app.add_handler(ChosenInlineResultHandler(chosen))
+app.add_handler(MessageHandler(filters.TEXT & filters.ChatType.PRIVATE, dm))
+app.add_handler(CallbackQueryHandler(dm_callback, pattern="^dm:"))
+app.run_polling()