Skip to content

Commit bbeb1cb

Browse files
NeloBlivionpre-commit-ci[bot]Paillat-devLulalaby
authored
feat: add Message.get_component and related functions (#2849)
* get_component * style(pre-commit): auto fixes from pre-commit.com hooks * cl * single loop --------- Signed-off-by: UK <[email protected]> Signed-off-by: Lala Sabathil <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Paillat <[email protected]> Co-authored-by: Lala Sabathil <[email protected]>
1 parent 890153a commit bbeb1cb

File tree

4 files changed

+98
-3
lines changed

4 files changed

+98
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ These changes are available on the `master` branch, but have not yet been releas
7575
([#2883](https://github.com/Pycord-Development/pycord/pull/2883))
7676
- Added `discord.User.primary_guild` and the `PrimaryGuild` class.
7777
([#2876](https://github.com/Pycord-Development/pycord/pull/2876))
78+
- Added `get_component` to `Message`, `Section`, `Container` and `ActionRow`.
79+
([#2849](https://github.com/Pycord-Development/pycord/pull/2849))
7880

7981
### Fixed
8082

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, find, get_slots
4343

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

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

654+
def get_component(self, id: str | int) -> Component | None:
655+
"""Get a component from this section. Roughly equivalent to `utils.get(section.walk_components(), ...)`.
656+
If an ``int`` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
657+
658+
Parameters
659+
----------
660+
id: Union[:class:`str`, :class:`int`]
661+
The custom_id or id of the component to get.
662+
663+
Returns
664+
-------
665+
Optional[:class:`Component`]
666+
The component with the matching ``id`` or ``custom_id`` if it exists.
667+
"""
668+
if not id:
669+
return None
670+
attr = "id" if isinstance(id, int) else "custom_id"
671+
if self.accessory and id == getattr(self.accessory, attr, None):
672+
return self.accessory
673+
component = find(lambda i: getattr(i, attr, None) == id, self.components)
674+
return component
675+
635676

636677
class TextDisplay(Component):
637678
"""Represents a Text Display from Components V2.
@@ -1048,6 +1089,32 @@ def walk_components(self) -> Iterator[Component]:
10481089
else:
10491090
yield c
10501091

1092+
def get_component(self, id: str | int) -> Component | None:
1093+
"""Get a component from this container. Roughly equivalent to `utils.get(container.components, ...)`.
1094+
If an ``int`` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
1095+
This method will also search for nested components.
1096+
1097+
Parameters
1098+
----------
1099+
id: Union[:class:`str`, :class:`int`]
1100+
The custom_id or id of the component to get.
1101+
1102+
Returns
1103+
-------
1104+
Optional[:class:`Component`]
1105+
The component with the matching ``id`` or ``custom_id`` if it exists.
1106+
"""
1107+
if not id:
1108+
return None
1109+
attr = "id" if isinstance(id, int) else "custom_id"
1110+
for i in self.components:
1111+
if getattr(i, attr, None) == id:
1112+
return i
1113+
elif hasattr(i, "get_component"):
1114+
if component := i.get_component(id):
1115+
return component
1116+
return None
1117+
10511118

10521119
class Label(Component):
10531120
"""Represents a Label used in modals as the top-level component.

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 (
@@ -2244,6 +2244,32 @@ def to_message_reference_dict(
22442244

22452245
return data
22462246

2247+
def get_component(self, id: str | int) -> Component | None:
2248+
"""Gets a component from this message. Roughly equal to `utils.get(message.components, ...)`.
2249+
If an :class:`int` is provided, the component will be retrieved by ``id``, otherwise by ``custom_id``.
2250+
This method will also search nested components.
2251+
2252+
Parameters
2253+
----------
2254+
id: Union[:class:`str`, :class:`int`]
2255+
The id or custom_id the item to get
2256+
2257+
Returns
2258+
-------
2259+
Optional[:class:`Component`]
2260+
The component with the matching ``custom_id`` or ``id`` if it exists.
2261+
"""
2262+
if not id:
2263+
return None
2264+
attr = "id" if isinstance(id, int) else "custom_id"
2265+
for i in self.components:
2266+
if getattr(i, attr, None) == id:
2267+
return i
2268+
elif hasattr(i, "get_component"):
2269+
if component := i.get_component(id):
2270+
return component
2271+
return None
2272+
22472273

22482274
class PartialMessage(Hashable):
22492275
"""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
@@ -445,7 +445,7 @@ def get_item(self, custom_id: str | int) -> Item[V] | None:
445445
446446
Parameters
447447
----------
448-
custom_id: :class:`str`
448+
custom_id: Union[:class:`str`, :class:`int`]
449449
The custom_id of the item to get
450450
451451
Returns

0 commit comments

Comments
 (0)