# Cheatsheet ## Dev Commands ```bash make install # Setup venv + install make test # Run tests make lint # Lint with ruff make run # Start bot (bare metal) make link # Symlink to ~/.local/bin derp -c config.toml # Run with custom config derp -v # Verbose/debug mode derp --cprofile # Profile to derp.prof ``` ## SASL Authentication ```toml # In config/derp.toml [server] sasl_user = "account" sasl_pass = "password" ``` ## Rate Limiting ```toml # In config/derp.toml (defaults shown) [bot] rate_limit = 2.0 # Messages per second rate_burst = 5 # Burst capacity ``` ## Per-Channel Plugin Control ```toml # Only allow specific plugins in a channel [channels."#public"] plugins = ["core", "dns", "cidr", "encode"] # Omit section entirely to allow all plugins ``` `core` always active. PMs unrestricted. Denied commands silently ignored. ## Structured Logging ```toml [logging] format = "json" # JSONL output (default: "text") ``` ## Container ```bash make build # Build image (only for dep changes) make up # Start (podman-compose) make down # Stop make logs # Follow logs ``` Code, plugins, config, and data are bind-mounted. No rebuild needed for code changes -- restart the container or use `!reload` for plugins. ## Bot Commands ``` !ping # Pong !help # List commands !help # Command help !help # Plugin description + commands !version # Bot version !uptime # Bot uptime !echo # Echo text back !h # Shorthand (any unambiguous prefix works) ``` ## Permission Tiers ``` user < trusted < oper < admin ``` ```toml # config/derp.toml [bot] admins = ["*!~root@*.ops.net"] # admin tier operators = ["*!~staff@trusted.host"] # oper tier trusted = ["*!~user@known.host"] # trusted tier ``` ``` !whoami # Show your hostmask + permission tier !admins # Show configured tiers + detected opers (admin) ``` IRC operators are auto-detected via WHO (admin tier). Hostmask patterns use fnmatch. `admin=True` on commands still works (maps to tier="admin"). ## Channel Management (admin) ``` !kick nick reason # Kick user from channel !ban *!*@bad.host # Ban hostmask !unban *!*@bad.host # Remove ban !topic New topic text # Set channel topic !topic # Query current topic !mode +m # Set channel mode !mode +o nick # Give ops ``` Auto-joins channels when invited by an admin/ircop. Persists across restarts. Removed from auto-rejoin list if bot is kicked. ## State Store (admin) ``` !state list myplugin # List keys !state get myplugin key # Get value !state del myplugin key # Delete key !state clear myplugin # Clear all keys ``` ## IRCv3 Capabilities ```toml # config/derp.toml [server] ircv3_caps = ["multi-prefix", "away-notify", "server-time"] ``` SASL auto-added when sasl_user/sasl_pass configured. ## Plugin Management (admin) ``` !plugins # List loaded plugins !load # Hot-load a plugin (admin) !reload # Reload a changed plugin (admin) !unload # Remove a plugin (admin) ``` ## Archive ``` !archive https://example.com/page # Save to Wayback Machine ``` URL must have `http://` or `https://` scheme. 30s timeout. SOCKS5-proxied. ## Bulk DNS ``` !resolve example.com github.com # A records (concurrent) !resolve example.com AAAA # Specific type !resolve 1.2.3.4 8.8.8.8 # Auto PTR for IPs ``` Max 10 hosts. Types: A, AAAA, MX, NS, TXT, CNAME, PTR, SOA. TCP DNS via SOCKS5, server 1.1.1.1. ## Recon ``` !dork list # List dork categories !dork admin example.com # Admin/login panel dorks !dork files example.com # Exposed document dorks !wayback example.com # Wayback Machine snapshot !wayback example.com 20240101 # Snapshot near date ``` Categories: admin, backup, cloud, config, creds, dirs, errors, exposed, files, login. ## OSINT ``` !username list # List services by category !username john # Full scan (~25 services) !username john github # Check single service !dns example.com # A record lookup (UDP, local resolver) !dns 1.2.3.4 # Reverse PTR lookup !dns example.com MX # Specific type (A/AAAA/MX/NS/TXT/CNAME/PTR/SOA) !tdns example.com # A record lookup (TCP via SOCKS5 proxy) !tdns example.com MX @8.8.8.8 # Explicit type + custom server !cert example.com # CT log lookup (max 5 domains) !whois example.com # WHOIS domain lookup !whois 8.8.8.8 # WHOIS IP lookup !subdomain example.com # CT log subdomain enum !subdomain example.com brute # + DNS wordlist brute !headers example.com # HTTP fingerprint (tech + security) ``` ## Ops ``` !opslog add Compromised target # Add timestamped entry !opslog list # Show last 5 entries !opslog list 10 # Show last 10 !opslog search pivot # Search entries !opslog del 3 # Delete entry by ID !opslog clear # Clear channel log (admin) !note set target 10.0.0.1 # Store a note !note get target # Retrieve a note !note del target # Delete a note !note list # List all keys !note clear # Clear all notes (admin) ``` ## Exploit-DB ``` !exploitdb search apache # Search by keyword !exploitdb 12345 # Lookup by EDB ID !exploitdb cve CVE-2024-1234 # Search by CVE !exploitdb update # Download latest CSV !exploitdb stats # Show index size ``` ## Payloads ``` !payload list # List categories !payload sqli # Show SQLi payloads !payload xss 3 # Show XSS payload #3 !payload ssti jinja # Search SSTI for 'jinja' !payload lfi all # Show all LFI payloads ``` Categories: sqli, xss, ssti, lfi, cmdi, xxe ## Red Team ``` !revshell bash 10.0.0.1 4444 # Reverse shell one-liner !revshell list # List types (bash/sh/nc/nce/python/perl/php/ruby/socat/lua/ps) !encode b64 hello # Base64 encode !decode hex 68656c6c6f # Hex decode !encode rot13 hello # ROT13 !hash hello # MD5 + SHA1 + SHA256 !hash sha512 hello # Specific algorithm !hashid # Identify hash type ``` ## OPSEC ``` !defang https://evil.com # Defang IOC !refang hxxps[://]evil[.]com # Refang IOC ``` ## Canary Tokens ``` !canary gen db-cred # 40-char hex token (default) !canary gen aws staging-key # AWS AKIA keypair !canary gen basic svc-login # user:pass pair !canary list # List channel canaries !canary info db-cred # Show full token !canary del db-cred # Delete canary (admin) ``` Types: `token` (hex), `aws` (AKIA+secret), `basic` (user:pass). Max 50/channel. `gen`/`del` admin only. Persists across restarts. ## Network ``` !tcping example.com # TCP latency (port 443, 3 probes) !tcping example.com 22 # Custom port !tcping example.com 80 5 # Custom port + count (max 10) !cidr 10.0.0.0/24 # Subnet info !cidr contains 10.0.0.0/8 10.1.2.3 # Membership check !portcheck 10.0.0.1 # Scan common ports !portcheck 10.0.0.1 22,80,443 # Scan specific ports !httpcheck https://example.com # HTTP status + timing !tlscheck example.com # TLS/cert inspection !tlscheck 10.0.0.1 8443 # Custom port !blacklist 1.2.3.4 # DNSBL reputation check ``` ## Intelligence (local databases + APIs) ``` !internetdb 8.8.8.8 # Shodan InternetDB: ports, CVEs, CPEs, tags !geoip 8.8.8.8 # GeoIP: city, country, coords, tz !asn 8.8.8.8 # ASN: number + organization !tor 1.2.3.4 # Check Tor exit node !tor update # Download exit list !iprep 1.2.3.4 # Firehol/ET blocklist check !iprep update # Download blocklist feeds !cve CVE-2024-1234 # Lookup specific CVE !cve search apache rce # Search CVE descriptions !cve update # Download NVD feed (slow) !cve stats # Show index size !mac AA:BB:CC:DD:EE:FF # MAC OUI vendor lookup !mac random # Generate random MAC !mac update # Download IEEE OUI database ``` ## Security Intelligence (API) ``` !abuse 8.8.8.8 # AbuseIPDB reputation check !abuse 8.8.8.8 1.1.1.1 # Batch check (max 5) !abuse 8.8.8.8 report 14 Spam # Report IP (admin) !vt # VirusTotal file hash lookup !vt 8.8.8.8 # VirusTotal IP lookup !vt example.com # VirusTotal domain lookup !vt https://evil.com # VirusTotal URL lookup !jwt eyJhbG... # Decode JWT token !emailcheck user@example.com # SMTP verification (admin) ``` API keys: set `ABUSEIPDB_API_KEY` / `VIRUSTOTAL_API_KEY` env vars or configure in `config/derp.toml` under `[abuseipdb]` / `[virustotal]`. VT rate limit: 4 req/min. Email check: max 5, admin only. ## FlaskPaste ``` !shorten https://long-url.com/x # Shorten URL !paste some text to paste # Create paste ``` Auto-shortens URLs in `!alert` announcements and history when plugin is loaded. Paste helper used internally for multi-line bot output. Config: `[flaskpaste]` in `config/derp.toml` or `FLASKPASTE_URL` env var. ### Data Setup ```bash ./scripts/update-data.sh # Update tor + iprep + oui MAXMIND_LICENSE_KEY=xxx ./scripts/update-data.sh # + GeoLite2 ``` ## Random ``` !rand password # 16-char random password !rand password 32 all # 32-char, full charset !rand hex 64 # Random hex string !rand uuid # UUID4 !rand bytes 32 # Random bytes (hex) !rand int 100 # Random 0..99 !rand coin # Heads or tails !rand dice 2d20 # Roll 2x d20 ``` ## Timer ``` !timer 5m # 5-minute countdown !timer 1h30m deploy # Named timer !timer 90 # 90 seconds !timer list # Show active timers !timer cancel deploy # Cancel a timer ``` ## Remind ``` !remind 5m check oven # One-shot (in-memory) !remind every 1h hydrate # Repeating (in-memory) !remind at 2027-06-15 deploy # Calendar one-shot (persisted) !remind at 2027-06-15 14:30 go # With explicit time !remind yearly 02-14 valentines # Yearly recurring (persisted) !remind yearly 12-25 09:00 xmas # Yearly with time !remind list # Show active reminders !remind cancel abc123 # Cancel by ID ``` Default time: 12:00. Timezone: `bot.timezone` config (default UTC). ## RSS ``` !rss add [name] # Subscribe feed (admin) !rss del # Unsubscribe feed (admin) !rss list # List channel feeds !rss check # Force-poll now ``` Names: lowercase alphanumeric + hyphens, 1-20 chars. Max 20 feeds/channel. Polls every 10min. Announces max 5 new items per cycle. Persists across restarts. ## YouTube ``` !yt follow [name] # Follow YouTube channel (admin) !yt unfollow # Unfollow channel (admin) !yt list # List followed channels !yt check # Force-poll now ``` Accepts any YouTube URL: video, channel, handle, shorts, embed. Names: lowercase alphanumeric + hyphens, 1-20 chars. Max 20 channels/channel. Polls every 10min. Announces max 5 new videos per cycle. Persists across restarts. ## Twitch ``` !twitch follow [name] # Follow streamer (admin) !twitch unfollow # Unfollow streamer (admin) !twitch list # List followed streamers !twitch check # Force-poll now ``` Names: lowercase alphanumeric + hyphens, 1-20 chars. Max 20 streamers/channel. Polls every 2min. Announces offline->live transitions. Persists across restarts. No API credentials needed (uses public GQL endpoint). ## Alert ``` !alert add # Add keyword alert (admin) !alert del # Remove alert (admin) !alert list # List alerts !alert check # Force-poll now !alert info # Show full result details !alert history [n] # Show recent results (default 5) ``` Searches keywords across 27 backends: YouTube (yt), Twitch (tw), SearXNG (sx), Reddit (rd), Mastodon (ft), DuckDuckGo (dg), Google News (gn), Kick (kk), Dailymotion (dm), PeerTube (pt), Bluesky (bs), Lemmy (ly), Odysee (od), Archive.org (ia), Hacker News (hn), GitHub (gh), Wikipedia (wp), Stack Exchange (se), GitLab (gl), npm (nm), PyPI (pp), Docker Hub (dh), arXiv (ax), Lobsters (lb), DEV.to (dv), Medium (md), Hugging Face (hf). Names: lowercase alphanumeric + hyphens, 1-20 chars. Keywords: 1-100 chars. Max 20 alerts/channel. Polls every 5min. Output: ACTION with `[name/tag/id] date - URL`, then PRIVMSG with full title. `add` replies instantly (seeds in background). Per-backend error tracking (5+ errors backs off that backend only). Multi-instance backends (pt, ft, ly, sx) fetch concurrently. Use `!alert info ` for details. Persists across restarts. History in `data/alert_history.db`. ## SearX ``` !searx # Search SearXNG ``` Shows top 3 results as `Title -- URL`. Channel only. Max query length: 200 chars. ## Cron (admin) ``` !cron add 1h #ops !rss check news # Schedule command every hour !cron add 2d #alerts !tor update # Every 2 days !cron del abc123 # Remove job by ID !cron list # List jobs in channel ``` Intervals: `5m`, `1h30m`, `2d`, `90s`, or raw seconds. Min 1m, max 7d. Max 20 jobs/channel. Persists across restarts. Channel only. ## Webhook (admin) ```toml # config/derp.toml [webhook] enabled = true host = "127.0.0.1" port = 8080 secret = "your-shared-secret" ``` ```bash # Send message to IRC channel via webhook SECRET="your-shared-secret" BODY='{"channel":"#ops","text":"Deploy done"}' SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}') curl -X POST http://127.0.0.1:8080/ \ -H "X-Signature: sha256=$SIG" -d "$BODY" ``` ``` !webhook # Show listener status (admin) ``` POST JSON: `{"channel":"#chan","text":"msg"}`. Optional `"action":true`. Auth: HMAC-SHA256 via `X-Signature` header. Starts on IRC connect. ## Teams Integration ```toml # config/derp.toml [teams] enabled = true proxy = true # SOCKS5 proxy for outbound HTTP bot_name = "derp" bind = "127.0.0.1" port = 8081 webhook_secret = "base64-secret-from-teams" incoming_webhook_url = "" # optional, for proactive msgs admins = ["aad-object-id-uuid"] # AAD object IDs operators = [] trusted = [] ``` Expose via Cloudflare Tunnel: `cloudflared tunnel --url http://127.0.0.1:8081` Teams endpoint: `POST /api/messages`. HMAC-SHA256 auth via `Authorization: HMAC `. Replies returned as JSON in HTTP response. IRC-only commands (kick, ban, topic) are no-ops. ~90% of plugins work without modification. ## Telegram Integration ```toml # config/derp.toml [telegram] enabled = true proxy = true # SOCKS5 proxy for HTTP bot_token = "123456:ABC-DEF..." # from @BotFather poll_timeout = 30 # long-poll seconds admins = [123456789] # Telegram user IDs operators = [] trusted = [] ``` Long-polling via `getUpdates` -- no public endpoint needed. HTTP through SOCKS5 proxy by default (`proxy = true`). Strips `@botusername` suffix in groups. Messages split at 4096 chars. IRC-only commands are no-ops. ~90% of plugins work. ## Mumble Integration ```toml # config/derp.toml [mumble] enabled = true proxy = false # pymumble connects directly host = "mumble.example.com" port = 64738 username = "derp" password = "" admins = ["admin_user"] # Mumble usernames operators = [] trusted = [] ``` Uses pymumble for protocol handling (connection, voice, Opus encoding). HTML stripped on receive, escaped on send. IRC-only commands are no-ops. ~90% of plugins work. ## Music (Mumble only) ``` !play # Play audio (YouTube, SoundCloud, etc.) !play # Playlist tracks expanded into queue !play classical music # YouTube search, random pick from top 10 !stop # Stop playback, clear queue (fades out) !skip # Skip current track (fades out) !prev # Go back to previous track (fades out) !seek 1:30 # Seek to position (also +30, -30) !resume # Resume last stopped/skipped track !queue # Show queue !queue # Add to queue (alias for !play) !np # Now playing !volume # Show current volume !volume 75 # Set volume (0-100, default 50) !keep # Keep current file + save metadata !kept # List kept files with metadata !kept clear # Delete all kept files + metadata !duck # Show ducking status !duck on # Enable voice ducking !duck off # Disable voice ducking !duck floor 5 # Set duck floor volume (0-100, default 1) !duck silence 20 # Set silence timeout seconds (default 15) !duck restore 45 # Set restore ramp duration seconds (default 30) ``` Requires: `yt-dlp`, `ffmpeg`, `libopus` on the host. Max 50 tracks in queue. Playlists auto-expand; excess truncated at limit. Skip/stop/prev/seek fade out smoothly (~0.8s); volume ramps over ~1s. `!prev` pops from a 10-track history stack (populated on skip/finish). `!keep` fetches title/artist/duration via yt-dlp and stores in `bot.state`. `!resume` restores position across restarts (persisted via `bot.state`). Auto-resumes on reconnect if channel is silent (waits up to 60s for silence). Mumble-only: `!play` replies with error on other adapters, others silently no-op. ## Plugin Template ```python from derp.plugin import command, event @command("name", help="Description") async def cmd_name(bot, message): text = message.text.split(None, 1) await bot.reply(message, "response") @event("JOIN") async def on_join(bot, message): await bot.send(message.target, f"Hi {message.nick}") ``` ## Message Object ``` msg.nick # Sender nick msg.target # Channel or nick msg.text # Message body msg.is_channel # True if channel msg.prefix # nick!user@host msg.command # PRIVMSG, JOIN, etc. msg.params # All params list msg.tags # IRCv3 tags dict ``` ## Multi-Server ```toml # config/derp.toml [bot] prefix = "!" # Shared defaults plugins_dir = "plugins" [servers.libera] host = "irc.libera.chat" port = 6697 nick = "derp" channels = ["#test"] [servers.oftc] host = "irc.oftc.net" port = 6697 nick = "derpbot" channels = ["#derp"] admins = ["*!~admin@oftc.host"] # Per-server override ``` Per-server blocks accept both server keys (host, port, nick, tls, ...) and bot overrides (prefix, channels, admins, ...). Unset keys inherit from `[bot]`/`[server]` defaults. Legacy `[server]` config still works. State isolated per server: `data/state-libera.db`, `data/state-oftc.db`. Plugins loaded once, shared across all servers. ## Config Locations ``` 1. --config PATH # CLI flag 2. ./config/derp.toml # Project dir 3. ~/.config/derp/derp.toml # User config 4. Built-in defaults # Fallback ```