Skip to content
This repository has been archived by the owner on Dec 26, 2022. It is now read-only.

✨ Adding message history #380

Merged
merged 6 commits into from
Jan 13, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions pincer/objects/guild/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,69 @@ async def fetch_message(self, message_id: int) -> UserMessage:
await self._http.get(f"channels/{self.id}/messages/{message_id}")
)

async def history(
self, limit: int = 50,
before: Union[int, Snowflake] = None,
after: Union[int, Snowflake] = None,
around: Union[int, Snowflake] = None,
Sigmanificient marked this conversation as resolved.
Show resolved Hide resolved
) -> AsyncIterator[UserMessage]:
"""
Sigmanificient marked this conversation as resolved.
Show resolved Hide resolved
Returns a list of messages in this channel.

Parameters
----------
around
The message ID to look around.
after
The message ID to look after.
before
The message ID to look before.
limit
The maximum number of messages to return.
Enderchief marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
AsyncIterator[:class:`~pincer.objects.message.user_message.UserMessage`]
An iterator of messages.
"""

if isinstance(before, int):
before = Snowflake(before)

if isinstance(after, int):
after = Snowflake(after)

if isinstance(around, int):
around = Snowflake(around)
Sigmanificient marked this conversation as resolved.
Show resolved Hide resolved

if limit is None:
limit = float('inf')

while limit > 0:
retrieve = min(limit, 100)
Comment on lines +811 to +812
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

limit HAS to be capped to 100. If they choose a number too big there will be rate limits and that will cause it to stall because of an "invisible error"

Copy link
Member Author

@Sigmanificient Sigmanificient Jan 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't agree, we need to provide an user-friendly way to get all messages within a channel, even if it is extremely slow.
Discord.py do it has well, see channel.history(limit=...).flatten()

Also it deal very nicely with ratelimiting.
I test it with 4000 messages, in 41.18647676300316 seconds
For 8000 messages, it took 84.87266815700423 seconds

Copy link
Member

@Lunarmagpie Lunarmagpie Jan 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point but you need to change things
There can be a lot of api calls so you should use gather. You can even use itertools.chain around gather. I bet that would be useful here.


raw_messages = await self._http.get(
f'/channels/{self.id}/messages',
params={
'limit': retrieve,
'before': before,
'after': after,
'around': around,
}
)

if not raw_messages:
break

for _message in raw_messages[:-1]:
Copy link
Member

@Lunarmagpie Lunarmagpie Jan 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry on mobile

before = raw_messages[-1].id
for message in raw_messages:
    yield UserMessage.from_dict(message)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raw_messages is not yet converted payload, so you cant access .id, i guess we can do ["id"] tho

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would be bettr

yield UserMessage.from_dict(_message)

last = UserMessage.from_dict(raw_messages[-1])
yield last

before = last.id
limit -= retrieve


class VoiceChannel(Channel):
"""A subclass of ``Channel`` for voice channels with all the same attributes."""
Expand Down