EveCogs/wormhole/models/message_map.py

55 lines
2 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
"""
In-memory bidirectional message map for tracking relayed messages.
Maps original message IDs ↔ relayed copies across channels within a network.
Capped at MAP_LIMIT entries per direction to bound memory usage.
"""
from __future__ import annotations
from collections import OrderedDict
from typing import Dict, List, Optional
from .config import MAP_LIMIT
class MessageMap:
"""Bidirectional map: original_id ↔ {channel_id: relayed_msg_id}.
``forward[net][original_id] = {ch_id: relayed_id, ...}``
``reverse[net][relayed_id] = original_id``
"""
def __init__(self) -> None:
self.forward: Dict[str, OrderedDict[int, Dict[int, int]]] = {}
self.reverse: Dict[str, OrderedDict[int, int]] = {}
def add(self, network: str, original_id: int, mapping: Dict[int, int]) -> None:
"""Record that *original_id* was relayed to *mapping* channels."""
fwd = self.forward.setdefault(network, OrderedDict())
rev = self.reverse.setdefault(network, OrderedDict())
fwd[original_id] = mapping
for relayed_id in mapping.values():
rev[relayed_id] = original_id
# Prune oldest entries
while len(fwd) > MAP_LIMIT:
_old_orig, old_map = fwd.popitem(last=False)
for rid in old_map.values():
rev.pop(rid, None)
while len(rev) > MAP_LIMIT * 2:
rev.popitem(last=False)
def get_relayed(self, network: str, original_id: int) -> Dict[int, int]:
"""Get ``{ch_id: relayed_id}`` for an original message."""
return self.forward.get(network, {}).get(original_id, {})
def get_original(self, network: str, relayed_id: int) -> Optional[int]:
"""Get the original message ID from a relayed copy ID."""
return self.reverse.get(network, {}).get(relayed_id)
def get_all_relayed_ids(self, network: str, original_id: int) -> List[int]:
"""Get all relayed message IDs for an original."""
return list(self.get_relayed(network, original_id).values())