Skip to content

Commit 02ea9f8

Browse files
committed
New source: DomainsProject
1 parent 2ba3645 commit 02ea9f8

2 files changed

Lines changed: 133 additions & 0 deletions

File tree

pkg/passive/sources.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/digitorus"
2626
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/dnsdb"
2727
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/dnsdumpster"
28+
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/domainsproject"
2829
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/dnsrepo"
2930
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/driftnet"
3031
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping/sources/facebook"
@@ -71,6 +72,7 @@ var AllSources = [...]subscraping.Source{
7172
&digitorus.Source{},
7273
&dnsdb.Source{},
7374
&dnsdumpster.Source{},
75+
&domainsproject.Source{},
7476
&dnsrepo.Source{},
7577
&driftnet.Source{},
7678
&fofa.Source{},
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Package domainsproject logic
2+
package domainsproject
3+
4+
import (
5+
"context"
6+
"fmt"
7+
"strings"
8+
"time"
9+
10+
jsoniter "github.com/json-iterator/go"
11+
12+
"github.com/projectdiscovery/subfinder/v2/pkg/subscraping"
13+
)
14+
15+
// Source is the passive scraping agent
16+
type Source struct {
17+
apiKeys []apiKey
18+
timeTaken time.Duration
19+
errors int
20+
results int
21+
skipped bool
22+
}
23+
24+
type apiKey struct {
25+
username string
26+
password string
27+
}
28+
29+
type domainsProjectResponse struct {
30+
Domains []string `json:"domains"`
31+
Error string `json:"error"`
32+
}
33+
34+
// Run function returns all subdomains found with the service
35+
func (s *Source) Run(ctx context.Context, domain string, session *subscraping.Session) <-chan subscraping.Result {
36+
results := make(chan subscraping.Result)
37+
s.errors = 0
38+
s.results = 0
39+
40+
go func() {
41+
defer func(startTime time.Time) {
42+
s.timeTaken = time.Since(startTime)
43+
close(results)
44+
}(time.Now())
45+
46+
randomApiKey := subscraping.PickRandom(s.apiKeys, s.Name())
47+
if randomApiKey.username == "" || randomApiKey.password == "" {
48+
s.skipped = true
49+
return
50+
}
51+
52+
searchURL := fmt.Sprintf("https://api.domainsproject.org/api/tld/search?domain=%s", domain)
53+
resp, err := session.HTTPRequest(
54+
ctx,
55+
"GET",
56+
searchURL,
57+
"",
58+
nil,
59+
nil,
60+
subscraping.BasicAuth{Username: randomApiKey.username, Password: randomApiKey.password},
61+
)
62+
if err != nil {
63+
session.DiscardHTTPResponse(resp)
64+
return
65+
}
66+
67+
defer func() {
68+
if err := resp.Body.Close(); err != nil {
69+
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
70+
s.errors++
71+
}
72+
}()
73+
74+
var response domainsProjectResponse
75+
err = jsoniter.NewDecoder(resp.Body).Decode(&response)
76+
if err != nil {
77+
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
78+
s.errors++
79+
return
80+
}
81+
82+
if response.Error != "" {
83+
results <- subscraping.Result{
84+
Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf("%v", response.Error),
85+
}
86+
s.errors++
87+
return
88+
}
89+
90+
for _, subdomain := range response.Domains {
91+
if !strings.HasPrefix(subdomain, ".") {
92+
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Subdomain, Value: subdomain}
93+
s.results++
94+
}
95+
}
96+
}()
97+
98+
return results
99+
}
100+
101+
// Name returns the name of the source
102+
func (s *Source) Name() string {
103+
return "domainsproject"
104+
}
105+
106+
func (s *Source) IsDefault() bool {
107+
return true
108+
}
109+
110+
func (s *Source) HasRecursiveSupport() bool {
111+
return false
112+
}
113+
114+
func (s *Source) NeedsKey() bool {
115+
return true
116+
}
117+
118+
func (s *Source) AddApiKeys(keys []string) {
119+
s.apiKeys = subscraping.CreateApiKeys(keys, func(k, v string) apiKey {
120+
return apiKey{k, v}
121+
})
122+
}
123+
124+
func (s *Source) Statistics() subscraping.Statistics {
125+
return subscraping.Statistics{
126+
Errors: s.errors,
127+
Results: s.results,
128+
TimeTaken: s.timeTaken,
129+
Skipped: s.skipped,
130+
}
131+
}

0 commit comments

Comments
 (0)