Skip to content

Commit 40b2bf6

Browse files
authored
get_component
1 parent 4ccb0c0 commit 40b2bf6

File tree

3 files changed

+96
-3
lines changed

3 files changed

+96
-3
lines changed

discord/components.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
)
4040
from .flags import AttachmentFlags
4141
from .partial_emoji import PartialEmoji, _EmojiTag
42-
from .utils import MISSING, get_slots
42+
from .utils import MISSING, get_slots, find
4343

4444
if TYPE_CHECKING:
4545
from .emoji import AppEmoji, GuildEmoji
@@ -187,6 +187,25 @@ def to_dict(self) -> ActionRowPayload:
187187
def walk_components(self) -> Iterator[Component]:
188188
yield from self.children
189189

190+
def get_component(self, id: str | int) -> Component | None:
191+
"""Get a component from this action row. Roughly equivalent to `utils.get(row.children, ...)`.
192+
If an ``int`` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
193+
194+
Parameters
195+
----------
196+
id: Union[:class:`str`, :class:`int`]
197+
The custom_id or id of the component to get.
198+
199+
Returns
200+
-------
201+
Optional[:class:`Component`]
202+
The component with the matching ``id`` or ``custom_id`` if it exists.
203+
"""
204+
if not id:
205+
return None
206+
attr = "id" if isinstance(id, int) else "custom_id"
207+
return find(lambda i: getattr(i, attr, None) == id, self.children)
208+
190209
@classmethod
191210
def with_components(cls, *components, id=None):
192211
return cls._raw_construct(
@@ -620,6 +639,28 @@ def walk_components(self) -> Iterator[Component]:
620639
yield from r + [self.accessory]
621640
yield from r
622641

642+
def get_component(self, id: str | int) -> Component | None:
643+
"""Get a component from this section. Roughly equivalent to `utils.get(section.walk_components(), ...)`.
644+
If an ``int`` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
645+
646+
Parameters
647+
----------
648+
id: Union[:class:`str`, :class:`int`]
649+
The custom_id or id of the component to get.
650+
651+
Returns
652+
-------
653+
Optional[:class:`Component`]
654+
The component with the matching ``id`` or ``custom_id`` if it exists.
655+
"""
656+
if not id:
657+
return None
658+
attr = "id" if isinstance(id, int) else "custom_id"
659+
if self.accessory and id == getattr(self.accessory, attr, None):
660+
return self.accessory
661+
component = find(lambda i: getattr(i, attr, None) == id, self.components)
662+
return component
663+
623664

624665
class TextDisplay(Component):
625666
"""Represents a Text Display from Components V2.
@@ -1036,6 +1077,32 @@ def walk_components(self) -> Iterator[Component]:
10361077
else:
10371078
yield c
10381079

1080+
def get_component(self, id: str | int) -> Component | None:
1081+
"""Get a component from this container. Roughly equivalent to `utils.get(container.components, ...)`.
1082+
If an ``int`` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
1083+
This method will also search for nested components.
1084+
1085+
Parameters
1086+
----------
1087+
id: Union[:class:`str`, :class:`int`]
1088+
The custom_id or id of the component to get.
1089+
1090+
Returns
1091+
-------
1092+
Optional[:class:`Component`]
1093+
The component with the matching ``id`` or ``custom_id`` if it exists.
1094+
"""
1095+
if not id:
1096+
return None
1097+
attr = "id" if isinstance(id, int) else "custom_id"
1098+
component = find(lambda i: getattr(i, attr, None) == id, self.components)
1099+
if not component:
1100+
for i in self.components:
1101+
if hasattr(i, "get_component"):
1102+
if component := i.get_component(id):
1103+
return component
1104+
return component
1105+
10391106

10401107
COMPONENT_MAPPINGS = {
10411108
1: ActionRow,

discord/message.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
from .reaction import Reaction
6060
from .sticker import StickerItem
6161
from .threads import Thread
62-
from .utils import MISSING, escape_mentions
62+
from .utils import MISSING, escape_mentions, find
6363

6464
if TYPE_CHECKING:
6565
from .abc import (
@@ -2211,6 +2211,32 @@ def to_message_reference_dict(
22112211

22122212
return data
22132213

2214+
def get_component(self, id: str | int) -> Component | None:
2215+
"""Gets a component from this message. Roughly equal to `utils.get(message.components, ...)`.
2216+
If an :class:`int` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
2217+
This method will also search nested components.
2218+
2219+
Parameters
2220+
----------
2221+
id: Union[:class:`str`, :class:`int`]
2222+
The id or custom_id the item to get
2223+
2224+
Returns
2225+
-------
2226+
Optional[:class:`Component`]
2227+
The component with the matching ``custom_id`` or ``id`` if it exists.
2228+
"""
2229+
if not id:
2230+
return None
2231+
attr = "id" if isinstance(id, int) else "custom_id"
2232+
component = find(lambda i: getattr(i, attr, None) == id, self.components)
2233+
if not component:
2234+
for i in self.components:
2235+
if hasattr(i, "get_component"):
2236+
if component := i.get_component(id):
2237+
return component
2238+
return component
2239+
22142240

22152241
class PartialMessage(Hashable):
22162242
"""Represents a partial message to aid with working messages when only

discord/ui/view.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ def get_item(self, custom_id: str | int) -> Item[V] | None:
434434
435435
Parameters
436436
----------
437-
custom_id: :class:`str`
437+
custom_id: Union[:class:`str`, :class:`int`]
438438
The custom_id of the item to get
439439
440440
Returns

0 commit comments

Comments
 (0)