diff --git a/src/core/backup_reader.py b/src/core/backup_reader.py index 71356e8..1006c34 100644 --- a/src/core/backup_reader.py +++ b/src/core/backup_reader.py @@ -221,7 +221,8 @@ class BackupMember: __slots__ = ("id", "name", "display_name", "bot", "color", "roles", "avatar", "guild_permissions", "discriminator", - "global_name", "created_at", "joined_at", "status", "activity", "system") + "global_name", "created_at", "joined_at", "status", "activity", "system", + "_avatar_url") def __init__(self, data: dict, role_objects: list | None = None, avatar_base: Path | None = None): @@ -241,6 +242,10 @@ class BackupMember: self.status = type("Status", (), {"value": "offline"})() self.activity = None + # CDN URL from Discord (saved during backup) + self._avatar_url = data.get("userAvatarUrl") + + # Local file asset (for reading bytes) avatar_rel = data.get("userAvatar") if avatar_rel and avatar_base: self.avatar = BackupAsset(avatar_base / avatar_rel) @@ -257,6 +262,11 @@ class BackupMember: @property def display_avatar(self) -> BackupAsset: + """Returns an asset with the CDN URL if available, otherwise the local file asset.""" + if self._avatar_url: + asset = BackupAsset(None) + asset.url = self._avatar_url + return asset return self.avatar def __repr__(self) -> str: diff --git a/src/disco_reaper/exporter.py b/src/disco_reaper/exporter.py index ccd39dc..da69407 100644 --- a/src/disco_reaper/exporter.py +++ b/src/disco_reaper/exporter.py @@ -523,7 +523,8 @@ class DiscordExporter: "userColor": str(author.color) if hasattr(author, "color") else None, "userIsBot": author.bot, "userRoles": roles, - "userAvatar": f"user_avatars/{user_id}.png" if author.avatar else None + "userAvatar": f"user_avatars/{user_id}.png" if author.avatar else None, + "userAvatarUrl": str(author.display_avatar.url) if author.avatar else None } reactions = [] diff --git a/src/fluxer/migrate_message.py b/src/fluxer/migrate_message.py index 25d2a6e..2847cf9 100644 --- a/src/fluxer/migrate_message.py +++ b/src/fluxer/migrate_message.py @@ -208,10 +208,14 @@ async def migrate_messages( else: logger.debug(f"Reply target Discord ID {msg.reference.message_id} not found in current session map.") + avatar_url = str(msg.author.display_avatar.url) if msg.author.display_avatar.url else None + if avatar_url and not avatar_url.startswith("http"): + avatar_url = None + fluxer_msg_id = await context.fluxer_writer.send_message( channel_id=target_channel_id, author_name=msg.author.display_name, - author_avatar_url=str(msg.author.display_avatar.url), + author_avatar_url=avatar_url, content=content, timestamp=msg.created_at.strftime("%Y-%m-%d %H:%M:%S"), files=files if files else None, diff --git a/src/stoat/migrate_message.py b/src/stoat/migrate_message.py index 2d30521..aa0dee0 100644 --- a/src/stoat/migrate_message.py +++ b/src/stoat/migrate_message.py @@ -213,10 +213,14 @@ async def migrate_messages( else: logger.debug(f"Reply target Discord ID {msg.reference.message_id} not found in current session map.") + avatar_url = str(msg.author.display_avatar.url) if msg.author.display_avatar.url else None + if avatar_url and not avatar_url.startswith("http"): + avatar_url = None + stoat_msg_id = await context.stoat_writer.send_message( channel_id=target_channel_id, author_name=msg.author.display_name, - author_avatar_url=str(msg.author.display_avatar.url), + author_avatar_url=avatar_url, content=content, timestamp=msg.created_at.strftime("%Y-%m-%d %H:%M:%S"), files=files if files else None,