implement channel linking in migrated messages

This commit is contained in:
rambros 2026-03-08 21:21:46 +05:30
parent 9a60759b7c
commit 7cf905f16f
3 changed files with 51 additions and 8 deletions

View file

@ -62,6 +62,7 @@ class DiscordReader:
self.guild: discord.Guild | None = None self.guild: discord.Guild | None = None
self.client: discord.Client | None = None self.client: discord.Client | None = None
self.role_map: Dict[int, str] = {} self.role_map: Dict[int, str] = {}
self.channel_name_map: Dict[int, str] = {}
def _create_client(self): def _create_client(self):
intents = discord.Intents.default() intents = discord.Intents.default()
@ -98,6 +99,18 @@ class DiscordReader:
logger.error(f"Failed to fetch roles: {e}") logger.error(f"Failed to fetch roles: {e}")
self.role_map = {} self.role_map = {}
# Pre-fetch channels via API
try:
channels = await self.guild.fetch_channels()
self.channel_name_map = {c.id: c.name for c in channels}
logger.debug(f"Pre-fetched {len(self.channel_name_map)} channels")
except discord.Forbidden:
logger.warning("403 Forbidden: Missing Access to fetch channels. Continuing without channel name mapping.")
self.channel_name_map = {}
except Exception as e:
logger.error(f"Failed to fetch channels: {e}")
self.channel_name_map = {}
async def validate(self) -> Dict[str, Any]: async def validate(self) -> Dict[str, Any]:
"""Validates the token, server ID, intents, and permissions.""" """Validates the token, server ID, intents, and permissions."""
results = { results = {

View file

@ -7,7 +7,7 @@ from src.core.base import MigrationContext
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def clean_mentions(content: str, guild, user_mentions=None, role_mentions=None, role_map=None, emoji_map=None) -> str: def clean_mentions(content: str, guild, user_mentions=None, role_mentions=None, role_map=None, emoji_map=None, channel_map=None, discord_channel_map=None) -> str:
if not content or not guild: if not content or not guild:
return content return content
@ -54,8 +54,19 @@ def clean_mentions(content: str, guild, user_mentions=None, role_mentions=None,
def replace_channel(match): def replace_channel(match):
cid = int(match.group(1)) cid = int(match.group(1))
# 1. Check if channel is mapped in state
if channel_map and str(cid) in channel_map:
return f"<#{channel_map[str(cid)]}>"
# 2. Fallback to name in backticks
# Try metadata map first (robust)
if discord_channel_map and cid in discord_channel_map:
return f"`#{discord_channel_map[cid]}`"
# Try cache
channel = guild.get_channel(cid) channel = guild.get_channel(cid)
return f"#{channel.name}" if channel else match.group(0) return f"`{channel.name}`" if channel else f"<#{cid}>"
def replace_emoji(match): def replace_emoji(match):
animated = match.group(1) == "a" animated = match.group(1) == "a"
@ -180,7 +191,9 @@ async def migrate_messages(
msg.mentions, msg.mentions,
msg.role_mentions, msg.role_mentions,
context.discord_reader.role_map, context.discord_reader.role_map,
context.state.emoji_map context.state.emoji_map,
context.state.channel_map,
context.discord_reader.channel_name_map
) )
# Process attachments # Process attachments
@ -209,7 +222,9 @@ async def migrate_messages(
snapshot.mentions if hasattr(snapshot, 'mentions') else None, snapshot.mentions if hasattr(snapshot, 'mentions') else None,
snapshot.role_mentions if hasattr(snapshot, 'role_mentions') else None, snapshot.role_mentions if hasattr(snapshot, 'role_mentions') else None,
context.discord_reader.role_map, context.discord_reader.role_map,
context.state.emoji_map context.state.emoji_map,
context.state.channel_map,
context.discord_reader.channel_name_map
) )
# Add snapshot attachments to the list to process # Add snapshot attachments to the list to process
attachments_to_process.extend(snapshot.attachments) attachments_to_process.extend(snapshot.attachments)

View file

@ -7,7 +7,7 @@ from src.core.base import MigrationContext
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def clean_mentions(content: str, guild, user_mentions=None, role_mentions=None, role_map=None, emoji_map=None) -> str: def clean_mentions(content: str, guild, user_mentions=None, role_mentions=None, role_map=None, emoji_map=None, channel_map=None, discord_channel_map=None) -> str:
if not content or not guild: if not content or not guild:
return content return content
@ -54,8 +54,19 @@ def clean_mentions(content: str, guild, user_mentions=None, role_mentions=None,
def replace_channel(match): def replace_channel(match):
cid = int(match.group(1)) cid = int(match.group(1))
# 1. Check if channel is mapped in state
if channel_map and str(cid) in channel_map:
return f"<#{channel_map[str(cid)]}>"
# 2. Fallback to name in backticks
# Try metadata map first (robust)
if discord_channel_map and cid in discord_channel_map:
return f"`#{discord_channel_map[cid]}`"
# Try cache
channel = guild.get_channel(cid) channel = guild.get_channel(cid)
return f"#{channel.name}" if channel else match.group(0) return f"`{channel.name}`" if channel else f"<#{cid}>"
def replace_emoji(match): def replace_emoji(match):
animated = match.group(1) == "a" animated = match.group(1) == "a"
@ -188,7 +199,9 @@ async def migrate_messages(
msg.mentions, msg.mentions,
msg.role_mentions, msg.role_mentions,
context.discord_reader.role_map, context.discord_reader.role_map,
context.state.emoji_map context.state.emoji_map,
context.state.channel_map,
context.discord_reader.channel_name_map
) )
# Process attachments # Process attachments
@ -213,7 +226,9 @@ async def migrate_messages(
snapshot.mentions if hasattr(snapshot, 'mentions') else None, snapshot.mentions if hasattr(snapshot, 'mentions') else None,
snapshot.role_mentions if hasattr(snapshot, 'role_mentions') else None, snapshot.role_mentions if hasattr(snapshot, 'role_mentions') else None,
context.discord_reader.role_map, context.discord_reader.role_map,
context.state.emoji_map context.state.emoji_map,
context.state.channel_map,
context.discord_reader.channel_name_map
) )
attachments_to_process.extend(snapshot.attachments) attachments_to_process.extend(snapshot.attachments)
logger.debug(f"Found forwarded snapshot content: {content[:50]}... and {len(snapshot.attachments)} attachments") logger.debug(f"Found forwarded snapshot content: {content[:50]}... and {len(snapshot.attachments)} attachments")