Source code for disnake.ext.components.impl.component.button

"""Default implementation of button-based components."""

from __future__ import annotations

import typing

import disnake
from disnake.ext.components import fields, interaction
from disnake.ext.components.api import component as component_api
from disnake.ext.components.impl import custom_id as custom_id_impl
from disnake.ext.components.impl.component import base as component_base

if typing.TYPE_CHECKING:
    import typing_extensions

__all__: typing.Sequence[str] = ("RichButton",)


_AnyEmoji = typing.Union[str, disnake.PartialEmoji, disnake.Emoji]


[docs]@typing.runtime_checkable class RichButton( component_api.RichButton, component_base.ComponentBase, typing.Protocol ): """The default implementation of a disnake-ext-components button. This works similar to a dataclass, but with some extra things to take into account. First and foremost, there are class variables for :attr:`label`, :attr:`style`, :attr:`emoji` and :attr:`disabled`. These set the corresponding attributes on the button class when they are sent to discord, and are meant to be overwritten by the user. Next, fields can be defined similarly to dataclasses, by means of a name, a type annotation, and an optional :func:`components.field` to set the default or a custom parser. Classes created in this way have auto-generated slots and an auto-generated ``__init__``. The init-signature contains all the custom id fields as keyword-only arguments. """ event = "on_button_click" custom_id = custom_id_impl.AutoID() label: typing.Optional[str] = fields.internal(None) style: disnake.ButtonStyle = fields.internal(disnake.ButtonStyle.secondary) emoji: typing.Optional[_AnyEmoji] = fields.internal(None) disabled: bool = fields.internal(False) # noqa: FBT003
[docs] async def as_ui_component(self) -> disnake.ui.Button[None]: # noqa: D102 # <<docstring inherited from component_api.RichButton>> return disnake.ui.Button( style=self.style, label=self.label, disabled=self.disabled, emoji=self.emoji, custom_id=await self.dumps(), )
[docs] @classmethod async def loads( # noqa: D102 cls, interaction: disnake.MessageInteraction, / ) -> typing_extensions.Self: # <<Docstring inherited from component_api.RichComponent>> # TODO: Maybe copy over internal attributes from the inter.component. # TODO: Error handling around match for more sensible errors. custom_id = typing.cast(str, interaction.component.custom_id) component_custom_id = typing.cast(custom_id_impl.CustomID, cls.custom_id) match = component_custom_id.match(custom_id, strict=True) return await cls.factory.loads(interaction, match.groupdict())
[docs] async def callback( # pyright: ignore[reportIncompatibleMethodOverride] # noqa: D102, E501 self, __inter: interaction.MessageInteraction, ) -> None: # <<docstring inherited from component_api.RichButton>> # NOTE: We narrow the interaction type down to a disnake.MessageInteraction # here. This isn't typesafe, but it's just cleaner for the user. ...