Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix timeout for ephemeral paginators and hybrid commands #1751

Open
wants to merge 2 commits into
base: unstable
Choose a base branch
from
Open
Changes from all commits
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
23 changes: 20 additions & 3 deletions interactions/ext/paginators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import textwrap
import uuid
from functools import partial
from typing import Callable, Coroutine, List, Optional, Sequence, TYPE_CHECKING, Union

import attrs
Expand Down Expand Up @@ -38,6 +39,8 @@ class Timeout:
repr=False,
)
"""The paginator that this timeout is associated with."""
edit: Callable[..., Coroutine] = attrs.field(repr=False, default=None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason to pass edit to Timeout instead of, say, ctx? At least that way you can forgo the if-else chain added in send() below to determine the right edit() by just using ctx.edit() regardless of command type, as have been done by the _on_button() callback. (Alternatively, add ctx to Paginator attributes instead of Timeout, then use self.paginator.ctx.edit().)

Copy link
Author

Choose a reason for hiding this comment

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

@mifuyutsuki HybridContext requires message. Storing ctx was the first thing I tried, but when testing, HybridContext types would error out since the message param was missing.

"""A coroutine that edits the current paginator message."""
run: bool = attrs.field(repr=False, default=True)
"""Whether or not this timeout is currently running."""
ping: asyncio.Event = asyncio.Event()
Expand All @@ -49,7 +52,7 @@ async def __call__(self) -> None:
await asyncio.wait_for(self.ping.wait(), timeout=self.paginator.timeout_interval)
except asyncio.TimeoutError:
if self.paginator.message:
await self.paginator.message.edit(components=self.paginator.create_components(True))
await self.edit(components=self.paginator.create_components(True))
return
else:
self.ping.clear()
Expand Down Expand Up @@ -378,8 +381,15 @@ async def send(self, ctx: BaseContext, **kwargs) -> Message:
self._message = await ctx.send(**self.to_dict(), **kwargs)
self._author_id = ctx.author.id

if hasattr(ctx, "token"): # SlashContext
edit = ctx.edit
elif hasattr(ctx, "_prefixed_ctx"): # HybridContext
edit = partial(ctx.edit, message=self._message)
else: # PrefixedContext
edit = self._message.edit

if self.timeout_interval > 1:
self._timeout_task = Timeout(self)
self._timeout_task = Timeout(self, edit)
_ = asyncio.create_task(self._timeout_task()) # noqa: RUF006

return self._message
Expand All @@ -399,8 +409,15 @@ async def reply(self, ctx: "PrefixedContext", **kwargs) -> Message:
self._message = await ctx.reply(**self.to_dict(), **kwargs)
self._author_id = ctx.author.id

if hasattr(ctx, "token"): # SlashContext
edit = ctx.edit
elif hasattr(ctx, "_prefixed_ctx"): # HybridContext
edit = partial(ctx.edit, message=self._message)
else: # PrefixedContext
edit = self._message.edit

if self.timeout_interval > 1:
self._timeout_task = Timeout(self)
self._timeout_task = Timeout(self, edit)
_ = asyncio.create_task(self._timeout_task()) # noqa: RUF006

return self._message
Expand Down