diff --git a/src/core/backup_reader.py b/src/core/backup_reader.py index 622eb40..e3af158 100644 --- a/src/core/backup_reader.py +++ b/src/core/backup_reader.py @@ -884,8 +884,8 @@ class BackupReader: self._member_map[uid] = stub return stub - def _load_channel_messages(self, channel_id: int) -> list[dict]: - """Loads the messages array from a channel JSON file.""" + def _load_channel_messages_data(self, channel_id: int) -> list[dict]: + """Loads the raw messages array from a channel JSON file.""" bp = self.backup_path / "message_backup" # Primary: message_backup/{channel_id}/messages.json @@ -957,6 +957,7 @@ class BackupReader: channel_id: int, limit: int = None, after_id: int = None, + inclusive: bool = False ) -> AsyncGenerator["BackupMessage", None]: """Yields BackupMessages from the backup, respecting after_id and limit.""" messages = self._load_channel_messages(channel_id) @@ -964,8 +965,11 @@ class BackupReader: for m in messages: msg_id = int(m["messageID"]) - if after_id and msg_id < after_id: - continue + if after_id: + if inclusive and msg_id < after_id: + continue + if not inclusive and msg_id <= after_id: + continue yield self._hydrate_message(m, channel_id) count += 1 diff --git a/src/core/discord_reader.py b/src/core/discord_reader.py index b3dd586..6b28cf3 100644 --- a/src/core/discord_reader.py +++ b/src/core/discord_reader.py @@ -213,13 +213,15 @@ class DiscordReader: return message return None - async def fetch_message_history(self, channel_id: int, limit: int = None, after_id: int = None) -> AsyncGenerator[discord.Message, None]: + async def fetch_message_history(self, channel_id: int, limit: int = None, after_id: int = None, inclusive: bool = False) -> AsyncGenerator[discord.Message, None]: """Yields messages from a given channel, optionally handling pagination.""" channel = await self.get_channel(channel_id) if isinstance(channel, discord.TextChannel) or isinstance(channel, discord.Thread): - # Discord's 'after' is exclusive. To make it inclusive, we use after_id - 1. - after = discord.Object(id=after_id - 1) if after_id else None - logger.info(f"Fetching message history for {channel.name} ({channel.id}) oldest_first=True after={after_id}") + # Discord's 'after' is exclusive. To make it inclusive, we use after_id - 1 if requested. + after = None + if after_id: + after = discord.Object(id=after_id - 1) if inclusive else discord.Object(id=after_id) + logger.info(f"Fetching message history for {channel.name} ({channel.id}) oldest_first=True after={after_id} inclusive={inclusive}") # To avoid exploding RAM, we yield items one by one async for message in channel.history(limit=limit, oldest_first=True, after=after): yield message