diff --git a/CHANGELOG.md b/CHANGELOG.md index c63b835f8c..aa3910bbe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ These changes are available on the `master` branch, but have not yet been releas ### Added +- Add `typing` context manager for Bridge `Context`s. + ([#3251](https://github.com/Pycord-Development/pycord/pull/3251)) + ### Changed ### Fixed diff --git a/discord/ext/bridge/context.py b/discord/ext/bridge/context.py index 8e7f9414f6..335ff576a5 100644 --- a/discord/ext/bridge/context.py +++ b/discord/ext/bridge/context.py @@ -25,10 +25,14 @@ from __future__ import annotations +import asyncio from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Any, Union, overload +from typing_extensions import Self + from discord.commands import ApplicationContext +from discord.context_managers import Typing from discord.interactions import Interaction, InteractionMessage from discord.message import Message from discord.webhook import WebhookMessage @@ -36,10 +40,51 @@ from ..commands import Context if TYPE_CHECKING: + from types import TracebackType + from .core import BridgeExtCommand, BridgeSlashCommand -__all__ = ("BridgeContext", "BridgeExtContext", "BridgeApplicationContext", "Context") +__all__ = ( + "BridgeContext", + "BridgeExtContext", + "BridgeApplicationContext", + "Context", + "DeferTyping", +) + + +class DeferTyping: + def __init__(self, ctx: BridgeApplicationContext, ephemeral: bool) -> None: + self.loop: asyncio.AbstractEventLoop = ctx._state.loop + self.ctx = ctx + self.ephemeral = ephemeral + + async def do_defer(self) -> None: + await self.ctx.defer(ephemeral=self.ephemeral) + + def __enter__(self) -> Self: + self.task: asyncio.Task = self.loop.create_task(self.do_defer()) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + self.task.cancel() + + async def __aenter__(self) -> Self: + return self.__enter__() + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + return self.__exit__(exc_type, exc_value, traceback) class BridgeContext(ABC): @@ -74,6 +119,9 @@ async def _respond( @abstractmethod async def _defer(self, *args, **kwargs) -> None: ... + @abstractmethod + def _typing(self, *args, **kwargs) -> Typing | DeferTyping: ... + @abstractmethod async def _edit(self, *args, **kwargs) -> InteractionMessage | Message: ... @@ -111,6 +159,14 @@ async def defer(self, *args, **kwargs) -> None: """ return await self._defer(*args, **kwargs) + def typing(self, *args, **kwargs) -> Typing | DeferTyping: + """ + Returns a context manager that allows you to type for an indefinite period of time. + In :class:`BridgeExtContext`, this will be :meth:`~Context.typing` while in :class:`BridgeApplicationContext`, + this is equivalent to a defer() call and does not do any typing calls. + """ + return self._typing(*args, **kwargs) + async def edit(self, *args, **kwargs) -> InteractionMessage | Message: """|coro| @@ -147,6 +203,9 @@ async def _respond(self, *args, **kwargs) -> Interaction | WebhookMessage: async def _defer(self, *args, **kwargs) -> None: return await self._get_super("defer")(*args, **kwargs) + def _typing(self, *args, **kwargs) -> DeferTyping: + return DeferTyping(self, *args, **kwargs) + async def _edit(self, *args, **kwargs) -> InteractionMessage: return await self._get_super("edit")(*args, **kwargs) @@ -174,6 +233,10 @@ async def _defer(self, *args, **kwargs) -> None: kwargs.pop("ephemeral", None) return await self._get_super("trigger_typing")(*args, **kwargs) + def _typing(self, *args, **kwargs) -> Typing: + kwargs.pop("ephemeral", None) + return self._get_super("typing")(*args, **kwargs) + async def _edit(self, *args, **kwargs) -> Message | None: if self._original_response_message: return await self._original_response_message.edit(*args, **kwargs) diff --git a/docs/ext/bridge/api.rst b/docs/ext/bridge/api.rst index 63fe6d18c0..feb954bf60 100644 --- a/docs/ext/bridge/api.rst +++ b/docs/ext/bridge/api.rst @@ -137,7 +137,10 @@ BridgeContext .. autoclass:: discord.ext.bridge.BridgeContext :members: - :exclude-members: _respond, _defer, _edit, _get_super + :exclude-members: _respond, _defer, _typing, _edit, _get_super, typing + + .. automethod:: typing + :async-with: BridgeContext Subclasses ~~~~~~~~~~~~~~~~~~~~~~~~