Add support for components V2

Co-authored-by: Michael H <michael@michaelhall.tech>
Co-authored-by: Soheab <33902984+Soheab@users.noreply.github.com>
Co-authored-by: owocado <24418520+owocado@users.noreply.github.com>
Co-authored-by: Jay3332 <40323796+jay3332@users.noreply.github.com>
Co-authored-by: Danny <1695103+Rapptz@users.noreply.github.com>
This commit is contained in:
DA344
2025-08-14 02:37:23 +02:00
committed by GitHub
parent 6ec2e5329b
commit 50caa3c82c
33 changed files with 4214 additions and 298 deletions

View File

@ -24,12 +24,13 @@ DEALINGS IN THE SOFTWARE.
from __future__ import annotations
from typing import Callable, Literal, Optional, TYPE_CHECKING, Tuple, TypeVar, Union
import copy
from typing import Any, Callable, Coroutine, Literal, Optional, TYPE_CHECKING, Tuple, TypeVar, Union
import inspect
import os
from .item import Item, ItemCallbackType
from .item import Item, I
from ..enums import ButtonStyle, ComponentType
from ..partial_emoji import PartialEmoji, _EmojiTag
from ..components import Button as ButtonComponent
@ -42,11 +43,16 @@ __all__ = (
if TYPE_CHECKING:
from typing_extensions import Self
from .view import View
from .view import BaseView
from .action_row import ActionRow
from ..emoji import Emoji
from ..interactions import Interaction
from ..types.components import ButtonComponent as ButtonComponentPayload
V = TypeVar('V', bound='View', covariant=True)
ItemCallbackType = Callable[['S', Interaction[Any], I], Coroutine[Any, Any, Any]]
S = TypeVar('S', bound='Union[BaseView, ActionRow]', covariant=True)
V = TypeVar('V', bound='BaseView', covariant=True)
class Button(Item[V]):
@ -77,11 +83,19 @@ class Button(Item[V]):
like to control the relative positioning of the row then passing an index is advised.
For example, row=1 will show up before row=2. Defaults to ``None``, which is automatic
ordering. The row number must be between 0 and 4 (i.e. zero indexed).
.. note::
This parameter is ignored when used in a :class:`ActionRow` or v2 component.
sku_id: Optional[:class:`int`]
The SKU ID this button sends you to. Can't be combined with ``url``, ``label``, ``emoji``
nor ``custom_id``.
.. versionadded:: 2.4
id: Optional[:class:`int`]
The ID of this component. This must be unique across the view.
.. versionadded:: 2.6
"""
__item_repr_attributes__: Tuple[str, ...] = (
@ -92,6 +106,7 @@ class Button(Item[V]):
'emoji',
'row',
'sku_id',
'id',
)
def __init__(
@ -105,6 +120,7 @@ class Button(Item[V]):
emoji: Optional[Union[str, Emoji, PartialEmoji]] = None,
row: Optional[int] = None,
sku_id: Optional[int] = None,
id: Optional[int] = None,
):
super().__init__()
if custom_id is not None and (url is not None or sku_id is not None):
@ -143,9 +159,19 @@ class Button(Item[V]):
style=style,
emoji=emoji,
sku_id=sku_id,
id=id,
)
self.row = row
@property
def id(self) -> Optional[int]:
"""Optional[:class:`int`]: The ID of this button."""
return self._underlying.id
@id.setter
def id(self, value: Optional[int]) -> None:
self._underlying.id = value
@property
def style(self) -> ButtonStyle:
""":class:`discord.ButtonStyle`: The style of the button."""
@ -242,6 +268,7 @@ class Button(Item[V]):
emoji=button.emoji,
row=None,
sku_id=button.sku_id,
id=button.id,
)
@property
@ -262,6 +289,28 @@ class Button(Item[V]):
def _refresh_component(self, button: ButtonComponent) -> None:
self._underlying = button
def copy(self) -> Self:
new = copy.copy(self)
custom_id = self.custom_id
if self.custom_id is not None and not self._provided_custom_id:
custom_id = os.urandom(16).hex()
new._underlying = ButtonComponent._raw_construct(
custom_id=custom_id,
url=self.url,
disabled=self.disabled,
label=self.label,
style=self.style,
emoji=self.emoji,
sku_id=self.sku_id,
id=self.id,
)
return new
def __deepcopy__(self, memo) -> Self:
return self.copy()
def button(
*,
@ -271,7 +320,8 @@ def button(
style: ButtonStyle = ButtonStyle.secondary,
emoji: Optional[Union[str, Emoji, PartialEmoji]] = None,
row: Optional[int] = None,
) -> Callable[[ItemCallbackType[V, Button[V]]], Button[V]]:
id: Optional[int] = None,
) -> Callable[[ItemCallbackType[S, Button[V]]], Button[V]]:
"""A decorator that attaches a button to a component.
The function being decorated should have three parameters, ``self`` representing
@ -308,9 +358,17 @@ def button(
like to control the relative positioning of the row then passing an index is advised.
For example, row=1 will show up before row=2. Defaults to ``None``, which is automatic
ordering. The row number must be between 0 and 4 (i.e. zero indexed).
.. note::
This parameter is ignored when used in a :class:`ActionRow` or v2 component.
id: Optional[:class:`int`]
The ID of this component. This must be unique across the view.
.. versionadded:: 2.6
"""
def decorator(func: ItemCallbackType[V, Button[V]]) -> ItemCallbackType[V, Button[V]]:
def decorator(func: ItemCallbackType[S, Button[V]]) -> ItemCallbackType[S, Button[V]]:
if not inspect.iscoroutinefunction(func):
raise TypeError('button function must be a coroutine function')
@ -324,6 +382,7 @@ def button(
'emoji': emoji,
'row': row,
'sku_id': None,
'id': id,
}
return func