diff --git a/src/core/backup_reader.py b/src/core/backup_reader.py index 670b6b9..1fb50b4 100644 --- a/src/core/backup_reader.py +++ b/src/core/backup_reader.py @@ -701,6 +701,7 @@ class BackupReader: self._stickers: List[BackupSticker] = [] self._members: List[BackupMember] = [] self._member_map: Dict[int, BackupMember] = {} + self._thread_info: Dict[int, Dict[str, Any]] = {} # channel_id -> metadata (like name, parentID) # ── startup ────────────────────────────────────────────────────────── @@ -898,6 +899,14 @@ class BackupReader: try: data = json.loads(json_file.read_text(encoding="utf-8")) + + # Cache thread info if this is a thread + if "parentID" in data: + self._thread_info[channel_id] = { + "name": data.get("channelName", "Unknown Thread"), + "parent_id": int(data["parentID"]) + } + return data.get("messages", []) except Exception as e: logger.error(f"[Backup] Failed to load messages for channel {channel_id}: {e}") @@ -910,6 +919,16 @@ class BackupReader: # Resolve channel object channel = next((c for c in self._channels if c.id == channel_id), None) + # If not found in channels, check if it's a known thread + if not channel and channel_id in self._thread_info: + info = self._thread_info[channel_id] + # Create a stub BackupChannel for the thread + channel = BackupChannel({ + "id": str(channel_id), + "name": info["name"], + "type": "thread" + }, category_id=info["parent_id"], guild=self.guild) + return BackupMessage( msg_data, author=author, diff --git a/src/fluxer/migrate_message.py b/src/fluxer/migrate_message.py index 2847cf9..fa1d817 100644 --- a/src/fluxer/migrate_message.py +++ b/src/fluxer/migrate_message.py @@ -109,6 +109,8 @@ async def migrate_messages( "messages": 0, "threads": 0, "attachments": 0, + "first_message_url": "", + "last_message_url": "", "last_message_content": "", "last_message_author": "" } @@ -128,7 +130,8 @@ async def migrate_messages( # Skip system messages like "pinned a message", etc. # We treat thread_starter_message (type 21) as our thread marker. if msg.type == context.discord_reader.MESSAGE_TYPE_THREAD_STARTER: - content = f"> <<< THREAD: **{msg.channel.name}** >>>" + channel_name = msg.channel.name if msg.channel else "Unknown Thread" + content = f"> <<< THREAD: **{channel_name}** >>>" elif msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY]: # If we are skipping the parent, we STILL need to check for a thread! if hasattr(msg, 'thread') and msg.thread: diff --git a/src/stoat/migrate_message.py b/src/stoat/migrate_message.py index aa0dee0..2c3c734 100644 --- a/src/stoat/migrate_message.py +++ b/src/stoat/migrate_message.py @@ -136,7 +136,8 @@ async def migrate_messages( # We treat thread_starter_message (type 21) as our thread marker. content = "" # Initialize content if msg.type == context.discord_reader.MESSAGE_TYPE_THREAD_STARTER: - content = f"> <<< THREAD: **{msg.channel.name}** >>>" + channel_name = msg.channel.name if msg.channel else "Unknown Thread" + content = f"> <<< THREAD: **{channel_name}** >>>" # If it's a thread starter and we already processed the thread at the top, # we might be double-posting. But we want it as a marker. elif msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY]: