Commit graph

44 commits

Author SHA1 Message Date
Rosie Val
5e41658d7d Re-enable Report/Delete/Profile context menus, remove Bookmark, fix reports
Re-enabled the "Report to Wormhole", "Delete from Network", and "Wormhole
Profile" context menus (previously disabled entirely). Removed "Bookmark
(Wormhole)" per request — the prefix `wh bm list`/`clear` commands are
untouched, but note this was the only way to *add* a bookmark, so that
feature is now list/clear-only for existing entries.

Wormhole Profile is now considerably richer: account creation date, total
cross-network message count, global-ban status, and per-network karma/
server-count/muted/banned status, sorted busiest-network-first.

Fixed both report-creation paths (the "Report to Wormhole" context menu's
modal, and `wh report msg`): report_counter was read before the config lock
and written after, so concurrent reports could collide on the same id with
the counter never advancing. Now computed and saved atomically inside the
lock. Also gave both paths full parity — message id, jump link, and a real
content preview (the context-menu path previously stored `hash()` of the
content, which is randomized per-process in Python 3 and useless for
anything; the prefix-command path never even recorded who wrote the
message). `wh report view` now surfaces all of it.

Also added the "Find Origin" context menu (right-click a message -> find
its true source server/channel/author across the network) as a separate,
complementary feature to Profile — not a replacement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 00:02:49 +01:00
Rosie Val
ece196748c Add Wormhole 'Find Origin' right-click context menu
Right-click any relayed message -> Apps -> Find Origin resolves it back to
the true source: origin server (name + ID), channel, author (name + ID),
message ID, and a jump link. Uses the existing message_map reverse lookup,
falling back to the same brute-force search across the network's member
channels that _ctx_delete_message/wh mod nuke already rely on when the
relay map doesn't have a direct answer. Mod-gated (deanonymizes real
identity across servers). Registered independently of the existing bulk
Report/Bookmark/Delete/Profile context-menu registration, which is
currently disabled — left that decision alone rather than reviving it as
a side effect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 23:53:57 +01:00
Rosie Val
6cc7f8e494
Add files via upload 2026-07-22 16:13:03 -04:00
Rosie Val
8459ecdcf7
Delete wormhole/commands/moderation.py 2026-07-22 16:12:54 -04:00
Rosie Val
7875ecea95
Add files via upload 2026-07-22 16:07:35 -04:00
Rosie Val
e211ce2950
Delete wormhole/utils.py 2026-07-22 16:07:26 -04:00
Rosie Val
e8bcbb8e24
Add files via upload 2026-07-22 16:07:09 -04:00
Rosie Val
76889459fa
Delete wormhole/listeners/relay.py 2026-07-22 16:06:56 -04:00
Rosie Val
1fbb2657fd fix: add network validation and logging to all settings commands
- Added null check for network existence in all wh set commands
- All setting changes now log to the log channel with descriptive titles
- Prevents KeyError crashes on invalid network names
- Improves audit trail for administrator actions
2026-07-21 22:34:31 -04:00
Rosie Val
0cad208455 fix: disable mention parsing in relay to prevent unintended pings
- Add `allowed_mentions=discord.AllowedMentions(parse=[])` to all webhook and channel sends
- Prevents users from being pinged when replies are relayed across the network
- Fixes issue where reply context could trigger unintended mentions across all servers
- Applies to webhook sends (primary and fallback) and embed/compact relay modes
2026-07-21 21:50:06 -04:00
root
2f97926ca6 fix(wormhole): remove wait_until_ready() from _init() to prevent load timeout
Root cause: _init() was blocking on wait_until_ready() for up to 30 seconds,
causing Red's package load to timeout. Red then reports 'Failed to load
package wormhole (timeout)' but the cog is actually partially loaded,
causing 'already loaded' errors on retry.

Timeline:
1. [p]load wormhole starts
2. setup() calls bot.add_cog(cog) ✓
3. setup() calls await cog._init()
4. _init() blocks on wait_until_ready() for 30s
5. Red's load timeout (30s) triggers
6. Red reports 'timeout' but cog is registered
7. [p]load wormhole again → 'already loaded' error

Solution: Remove wait_until_ready() from _init() since:
- Bot is already ready when cogs load on startup
- Background loops have their own wait_until_ready() calls
- _init() shouldn't block setup()

Background loops still wait_until_ready() independently (correct behavior).

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:43:46 +00:00
root
6fd48e93af fix(wormhole): rename cog class to WormholeV4 to bypass stale registration
Problem: Red's internal state has stale 'Wormhole' cog registrations from
previous versions (both identifier 7730187301 and 928374650), causing
'Cog named Wormhole already loaded' errors even on fresh bot starts.

Root cause: Multiple config identifiers registered under same cog name:
  - wormhole: {'wormhole': {}}  (old lowercase)
  - Wormhole: {'7730187301': {}, '928374650': {}}  (two identifiers!)

Solution: Rename cog class Wormhole → WormholeV4 to bypass all stale
registration state. This gives a clean slate without requiring users to
manually purge config data.

Changes:
- class Wormhole → class WormholeV4 in core.py
- Updated __init__.py import and setup()
- Config identifier unchanged (928374650)

This completely sidesteps the phantom load bug without touching user data.

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:38:56 +00:00
root
0c41ae0b9f feat(wormhole): disable context menus to eliminate load issues
Problem: Context menus persist in Discord's command tree even after bot
shutdown, causing 'already loaded' errors on restart. The idempotent
registration fix helped but added complexity.

Solution: Disable context menus entirely. All functionality remains
available via slash/prefix commands:
  - Report: /wh report message [msg_id] [reason]
  - Bookmark: /wh bookmark save [msg_id]
  - Delete: /wh delete [msg_id] (staff only)
  - Profile: /wh profile [user]

Changes:
- Commented out _register_context_menus() call in _init()
- Kept registration/callback code for future reference
- Simplified cog_unload() - no context menus to remove

Benefits:
- No command tree registration complexity
- Clean reload every time
- No phantom 'already loaded' state
- Simpler cog lifecycle

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:35:27 +00:00
root
c8bc14fb42 fix(wormhole): make context menu registration idempotent
Problem: If bot crashes or shuts down ungracefully, context menus stay
registered in Discord's command tree. On restart, add_command() fails
with 'already loaded' error.

Solution: Remove existing context menus before registering new ones.
This makes registration idempotent (safe to run multiple times).

Changes:
- _register_context_menus() now removes existing menus first
- Wrapped in try/except to handle 'not found' gracefully
- Ensures clean reload even after ungraceful shutdown

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:33:09 +00:00
root
15eb047d15 chore(wormhole): remove archived monolith - not needed in repo
The old monolithic file is not needed in version control.

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:27:08 +00:00
root
dc695a43ed chore(wormhole): archive old monolithic wormhole.py for reference
Keeping the 4,782-line v3.4.6 monolith as wormhole.py.old for:
- Historical reference
- Rollback safety
- Migration verification

This file is NOT loaded by the cog - it's purely archival.

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:26:42 +00:00
root
44d7f79c13 fix(wormhole): fix persistence bug and finalize v4.0.0 modular architecture
BREAKING: Removed obsolete monolithic wormhole.py (4,782 lines)
The v4.0.0 modular architecture was already implemented but the old
file was still present causing confusion.

Fixes:
- Fix context menu cleanup in cog_unload (add type parameter)
- Remove obsolete wormhole.py monolith (archived as .old)
- Context menus now properly unregister on reload

Architecture:
- core.py (731 lines) - main cog class
- commands/ (14 modules, 2,645 lines) - command mixins
- listeners/ (3 modules) - event handlers
- models/ (3 modules) - data structures
- services/ (1 module) - business logic
- ui/ (2 modules) - Discord UI components

Documentation:
+ ARCHITECTURE.md - design overview and history
+ MODULE_MAP.md - developer quick reference

This fixes the "already loaded" phantom state bug where wormhole
wouldn't persist through restarts and required double-loading.

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-05-26 16:26:03 +00:00
Viktor AI
2ad7a7b691 fix: wire up missing feature enforcement in relay
- Mirror channels now receive relayed messages (was blocked from sending but never sent to)
- Server allowlist enforced in relay (allowlist_servers gate check)
- Silent mode suppresses status broadcasts (_status respects 'silent' flag)
- Welcome message sent when channel joins via 'wh open'
2026-05-14 19:33:58 +00:00
Viktor AI
4bc143b26f fix: group all commands under 'wh' parent — no more flat wh-xxx commands
Commands now show as 'wh create', 'wh staff add', 'wh set relaymode'
instead of 'wh-create', 'wh-staff add', 'wh-set relaymode'.

- Added commands/_base.py with root 'wh' group and all 20 subgroup stubs
- All 13 command mixins inherit from WormholeBase
- Decorators changed: @commands.hybrid_command(name='wh-X') → @WormholeBase.wh.command(name='X')
- Subgroup commands: @wh_X.command() → @WormholeBase.wh_X.command()
- Removed duplicate 'wh' group from core.py (now in _base.py)
- Fixed alias: 'wh-color' → 'color' for colour command
2026-05-14 19:24:37 +00:00
Viktor AI
5a4421fb6c fix: remove duplicate slash command registrations causing CommandAlreadyRegistered
The hybrid_command decorator on mixin classes already auto-registers
slash commands. The manual registrations in _register_context_menus
clashed, causing 'wh-list already registered' on load. Removed all
manual slash commands — only context menus remain.
2026-05-14 19:12:55 +00:00
Viktor AI
0b028e7bb9 refactor: Wormhole v4.0.0 — full modular architecture with hierarchical staff
BREAKING: Complete cog restructure from monolithic wormhole.py into modular architecture.

## Architecture
- models/permissions.py — Role IntEnum (MEMBER→OWNER), requires_role() decorator
- models/config.py — DEFAULT_NETWORK/DEFAULT_GLOBAL with 80+ config keys
- models/message_map.py — MessageMap class (extracted from _MessageMap)
- services/emoji.py — Foreign emoji resolution and relay
- ui/views.py — Reply jump button view
- ui/modals.py — Report modal
- core.py — Main Wormhole class, helpers, background loops, context menus
- commands/ — 13 command modules as mixin classes
- listeners/ — relay pipeline, edit/delete/reaction sync, typing/pin sync

## Staff System (new)
Per-network hierarchical roles replacing flat owner/staff:
  Bot Owner (Red built-in) — global override
  └─ Network Owner → Admin → Moderator → Helper → Member
  Each role assigned per-network. Higher roles can assign lower.
  Legacy staff_ids auto-migrated to ADMIN role.

## Enhanced Moderation
- Server-level ban/mute (not just user-level)
- Allowlist mode (only whitelisted servers can send)
- Mod edit and nuke (delete N messages by user)
- Anti-raid detector with auto-freeze
- Expanded automod: anti-zalgo, anti-emote-spam, anti-newline-spam

## Commands (100+)
network, settings, staff, moderation, filters, social, dm, mentions,
tos, reports, bridge, advanced (polls/afk/auto-responses/scheduled/
analytics/quiet-hours/colours/invites/announcements/blackout/portal),
debug (health/trace/testsend/relaydebug/backup/restore/version)

## Files
- 30 Python files, 5,274 lines total (was 4,782 in monolith)
- Original wormhole.py preserved for reference
- utils.py unchanged (all helpers reused)
2026-05-14 19:07:49 +00:00
Viktor
f48f755223 fix(wormhole): add emoji thumbnails to embed relay mode
Embed mode was missing foreign emoji support. Now all three relay
modes (webhook, embed, compact) show unknown emojis as embed
thumbnails via attachment:// scheme.
2026-05-14 16:11:15 +00:00
Viktor
bd0f55b243 fix(wormhole): show foreign emojis as embed thumbnails (~80px) not full-size
File attachments render as massive images in Discord regardless of
source size. Switch to embed thumbnails via the attachment:// scheme:

1. Download emoji from CDN at 48px
2. Attach as a File to the message
3. Reference via attachment://name.png in a minimal embed's thumbnail
4. Thumbnails render at ~80×80 px — much closer to emoji size

Fresh File/Embed objects are built per channel (consumed on send).
Bumps to v3.4.6.
2026-05-14 16:00:09 +00:00
Viktor
f74e9b7897 fix(wormhole): use inline links for foreign emojis instead of file attachments
File attachments render as massive images in Discord. Replace the
download-and-attach approach with clickable [:name:](cdn_url) inline
links — keeps foreign emojis compact and inline with the message text.

Removes aiohttp dependency and simplifies the helper to synchronous.
Bumps to v3.4.5.
2026-05-14 15:53:01 +00:00
Viktor
424403cf4f feat(wormhole): relay unknown custom emojis as 64px image attachments
Custom emojis the bot can't see (bot.get_emoji returns None) are now:
1. Replaced with :name: in message text
2. Downloaded from Discord CDN at 64px
3. Attached as small image files to the relay message

Known emojis (from any server the bot is in) keep the <:name:id>
syntax and render normally. Up to 5 emoji images per message.

Works in webhook and compact relay modes. Bumps to v3.4.4.
2026-05-14 15:40:36 +00:00
Viktor
2acee87123 fix(wormhole): resolve reply button to local copy, not original server
The forward map only stores relay targets — the source channel (where
the original message was typed) was never included. When someone in
Server B replied to a relayed message, the button for Server A fell
back to the fallback URL pointing at Server B instead of Server A.

Fix: after building the relay-target URLs, identify the source channel
by finding network channels not present in the forward map, and map
them to the original message ID.
2026-05-14 15:23:27 +00:00
Viktor
2a14a08801 fix(wormhole): only pass view kwarg when reply button exists
Passing view=None to wh.send() on every message caused all relays
to fail. Now uses **_view_kw dict unpacking so the view parameter
is only included when there is actually a reply-jump button to show.
2026-05-14 15:18:51 +00:00
Viktor
13b28d3800 feat(wormhole): add 'Jump to replied message' button on relayed replies
When a reply is relayed across servers, each copy now includes a URL
button underneath the quoted reply text:

- If the referenced message has a relayed copy in the target channel,
  the button links to that local copy (so users stay in their own server).
- Otherwise, it falls back to the original message URL.

Works across all relay modes (webhook, embed, compact) and leverages
the existing msg_map to resolve per-channel message IDs.

Bumps version to 3.4.3.
2026-05-14 15:13:20 +00:00
Viktor AI
bbf427284e feat: per-network mention config + user opt-in/out for pings
- Migration now uses a _mention_migrated flag so it only forces mentions
  off once. After that, admins can freely toggle per-network settings
  with 'wh mentions set <network> <type> <true/false>'

- New mention_optout_users list per network: users can opt out of being
  @pinged through the relay even when user mentions are enabled
  network-wide. Their <@ID> mentions are stripped; everyone else's pass
  through. Default: opted in.

- New commands:
  • wh mentions optout <network>  — stop receiving relay pings
  • wh mentions optin <network>   — start receiving relay pings again
  • wh mentions mystatus <network> — check your current ping status

- apply_mention_policy() now accepts optout_users set and selectively
  strips only opted-out users' mentions when user mentions are globally
  allowed

- Updated 'wh mentions status' to show opt-out count and correct
  defaults
2026-05-12 15:49:56 +00:00
Viktor AI
8c5b422d83 fix: migrate existing networks to strip all mentions + revert empty-prefix guard
- On cog load, all existing networks are migrated to disable every
  mention type (user, role, everyone, here) — changing the default
  only affected new networks, not existing ones
- Reverted the v3.4.2 'and ctx.prefix' guard in the command filter —
  the real relay bug was the regex crash, not the empty prefix.
  ctx.valid alone correctly identifies registered commands even with
  an empty-string prefix
2026-05-12 15:21:08 +00:00
Viktor AI
9e8650c01a feat: strip all mentions from relayed messages by default (v3.4.3)
- Default mention_policy now disables all mention types including user
  mentions (previously allow_user_mentions defaulted to True)
- Blocked mentions are now removed entirely instead of replaced with
  ZWSP placeholders — '@mention HI!' becomes 'HI!' on the other side
- Trailing whitespace from removed mentions is cleaned up
- Updated both apply_mention_policy() and sanitise_mentions()
2026-05-12 14:55:56 +00:00
Viktor AI
f1c8970d3d fix: raw string in mention_policy regex crashes every relay (v3.4.3)
Root cause: apply_mention_policy() in utils.py used raw strings for
re.sub replacement arguments:
  re.sub(r'<@&(\d+)>', r'@\u200brole', content)

The r-prefix makes \u200b literal backslash-u instead of Unicode ZWSP.
Python's re.sub always validates the replacement template, so \u at
position 1 raises re.error on EVERY message — even without matches.

Since _DEFAULT_NETWORK sets mention_policy.allow_role_mentions=False,
this code path runs for all networks, causing _do_relay to throw on
every single message. The exception was caught by on_message's
try/except, silently killing relay with total_messages stuck at 0.

Fix: remove r-prefix from replacement strings so \u200b is correctly
interpreted as the Unicode zero-width space character.
2026-05-12 14:52:22 +00:00
Viktor AI
39188d9f4e feat: add relay diagnostic commands (relaydebug, testsend, tracemode)
Added three diagnostic tools to help debug relay issues:

- wh relaydebug: static check of all on_message gates against the
  current channel — reports which checks pass/fail
- wh testsend [text]: bypasses on_message entirely and sends a test
  message directly through the webhook to verify connectivity
- wh tracemode: toggles live tracing for the channel — when enabled,
  every message produces a diagnostic embed showing exactly which
  gate-check blocked it or that the relay succeeded

Also added trace checkpoints at every early-return in on_message so
tracemode can pinpoint the exact check that blocks a message.
2026-05-12 13:38:15 +00:00
Viktor AI
9598f752c1 fix: Wormhole v3.4.2 — empty-prefix command filter bug
The v3.4.1 command filter used bot.get_context() to detect commands,
but an empty-string prefix ('') matched EVERY message, causing
ctx.valid to return True for any message whose first word happened
to be a registered command.  With enough built-in commands (help,
ping, info, set, etc.) this silently dropped most or all relay
traffic (total_messages stayed at 0).

Fix: require ctx.prefix to be truthy (non-empty) before skipping
a message as a command.  Empty-prefix matches are now ignored,
so only messages with a real prefix (!, @bot, etc.) are filtered.

Also re-added the empty-prefix warning to 'wh debug' output so
users know to clean up their bot prefix configuration.
2026-05-12 12:53:18 +00:00
Viktor AI
5ece19dae7 fix: Wormhole v3.4.1 — relay engine hardening 2026-05-12 12:24:44 +00:00
everestmcarthur
2bde18b727 fix: Discord 25-subcommand limit — use prefix group + standalone slash commands
Discord enforces a max of 25 subcommands per slash command group.
Wormhole has 50 children on the main group and 39 on wh set, making
hybrid_group impossible.

Fix: wh is now a regular prefix group, with 7 standalone slash commands
registered for the most common user-facing operations:
  /wormhole-list, /wormhole-info, /wormhole-discover,
  /wormhole-accept, /wormhole-agree, /wormhole-report,
  /wormhole-profile

All 4 context menus still work (Report, Bookmark, Delete, Profile).
All 85+ prefix commands still work via [p]wh.
2026-05-08 03:06:05 +00:00
everestmcarthur
15e42fb454 fix: mod edit/nuke resolve relayed IDs back to original — any copy's ID works
get_relayed() now checks reverse map as fallback, so passing any
relayed copy's message ID resolves to the full mapping.

mod edit and mod nuke both call get_original() first, so staff can
right-click or copy ANY copy of a message and it deletes/edits the
entire chain across all servers.
2026-05-08 03:02:39 +00:00
everestmcarthur
f8fcb1670b v3.4.0 — Phase 5: hybrid commands, context menus, mention policy, ToS gate, reports, mod edit/delete
Phase 5 — Security, Privacy & Power Update:

HYBRID COMMANDS
- Main command group converted to hybrid_group (slash + prefix)
- All commands work as both /wh and [p]wh

CONTEXT MENU ACTIONS (right-click)
- Report to Wormhole — opens modal for report reason
- Wormhole Bookmark — saves message to DM
- Wormhole Delete — staff can delete from entire network
- Wormhole Profile — view user stats across networks

GRANULAR MENTION POLICY
- Per-network control: allow/block @user, @role, @everyone, @here
- Per-server overrides (different rules per guild)
- Per-user exemptions (trusted users bypass policy)
- Replaces legacy strip-* with proper policy engine
- wh mentions set/server-set/exempt/unexempt/status

TERMS OF SERVICE / RULES ACCEPTANCE GATE
- wh tos enable — require acceptance before messaging
- Built-in legal template (6 sections, prosecution-ready)
- Consent tracking with timestamps
- wh tos set (custom text), template (reset), accepted (view), reset (force re-accept)
- wh accept / wh agree — user-facing acceptance flow
- Blocks relay for non-accepted users with helpful reminder

MOD EDIT/DELETE ACROSS NETWORK
- wh mod edit <name> <msg_id> <new_content> — edits all relayed copies
- wh mod nuke <name> <msg_id> — deletes from every server + original
- Both audit-logged

REPORT SYSTEM
- wh report message — report via reply or message ID
- Context menu report with modal (reason input)
- Anti-abuse cooldown (60s between reports)
- Content hashing for audit trails
- Reports sent to log channel + network owner DM
- wh report list/resolve/action (ban/mute/warn/dismiss)
- Capped at 200 reports per network

PRIVACY & SECURITY
- _ReportModal class for context menu reporting
- Content hash stored instead of plaintext in report records
- Report cooldowns prevent abuse
- ToS acceptance with ISO timestamps for legal compliance

4,196 lines in wormhole.py, 419 in utils.py — 85+ commands total
2026-05-08 02:53:38 +00:00
everestmcarthur
622d9afdb8 fix: remove stats alias conflicting with other cogs 2026-05-07 22:59:05 +00:00
everestmcarthur
627e5a426d v3.3.0 — Phase 4: hardened command filter, anonymous mode, polls, AFK, analytics, bridging, 15+ new features
Phase 4 additions:
- Hardened 4-layer command filtering (bot prefix, common prefixes, slash commands, context validation)
- Anonymous mode (hashed usernames, default avatars)
- One-way mirror channels (receive-only)
- Network-wide polls with reaction voting and auto-expiry
- AFK system with auto-clear on message send
- Personal ignore lists (per-user DM relay blocking)
- Staff auto-responses (word + regex triggers)
- Ephemeral messages (auto-delete after configurable seconds)
- Media-only mode (only relay attachments/images)
- Network analytics dashboard (hourly activity, peak hours, top users)
- Relay health monitor (15-min background check for channel accessibility)
- Message bookmarks (saved to DM)
- Per-user vanity embed colours
- Quiet hours (DM relay pause during configurable hours)
- Inter-network bridging (one-way or two-way)
- Updated README with full command reference (70+ commands)
- 3,376 lines in wormhole.py
2026-05-07 22:53:20 +00:00
everestmcarthur
a4f5265083 v3.2.1 — Fix relay issues: robust init, webhook fallback, debug command
Fixes:
- _init() now always sets _ready event even on error (prevents
  permanent relay blockage if init fails)
- Webhook method retries with cache refresh on stale/deleted webhooks
- Falls back to embed mode if webhooks fail (permissions, etc.)
- Empty content guard (prevents 400 errors on empty messages)
- Fixed deprecated discord.Embed.Empty usage for discord.py 2.x
- Prefix check now skips empty prefixes (prevents all-message block)
- asyncio.ensure_future() instead of bot.loop.create_task()
- Better error logging with exc_info for relay failures

New:
- [p]wh debug command — shows cog state, intents, permissions,
  webhook status, connected channels, and prefix diagnostics
2026-05-07 22:39:12 +00:00
Viktor AI
56d5b11882 Fix discord.py 2.x compat: replace Embed.Empty with conditional kwargs
Embed.Empty was removed in discord.py 2.x — set_footer and set_author
now only pass icon_url when a value actually exists.
2026-05-07 22:38:02 +00:00
everestmcarthur
680b87db39 v3.2.0 — Phase 3: DM relay, starboard, karma, auto-mod, highlights, search & more
Complete ground-up rewrite (2,762 lines across 3 files):

Phase 3 features:
- Bidirectional DM relay (subscribe, send, receive, 3 formats)
- Cross-network starboard with configurable threshold
- Reputation/karma system with leaderboard
- Keyword highlight notifications (DM alerts)
- Anti-raid detection with auto-freeze
- Attachment filters (blocked extensions, max filesize)
- Pin sync across channels
- Typing indicator relay
- Network discovery (public flag + tags)
- Message search across network
- Scheduled messages (timed broadcasts)
- Network-wide slowmode
- Relay delay (configurable)
- Vanity invite codes
- Per-channel setting overrides
- Purge command (mass delete relayed)
- Audit log (500 entries, full trail)
- MOTD and rules
- Comprehensive README with full command reference

Phase 2 features (carried forward):
- Auto-moderation engine (spam, caps, invites, links, zalgo, spoiler, emote/newline spam)
- Invite system with expiry and max uses
- Staff announcements and portal messages
- Welcome messages and mention control
- User profiles and network stats
- Backup/restore (JSON export/import)
- Blackout scheduling
- Global blocklist (bot owner)
- Embed and compact relay modes

Phase 1 features (carried forward):
- Named networks with webhook relay
- Edit/delete/reply/reaction/sticker sync
- Staff system with ownership transfer
- Word and regex content filters
- Rate limiting and NSFW gate
- Server nicknames, custom identity
- Logging channel
2026-05-07 22:19:09 +00:00
everestmcarthur
6ca37b9ba1 Initial commit — Wormhole v3.0.0: advanced cross-server relay cog
Features:
- Named wormhole networks with full per-network config
- Webhook relay with custom avatar/name modes (user, server, both, custom)
- Message edit, delete, reply, reaction, thread & sticker sync
- Staff system (owner + staff) with granular permissions
- Moderation: user ban/mute, server ban/mute, allowlist
- Word & regex content filters with auto-delete
- Token-bucket rate limiting per user per network
- Per-network logging channel
- Statistics dashboard
- NSFW gating, freeze/pause, silent mode
- Custom network icon, description, accent colour
- Server nickname overrides
- Ownership transfer
- Thread support
- Embed forwarding
- Professional README, info.json, LICENSE
2026-05-07 21:53:21 +00:00