EveCogs/wormhole/commands/advanced.py

412 lines
20 KiB
Python
Raw Normal View History

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
"""Advanced commands — polls, AFK, auto-responses, scheduled messages,
analytics, ephemeral, quiet hours, user colours, invites, announcements."""
from __future__ import annotations
import secrets
from datetime import datetime, timedelta, timezone
from typing import Optional
import discord
from redbot.core import commands
from ..models.permissions import Role, requires_role, has_role
from ..utils import (
ok_embed, err_embed, info_embed, warn_embed, announce_embed,
truncate, generate_invite_code, human_timedelta, COLOUR_INFO,
)
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
class AdvancedCommands(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 — advanced features."""
# ── Polls ──────────────────────────────────────────────────────────────
@WormholeBase.wh_poll.command(name="create")
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.MODERATOR)
async def wh_poll_create(self, ctx: commands.Context, name: str, duration_minutes: int, question: str, *, options: str) -> None:
"""Create a poll. Options separated by ``|``.
Example: ``wh poll create mynet 60 Favourite colour? Red | Blue | Green``
"""
option_list = [o.strip() for o in options.split("|") if o.strip()]
if len(option_list) < 2:
return await ctx.send(embed=err_embed("Need at least 2 options separated by `|`."))
if len(option_list) > 10:
return await ctx.send(embed=err_embed("Maximum 10 options."))
expires = (datetime.now(timezone.utc) + timedelta(minutes=duration_minutes)).isoformat()
poll_id = secrets.token_hex(4)
poll = {
"question": question,
"options": option_list,
"votes": {},
"expires": expires,
"creator": ctx.author.id,
}
async with self.config.networks() as ns:
ns[name].setdefault("active_polls", {})[poll_id] = poll
emojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"]
desc = "\n".join(f"{emojis[i]} {opt}" for i, opt in enumerate(option_list))
desc += f"\n\nVote with `wh poll vote {name} {poll_id} <number>`\nExpires in {duration_minutes} minutes."
em = discord.Embed(title=f"📊 {question}", description=desc, colour=COLOUR_INFO)
nd = await self._net(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(f"Poll `{poll_id}` created in `{name}`."))
@WormholeBase.wh_poll.command(name="vote")
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_poll_vote(self, ctx: commands.Context, name: str, poll_id: str, choice: int) -> None:
"""Vote in a poll (choice = option number, 1-based)."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
poll = nd.get("active_polls", {}).get(poll_id)
if not poll:
return await ctx.send(embed=err_embed("Poll not found or expired."))
if choice < 1 or choice > len(poll["options"]):
return await ctx.send(embed=err_embed(f"Choose 1–{len(poll['options'])}."))
idx = str(choice - 1)
uid = ctx.author.id
async with self.config.networks() as ns:
p = ns[name]["active_polls"][poll_id]
# Remove previous vote
for k, voters in p.get("votes", {}).items():
if uid in voters:
voters.remove(uid)
p.setdefault("votes", {}).setdefault(idx, []).append(uid)
await ctx.send(embed=ok_embed(f"Voted for **{poll['options'][choice-1]}**."), delete_after=5)
@WormholeBase.wh_poll.command(name="results")
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_poll_results(self, ctx: commands.Context, name: str, poll_id: str) -> None:
"""View current poll results."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
poll = nd.get("active_polls", {}).get(poll_id)
if not poll:
return await ctx.send(embed=err_embed("Poll not found."))
results = self._format_poll_results(poll)
await ctx.send(embed=info_embed(results, title=f"📊 {poll['question']}"))
@WormholeBase.wh_poll.command(name="end")
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.MODERATOR)
async def wh_poll_end(self, ctx: commands.Context, name: str, poll_id: str) -> None:
"""End a poll early."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
poll = nd.get("active_polls", {}).get(poll_id)
if not poll:
return await ctx.send(embed=err_embed("Poll not found."))
results = self._format_poll_results(poll)
async with self.config.networks() as ns:
ns[name].get("active_polls", {}).pop(poll_id, None)
for ch_id in nd.get("channels", []):
ch = self.bot.get_channel(ch_id)
if ch:
try:
await ch.send(embed=info_embed(results, title=f"📊 Poll Ended: {poll['question']}"))
except Exception:
pass
await ctx.send(embed=ok_embed("Poll ended."))
# ── AFK ────────────────────────────────────────────────────────────────
@WormholeBase.wh.command(name="afk")
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_afk(self, ctx: commands.Context, name: str, *, reason: str = "AFK") -> None:
"""Set your AFK status in a network."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
async with self.config.networks() as ns:
ns[name].setdefault("afk_users", {})[str(ctx.author.id)] = {
"reason": reason,
"since_iso": datetime.now(timezone.utc).isoformat(),
}
await ctx.send(embed=ok_embed(f"AFK set: **{reason}**"))
# ── Auto-responses ─────────────────────────────────────────────────────
@WormholeBase.wh_ar.command(name="add")
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_ar_add(self, ctx: commands.Context, name: str, trigger: str, *, reply: str) -> None:
"""Add an auto-response. Use ``regex:pattern`` for regex triggers."""
is_regex = trigger.startswith("regex:")
if is_regex:
trigger = trigger[6:]
import re
try:
re.compile(trigger)
except re.error as e:
return await ctx.send(embed=err_embed(f"Invalid regex: {e}"))
async with self.config.networks() as ns:
ns[name].setdefault("auto_responses", {})[trigger] = {
"reply": reply,
"regex": is_regex,
"cooldown": 30,
"last_used": 0,
}
await ctx.send(embed=ok_embed(f"Auto-response added for `{trigger}`."))
@WormholeBase.wh_ar.command(name="remove", aliases=["rm"])
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_ar_rm(self, ctx: commands.Context, name: str, *, trigger: str) -> None:
"""Remove an auto-response."""
async with self.config.networks() as ns:
ns[name].get("auto_responses", {}).pop(trigger, None)
await ctx.send(embed=ok_embed(f"Auto-response removed for `{trigger}`."))
@WormholeBase.wh_ar.command(name="list")
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.HELPER)
async def wh_ar_list(self, ctx: commands.Context, name: str) -> None:
"""List auto-responses."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
ars = nd.get("auto_responses", {})
if not ars:
return await ctx.send(embed=info_embed("No auto-responses configured."))
lines = []
for trigger, cfg in ars.items():
kind = "regex" if cfg.get("regex") else "text"
lines.append(f"• `{trigger}` ({kind}) → {truncate(cfg.get('reply', ''), 60)}")
await ctx.send(embed=info_embed("\n".join(lines), title=f"🤖 Auto-Responses — {name}"))
# ── Scheduled messages ─────────────────────────────────────────────────
@WormholeBase.wh_schedule.command(name="add")
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_schedule_add(self, ctx: commands.Context, name: str, minutes_from_now: int, *, content: str) -> None:
"""Schedule a message to be sent in N minutes."""
send_at = (datetime.now(timezone.utc) + timedelta(minutes=minutes_from_now)).isoformat()
async with self.config.networks() as ns:
ns[name].setdefault("scheduled_messages", []).append({
"content": content,
"send_at_iso": send_at,
"creator": ctx.author.id,
})
await ctx.send(embed=ok_embed(f"Message scheduled for {minutes_from_now} minutes from now."))
@WormholeBase.wh_schedule.command(name="list")
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.HELPER)
async def wh_schedule_list(self, ctx: commands.Context, name: str) -> None:
"""List scheduled messages."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
msgs = nd.get("scheduled_messages", [])
if not msgs:
return await ctx.send(embed=info_embed("No scheduled messages."))
lines = []
for i, sm in enumerate(msgs, 1):
lines.append(f"**{i}.** {sm.get('send_at_iso', '?')[:16]} — {truncate(sm.get('content', ''), 60)}")
await ctx.send(embed=info_embed("\n".join(lines), title=f"📅 Scheduled — {name}"))
@WormholeBase.wh_schedule.command(name="clear")
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_schedule_clear(self, ctx: commands.Context, name: str) -> None:
"""Clear all scheduled messages."""
async with self.config.networks() as ns:
ns[name]["scheduled_messages"] = []
await ctx.send(embed=ok_embed("All scheduled messages cleared."))
# ── Analytics ──────────────────────────────────────────────────────────
@WormholeBase.wh.command(name="analytics")
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.HELPER)
async def wh_analytics(self, ctx: commands.Context, name: str) -> None:
"""View network analytics dashboard."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
analytics = nd.get("analytics", {})
hourly = analytics.get("hourly", {})
top_users = analytics.get("top_users", {})
em = discord.Embed(title=f"📈 Analytics — {name}", colour=COLOUR_INFO)
em.add_field(name="Total Messages", value=f"{nd.get('total_messages', 0):,}", inline=True)
em.add_field(name="Channels", value=str(len(nd.get("channels", []))), inline=True)
# Last 24h
now = datetime.now(timezone.utc)
last_24h = sum(v for k, v in hourly.items() if k >= (now - timedelta(hours=24)).strftime("%Y-%m-%d-%H"))
last_7d = sum(hourly.values())
em.add_field(name="Last 24h", value=f"{last_24h:,}", inline=True)
em.add_field(name="Last 7d", value=f"{last_7d:,}", inline=True)
# Top users
if top_users:
sorted_users = sorted(top_users.items(), key=lambda x: x[1], reverse=True)[:5]
top_lines = []
for uid_str, count in sorted_users:
user = self.bot.get_user(int(uid_str))
top_lines.append(f"**{user or uid_str}** — {count:,}")
em.add_field(name="Top Users (all time)", value="\n".join(top_lines), inline=False)
await ctx.send(embed=em)
# ── Quiet hours ────────────────────────────────────────────────────────
@WormholeBase.wh.command(name="quiet")
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_quiet(self, ctx: commands.Context, name: str, start_hour: int, end_hour: int, tz_offset: int = 0) -> None:
"""Set quiet hours — DM relay pauses during this window.
Hours are 0-23. ``tz_offset`` is hours from UTC.
"""
if not (0 <= start_hour <= 23 and 0 <= end_hour <= 23):
return await ctx.send(embed=err_embed("Hours must be 0–23."))
async with self.config.networks() as ns:
ns[name].setdefault("quiet_hours", {})[str(ctx.author.id)] = {
"start_hour": start_hour,
"end_hour": end_hour,
"tz_offset": tz_offset,
}
await ctx.send(embed=ok_embed(f"Quiet hours set: {start_hour}:00–{end_hour}:00 (UTC{tz_offset:+d})"))
@WormholeBase.wh.command(name="unquiet")
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_unquiet(self, ctx: commands.Context, name: str) -> None:
"""Remove your quiet hours."""
async with self.config.networks() as ns:
ns[name].get("quiet_hours", {}).pop(str(ctx.author.id), None)
await ctx.send(embed=ok_embed("Quiet hours removed."))
# ── User colours ───────────────────────────────────────────────────────
@WormholeBase.wh.command(name="colour", aliases=["color"])
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_colour(self, ctx: commands.Context, name: str, hex_code: str = None) -> None:
"""Set your name colour in embed mode (hex, e.g. ``#ff5733``)."""
if hex_code:
try:
int(hex_code.lstrip("#"), 16)
except ValueError:
return await ctx.send(embed=err_embed("Invalid hex colour."))
async with self.config.networks() as ns:
if hex_code:
ns[name].setdefault("user_colours", {})[str(ctx.author.id)] = hex_code.lstrip("#")
else:
ns[name].get("user_colours", {}).pop(str(ctx.author.id), None)
await ctx.send(embed=ok_embed(f"Colour {'set' if hex_code else 'cleared'}."))
# ── Invites ────────────────────────────────────────────────────────────
@WormholeBase.wh_invite.command(name="create")
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_invite_create(self, ctx: commands.Context, name: str, max_uses: int = 0) -> None:
"""Create an invite code (``max_uses`` 0 = unlimited)."""
code = generate_invite_code()
async with self.config.networks() as ns:
ns[name].setdefault("invites", {})[code] = {
"creator": ctx.author.id,
"max_uses": max_uses,
"uses": 0,
"created_at": datetime.now(timezone.utc).isoformat(),
}
await ctx.send(embed=ok_embed(f"Invite code: `{code}`\nMax uses: {'unlimited' if max_uses == 0 else max_uses}"))
@WormholeBase.wh_invite.command(name="vanity")
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.OWNER)
async def wh_invite_vanity(self, ctx: commands.Context, name: str, code: str) -> None:
"""Set a vanity invite code."""
if len(code) < 3 or len(code) > 20:
return await ctx.send(embed=err_embed("Code must be 3–20 characters."))
async with self.config.networks() as ns:
ns[name]["vanity_invite"] = code
await ctx.send(embed=ok_embed(f"Vanity invite set: `{code}`"))
@WormholeBase.wh_invite.command(name="list")
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_invite_list(self, ctx: commands.Context, name: str) -> None:
"""List all invite codes."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
invites = nd.get("invites", {})
if not invites:
return await ctx.send(embed=info_embed("No invites."))
lines = []
for code, data in invites.items():
uses = data.get("uses", 0)
mx = data.get("max_uses", 0)
lines.append(f"`{code}` — {uses}/{mx if mx else '∞'} uses")
vanity = nd.get("vanity_invite")
if vanity:
lines.append(f"\n✨ Vanity: `{vanity}`")
await ctx.send(embed=info_embed("\n".join(lines), title=f"🔗 Invites — {name}"))
@WormholeBase.wh_invite.command(name="revoke")
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_invite_revoke(self, ctx: commands.Context, name: str, code: str) -> None:
"""Revoke an invite code."""
async with self.config.networks() as ns:
ns[name].get("invites", {}).pop(code, None)
await ctx.send(embed=ok_embed(f"Invite `{code}` revoked."))
# ── Announcements ──────────────────────────────────────────────────────
@WormholeBase.wh.command(name="announce")
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_announce(self, ctx: commands.Context, name: str, *, message: str) -> None:
"""Broadcast an announcement to all channels in the network."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
em = announce_embed(message, title=f"📢 {name} — Announcement")
sent = 0
for ch_id in nd.get("channels", []):
ch = self.bot.get_channel(ch_id)
if ch:
try:
await ch.send(embed=em)
sent += 1
except Exception:
pass
await ctx.send(embed=ok_embed(f"Announcement sent to {sent} channels."))
await self._audit(name, "announce", str(ctx.author), details=truncate(message, 100))
# ── Blackout schedules ─────────────────────────────────────────────────
@WormholeBase.wh_blackout.command(name="add")
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_blackout_add(self, ctx: commands.Context, name: str, start_hour: int, end_hour: int, *, days: str = "0,1,2,3,4,5,6") -> None:
"""Add a blackout schedule. Days: 0=Mon … 6=Sun."""
day_list = [int(d.strip()) for d in days.split(",") if d.strip().isdigit()]
async with self.config.networks() as ns:
ns[name].setdefault("blackout_schedules", []).append({
"start_hour": start_hour,
"end_hour": end_hour,
"days": day_list,
})
await ctx.send(embed=ok_embed(f"Blackout added: {start_hour}:00–{end_hour}:00 UTC on days {day_list}"))
@WormholeBase.wh_blackout.command(name="clear")
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_blackout_clear(self, ctx: commands.Context, name: str) -> None:
"""Clear all blackout schedules."""
async with self.config.networks() as ns:
ns[name]["blackout_schedules"] = []
await ctx.send(embed=ok_embed("All blackout schedules cleared."))
# ── Portal embed ───────────────────────────────────────────────────────
@WormholeBase.wh.command(name="portal")
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_portal(self, ctx: commands.Context, name: str) -> None:
"""Post a self-updating portal embed in this channel."""
nd = await self._net(name)
if not nd:
return await ctx.send(embed=err_embed(f"Network `{name}` not found."))
from ..utils import build_portal_embed
em = build_portal_embed(name, nd, len(nd.get("channels", [])), nd.get("total_messages", 0))
msg = await ctx.send(embed=em)
async with self.config.networks() as ns:
ns[name].setdefault("portal_messages", {})[str(ctx.channel.id)] = msg.id
await ctx.send(embed=ok_embed("Portal embed posted. It will auto-update every 5 minutes."), delete_after=10)