Skip to content
Merged
Show file tree
Hide file tree
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
71 changes: 71 additions & 0 deletions discord/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
ContainerComponent as ContainerComponentPayload,
UnfurledMediaItem as UnfurledMediaItemPayload,
LabelComponent as LabelComponentPayload,
FileUploadComponent as FileUploadComponentPayload,
)

from .emoji import Emoji
Expand Down Expand Up @@ -112,6 +113,7 @@
'TextDisplay',
'SeparatorComponent',
'LabelComponent',
'FileUploadComponent',
)


Expand All @@ -131,6 +133,8 @@ class Component:
- :class:`FileComponent`
- :class:`SeparatorComponent`
- :class:`Container`
- :class:`LabelComponent`
- :class:`FileUploadComponent`

This class is abstract and cannot be instantiated.

Expand Down Expand Up @@ -1384,6 +1388,71 @@ def to_dict(self) -> LabelComponentPayload:
return payload


class FileUploadComponent(Component):
"""Represents a file upload component from the Discord Bot UI Kit.

This inherits from :class:`Component`.

.. note::

The user constructible and usable type for creating a file upload is
:class:`discord.ui.FileUpload` not this one.

.. versionadded:: 2.7

Attributes
------------
custom_id: Optional[:class:`str`]
The ID of the component that gets received during an interaction.
min_values: :class:`int`
The minimum number of files that must be uploaded for this component.
Defaults to 1 and must be between 0 and 10.
max_values: :class:`int`
The maximum number of files that must be uploaded for this component.
Defaults to 1 and must be between 1 and 10.
id: Optional[:class:`int`]
The ID of this component.
required: :class:`bool`
Whether the component is required.
Defaults to ``True``.
"""

__slots__: Tuple[str, ...] = (
'custom_id',
'min_values',
'max_values',
'required',
'id',
)

__repr_info__: ClassVar[Tuple[str, ...]] = __slots__

def __init__(self, data: FileUploadComponentPayload, /) -> None:
self.custom_id: str = data['custom_id']
self.min_values: int = data.get('min_values', 1)
self.max_values: int = data.get('max_values', 1)
self.required: bool = data.get('required', True)
self.id: Optional[int] = data.get('id')

@property
def type(self) -> Literal[ComponentType.file_upload]:
""":class:`ComponentType`: The type of component."""
return ComponentType.file_upload

def to_dict(self) -> FileUploadComponentPayload:
payload: FileUploadComponentPayload = {
'type': self.type.value,
'custom_id': self.custom_id,
'min_values': self.min_values,
'max_values': self.max_values,
'required': self.required,
}
if self.id is not None:
payload['id'] = self.id

return payload


def _component_factory(data: ComponentPayload, state: Optional[ConnectionState] = None) -> Optional[Component]:
if data['type'] == 1:
return ActionRow(data)
Expand All @@ -1409,3 +1478,5 @@ def _component_factory(data: ComponentPayload, state: Optional[ConnectionState]
return Container(data, state)
elif data['type'] == 18:
return LabelComponent(data, state)
elif data['type'] == 19:
return FileUploadComponent(data)
1 change: 1 addition & 0 deletions discord/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ class ComponentType(Enum):
separator = 14
container = 17
label = 18
file_upload = 19

def __int__(self) -> int:
return self.value
Expand Down
3 changes: 2 additions & 1 deletion discord/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,8 @@ def parse_interaction_create(self, data: gw.InteractionCreateEvent) -> None:
inner_data = data['data']
custom_id = inner_data['custom_id']
components = inner_data['components']
self._view_store.dispatch_modal(custom_id, interaction, components)
resolved = inner_data.get('resolved', {})
self._view_store.dispatch_modal(custom_id, interaction, components, resolved)
self.dispatch('interaction', interaction)

def parse_presence_update(self, data: gw.PresenceUpdateEvent) -> None:
Expand Down
14 changes: 11 additions & 3 deletions discord/types/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from .emoji import PartialEmoji
from .channel import ChannelType

ComponentType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18]
ComponentType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 19]
ButtonStyle = Literal[1, 2, 3, 4, 5, 6]
TextStyle = Literal[1, 2]
DefaultValueType = Literal['user', 'role', 'channel']
Expand Down Expand Up @@ -192,7 +192,15 @@ class LabelComponent(ComponentBase):
type: Literal[18]
label: str
description: NotRequired[str]
component: Union[StringSelectComponent, TextInput]
component: Union[SelectMenu, TextInput, FileUploadComponent]


class FileUploadComponent(ComponentBase):
type: Literal[19]
custom_id: str
max_values: NotRequired[int]
min_values: NotRequired[int]
required: NotRequired[bool]


ActionRowChildComponent = Union[ButtonComponent, SelectMenu, TextInput]
Expand All @@ -207,4 +215,4 @@ class LabelComponent(ComponentBase):
SeparatorComponent,
ThumbnailComponent,
]
Component = Union[ActionRowChildComponent, LabelComponent, ContainerChildComponent]
Component = Union[ActionRowChildComponent, LabelComponent, FileUploadComponent, ContainerChildComponent]
29 changes: 23 additions & 6 deletions discord/types/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from .snowflake import Snowflake
from .user import User
from .guild import GuildFeature
from .components import ComponentBase

if TYPE_CHECKING:
from .message import Message
Expand Down Expand Up @@ -204,39 +205,55 @@ class SelectMessageComponentInteractionData(_BaseMessageComponentInteractionData
MessageComponentInteractionData = Union[ButtonMessageComponentInteractionData, SelectMessageComponentInteractionData]


class ModalSubmitTextInputInteractionData(TypedDict):
class ModalSubmitTextInputInteractionData(ComponentBase):
type: Literal[4]
custom_id: str
value: str


class ModalSubmitStringSelectInteractionData(TypedDict):
type: Literal[3]
class ModalSubmitSelectInteractionData(ComponentBase):
type: Literal[3, 5, 6, 7, 8]
custom_id: str
values: List[str]


class ModalSubmitFileUploadInteractionData(ComponentBase):
type: Literal[19]
custom_id: str
values: List[str]


ModalSubmitComponentItemInteractionData = Union[ModalSubmitTextInputInteractionData, ModalSubmitStringSelectInteractionData]
ModalSubmitComponentItemInteractionData = Union[
ModalSubmitSelectInteractionData, ModalSubmitTextInputInteractionData, ModalSubmitFileUploadInteractionData
]


class ModalSubmitActionRowInteractionData(TypedDict):
type: Literal[1]
components: List[ModalSubmitComponentItemInteractionData]


class ModalSubmitLabelInteractionData(TypedDict):
class ModalSubmitTextDisplayInteractionData(ComponentBase):
type: Literal[10]
content: str


class ModalSubmitLabelInteractionData(ComponentBase):
type: Literal[18]
component: ModalSubmitComponentItemInteractionData


ModalSubmitComponentInteractionData = Union[
ModalSubmitLabelInteractionData, ModalSubmitActionRowInteractionData, ModalSubmitComponentItemInteractionData
ModalSubmitActionRowInteractionData,
ModalSubmitTextDisplayInteractionData,
ModalSubmitLabelInteractionData,
]


class ModalSubmitInteractionData(TypedDict):
custom_id: str
components: List[ModalSubmitComponentInteractionData]
resolved: NotRequired[ResolvedData]


InteractionData = Union[
Expand Down
1 change: 1 addition & 0 deletions discord/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
from .thumbnail import *
from .action_row import *
from .label import *
from .file_upload import *
Loading
Loading