Refactor AsyncIter to use 3.6+ asynchronous generators

This commit is contained in:
Kaylynn Morgan
2022-02-20 13:58:13 +11:00
committed by GitHub
parent dc19c6c7d5
commit 588cda0996
8 changed files with 386 additions and 930 deletions

View File

@@ -23,15 +23,18 @@ DEALINGS IN THE SOFTWARE.
"""
from __future__ import annotations
from typing import Any, TYPE_CHECKING, Union, Optional
from typing import Any, TYPE_CHECKING, AsyncIterator, List, Union, Optional
from typing_extensions import reveal_type
from .iterators import ReactionIterator
from .object import Object
__all__ = (
'Reaction',
)
if TYPE_CHECKING:
from .user import User
from .member import Member
from .types.message import Reaction as ReactionPayload
from .message import Message
from .partial_emoji import PartialEmoji
@@ -155,8 +158,8 @@ class Reaction:
"""
await self.message.clear_reaction(self.emoji)
def users(self, *, limit: Optional[int] = None, after: Optional[Snowflake] = None) -> ReactionIterator:
"""Returns an :class:`AsyncIterator` representing the users that have reacted to the message.
async def users(self, *, limit: Optional[int] = None, after: Optional[Snowflake] = None) -> AsyncIterator[Union[Member, User]]:
"""Returns an :term:`asynchronous iterator` representing the users that have reacted to the message.
The ``after`` parameter must represent a member
and meet the :class:`abc.Snowflake` abc.
@@ -176,7 +179,7 @@ class Reaction:
Flattening into a list: ::
users = await reaction.users().flatten()
users = [user async for user in reaction.users()]
# users is now a list of User...
winner = random.choice(users)
await channel.send(f'{winner} has won the raffle.')
@@ -212,4 +215,31 @@ class Reaction:
if limit is None:
limit = self.count
return ReactionIterator(self.message, emoji, limit, after)
while limit > 0:
retrieve = min(limit, 100)
message = self.message
guild = message.guild
state = message._state
after_id = after.id if after else None
data = await state.http.get_reaction_users(
message.channel.id, message.id, emoji, retrieve, after=after_id
)
if data:
limit -= len(data)
after = Object(id=int(data[-1]['id']))
if guild is None or isinstance(guild, Object):
for raw_user in reversed(data):
yield User(state=state, data=raw_user)
continue
for raw_user in reversed(data):
member_id = int(raw_user['id'])
member = guild.get_member(member_id)
yield member or User(state=state, data=raw_user)