Files
iknowyou/back/internal/tools/user-scanner/tool.go
2026-04-06 15:12:34 +02:00

96 lines
2.7 KiB
Go

package userscanner
import (
"context"
"os/exec"
"strings"
"github.com/anotherhadi/iknowyou/internal/tools"
)
const (
name = "user-scanner"
description = "🕵️‍♂️ (2-in-1) Email & Username OSINT suite. Analyzes 195+ scan vectors (95+ email / 100+ username) for security research, investigations, and digital footprinting."
link = "https://github.com/kaifcodec/user-scanner"
icon = ""
)
type Config struct {
AllowLoud bool `yaml:"allow_loud" iky:"desc=Enable scanning sites that may send emails/notifications (password resets, etc.);default=false"`
OnlyFound bool `yaml:"only_found" iky:"desc=Only show sites where the username/email was found;default=true"`
}
type Runner struct {
cfg Config
}
func New() tools.ToolRunner {
cfg := Config{}
tools.ApplyDefaults(&cfg)
return &Runner{cfg: cfg}
}
func (r *Runner) Name() string { return name }
func (r *Runner) Description() string { return description }
func (r *Runner) Link() string { return link }
func (r *Runner) Icon() string { return icon }
func (r *Runner) InputTypes() []tools.InputType {
return []tools.InputType{
tools.InputTypeEmail,
tools.InputTypeUsername,
}
}
func (r *Runner) ConfigPtr() interface{} { return &r.cfg }
func (r *Runner) ConfigFields() []tools.ConfigField {
return tools.ReflectConfigFields(r.cfg)
}
func (r *Runner) Available() (bool, string) {
if _, err := exec.LookPath("user-scanner"); err != nil {
return false, "user-scanner binary not found in PATH"
}
return true, ""
}
func (r *Runner) Dependencies() []string { return []string{"user-scanner"} }
func (r *Runner) Run(ctx context.Context, target string, inputType tools.InputType, out chan<- tools.Event) error {
defer close(out)
args := make([]string, 0, 6)
switch inputType {
case tools.InputTypeEmail:
args = append(args, "-e", target)
default:
args = append(args, "-u", target)
}
if r.cfg.AllowLoud {
args = append(args, "--allow-loud")
}
if r.cfg.OnlyFound {
args = append(args, "--only-found")
}
cmd := exec.CommandContext(ctx, "user-scanner", args...)
output, err := tools.RunWithPTY(ctx, cmd)
// Removing banner
output = tools.RemoveFirstLines(output, 8)
// count =
output = tools.CropAfterExclude(output, "[i] Scan complete.")
count := 0
if err != nil && ctx.Err() != nil {
out <- tools.Event{Tool: name, Type: tools.EventTypeError, Payload: "scan cancelled"}
} else if output != "" {
out <- tools.Event{Tool: name, Type: tools.EventTypeOutput, Payload: output}
count = strings.Count(output, "[✔]")
}
out <- tools.Event{Tool: name, Type: tools.EventTypeCount, Payload: count}
out <- tools.Event{Tool: name, Type: tools.EventTypeDone}
return nil
}