Updated README.md
updated typos added 'easy time' upgrade to log filtering
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 211 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
@@ -271,11 +271,29 @@ The logs can be easily queried from the Dehasher CLI.
|
||||
dehasher logs -l 10
|
||||
|
||||
# Show logs from the last 24 hours
|
||||
dehasher logs -s "24 hours ago"
|
||||
dehasher logs -s "last 24 hours"
|
||||
|
||||
# Show logs from the last 24 hours with a severity of error or fatal
|
||||
dehasher logs -s "24 hours ago" -v error,fatal
|
||||
dehasher logs -s "05-01-2025" -v error,fatal
|
||||
```
|
||||
|
||||
### Logs Dates
|
||||
#### Dehasher utilized 'easy time' to determine the appropriate time for a given query.
|
||||

|
||||
#### You may also used dates mixed with easy time to perform queries.
|
||||

|
||||
#### The following formats are supported:
|
||||
- `last 24 hours`
|
||||
- `last 2 days`
|
||||
- `30 minutes ago`
|
||||
- `45 seconds ago`
|
||||
- `1 week ago`
|
||||
- `05-01-2025`
|
||||
- `05/01/2025`
|
||||
- `05/01/25`
|
||||
- `05-01-25`
|
||||
- `May 01, 2025`
|
||||
|
||||
## 🎉 Sample Run
|
||||
```bash
|
||||
ar1ste1a@kali:~$ dehasher api -D <redacted>.com -o <redacted> -f json
|
||||
|
||||
+14
-1
@@ -2,10 +2,12 @@ package cmd
|
||||
|
||||
import (
|
||||
"dehasher/internal/badger"
|
||||
"dehasher/internal/debug"
|
||||
"dehasher/internal/dehashed"
|
||||
"dehasher/internal/sqlite"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -116,7 +118,18 @@ var (
|
||||
dehasher.Start()
|
||||
fmt.Println("\n[*] Completing Process")
|
||||
|
||||
sqlite.StoreQueryOptions(queryOptions)
|
||||
err := sqlite.StoreQueryOptions(queryOptions)
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to store query options")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("store_query_options",
|
||||
zap.String("message", "failed to store query options"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error storing query options: %v\n", err)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
+11
-32
@@ -1,6 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"dehasher/internal/easyTime"
|
||||
"dehasher/internal/pretty"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -73,6 +74,11 @@ var (
|
||||
allLogs = append(allLogs, filepath.Join(logsPath, "info.log"), filepath.Join(logsPath, "error.log"))
|
||||
}
|
||||
|
||||
var timeChunk easyTime.TimeChunk
|
||||
if logStartDate != "" {
|
||||
timeChunk = easyTime.NewTimeChunk(logStartDate, logEndDate, debugGlobal)
|
||||
}
|
||||
|
||||
var parsedLogs []LogEntry
|
||||
for _, logFile := range allLogs {
|
||||
// Read the log file
|
||||
@@ -97,7 +103,7 @@ var (
|
||||
continue
|
||||
}
|
||||
|
||||
// Also unmarshal to get additional fields
|
||||
// Unmarshal to get additional fields
|
||||
if err := json.Unmarshal([]byte(line), &rawEntry); err != nil {
|
||||
fmt.Printf("Error parsing raw log entry: %v\n", err)
|
||||
continue
|
||||
@@ -106,10 +112,10 @@ var (
|
||||
// Parse the timestamp
|
||||
parsedTime, err := time.Parse("2006-01-02T15:04:05.999-0700", entry.Timestamp)
|
||||
if err != nil {
|
||||
// Try alternative formats
|
||||
// Try RFC3339
|
||||
parsedTime, err = time.Parse(time.RFC3339, entry.Timestamp)
|
||||
if err != nil {
|
||||
// Try another format
|
||||
// Try RFC3339Nano
|
||||
parsedTime, err = time.Parse(time.RFC3339Nano, entry.Timestamp)
|
||||
if err != nil {
|
||||
fmt.Printf("Error parsing timestamp '%s': %v\n", entry.Timestamp, err)
|
||||
@@ -133,22 +139,8 @@ var (
|
||||
(logFatal && strings.EqualFold(entry.Level, "FATAL")) {
|
||||
|
||||
// Filter by date range if specified
|
||||
if logStartDate != "" {
|
||||
startDate, err := time.Parse("2006-01-02", logStartDate)
|
||||
if err != nil {
|
||||
fmt.Printf("Error parsing start date: %v\n", err)
|
||||
} else if entry.ParsedTime.Before(startDate) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if logEndDate != "" {
|
||||
endDate, err := time.Parse("2006-01-02", logEndDate)
|
||||
// Add one day to include the end date
|
||||
endDate = endDate.Add(24 * time.Hour)
|
||||
if err != nil {
|
||||
fmt.Printf("Error parsing end date: %v\n", err)
|
||||
} else if entry.ParsedTime.After(endDate) {
|
||||
if timeChunk.IsSet() {
|
||||
if entry.ParsedTime.Before(timeChunk.StartTime) || entry.ParsedTime.After(timeChunk.EndTime) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -211,16 +203,3 @@ const (
|
||||
FATAL
|
||||
UNKNOWN Severity = -1
|
||||
)
|
||||
|
||||
func getSeverity(logLevel string) Severity {
|
||||
switch logLevel {
|
||||
case "INFO":
|
||||
return INFO
|
||||
case "ERROR":
|
||||
return ERROR
|
||||
case "FATAL":
|
||||
return FATAL
|
||||
default:
|
||||
return UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ var (
|
||||
// rootCmd is the base command for the CLI.
|
||||
rootCmd = &cobra.Command{
|
||||
Use: "dehasher",
|
||||
Short: `Dehasher is a cli tool for querying query.`,
|
||||
Short: `Dehasher is a cli tool for querying the dehashed api.`,
|
||||
Long: fmt.Sprintf(
|
||||
"%s\n%s",
|
||||
`
|
||||
@@ -42,7 +42,7 @@ var (
|
||||
––•–√\/––√\/––•––––•–√\/––√\/––•––––•–√\/––√\/––•––√\/––•––––•–√\/––√\/––•––
|
||||
`,
|
||||
),
|
||||
Version: "v1.0",
|
||||
Version: "v1.2.1",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -63,7 +63,7 @@ func init() {
|
||||
rootCmd.CompletionOptions.HiddenDefaultCmd = true
|
||||
|
||||
// Add global flags
|
||||
rootCmd.PersistentFlags().BoolVar(&debugGlobal, "debug", false, "Show debugGlobal information")
|
||||
rootCmd.PersistentFlags().BoolVar(&debugGlobal, "debug", false, "Show debug information")
|
||||
|
||||
// Add subcommands
|
||||
rootCmd.AddCommand(setKeyCmd)
|
||||
|
||||
+25
-102
@@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -97,15 +98,9 @@ var (
|
||||
// Show credits if requested
|
||||
if whoisShowCredits {
|
||||
fmt.Println("[*] Getting WHOIS balance...")
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
if whoisShowCredits {
|
||||
checkBalance(w)
|
||||
}
|
||||
fmt.Printf("WHOIS Credits: %d\n", balance)
|
||||
}
|
||||
|
||||
// Check if domain is provided for history and subdomain scan
|
||||
@@ -115,15 +110,7 @@ var (
|
||||
return
|
||||
}
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,19 +134,7 @@ var (
|
||||
}
|
||||
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to get whois balance")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
|
||||
// Fix the output format to use proper formatting
|
||||
@@ -212,19 +187,7 @@ var (
|
||||
fmt.Printf("[!] Error performing WHOIS history lookup: %v\n", err)
|
||||
} else {
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to get whois balance")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
|
||||
// Write history records to file if any
|
||||
@@ -274,19 +237,7 @@ var (
|
||||
subdomains, err := w.WhoisSubdomainScan(whoisDomain)
|
||||
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to get whois balance")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -371,19 +322,7 @@ var (
|
||||
|
||||
// Get credits
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to get whois balance")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
@@ -445,19 +384,7 @@ var (
|
||||
|
||||
// Get credits
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to get whois balance")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
@@ -519,19 +446,7 @@ var (
|
||||
|
||||
// Get credits
|
||||
if whoisShowCredits {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
debug.PrintInfo("failed to get whois balance")
|
||||
debug.PrintError(err)
|
||||
}
|
||||
zap.L().Error("get_whois_credits",
|
||||
zap.String("message", "failed to get whois balance"),
|
||||
zap.Error(err),
|
||||
)
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
checkBalance(w)
|
||||
}
|
||||
|
||||
if len(result) == 0 {
|
||||
@@ -625,6 +540,18 @@ var (
|
||||
fmt.Println(result)
|
||||
|
||||
if whoisShowCredits {
|
||||
checkBalance(w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If no specific operation was requested
|
||||
cmd.Help()
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func checkBalance(w *whois.DehashedWhoIs) {
|
||||
balance, err := w.Balance()
|
||||
if err != nil {
|
||||
if debugGlobal {
|
||||
@@ -638,12 +565,8 @@ var (
|
||||
fmt.Printf("Error getting WHOIS balance: %v\n", err)
|
||||
}
|
||||
fmt.Println("WHOIS Credits: ", balance)
|
||||
if balance == 0 {
|
||||
fmt.Println("[!] No WHOIS credits remaining.")
|
||||
os.Exit(0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If no specific operation was requested
|
||||
cmd.Help()
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
package easyTime
|
||||
|
||||
import (
|
||||
"dehasher/internal/debug"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TimeChunk struct {
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
set bool
|
||||
}
|
||||
|
||||
func (tc *TimeChunk) isValid() bool {
|
||||
if !tc.StartTime.IsZero() && !tc.EndTime.IsZero() && tc.StartTime.Before(tc.EndTime) {
|
||||
tc.set = true
|
||||
return true
|
||||
}
|
||||
tc.set = false
|
||||
return false
|
||||
}
|
||||
|
||||
func (tc *TimeChunk) IsSet() bool {
|
||||
return tc.set
|
||||
}
|
||||
|
||||
func NewTimeChunk(start, end string, debugOn bool) TimeChunk {
|
||||
if debugOn {
|
||||
debug.PrintInfo("parsing time chunk")
|
||||
debug.PrintInfo(fmt.Sprintf("Start: %s, End: %s", start, end))
|
||||
zap.L().Info("parsing time chunk",
|
||||
zap.String("start", start),
|
||||
zap.String("end", end),
|
||||
)
|
||||
}
|
||||
|
||||
if end == "" {
|
||||
if debugOn {
|
||||
debug.PrintInfo("no end time provided, using now")
|
||||
}
|
||||
end = "now"
|
||||
}
|
||||
|
||||
tc := TimeChunk{
|
||||
StartTime: parseUserTime(start),
|
||||
EndTime: parseUserTime(end),
|
||||
}
|
||||
|
||||
if debugOn {
|
||||
debug.PrintInfo("checking if time chunk is valid")
|
||||
debug.PrintInfo(fmt.Sprintf("Start: %s, End: %s", tc.StartTime, tc.EndTime))
|
||||
}
|
||||
if !tc.isValid() {
|
||||
fmt.Println("[!] Invalid time chunk")
|
||||
zap.L().Fatal("invalid_time_chunk",
|
||||
zap.String("message", "invalid time chunk"),
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return tc
|
||||
}
|
||||
|
||||
func parseUserTime(args string) time.Time {
|
||||
args = strings.TrimSpace(args)
|
||||
|
||||
if strings.EqualFold(args, "now") {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// Check if time contains a space, if so, it's in 'last 24 hours' format
|
||||
if strings.Contains(args, " ") && !containsMonth(strings.Split(args, " ")) {
|
||||
splitArgs := strings.Split(args, " ")
|
||||
if len(splitArgs) == 0 {
|
||||
fmt.Println("[!] No time provided")
|
||||
zap.L().Fatal("no_time_provided",
|
||||
zap.String("message", "no time provided"),
|
||||
)
|
||||
os.Exit(1)
|
||||
} else if len(splitArgs) < 3 {
|
||||
fmt.Println("[!] Invalid time format")
|
||||
zap.L().Fatal("invalid_time_format",
|
||||
zap.String("message", "invalid time format"),
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Handle 'last 24 hours' format
|
||||
var (
|
||||
tense string
|
||||
amount int
|
||||
duration time.Duration
|
||||
)
|
||||
for _, arg := range splitArgs {
|
||||
if isPasteTense(arg) {
|
||||
tense = arg
|
||||
} else if isNumber(arg) {
|
||||
amount, _ = strconv.Atoi(arg)
|
||||
} else if isDuration(arg) {
|
||||
duration = getDuration(arg)
|
||||
}
|
||||
}
|
||||
|
||||
if tense == "" {
|
||||
fmt.Println("[!] Invalid time format: tense not found")
|
||||
zap.L().Fatal("invalid_time_format",
|
||||
zap.String("message", "invalid time format"),
|
||||
)
|
||||
os.Exit(1)
|
||||
} else if amount == 0 {
|
||||
fmt.Println("[!] Invalid time format: amount not found")
|
||||
zap.L().Fatal("invalid_time_format",
|
||||
zap.String("message", "invalid time format"),
|
||||
)
|
||||
os.Exit(1)
|
||||
} else if duration == 0 {
|
||||
fmt.Println("[!] Invalid time format: duration not found")
|
||||
zap.L().Fatal("invalid_time_format",
|
||||
zap.String("message", "invalid time format"),
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Return the appropriate time
|
||||
if tense == "last" {
|
||||
return time.Now().Add(-time.Duration(amount) * duration)
|
||||
} else if tense == "ago" {
|
||||
return time.Now().Add(-time.Duration(amount) * duration)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle possible formats 'May 01, 2025', '05-01-2025', '05/01/2025', '05/01/25', '05-01-25'
|
||||
var (
|
||||
t time.Time
|
||||
err error
|
||||
found bool
|
||||
)
|
||||
possible := []string{"01-02-2006", "01/02/2006", "01/02/06", "01-02-06", "Jan 02, 2006", "Jan 2, 2006"}
|
||||
for _, format := range possible {
|
||||
t, err = time.Parse(format, args)
|
||||
if err == nil {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
fmt.Println("[!] Invalid time format")
|
||||
zap.L().Fatal("invalid_time_format",
|
||||
zap.String("message", "invalid time format"),
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Convert UTC time to local time
|
||||
local, err := time.LoadLocation("Local")
|
||||
if err != nil {
|
||||
fmt.Println("[!] Error loading local timezone")
|
||||
zap.L().Error("load_timezone",
|
||||
zap.String("message", "failed to load local timezone"),
|
||||
zap.Error(err),
|
||||
)
|
||||
return t
|
||||
}
|
||||
|
||||
// Convert the parsed time to local time
|
||||
return time.Date(
|
||||
t.Year(),
|
||||
t.Month(),
|
||||
t.Day(),
|
||||
t.Hour(),
|
||||
t.Minute(),
|
||||
t.Second(),
|
||||
t.Nanosecond(),
|
||||
local,
|
||||
)
|
||||
}
|
||||
|
||||
func isPasteTense(value string) bool {
|
||||
for _, v := range []string{"last", "ago"} {
|
||||
if strings.EqualFold(value, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isDuration(value string) bool {
|
||||
for _, v := range []string{"hour", "hours", "minute", "minutes", "second", "seconds", "day", "days", "week", "weeks", "month", "months", "year", "years"} {
|
||||
if strings.EqualFold(value, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isNumber(value string) bool {
|
||||
_, err := strconv.Atoi(value)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func getDuration(timeBlock string) time.Duration {
|
||||
timeBlock = strings.TrimSpace(strings.ToLower(timeBlock))
|
||||
|
||||
switch timeBlock {
|
||||
case "hour":
|
||||
return time.Hour
|
||||
case "hours":
|
||||
return time.Hour
|
||||
case "minute":
|
||||
return time.Minute
|
||||
case "minutes":
|
||||
return time.Minute
|
||||
case "second":
|
||||
return time.Second
|
||||
case "seconds":
|
||||
return time.Second
|
||||
case "day":
|
||||
return 24 * time.Hour
|
||||
case "days":
|
||||
return 24 * time.Hour
|
||||
case "week":
|
||||
return 7 * 24 * time.Hour
|
||||
case "weeks":
|
||||
return 7 * 24 * time.Hour
|
||||
case "month":
|
||||
return 30 * 24 * time.Hour
|
||||
case "months":
|
||||
return 30 * 24 * time.Hour
|
||||
case "year":
|
||||
return 365 * 24 * time.Hour
|
||||
case "years":
|
||||
return 365 * 24 * time.Hour
|
||||
default:
|
||||
fmt.Printf("[!] Unknown duration: %s", timeBlock)
|
||||
zap.L().Fatal("unknown_duration",
|
||||
zap.String("message", "unknown duration"),
|
||||
zap.String("duration", timeBlock),
|
||||
)
|
||||
os.Exit(1)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func containsMonth(arr []string) bool {
|
||||
for _, v := range arr {
|
||||
if isMonth(v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isMonth(value string) bool {
|
||||
for _, v := range []string{"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"} {
|
||||
if strings.EqualFold(value, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user