Updates to allow for enhanced debugging.
Added structs for whois calls. Added ability to write WhoIs to file. Added structured output for Whois Records. Added String Method for WhoIsRecord and WhoIsHistory Records.
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
package dehashed
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"dehasher/internal/debug"
|
||||
"dehasher/internal/sqlite"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type DehashedParameter string
|
||||
|
||||
const (
|
||||
Username DehashedParameter = "username"
|
||||
Email DehashedParameter = "email"
|
||||
Password DehashedParameter = "password"
|
||||
HashedPassword DehashedParameter = "hashed_password"
|
||||
Name DehashedParameter = "name"
|
||||
IpAddress DehashedParameter = "ip_address"
|
||||
Domain DehashedParameter = "domain"
|
||||
Vin DehashedParameter = "vin"
|
||||
LicensePlate DehashedParameter = "license_plate"
|
||||
Address DehashedParameter = "address"
|
||||
Phone DehashedParameter = "phone"
|
||||
Social DehashedParameter = "social"
|
||||
CryptoAddress DehashedParameter = "cryptocurrency_address"
|
||||
)
|
||||
|
||||
func (dp DehashedParameter) GetArgumentString(arg string) string {
|
||||
return fmt.Sprintf("%s:%s", string(dp), arg)
|
||||
}
|
||||
|
||||
type DehashedSearchRequest struct {
|
||||
ForcePlaintext bool `json:"-"`
|
||||
Debug bool `json:"-"`
|
||||
Page int `json:"page"`
|
||||
Query string `json:"query"`
|
||||
Size int `json:"size"`
|
||||
Wildcard bool `json:"wildcard"`
|
||||
Regex bool `json:"regex"`
|
||||
DeDupe bool `json:"de_dupe"`
|
||||
}
|
||||
|
||||
func NewDehashedSearchRequest(page, size int, wildcard, regex, forcePlaintext, debug bool) *DehashedSearchRequest {
|
||||
return &DehashedSearchRequest{Page: page, Query: "", Size: size, Wildcard: wildcard, Regex: regex, DeDupe: true, ForcePlaintext: forcePlaintext, Debug: debug}
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) buildQuery(query string) {
|
||||
if dsr.Debug {
|
||||
debug.PrintInfo(fmt.Sprintf("building query: %s", query))
|
||||
}
|
||||
// Ensure query is properly formatted
|
||||
query = strings.TrimSpace(query)
|
||||
|
||||
// For regex queries, we need to ensure the regex pattern is properly escaped
|
||||
// and not enquoted, as that would break the regex pattern
|
||||
if dsr.Regex && !strings.HasPrefix(query, "\"") && !strings.HasSuffix(query, "\"") {
|
||||
// Don't add extra quotes for regex patterns
|
||||
} else if strings.Contains(query, " ") && !strings.HasPrefix(query, "\"") {
|
||||
query = fmt.Sprintf("\"%s\"", query)
|
||||
}
|
||||
|
||||
if len(dsr.Query) > 0 {
|
||||
dsr.Query = fmt.Sprintf("%s&%s", strings.TrimSpace(dsr.Query), query)
|
||||
} else {
|
||||
dsr.Query = query
|
||||
}
|
||||
|
||||
if dsr.Debug {
|
||||
debug.PrintInfo(fmt.Sprintf("query built: %s", dsr.Query))
|
||||
}
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddUsernameQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Username.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddEmailQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Email.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddIpAddressQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(IpAddress.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddDomainQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Domain.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddPasswordQuery(query string) {
|
||||
if dsr.ForcePlaintext {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Password.GetArgumentString(query))
|
||||
return
|
||||
}
|
||||
hash := sha256.Sum256([]byte(query))
|
||||
query = hex.EncodeToString(hash[:])
|
||||
dsr.AddHashedPasswordQuery(query)
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddVinQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Vin.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddLicensePlateQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(LicensePlate.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddAddressQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Address.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddPhoneQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Phone.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddSocialQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Social.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddCryptoAddressQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(CryptoAddress.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddHashedPasswordQuery(query string) {
|
||||
query = strings.TrimSpace(query)
|
||||
dsr.buildQuery(HashedPassword.GetArgumentString(query))
|
||||
}
|
||||
|
||||
func (dsr *DehashedSearchRequest) AddNameQuery(query string) {
|
||||
query = enquoteSpaced(query)
|
||||
dsr.buildQuery(Name.GetArgumentString(query))
|
||||
}
|
||||
|
||||
type DehashedClientV2 struct {
|
||||
apiKey string
|
||||
results []sqlite.Result
|
||||
debug bool
|
||||
}
|
||||
|
||||
func NewDehashedClientV2(apiKey string, debug bool) *DehashedClientV2 {
|
||||
return &DehashedClientV2{apiKey: apiKey, debug: debug}
|
||||
}
|
||||
|
||||
func (dcv2 *DehashedClientV2) Search(searchRequest DehashedSearchRequest) (int, int, error) {
|
||||
if dcv2.debug {
|
||||
debug.PrintInfo("preparing search request")
|
||||
zap.L().Info("v2_search_debug",
|
||||
zap.String("message", "preparing search request"),
|
||||
)
|
||||
}
|
||||
reqBody, _ := json.Marshal(searchRequest)
|
||||
|
||||
if dcv2.debug {
|
||||
j := string(reqBody)
|
||||
jReq := fmt.Sprintf("Request Body: %s\n", j)
|
||||
debug.PrintJson(jReq)
|
||||
zap.L().Info("v2_search_debug",
|
||||
zap.String("message", jReq),
|
||||
zap.String("body", j),
|
||||
)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", "https://api.dehashed.com/v2/search", bytes.NewReader(reqBody))
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
|
||||
if dcv2.debug {
|
||||
debug.PrintInfo("setting headers")
|
||||
zap.L().Info("v2_search_debug",
|
||||
zap.String("message", "setting headers"),
|
||||
)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Dehashed-Api-Key", dcv2.apiKey)
|
||||
|
||||
if dcv2.debug {
|
||||
headers := req.Header.Clone()
|
||||
h := fmt.Sprintf("Headers: %v\n", headers)
|
||||
debug.PrintJson(h)
|
||||
zap.L().Info("v2_search_debug",
|
||||
zap.String("message", h),
|
||||
zap.String("headers", fmt.Sprintf("%v", headers)),
|
||||
)
|
||||
|
||||
debug.PrintInfo("performing request")
|
||||
zap.L().Info("v2_search_debug",
|
||||
zap.String("message", "performing request"),
|
||||
)
|
||||
}
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
if dcv2.debug {
|
||||
debug.PrintInfo("failed to perform request")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("v2_search",
|
||||
zap.String("message", "failed to perform request"),
|
||||
zap.Error(err),
|
||||
)
|
||||
return -1, -1, err
|
||||
}
|
||||
if res == nil {
|
||||
if dcv2.debug {
|
||||
debug.PrintInfo("response was nil")
|
||||
}
|
||||
zap.L().Error("v2_search",
|
||||
zap.String("message", "response was nil"),
|
||||
)
|
||||
return -1, -1, errors.New("response was nil")
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
zap.L().Error("v2_search",
|
||||
zap.String("message", "failed to read response body"),
|
||||
zap.Error(err),
|
||||
)
|
||||
return -1, -1, err
|
||||
}
|
||||
|
||||
// Check for HTTP status code errors
|
||||
if res.StatusCode != 200 {
|
||||
if dcv2.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 := GetDehashedError(res.StatusCode)
|
||||
zap.L().Error("v2_search",
|
||||
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 -1, -1, &dhErr
|
||||
}
|
||||
|
||||
var responseResults sqlite.DehashedResponse
|
||||
err = json.Unmarshal(b, &responseResults)
|
||||
if err != nil {
|
||||
if dcv2.debug {
|
||||
debug.PrintInfo("failed to unmarshal response body")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("v2_search",
|
||||
zap.String("message", "failed to unmarshal response body"),
|
||||
zap.Error(err),
|
||||
)
|
||||
return -1, -1, err
|
||||
}
|
||||
|
||||
if dcv2.debug {
|
||||
debug.PrintInfo("appending results")
|
||||
debug.PrintJson(fmt.Sprintf("Total Results: %d\n", responseResults.TotalResults))
|
||||
debug.PrintJson(fmt.Sprintf("Balance: %d\n", responseResults.Balance))
|
||||
debug.PrintJson(fmt.Sprintf("Entries: %d\n", len(responseResults.Entries)))
|
||||
}
|
||||
|
||||
dcv2.results = append(dcv2.results, responseResults.Entries...)
|
||||
return responseResults.TotalResults, responseResults.Balance, nil
|
||||
}
|
||||
|
||||
func (dcv2 *DehashedClientV2) GetResults() sqlite.DehashedResults {
|
||||
return sqlite.DehashedResults{Results: dcv2.results}
|
||||
}
|
||||
|
||||
func (dcv2 *DehashedClientV2) GetTotalResults() int {
|
||||
return len(dcv2.results)
|
||||
}
|
||||
|
||||
func enquoteSpaced(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if strings.Contains(s, " ") {
|
||||
return fmt.Sprintf("\"%s\"", s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
package dehashed
|
||||
|
||||
import (
|
||||
"dehasher/internal/debug"
|
||||
"dehasher/internal/export"
|
||||
"dehasher/internal/sqlite"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Dehasher is a struct for querying the Dehashed API
|
||||
type Dehasher struct {
|
||||
options sqlite.QueryOptions
|
||||
nextPage int
|
||||
debug bool
|
||||
balance int
|
||||
request *DehashedSearchRequest
|
||||
client *DehashedClientV2
|
||||
}
|
||||
|
||||
// NewDehasher creates a new Dehasher
|
||||
func NewDehasher(options *sqlite.QueryOptions) *Dehasher {
|
||||
dh := &Dehasher{
|
||||
options: *options,
|
||||
nextPage: options.StartingPage + 1,
|
||||
debug: options.Debug,
|
||||
balance: 0,
|
||||
}
|
||||
dh.setQueries()
|
||||
dh.request = NewDehashedSearchRequest(dh.options.StartingPage, dh.options.MaxRecords, dh.options.WildcardMatch, dh.options.RegexMatch, false, options.Debug)
|
||||
dh.buildRequest()
|
||||
return dh
|
||||
}
|
||||
|
||||
// SetClientCredentials sets the client credentials for the dehasher
|
||||
func (dh *Dehasher) SetClientCredentials(key string) {
|
||||
dh.client = NewDehashedClientV2(key, dh.debug)
|
||||
}
|
||||
|
||||
func (dh *Dehasher) getNextPage() int {
|
||||
if dh.debug {
|
||||
debug.PrintInfo(fmt.Sprintf("getting next page: %d", dh.nextPage))
|
||||
}
|
||||
nextPage := dh.nextPage
|
||||
dh.nextPage += 1
|
||||
return nextPage
|
||||
}
|
||||
|
||||
// setQueries sets the number of queries to make based on the number of records and requests
|
||||
func (dh *Dehasher) setQueries() {
|
||||
var numQueries int
|
||||
|
||||
if dh.debug {
|
||||
debug.PrintInfo("setting queries")
|
||||
}
|
||||
|
||||
switch {
|
||||
case dh.options.MaxRequests == 0:
|
||||
zap.L().Error("max requests cannot be zero")
|
||||
fmt.Println("[!] Max Requests cannot be zero")
|
||||
os.Exit(1)
|
||||
case dh.options.MaxRecords <= 10000 || dh.options.MaxRequests == 1:
|
||||
numQueries = 1
|
||||
if dh.options.MaxRecords > 10000 {
|
||||
dh.options.MaxRecords = 10000
|
||||
}
|
||||
zap.L().Info("max requests set to 1", zap.Int("max_records", dh.options.MaxRecords))
|
||||
case dh.options.MaxRequests < 0 && dh.options.MaxRecords > 20000:
|
||||
numQueries = 3
|
||||
dh.options.MaxRecords = 10000
|
||||
zap.L().Info("max requests set to 3", zap.Int("max_records", dh.options.MaxRecords))
|
||||
case dh.options.MaxRequests < 0 && dh.options.MaxRecords > 10000:
|
||||
numQueries = 2
|
||||
dh.options.MaxRecords = 10000
|
||||
zap.L().Info("max requests set to 2", zap.Int("max_records", dh.options.MaxRecords))
|
||||
case dh.options.MaxRecords < 0 && dh.options.MaxRecords < 10000:
|
||||
numQueries = 1
|
||||
zap.L().Info("max requests set to 1", zap.Int("max_records", dh.options.MaxRecords))
|
||||
case dh.options.MaxRequests == 2 && dh.options.MaxRecords > 20000:
|
||||
numQueries = 2
|
||||
dh.options.MaxRecords = 10000
|
||||
zap.L().Info("max requests set to 2", zap.Int("max_records", dh.options.MaxRecords))
|
||||
case dh.options.MaxRequests == 2 && dh.options.MaxRecords <= 10000:
|
||||
numQueries = 1
|
||||
zap.L().Info("max requests set to 1", zap.Int("max_records", dh.options.MaxRecords))
|
||||
default:
|
||||
numQueries = 3
|
||||
dh.options.MaxRecords = 10000
|
||||
zap.L().Info("max requests set to 3", zap.Int("max_records", dh.options.MaxRecords))
|
||||
}
|
||||
|
||||
dh.options.MaxRequests = numQueries
|
||||
|
||||
if dh.debug {
|
||||
debug.PrintInfo(fmt.Sprintf("setting max requests: %d", numQueries))
|
||||
debug.PrintInfo(fmt.Sprintf("setting max records: %d", dh.options.MaxRecords))
|
||||
}
|
||||
|
||||
fmt.Printf("Making %d Requests for %d Records (%d Total)\n", dh.options.MaxRequests, dh.options.MaxRecords, dh.options.MaxRequests*dh.options.MaxRecords)
|
||||
}
|
||||
|
||||
// Start starts the querying process
|
||||
func (dh *Dehasher) Start() {
|
||||
fmt.Printf("[*] Querying Dehashed API...\n")
|
||||
for i := 0; i < dh.options.MaxRequests; i++ {
|
||||
fmt.Printf(" [*] Performing Request...\n")
|
||||
count, balance, err := dh.client.Search(*dh.request)
|
||||
if err != nil {
|
||||
if dh.debug {
|
||||
debug.PrintInfo("error performing request")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
|
||||
// Check if it's a DehashError
|
||||
if dhErr, ok := err.(*DehashError); ok {
|
||||
fmt.Printf(" [!] Dehashed API Error: %s (Code: %d)\n", dhErr.Message, dhErr.Code)
|
||||
zap.L().Error("dehashed_api_error",
|
||||
zap.String("message", dhErr.Message),
|
||||
zap.Int("code", dhErr.Code),
|
||||
)
|
||||
} else {
|
||||
fmt.Printf(" [!] Error performing request: %v\n", err)
|
||||
zap.L().Error("request_error",
|
||||
zap.String("message", "failed to perform request"),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
|
||||
if len(dh.client.results) > 0 {
|
||||
fmt.Printf(" [!] Partial results retrieved. Storing Results...\n")
|
||||
err := sqlite.StoreResults(dh.client.GetResults())
|
||||
if err != nil {
|
||||
zap.L().Error("store_results",
|
||||
zap.String("message", "failed to store results"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf(" [!] Error storing results: %v\n", err)
|
||||
}
|
||||
}
|
||||
dh.parseResults()
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
dh.balance = balance
|
||||
|
||||
if count < dh.options.MaxRecords {
|
||||
fmt.Printf(" [+] Retrieved %d records\n", count)
|
||||
fmt.Printf(" [-] Not enough entries, ending queries\n")
|
||||
break
|
||||
} else {
|
||||
fmt.Printf(" [+] Retrieved %d records\n", dh.options.MaxRecords)
|
||||
}
|
||||
|
||||
if dh.options.PrintBalance {
|
||||
fmt.Printf(" [*] Balance: %d\n", balance)
|
||||
}
|
||||
|
||||
dh.request.Page = dh.getNextPage()
|
||||
}
|
||||
|
||||
dh.parseResults()
|
||||
}
|
||||
|
||||
// buildRequest constructs the query map
|
||||
func (dh *Dehasher) buildRequest() {
|
||||
if len(dh.options.UsernameQuery) > 0 {
|
||||
dh.request.AddUsernameQuery(dh.options.UsernameQuery)
|
||||
}
|
||||
if len(dh.options.EmailQuery) > 0 {
|
||||
dh.request.AddEmailQuery(dh.options.EmailQuery)
|
||||
}
|
||||
if len(dh.options.IpQuery) > 0 {
|
||||
dh.request.AddIpAddressQuery(dh.options.IpQuery)
|
||||
}
|
||||
if len(dh.options.HashQuery) > 0 {
|
||||
dh.request.AddHashedPasswordQuery(dh.options.HashQuery)
|
||||
}
|
||||
if len(dh.options.PassQuery) > 0 {
|
||||
dh.request.AddPasswordQuery(dh.options.PassQuery)
|
||||
}
|
||||
if len(dh.options.NameQuery) > 0 {
|
||||
dh.request.AddNameQuery(dh.options.NameQuery)
|
||||
}
|
||||
if len(dh.options.DomainQuery) > 0 {
|
||||
dh.request.AddDomainQuery(dh.options.DomainQuery)
|
||||
}
|
||||
if len(dh.options.VinQuery) > 0 {
|
||||
dh.request.AddVinQuery(dh.options.VinQuery)
|
||||
}
|
||||
if len(dh.options.LicensePlateQuery) > 0 {
|
||||
dh.request.AddLicensePlateQuery(dh.options.LicensePlateQuery)
|
||||
}
|
||||
if len(dh.options.AddressQuery) > 0 {
|
||||
dh.request.AddAddressQuery(dh.options.AddressQuery)
|
||||
}
|
||||
if len(dh.options.PhoneQuery) > 0 {
|
||||
dh.request.AddPhoneQuery(dh.options.PhoneQuery)
|
||||
}
|
||||
if len(dh.options.SocialQuery) > 0 {
|
||||
dh.request.AddSocialQuery(dh.options.SocialQuery)
|
||||
}
|
||||
if len(dh.options.CryptoAddressQuery) > 0 {
|
||||
dh.request.AddCryptoAddressQuery(dh.options.CryptoAddressQuery)
|
||||
}
|
||||
}
|
||||
|
||||
// parseResults parses the results and writes them to a file
|
||||
func (dh *Dehasher) parseResults() {
|
||||
var data []byte
|
||||
|
||||
zap.L().Info("extracting_credentials")
|
||||
results := dh.client.GetResults()
|
||||
creds := results.ExtractCredentials()
|
||||
fmt.Printf("\n\t[+] Discovered %d Credentials", len(creds))
|
||||
err := sqlite.StoreCreds(creds)
|
||||
if err != nil {
|
||||
zap.L().Error("store_creds",
|
||||
zap.String("message", "failed to store creds"),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
zap.L().Info("creds_stored", zap.Int("count", len(creds)))
|
||||
|
||||
zap.L().Info("storing_results")
|
||||
err = sqlite.StoreResults(results)
|
||||
if err != nil {
|
||||
zap.L().Error("store_results",
|
||||
zap.String("message", "failed to store results"),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
zap.L().Info("results_stored", zap.Int("count", len(results.Results)))
|
||||
|
||||
if len(results.Results) > 0 {
|
||||
fmt.Printf("\n\t[*] Writing entries to file: %s.%s", dh.options.OutputFile, dh.options.OutputFormat.String())
|
||||
if !dh.options.CredsOnly {
|
||||
err := export.WriteToFile(results, dh.options.OutputFile, dh.options.OutputFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("\n[!] Error Writing to file: %v\n\tOutputting to terminal.", err)
|
||||
data, err = json.MarshalIndent(results, "", " ")
|
||||
fmt.Println(string(data))
|
||||
os.Exit(0)
|
||||
} else {
|
||||
fmt.Println("\n\t\t[*] Success\n")
|
||||
}
|
||||
} else {
|
||||
creds := results.ExtractCredentials()
|
||||
err := export.WriteCredsToFile(creds, dh.options.OutputFile, dh.options.OutputFormat)
|
||||
if err != nil {
|
||||
fmt.Printf("\n[!] Error Writing to file: %v\n\tOutputting to terminal.", err)
|
||||
data, err = json.MarshalIndent(creds, "", " ")
|
||||
fmt.Println(string(data))
|
||||
os.Exit(0)
|
||||
} else {
|
||||
fmt.Println("\n\t\t[*] Success\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dehashed
|
||||
|
||||
type DehashError struct {
|
||||
Message string
|
||||
Code int
|
||||
}
|
||||
|
||||
type DehashResponseError struct {
|
||||
HttpResponse int `json:"HTTP Response Code"`
|
||||
}
|
||||
|
||||
func (de *DehashError) Error() string {
|
||||
return de.Message
|
||||
}
|
||||
|
||||
func GetDehashedError(c int) DehashError {
|
||||
switch c {
|
||||
case 400:
|
||||
return DehashError{Code: 400, Message: "There is an issue with authentication. Please check your API key and email. If you haven't, refresh your API Key "}
|
||||
case 401:
|
||||
return DehashError{Code: 401, Message: "You need a search subscription and API credits to use the API, please purchase a search subscription and add credits to your account."}
|
||||
case 403:
|
||||
return DehashError{Code: 403, Message: "Insufficient Credits"}
|
||||
case 404:
|
||||
return DehashError{Code: 404, Message: "Method not permitted"}
|
||||
case 429:
|
||||
return DehashError{Code: 420, Message: "Rate Limited"}
|
||||
case 302:
|
||||
return DehashError{Code: 302, Message: "Invalid/Missing Query"}
|
||||
default:
|
||||
return DehashError{Code: -1, Message: "An unknown error has occurred"}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user