Commit Graph

47 Commits

Author SHA1 Message Date
user
3bcba8b0a9 feat: add Telegram bot support via long-polling
TelegramBot adapter with getUpdates long-polling, all HTTP through
SOCKS5 proxy. Duck-typed TelegramMessage compatible with IRC Message.
Message splitting at 4096 chars, @botusername suffix stripping,
permission tiers via user IDs. 75 test cases.
2026-02-21 20:06:25 +01:00
user
014b609686 feat: add Microsoft Teams support via outgoing webhooks
TeamsBot adapter exposes the same plugin API as IRC Bot so ~90% of
plugins work without modification.  Uses raw asyncio HTTP server
(no MS SDK dependency) with HMAC-SHA256 signature validation.

- TeamsMessage dataclass duck-typed with IRC Message
- Permission tiers via AAD object IDs (exact match)
- Reply buffer collected and returned as HTTP JSON response
- Incoming webhook support for proactive send()
- IRC-only methods (join/part/kick/mode) as no-ops
- 74 new tests (1302 total)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:52:33 +01:00
user
073659607e feat: add multi-server support
Connect to multiple IRC servers concurrently from a single config file.
Plugins are loaded once and shared; per-server state is isolated via
separate SQLite databases and per-bot runtime state (bot._pstate).

- Add build_server_configs() for [servers.*] config layout
- Bot.__init__ gains name parameter, _pstate dict for plugin isolation
- cli.py runs multiple bots via asyncio.gather
- 9 stateful plugins migrated from module-level dicts to _ps(bot) pattern
- Backward compatible: legacy [server] config works unchanged

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:04:20 +01:00
user
c483beb555 feat: add webhook listener for push events to channels
HTTP POST endpoint for external services (CI, monitoring, GitHub).
HMAC-SHA256 auth, JSON body, single POST endpoint at /.

- asyncio.start_server with raw HTTP parsing (zero deps)
- Body validation: channel prefix, non-empty text, 64KB cap
- !webhook admin command shows address, request count, uptime
- Module-level server guard prevents duplicates on reconnect
- 22 test cases in test_webhook.py
2026-02-21 17:59:14 +01:00
user
2514aa777d feat: add granular ACL tiers (trusted/oper/admin)
4-tier permission model: user < trusted < oper < admin.
Commands specify a required tier via tier= parameter.
Backward compatible: admin=True maps to tier="admin".

- TIERS constant and Handler.tier field in plugin.py
- _get_tier() method in bot.py with pattern matching
- _is_admin() preserved as thin wrapper
- operators/trusted config lists in config.py
- whoami shows tier, admins shows all configured tiers
- 32 test cases in test_acl.py
2026-02-21 17:59:05 +01:00
user
7b14efb30f feat: add cron plugin for scheduled commands
Admin-only plugin for interval-based command execution.
Supports add/del/list, 1m-7d intervals, 20 jobs/channel.
Persists via bot.state, restores on reconnect.
Includes test_cron.py (~38 cases).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:35:08 +01:00
user
aebe1589d2 feat: add URL shortening to subscription announcements
Bot.shorten_url() method delegates to flaskpaste plugin when loaded.
RSS, YouTube, and pastemoni announcements auto-shorten links.
Includes test_flaskpaste.py (9 cases) and FakeBot updates in 3 test files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:35:03 +01:00
user
9abf8dce64 feat: add !paste command and unit tests for 5 core plugins
Add cmd_paste to flaskpaste plugin (create paste, return URL).
Add test suites for encode, hash, defang, cidr, and dns plugins
(83 new test cases, 1093 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:54:18 +01:00
user
e3bb793574 feat: add canary, tcping, archive, resolve plugins
canary: generate realistic fake credentials (token/aws/basic) for
planting as canary tripwires. Per-channel state persistence.

tcping: TCP connect latency probe through SOCKS5 proxy with
min/avg/max reporting. Proxy-compatible alternative to traceroute.

archive: save URLs to Wayback Machine via Save Page Now API,
routed through SOCKS5 proxy.

resolve: bulk DNS resolution (up to 10 hosts) via TCP DNS through
SOCKS5 proxy with concurrent asyncio.gather.

83 new tests (1010 total), docs updated.
2026-02-20 19:38:10 +01:00
user
3de3f054df feat: add internetdb plugin (Shodan InternetDB host recon)
Free, keyless API returning open ports, hostnames, CPEs, tags, and
known CVEs for any public IP. All requests routed through SOCKS5.
21 test cases (927 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 17:41:51 +01:00
user
442fea703c feat: replace MaxMind ASN with iptoasn.com TSV backend
Drop GeoLite2-ASN.mmdb dependency (required license key) in favor of
iptoasn.com ip2asn-v4.tsv (no auth, public domain).  Bisect-based
lookup in pure stdlib, downloaded via SOCKS5 in update-data.sh.
Adds 30 test cases covering load, lookup, and command handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:43:00 +01:00
user
8ce6922cc3 feat: add video duration to YouTube announcements
Fetches duration via InnerTube player API for new videos at
announcement time. Displayed as compact h:mm:ss before views/likes.
Gracefully omitted for Shorts and unavailable content.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:28:40 +01:00
user
1fe7da9ed8 feat: metadata enrichment for alerts and subscription plugins
Alert backends now populate structured `extra` field with engagement
metrics (views, stars, votes, etc.) instead of embedding them in titles.
Subscription plugins show richer announcements: Twitch viewer counts,
YouTube views/likes/dates, RSS published dates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 10:00:17 +01:00
user
c3b19feb0f feat: add paste site keyword monitor plugin
Poll Pastebin archive and GitHub Gists for keyword matches,
announce hits to subscribed IRC channels. Follows rss.py
polling/subscription pattern with state persistence.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:01:46 +01:00
user
1836fa50af feat: paste overflow via FlaskPaste for long replies
Add Bot.long_reply() that sends lines directly when under threshold,
or creates a FlaskPaste paste with preview + link when over. Refactor
abuseipdb, alert history, crtsh, dork, exploitdb, and subdomain
plugins to use long_reply(). Configurable paste_threshold (default: 4).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:07:31 +01:00
user
8cabe0f8e8 feat: add URL title preview plugin
Event-driven plugin that auto-fetches page titles for URLs posted in
channel messages. HEAD-then-GET via SOCKS5 pool, og:title priority,
cooldown dedup, !-suppression, binary/host filtering. 52 tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:57:00 +01:00
user
7606280358 fix: repair broken tests across alert, chanmgmt, and integration
- test_alert: remove stale _MAX_ANNOUNCE import/test, update _errors
  assertions for per-backend dict, fix announcement checks (action vs
  send), mock _fetch_og_batch in seeding tests, fix YouTube/SearX mock
  targets (urllib.request.urlopen), include keyword in fake data titles
- test_chanmgmt: add _FakeState to _FakeBot (on_invite now persists)
- test_integration: update help assertion for new output format

696 tests pass, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:14:44 +01:00
user
94f563d55a feat: connection pooling via urllib3 + batch OG fetching
Replace per-request SOCKS5+TLS handshakes with urllib3 SOCKSProxyManager
connection pool (20 pools, 4 conns/host). Batch _fetch_og calls via
ThreadPoolExecutor to parallelize OG tag enrichment in alert polling.
Cache flaskpaste SSL context at module level.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:52:22 +01:00
user
933d9e1ddd perf: cache default HTTP opener at module level
Avoid rebuilding _ProxyHandler + build_opener() on every request.
Default-context callers (16 of 18 plugins) reuse one cached opener;
custom-context callers still get a fresh one.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 10:15:20 +01:00
user
6d86e8d7f8 fix: retry transient SSL/connection errors in alert backends
Add retry loop (3 attempts, exponential backoff) for SSLError,
ConnectionError, TimeoutError, and OSError in alert poll cycle.
Non-transient errors fail immediately. Also fixes searx test
mocks to match direct urlopen usage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 18:51:28 +01:00
user
b973635445 fix: route SearXNG direct via static route, drop proxy
SearXNG instance at 192.168.122.119 is reachable via grokbox
static route -- no need to tunnel through SOCKS5. Reverts searx
and alert plugins to stdlib urlopen for SearXNG queries. YouTube
and Twitch in alert.py still use the proxy. Also removes cprofile
flag from docker-compose command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 17:52:43 +01:00
user
29e77f97b2 fix: route searx and alert SearXNG traffic through SOCKS5 proxy
Both plugins called urllib.request.urlopen directly, bypassing the
proxy. Switch to derp.http.urlopen and update the SearXNG endpoint
to the public domain (searx.mymx.me). Update test mocks to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:56:45 +01:00
user
26063a0e8f feat: add TCP DNS plugin with SOCKS5 proxy support
Extract shared DNS wire-format helpers into src/derp/dns.py so both
the UDP plugin (dns.py) and the new TCP plugin (tdns.py) share the
same encode/decode/build/parse logic.

The !tdns command routes queries through the SOCKS5 proxy via
derp.http.open_connection, using TCP framing (2-byte length prefix).
Default server: 1.1.1.1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:09:35 +01:00
user
1bdba0ea06 feat: route raw TCP traffic through SOCKS5 proxy
Add create_connection and open_connection helpers to the shared proxy
module, covering portcheck, whois, tlscheck, and crtsh live-cert check.
UDP-based plugins (dns, blacklist, subdomain) stay direct.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 16:01:17 +01:00
user
97bbc6a825 feat: route plugin HTTP traffic through SOCKS5 proxy
Add PySocks dependency and shared src/derp/http.py module providing
proxy-aware urlopen() and build_opener() that route through
socks5h://127.0.0.1:1080. Subclassed SocksiPyHandler passes SSL
context through to HTTPS connections.

Swapped 14 external-facing plugins to use the proxied helpers.
Local-only traffic (SearXNG, raw DNS/TLS sockets) stays direct.
Updated test mocks in test_twitch and test_alert accordingly.
2026-02-15 15:53:49 +01:00
user
10f62631be feat: add SearX search plugin and alert backend
Add standalone !searx command for on-demand SearXNG search (top 3 results).
Add SearX as a third backend (sx) to the alert plugin for keyword monitoring.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 15:28:00 +01:00
user
8fd6393273 feat: add keyword alert subscription plugin
Search keywords across YouTube (InnerTube) and Twitch (GQL)
simultaneously, announcing new results per channel. Supports
add/del/list/check subcommands with per-platform seen lists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 15:16:29 +01:00
user
50fb8015cd feat: add Twitch livestream notification plugin
Poll Twitch streamers via public GQL endpoint and announce
offline-to-live transitions in IRC channels. Tracks stream ID
to avoid re-announcing the same stream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:50:30 +01:00
user
3955935da4 feat: add YouTube channel follow plugin
Follow YouTube channels via Atom feeds with !yt follow/unfollow/list/check.
Resolves any YouTube URL to a channel ID, polls for new videos, and
announces them in IRC channels.
2026-02-15 14:34:20 +01:00
user
6b7572defc feat: auto-join channels on admin invite 2026-02-15 13:52:15 +01:00
user
125a4c5d4d feat: add per-channel RSS feed subscription plugin
Subscribe RSS/Atom feeds to IRC channels with periodic polling,
new-item announcements, deduplication, and persistence across restarts.
Supports conditional HTTP requests (ETag/Last-Modified), automatic
backoff on errors, and per-channel feed limits.
2026-02-15 13:36:23 +01:00
user
02ea81d059 fix: debounce WHO on JOIN to prevent flood on netsplit recovery
WHO doesn't support multiple targets (absent from TARGMAX on all
major IRCds). Replace per-nick WHO with a debounced per-channel WHO:
on JOIN, schedule WHO #channel after 2s delay. Subsequent JOINs
within the window reset the timer, so a netsplit producing dozens
of JOINs results in a single WHO.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 13:03:35 +01:00
user
fd8f72c3cc fix: detect oper status when users join channels
Previously the bot only sent WHO on connect (001), so users joining
after the initial scan were never checked for oper status. Now sends
WHO <nick> on every JOIN event to detect opers mid-session.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:53:12 +01:00
user
f888faf2bd feat: add calendar-based reminders (at/yearly) with persistence
Calendar reminders use bot.state (SQLite KV) for persistence across
restarts. Supports one-shot at specific date/time and yearly recurring
reminders with leap day handling. Restored automatically on connect
via 001 event handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:39:42 +01:00
user
021a0ddbe3 test: comprehensive remind plugin tests with IndexError fix
Expand test coverage from 23 pure helper tests to 53 tests covering
the full plugin: _cleanup, _remind_once, _remind_repeat, and the
complete cmd_remind handler (usage, oneshot, repeating, list, cancel,
target routing). Fix IndexError on `!remind every` with no arguments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:17:31 +01:00
user
70d203f96e feat: add remind plugin with one-shot and repeating reminders
Supports duration parsing (5m, 1h30m, 2d12h), short hex IDs for
tracking, list/cancel subcommands, and repeating intervals via
`!remind every <duration> <text>`. Includes 23 unit tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 12:09:34 +01:00
user
f48b32cd65 fix: resolve test_crtsh.py import for plugins/ directory
Same importlib fix as test_username.py -- load plugins.crtsh from
file path since plugins/ is not a Python package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 06:18:06 +01:00
user
7184c43b08 fix: resolve test_username.py import for plugins/ directory
Load plugins.username via importlib.util.spec_from_file_location
since plugins/ is not a Python package on sys.path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 06:17:11 +01:00
user
fa88422c36 test: add integration tests with mock IRC server
Queue-based _MockConnection replaces IRCConnection to test the full
bot pipeline (registration -> dispatch -> handler -> response) without
network I/O. 14 tests cover CAP negotiation, PING/PONG, command
dispatch, prefix matching, admin enforcement, channel filtering,
and CTCP responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 06:09:14 +01:00
user
13c1f76767 test: add username plugin tests
53 tests covering regex validation, service registry integrity,
classification logic (status/json/body), formatting, and category
grouping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 04:47:26 +01:00
user
668d7f89b8 test: add channel filter and JSON log tests
TestChannelFilter: allowed/denied/PM/no-config/core-exempt/ampersand.
TestChannelConfig: TOML loading, defaults. TestJsonFormatter: fields,
exception, unicode, single-line, timestamp format.
2026-02-15 04:16:49 +01:00
user
8129b79cdb test: add config, format_msg, and Bot API tests
New test_config.py: merge, load, resolve_config tests.
Extend test_irc.py: format_msg edge cases (colon, empty, multi-param).
Extend test_plugin.py: Bot API via FakeConnection, _split_utf8 tests.
Test count: 92 -> 120.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 03:27:18 +01:00
user
f86cd1ad49 feat: add IRCv3 cap negotiation, channel management, state persistence
Implement CAP LS 302 flow with configurable ircv3_caps list, replacing
the minimal SASL-only registration. Parse IRCv3 message tags (@key=value)
with proper value unescaping. Add channel management plugin (kick, ban,
unban, topic, mode) and bot API methods. Add SQLite key-value StateStore
for plugin state persistence with !state inspection command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 03:07:06 +01:00
user
f96224afb1 feat: add admin/owner permission system
Hostmask-based admin controls with automatic IRCOP detection via WHO.
Permission enforcement in the central dispatch path denies restricted
commands to non-admins. Includes !whoami and !admins commands, marks
load/reload/unload as admin-only.

Also lands previously-implemented SASL PLAIN auth, token-bucket rate
limiting, and CTCP VERSION/TIME/PING responses that were staged but
uncommitted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 02:26:27 +01:00
user
77f9a364e6 feat: add hot-reload, shorthand commands, and plugin help
- Plugin registry: add unload_plugin(), reload_plugin(), path tracking
- Bot: add load_plugin(), reload_plugin(), unload_plugin() public API
- Core plugin: add !load, !reload, !unload, !plugins commands
- Command dispatch: support unambiguous prefix matching (!h -> !help)
- Help: support !help <plugin> to show plugin description and commands
- Tests: 17 new tests covering hot-reload, prefix matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 01:15:59 +01:00
user
ad18a902dd feat: add crt.sh certificate transparency lookup plugin
Query CT logs via crt.sh to enumerate SSL certs for domains,
report expired/valid counts, and flag live expired certs.
Uses ThreadPoolExecutor(3) for blocking I/O on RPi5.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:56:55 +01:00
user
bf45abcbad feat: initial implementation
Asyncio IRC bot with decorator-based plugin system.
Zero external dependencies, Python 3.11+.

- IRC protocol: message parsing, formatting, async TCP/TLS connection
- Plugin system: @command and @event decorators, file-based loading
- Bot orchestrator: connect, dispatch, reconnect, nick recovery
- CLI: argparse entry point with TOML config
- Built-in plugins: ping, help, version, echo
- 28 unit tests for parser and plugin system
2026-02-15 00:37:31 +01:00