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
|
|
|
"""DM relay commands — subscribe, send, configure DM relay."""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import discord
|
|
|
|
|
from redbot.core import commands
|
|
|
|
|
|
|
|
|
|
from ..models.permissions import Role, requires_role
|
|
|
|
|
from ..utils import ok_embed, err_embed, info_embed, dm_embed, truncate
|
2026-05-14 19:24:37 +00:00
|
|
|
from ._base import WormholeBase
|
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
|
|
|
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
class DMCommands(WormholeBase):
|
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
|
|
|
"""Mixin — DM relay management."""
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="enable")
|
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
|
|
|
@requires_role(Role.ADMIN)
|
|
|
|
|
async def wh_dm_enable(self, ctx: commands.Context, name: str, enabled: bool = True) -> None:
|
|
|
|
|
"""Enable or disable DM relay for a network."""
|
|
|
|
|
async with self.config.networks() as ns:
|
|
|
|
|
ns[name]["dm_enabled"] = enabled
|
|
|
|
|
await ctx.send(embed=ok_embed(f"DM relay {'enabled' if enabled else 'disabled'} for `{name}`."))
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="subscribe", aliases=["sub"])
|
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
|
|
|
async def wh_dm_sub(self, ctx: commands.Context, name: str) -> None:
|
|
|
|
|
"""Subscribe to receive network messages via DM."""
|
|
|
|
|
nd = await self._net(name)
|
|
|
|
|
if not nd:
|
|
|
|
|
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
|
|
|
|
|
if not nd.get("dm_enabled"):
|
|
|
|
|
return await ctx.send(embed=err_embed(f"DM relay isn't enabled for `{name}`."))
|
|
|
|
|
async with self.config.networks() as ns:
|
|
|
|
|
subs = ns[name].setdefault("dm_subscribers", [])
|
|
|
|
|
if ctx.author.id in subs:
|
|
|
|
|
return await ctx.send(embed=err_embed("You're already subscribed."))
|
|
|
|
|
subs.append(ctx.author.id)
|
|
|
|
|
await ctx.send(embed=ok_embed(f"Subscribed to DM relay for `{name}`."))
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="unsubscribe", aliases=["unsub"])
|
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
|
|
|
async def wh_dm_unsub(self, ctx: commands.Context, name: str) -> None:
|
|
|
|
|
"""Unsubscribe from DM relay."""
|
|
|
|
|
async with self.config.networks() as ns:
|
|
|
|
|
subs = ns[name].get("dm_subscribers", [])
|
|
|
|
|
if ctx.author.id in subs:
|
|
|
|
|
subs.remove(ctx.author.id)
|
|
|
|
|
await ctx.send(embed=ok_embed(f"Unsubscribed from DM relay for `{name}`."))
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="mode")
|
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
|
|
|
@requires_role(Role.ADMIN)
|
|
|
|
|
async def wh_dm_mode(self, ctx: commands.Context, name: str, mode: str) -> None:
|
|
|
|
|
"""Set DM relay mode: ``embed``, ``compact``, or ``plain``."""
|
|
|
|
|
if mode not in ("embed", "compact", "plain"):
|
|
|
|
|
return await ctx.send(embed=err_embed("Mode must be `embed`, `compact`, or `plain`."))
|
|
|
|
|
async with self.config.networks() as ns:
|
|
|
|
|
ns[name]["dm_relay_mode"] = mode
|
|
|
|
|
await ctx.send(embed=ok_embed(f"DM relay mode set to **{mode}** for `{name}`."))
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="send")
|
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
|
|
|
async def wh_dm_send(self, ctx: commands.Context, name: str, *, message: str) -> None:
|
|
|
|
|
"""Send a message to the network from your DMs."""
|
|
|
|
|
nd = await self._net(name)
|
|
|
|
|
if not nd:
|
|
|
|
|
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
|
|
|
|
|
if not nd.get("dm_enabled"):
|
|
|
|
|
return await ctx.send(embed=err_embed("DM relay isn't enabled for this network."))
|
|
|
|
|
if ctx.author.id in nd.get("banned_users", []):
|
|
|
|
|
return await ctx.send(embed=err_embed("You're banned from this network."))
|
|
|
|
|
if ctx.author.id in nd.get("muted_users", []):
|
|
|
|
|
return await ctx.send(embed=err_embed("You're muted in this network."))
|
|
|
|
|
|
|
|
|
|
from ..utils import build_dm_relay_embed
|
|
|
|
|
em = build_dm_relay_embed(ctx.author, message, name)
|
|
|
|
|
for ch_id in nd.get("channels", []):
|
|
|
|
|
ch = self.bot.get_channel(ch_id)
|
|
|
|
|
if ch:
|
|
|
|
|
try:
|
|
|
|
|
await ch.send(embed=em)
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
await ctx.send(embed=ok_embed("Message sent to the network."))
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="ignore")
|
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
|
|
|
async def wh_dm_ignore(self, ctx: commands.Context, name: str, user: discord.User) -> None:
|
|
|
|
|
"""Ignore a user in DM relay (you won't see their messages)."""
|
|
|
|
|
async with self.config.networks() as ns:
|
|
|
|
|
ignores = ns[name].setdefault("user_ignores", {})
|
|
|
|
|
uid_str = str(ctx.author.id)
|
|
|
|
|
user_ignores = ignores.setdefault(uid_str, [])
|
|
|
|
|
if user.id not in user_ignores:
|
|
|
|
|
user_ignores.append(user.id)
|
|
|
|
|
await ctx.send(embed=ok_embed(f"{user.display_name} ignored in DM relay for `{name}`."))
|
|
|
|
|
|
2026-05-14 19:24:37 +00:00
|
|
|
@WormholeBase.wh_dm.command(name="unignore")
|
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
|
|
|
async def wh_dm_unignore(self, ctx: commands.Context, name: str, user: discord.User) -> None:
|
|
|
|
|
"""Stop ignoring a user in DM relay."""
|
|
|
|
|
async with self.config.networks() as ns:
|
|
|
|
|
ignores = ns[name].get("user_ignores", {})
|
|
|
|
|
uid_str = str(ctx.author.id)
|
|
|
|
|
user_ignores = ignores.get(uid_str, [])
|
|
|
|
|
if user.id in user_ignores:
|
|
|
|
|
user_ignores.remove(user.id)
|
|
|
|
|
await ctx.send(embed=ok_embed(f"{user.display_name} unignored in DM relay for `{name}`."))
|