Source code for discord.ext.bridge.context

# SPDX-License-Identifier: MIT
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Union, overload

from discord.commands import ApplicationContext
from discord.interactions import Interaction, InteractionMessage
from discord.message import Message
from discord.webhook import WebhookMessage

from ..commands import Context

if TYPE_CHECKING:
    from .core import BridgeExtCommand, BridgeSlashCommand


__all__ = ("BridgeContext", "BridgeExtContext", "BridgeApplicationContext", "Context")


[docs]class BridgeContext(ABC): """ The base context class for compatibility commands. This class is an :term:`abstract base class` (also known as an ``abc``), which is subclassed by :class:`BridgeExtContext` and :class:`BridgeApplicationContext`. The methods in this class are meant to give parity between the two contexts, while still allowing for all of their functionality. When this is passed to a command, it will either be passed as :class:`BridgeExtContext`, or :class:`BridgeApplicationContext`. Since they are two separate classes, it's easy to use the :attr:`BridgeContext.is_app` attribute. to make different functionality for each context. For example, if you want to respond to a command with the command type that it was invoked with, you can do the following: .. code-block:: python3 @bot.bridge_command() async def example(ctx: BridgeContext): if ctx.is_app: command_type = "Application command" else: command_type = "Traditional (prefix-based) command" await ctx.send(f"This command was invoked with a(n) {command_type}.") .. versionadded:: 2.0 """ @abstractmethod async def _respond(self, *args, **kwargs) -> Interaction | WebhookMessage | Message: ... @abstractmethod async def _defer(self, *args, **kwargs) -> None: ... @abstractmethod async def _edit(self, *args, **kwargs) -> InteractionMessage | Message: ... @overload async def invoke( self, command: BridgeSlashCommand | BridgeExtCommand, *args, **kwargs ) -> None: ...
[docs] async def respond(self, *args, **kwargs) -> Interaction | WebhookMessage | Message: """|coro| Responds to the command with the respective response type to the current context. In :class:`BridgeExtContext`, this will be :meth:`~.Context.reply` while in :class:`BridgeApplicationContext`, this will be :meth:`~.ApplicationContext.respond`. """ return await self._respond(*args, **kwargs)
[docs] async def reply(self, *args, **kwargs) -> Interaction | WebhookMessage | Message: """|coro| Alias for :meth:`~.BridgeContext.respond`. """ return await self.respond(*args, **kwargs)
[docs] async def defer(self, *args, **kwargs) -> None: """|coro| Defers the command with the respective approach to the current context. In :class:`BridgeExtContext`, this will be :meth:`~discord.abc.Messageable.trigger_typing` while in :class:`BridgeApplicationContext`, this will be :attr:`~.ApplicationContext.defer`. .. note:: There is no ``trigger_typing`` alias for this method. ``trigger_typing`` will always provide the same functionality across contexts. """ return await self._defer(*args, **kwargs)
[docs] async def edit(self, *args, **kwargs) -> InteractionMessage | Message: """|coro| Edits the original response message with the respective approach to the current context. In :class:`BridgeExtContext`, this will have a custom approach where :meth:`.respond` caches the message to be edited here. In :class:`BridgeApplicationContext`, this will be :attr:`~.ApplicationContext.edit`. """ return await self._edit(*args, **kwargs)
def _get_super(self, attr: str) -> Any: return getattr(super(), attr) @property def is_app(self) -> bool: """Whether the context is an :class:`BridgeApplicationContext` or not.""" return isinstance(self, BridgeApplicationContext)
[docs]class BridgeApplicationContext(BridgeContext, ApplicationContext): """ The application context class for compatibility commands. This class is a subclass of :class:`BridgeContext` and :class:`~.ApplicationContext`. This class is meant to be used with :class:`BridgeCommand`. .. versionadded:: 2.0 """ def __init__(self, *args, **kwargs): # This is needed in order to represent the correct class init signature on the docs super().__init__(*args, **kwargs) async def _respond(self, *args, **kwargs) -> Interaction | WebhookMessage: return await self._get_super("respond")(*args, **kwargs) async def _defer(self, *args, **kwargs) -> None: return await self._get_super("defer")(*args, **kwargs) async def _edit(self, *args, **kwargs) -> InteractionMessage: return await self._get_super("edit")(*args, **kwargs)
[docs]class BridgeExtContext(BridgeContext, Context): """ The ext.commands context class for compatibility commands. This class is a subclass of :class:`BridgeContext` and :class:`~.Context`. This class is meant to be used with :class:`BridgeCommand`. .. versionadded:: 2.0 """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._original_response_message: Message | None = None async def _respond(self, *args, **kwargs) -> Message: kwargs.pop("ephemeral", None) message = await self._get_super("reply")(*args, **kwargs) if self._original_response_message is None: self._original_response_message = message return message async def _defer(self, *args, **kwargs) -> None: kwargs.pop("ephemeral", None) return await self._get_super("trigger_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)
[docs] async def delete( self, *, delay: float | None = None, reason: str | None = None ) -> None: """|coro| Deletes the original response message, if it exists. Parameters ---------- delay: Optional[:class:`float`] If provided, the number of seconds to wait before deleting the message. reason: Optional[:class:`str`] The reason for deleting the message. Shows up on the audit log. """ if self._original_response_message: await self._original_response_message.delete(delay=delay, reason=reason)
Context = Union[BridgeExtContext, BridgeApplicationContext] """ A Union class for either :class:`BridgeExtContext` or :class:`BridgeApplicationContext`. Can be used as a type hint for Context for bridge commands. """