package whois import ( "bytes" "encoding/json" "errors" "fmt" "io" "net/http" "go.uber.org/zap" "hub.krkn.tech/KrakenTech/crowsnest/internal/debug" "hub.krkn.tech/KrakenTech/crowsnest/internal/dehashed" "hub.krkn.tech/KrakenTech/crowsnest/internal/sqlite" ) type DehashedWHOISSearchRequest struct { Include []string `json:"include,omitempty"` Exclude []string `json:"exclude,omitempty"` IPAddress string `json:"ip_address,omitempty"` ReverseType string `json:"reverse_type,omitempty"` Domain string `json:"domain,omitempty"` MXAddress string `json:"mx_address,omitempty"` NSAddress string `json:"ns_address,omitempty"` SearchType string `json:"search_type,omitempty"` } type DehashedWhoIs struct { balance int debug bool apiKey string } func NewWhoIs(apiKey string, debug bool) *DehashedWhoIs { return &DehashedWhoIs{apiKey: apiKey, debug: debug, balance: -1} } func (w *DehashedWhoIs) WhoisSearch(domain string) (sqlite.WhoisRecord, error) { var whois sqlite.WhoIsLookupResult var whoisRecord sqlite.WhoisRecord if w.debug { debug.PrintInfo("performing whois search") zap.L().Info("whois_search_debug", zap.String("message", "performing whois search"), ) } whoisSearchRequest := DehashedWHOISSearchRequest{ Domain: domain, SearchType: "whois", } if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("whois_search_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } reqBody, _ := json.Marshal(whoisSearchRequest) req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { return whoisRecord, err } if w.debug { debug.PrintInfo("setting headers") zap.L().Info("whois_search_debug", zap.String("message", "setting headers"), ) } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("headers set") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) debug.PrintInfo("performing request") zap.L().Info("whois_search_debug", zap.String("message", "performing request"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("whois_search", zap.String("message", "failed to perform request"), zap.Error(err), ) return whoisRecord, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("whois_search", zap.String("message", "response was nil"), ) return whoisRecord, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { zap.L().Error("whois_search", zap.String("message", "failed to read response body"), zap.Error(err), ) return whoisRecord, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("whois_search", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), ) return whoisRecord, &dhErr } err = json.Unmarshal(b, &whois) if err != nil { if w.debug { debug.PrintInfo("failed to unmarshal response body") debug.PrintError(err) } zap.L().Error("whois_search", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) fmt.Println("Error unmarshalling response body:", err) fmt.Println("Response body:", string(b)) return whoisRecord, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whois.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whois.Data)) } w.balance = whois.RemainingCredits return whois.Data.WhoisRecord, nil } func (w *DehashedWhoIs) WhoisHistory(domain string) ([]sqlite.HistoryRecord, error) { var whois sqlite.WhoIsHistory var historyRecords []sqlite.HistoryRecord if w.debug { debug.PrintInfo("performing whois history search") zap.L().Info("whois_history_debug", zap.String("message", "performing whois history search"), ) } whoisSearchRequest := DehashedWHOISSearchRequest{ Domain: domain, SearchType: "whois-history", } reqBody, _ := json.Marshal(whoisSearchRequest) if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("whois_history_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { if w.debug { debug.PrintInfo("failed to create request") debug.PrintError(err) } zap.L().Error("whois_history", zap.String("message", "failed to create request"), zap.Error(err), ) return historyRecords, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing request") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) zap.L().Info("whois_history_debug", zap.String("message", "performing request"), ) } res, err := http.DefaultClient.Do(req) if res != nil { if w.debug { debug.PrintInfo("response was not nil") } zap.L().Info("whois_history", zap.String("message", "response was not nil"), ) defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("whois_history", zap.String("message", "failed to perform request"), zap.Error(err), ) return historyRecords, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("whois_history", zap.String("message", "response was nil"), ) return historyRecords, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { if w.debug { debug.PrintInfo("failed to read response body") debug.PrintError(err) } zap.L().Error("whois_history", zap.String("message", "failed to read response body"), zap.Error(err), ) return historyRecords, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("whois_history", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return historyRecords, &dhErr } err = json.Unmarshal(b, &whois) if err != nil { if w.debug { debug.PrintInfo("failed to unmarshal response body") debug.PrintError(err) } zap.L().Error("whois_history", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) fmt.Println("Error unmarshalling response body:", err) fmt.Println("Response body:", string(b)) return historyRecords, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whois.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whois.Data)) } w.balance = whois.RemainingCredits return whois.Data.Records, nil } func (w *DehashedWhoIs) ReverseWHOIS(include []string, exclude []string, reverseType string) (sqlite.ReverseWhoisData, error) { var whois sqlite.ReverseWhoisData if w.debug { debug.PrintInfo("performing reverse whois search") zap.L().Info("reverse_whois_debug", zap.String("message", "performing reverse whois search"), ) } whoisSearchRequest := DehashedWHOISSearchRequest{ Include: include, Exclude: exclude, ReverseType: reverseType, SearchType: "reverse-whois", } reqBody, _ := json.Marshal(whoisSearchRequest) if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("reverse_whois_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { zap.L().Error("reverse_whois", zap.String("message", "failed to create request"), zap.Error(err), ) return whois, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing reverse whois search") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) zap.L().Info("reverse_whois_debug", zap.String("message", "performing reverse whois search"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("reverse_whois", zap.String("message", "failed to perform request"), zap.Error(err), ) return whois, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("reverse_whois", zap.String("message", "response was nil"), ) return whois, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { if w.debug { debug.PrintInfo("failed to read response body") debug.PrintError(err) } zap.L().Error("reverse_whois", zap.String("message", "failed to read response body"), zap.Error(err), ) return whois, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("reverse_whois", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return whois, &dhErr } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } var whoisResponse sqlite.ReverseWhoisResponse err = json.Unmarshal(b, &whoisResponse) if err != nil { if w.debug { debug.PrintInfo("failed to unmarshal response body") debug.PrintError(err) } zap.L().Error("reverse_whois", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) return whois, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whoisResponse.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whoisResponse.Data)) } w.balance = whoisResponse.RemainingCredits whois = whoisResponse.Data return whois, nil } func (w *DehashedWhoIs) WhoisIP(ipAddress string) ([]sqlite.LookupResult, error) { if w.debug { debug.PrintInfo("performing whois ip search") zap.L().Info("whois_ip_debug", zap.String("message", "performing whois ip search"), ) } type IPSearchRequest struct { IPAddress string `json:"domain"` SearchType string `json:"search_type"` } whoisSearchRequest := IPSearchRequest{ IPAddress: ipAddress, SearchType: "reverse-ip", } reqBody, _ := json.Marshal(whoisSearchRequest) if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("whois_ip_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { zap.L().Error("whois_ip", zap.String("message", "failed to create request"), zap.Error(err), ) return nil, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing whois ip search") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) zap.L().Info("whois_ip_debug", zap.String("message", "performing whois ip search"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("whois_ip", zap.String("message", "failed to perform request"), zap.Error(err), ) return nil, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("whois_ip", zap.String("message", "response was nil"), ) return nil, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { if w.debug { debug.PrintInfo("failed to read response body") debug.PrintError(err) } zap.L().Error("whois_ip", zap.String("message", "failed to read response body"), zap.Error(err), ) return nil, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("whois_ip", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return nil, &dhErr } if w.debug { debug.PrintInfo("read response body") debug.PrintJson(fmt.Sprintf("Response Body: %s\n", string(b))) zap.L().Info("whois_ip_debug", zap.String("message", "read response body"), zap.String("body", string(b)), ) } var whois sqlite.WhoIsIPLookup err = json.Unmarshal(b, &whois) if err != nil { if w.debug { debug.PrintInfo("failed to unmarshal response body") debug.PrintError(err) } zap.L().Error("whois_ip", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) return nil, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whois.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whois.Data)) } w.balance = whois.RemainingCredits var lookups []sqlite.LookupResult for _, v := range whois.Data.Result { lookups = append(lookups, sqlite.LookupResult{ FirstSeen: v.FirstSeen, LastVisit: v.LastVisit, Name: v.Name, SearchTerm: ipAddress, Type: "Reverse IP", }) } sqlite.StoreWhoisLookup(lookups) return lookups, nil } func (w *DehashedWhoIs) WhoisMX(mxHostname string) ([]sqlite.LookupResult, error) { if w.debug { debug.PrintInfo("performing whois mx search") zap.L().Info("whois_mx_debug", zap.String("message", "performing whois mx search"), ) } type ReverseMX struct { Domain string `json:"domain"` SearchType string `json:"search_type"` } whoisSearchRequest := ReverseMX{ Domain: mxHostname, SearchType: "reverse-mx", } reqBody, _ := json.Marshal(whoisSearchRequest) if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("whois_mx_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { if w.debug { debug.PrintInfo("failed to create request") debug.PrintError(err) } zap.L().Error("whois_mx", zap.String("message", "failed to create request"), zap.Error(err), ) return nil, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing whois mx search") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) zap.L().Info("whois_mx_debug", zap.String("message", "performing whois mx search"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("whois_mx", zap.String("message", "failed to perform request"), zap.Error(err), ) return nil, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("whois_mx", zap.String("message", "response was nil"), ) return nil, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { if w.debug { debug.PrintInfo("failed to read response body") debug.PrintError(err) } zap.L().Error("whois_mx", zap.String("message", "failed to read response body"), zap.Error(err), ) return nil, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("whois_mx", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return nil, &dhErr } if w.debug { debug.PrintInfo("read response body") debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } var whois sqlite.WhoIsMXLookup err = json.Unmarshal(b, &whois) if err != nil { if w.debug { debug.PrintInfo("failed to unmarshal response body") debug.PrintError(err) } zap.L().Error("whois_mx", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) return nil, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whois.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whois.Data)) } var mxLookups []sqlite.LookupResult for _, v := range whois.Data.Result { mxLookups = append(mxLookups, sqlite.LookupResult{ FirstSeen: v.FirstSeen, LastVisit: v.LastVisit, Name: v.Name, SearchTerm: mxHostname, Type: "MX", }) } sqlite.StoreWhoisLookup(mxLookups) return mxLookups, nil } func (w *DehashedWhoIs) WhoisNS(nsHostname string) ([]sqlite.LookupResult, error) { if w.debug { debug.PrintInfo("performing whois ns search") zap.L().Info("whois_ns_debug", zap.String("message", "performing whois ns search"), ) } type NSLookup struct { Domain string `json:"domain"` SearchType string `json:"search_type"` } whoisSearchRequest := NSLookup{ Domain: nsHostname, SearchType: "reverse-ns", } reqBody, _ := json.Marshal(whoisSearchRequest) if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("whois_ns_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { zap.L().Error("whois_ns", zap.String("message", "failed to create request"), zap.Error(err), ) return nil, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing request") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) zap.L().Info("whois_ns_debug", zap.String("message", "performing request"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("whois_ns", zap.String("message", "failed to perform request"), zap.Error(err), ) return nil, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("whois_ns", zap.String("message", "response was nil"), ) return nil, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { zap.L().Error("whois_ns", zap.String("message", "failed to read response body"), zap.Error(err), ) return nil, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("whois_ns", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return nil, &dhErr } if w.debug { debug.PrintInfo("read response body") debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) zap.L().Info("whois_ns_debug", zap.String("message", "read response body"), zap.String("body", string(b)), ) } var whois sqlite.WhoIsNSLookup err = json.Unmarshal(b, &whois) if err != nil { if w.debug { debug.PrintInfo("failed to unmarshal response body") debug.PrintError(err) } zap.L().Error("whois_ns", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) return nil, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whois.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whois.Data)) } w.balance = whois.RemainingCredits var nsLookups []sqlite.LookupResult for _, v := range whois.Data.Result { nsLookups = append(nsLookups, sqlite.LookupResult{ FirstSeen: v.FirstSeen, LastVisit: v.LastVisit, Name: v.Name, SearchTerm: nsHostname, Type: "NS", }) } sqlite.StoreWhoisLookup(nsLookups) return nsLookups, nil } func (w *DehashedWhoIs) WhoisSubdomainScan(domain string) ([]sqlite.SubdomainRecord, error) { var whois sqlite.WhoIsSubdomainScan var subdomains []sqlite.SubdomainRecord if w.debug { debug.PrintInfo("performing whois subdomain scan") zap.L().Info("whois_subdomain_scan_debug", zap.String("message", "performing whois subdomain scan"), ) } whoisSearchRequest := DehashedWHOISSearchRequest{ Domain: domain, SearchType: "subdomain-scan", } reqBody, _ := json.Marshal(whoisSearchRequest) if w.debug { debug.PrintInfo("building request body") debug.PrintJson(fmt.Sprintf("Request Body: %v\n", whoisSearchRequest)) zap.L().Info("whois_subdomain_scan_debug", zap.String("message", "building request body"), zap.String("body", fmt.Sprintf("%v", whoisSearchRequest)), ) } req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/whois/search", bytes.NewReader(reqBody)) if err != nil { if w.debug { debug.PrintInfo("failed to create request") debug.PrintError(err) } zap.L().Error("whois_subdomain_scan", zap.String("message", "failed to create request"), zap.Error(err), ) return subdomains, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing request") debug.PrintJson(fmt.Sprintf("Headers: %v\n", req.Header.Clone())) zap.L().Info("whois_subdomain_scan_debug", zap.String("message", "performing request"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("whois_subdomain_scan", zap.String("message", "failed to perform request"), zap.Error(err), ) return subdomains, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("whois_subdomain_scan", zap.String("message", "response was nil"), ) return subdomains, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { if w.debug { debug.PrintInfo("failed to read response body") debug.PrintError(err) } zap.L().Error("whois_subdomain_scan", zap.String("message", "failed to read response body"), zap.Error(err), ) return subdomains, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("whois_subdomain_scan", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return subdomains, &dhErr } err = json.Unmarshal(b, &whois) if err != nil { zap.L().Error("whois_subdomain_scan", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) fmt.Println("Error unmarshalling response body:", err) fmt.Println("Response body:", string(b)) return subdomains, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whois.RemainingCredits)) debug.PrintJson(fmt.Sprintf("Data: %v\n", whois.Data)) } w.balance = whois.RemainingCredits return whois.Data.Result.Records, nil } func (w *DehashedWhoIs) Balance() (int, error) { if w.debug { debug.PrintInfo("getting whois credits") zap.L().Info("whois_debug", zap.String("message", "getting whois credits"), ) } return w.getBalance() } func (w *DehashedWhoIs) getBalance() (int, error) { var whoisCredits sqlite.WhoIsCredits req, err := http.NewRequest("GET", "https://api.dehashed.com/v2/whois/credits", nil) if err != nil { if w.debug { debug.PrintInfo("failed to create request") debug.PrintError(err) } return whoisCredits.WhoisCredits, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Dehashed-Api-Key", w.apiKey) if w.debug { debug.PrintInfo("performing request") h := req.Header.Clone() debug.PrintJson(fmt.Sprintf("Headers: %v\n", h)) zap.L().Info("whois_debug", zap.String("message", "performing request"), ) } res, err := http.DefaultClient.Do(req) if res != nil { defer res.Body.Close() } if err != nil { if w.debug { debug.PrintInfo("failed to perform request") debug.PrintError(err) } zap.L().Error("get_whois_credits", zap.String("message", "failed to perform request"), zap.Error(err), ) return whoisCredits.WhoisCredits, err } if res == nil { if w.debug { debug.PrintInfo("response was nil") } zap.L().Error("get_whois_credits", zap.String("message", "response was nil"), ) return whoisCredits.WhoisCredits, errors.New("response was nil") } b, err := io.ReadAll(res.Body) if err != nil { if w.debug { debug.PrintInfo("failed to read response body") debug.PrintError(err) } zap.L().Error("get_whois_credits", zap.String("message", "failed to read response body"), zap.Error(err), ) return whoisCredits.WhoisCredits, err } // Check for HTTP status code errors if res.StatusCode != 200 { if w.debug { debug.PrintInfo("received error status code") debug.PrintJson(fmt.Sprintf("Status Code: %d\n", res.StatusCode)) debug.PrintJson(fmt.Sprintf("Body: %s\n", string(b[:]))) } dhErr := dehashed.GetDehashedError(res.StatusCode) fmt.Printf("[%d] API Error message: %s\n", res.StatusCode, dhErr.Error()) zap.L().Error("get_whois_credits", zap.String("message", "received error status code"), zap.Int("status_code", res.StatusCode), zap.String("error", dhErr.Error()), zap.String("body_error", string(b)), ) return whoisCredits.WhoisCredits, &dhErr } err = json.Unmarshal(b, &whoisCredits) if err != nil { zap.L().Error("get_whois_credits", zap.String("message", "failed to unmarshal response body"), zap.Error(err), ) fmt.Println("Error unmarshalling response body:", err) fmt.Println("Response body:", string(b)) return whoisCredits.WhoisCredits, err } if w.debug { debug.PrintInfo("unmarshalled response body") debug.PrintJson(fmt.Sprintf("Remaining Credits: %d\n", whoisCredits.WhoisCredits)) } return whoisCredits.WhoisCredits, nil }