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

90 lines
2.5 KiB
Go

package maigret
import (
"context"
"os/exec"
"regexp"
"strconv"
"strings"
"github.com/anotherhadi/iknowyou/internal/tools"
)
const (
name = "maigret"
description = "Username OSINT across 3000+ sites. Searches social networks, forums, and online platforms for an account matching the target username."
link = "https://github.com/soxoj/maigret"
icon = ""
)
var accountsRe = regexp.MustCompile(`returned (\d+) accounts`)
type Config struct {
AllSites bool `yaml:"all_sites" iky:"desc=Scan all sites in the database instead of just the top 500 (slower);default=false"`
}
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.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("maigret"); err != nil {
return false, "maigret binary not found in PATH"
}
return true, ""
}
func (r *Runner) Dependencies() []string { return []string{"maigret"} }
func (r *Runner) Run(ctx context.Context, target string, _ tools.InputType, out chan<- tools.Event) error {
defer close(out)
args := []string{"--no-progressbar", target}
if r.cfg.AllSites {
args = append(args, "-a")
}
cmd := exec.CommandContext(ctx, "maigret", args...)
output, err := tools.RunWithPTY(ctx, cmd)
// Crop at Python traceback (NixOS read-only store error — results are unaffected)
if idx := strings.Index(output, "Traceback (most recent call last)"); idx != -1 {
output = strings.TrimSpace(output[:idx])
}
count := 0
if err != nil && ctx.Err() != nil {
out <- tools.Event{Tool: name, Type: tools.EventTypeError, Payload: "scan cancelled"}
} else if output != "" {
// Parse count from summary line: "returned N accounts"
if m := accountsRe.FindStringSubmatch(output); len(m) == 2 {
count, _ = strconv.Atoi(m[1])
}
out <- tools.Event{Tool: name, Type: tools.EventTypeOutput, Payload: output}
}
out <- tools.Event{Tool: name, Type: tools.EventTypeCount, Payload: count}
out <- tools.Event{Tool: name, Type: tools.EventTypeDone}
return nil
}