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.
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
- CV2 HelpPaginatorView: Close button in its own ActionRow,
category Select in a separate ActionRow (Discord requires
selects to be alone in their row)
- Cap overview embed to 20 category fields to stay under
Discord's 25-field limit
Major rewrite of help rendering:
- Embed mode (default): Rich embeds with interactive View buttons
(⏮◀️▶️⏭) + category select dropdown + close button
- CV2 mode (when `cv2 toggle` is on): Components V2 containers
with the same navigation
- Shared data-gathering layer: both modes use the same logic to
gather commands, filter permissions, handle categories
- All Red help features: command filtering, permission checks,
aliases, subcommands, cooldowns, format_help_for_context
- Text fallback for DMs
- Help command now always tries CV2 in guilds (that's its purpose)
with text fallback only on error or in DMs
- cv2 group invoke no longer calls ctx.send_help() which relied
on Red's internal formatter — sends usage text directly
- Context.send calls Messageable.send internally, both patched —
use asyncio task ID set to prevent re-entry loop
- Text fallback for help now paginates at 1900 chars to stay
under Discord's 2000-char limit
The classic Red/discord.py pattern: bot.remove_command('help') in
__init__.py's setup() BEFORE bot.add_cog(), so the cog's own
@commands.command(name='help') decorator doesn't clash with Red's
built-in help.
Original help command stored on cog instance and restored in cog_unload.
- Removes Red's built-in help command on cog load, restores on unload
- Our help command fully replaces it (CV2 when enabled, text fallback for DMs)
- Monkey-patches both Context.send AND Messageable.send so ALL bot embeds
everywhere (channels, threads, DMs) get auto-converted to CV2 containers
- Per-cog overrides still respected for Context sends
- Clean restore of everything on cog unload
Replaces embed-based help with full Components V2 system:
- converter.py: Embed → Container conversion engine
- formatter.py: CV2 help page builder + paginator views
- newhelpmenu.py: Main cog with settings, monkey-patching, public API
- 1,747 lines across 4 files, default off