Skip to content

Commit 3e1c78c

Browse files
authored
feat: implement emoji helper methods (#620)
* fix!: fix EmbedImageStruct serialization * fix!: Button emoji serialization * fix!: message serialization in context * Update guild.py * Update message.py * refactor: remove leftover slots * feat: implement Emoji helper methods * feat: get for emoji * feat: helper methods for emoji * feat: reaction methods * feat: reaction methods
1 parent 576d669 commit 3e1c78c

File tree

5 files changed

+303
-6
lines changed

5 files changed

+303
-6
lines changed

interactions/api/models/guild.py

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,58 @@ async def get_bans(self) -> List[dict]:
14801480
ban["user"] = User(**ban["user"])
14811481
return res
14821482

1483+
async def get_emoji(
1484+
self,
1485+
emoji_id: int,
1486+
) -> Emoji:
1487+
"""
1488+
Gets an emoji of the guild and returns it.
1489+
1490+
:param emoji_id: The id of the emoji
1491+
:type emoji_id: int
1492+
:return: The specified Emoji, if found
1493+
:rtype: Emoji
1494+
"""
1495+
if not self._client:
1496+
raise AttributeError("HTTPClient not found!")
1497+
1498+
res = await self._client.get_guild_emoji(guild_id=int(self.id), emoji_id=emoji_id)
1499+
return Emoji(**res, _client=self._client)
1500+
1501+
async def get_all_emojis(self) -> List[Emoji]:
1502+
"""
1503+
Gets all emojis of a guild.
1504+
1505+
:return: All emojis of the guild
1506+
:rtype: List[Emoji]
1507+
"""
1508+
if not self._client:
1509+
raise AttributeError("HTTPClient not found!")
1510+
res = await self._client.get_all_emoji(guild_id=int(self.id))
1511+
return [Emoji(**emoji, _client=self._client) for emoji in res]
1512+
1513+
async def delete_emoji(
1514+
self,
1515+
emoji: Union[Emoji, int],
1516+
reason: Optional[str] = None,
1517+
) -> None:
1518+
"""
1519+
Deletes an emoji of the guild.
1520+
1521+
:param emoji: The emoji or the id of the emoji to delete
1522+
:type emoji: Union[Emoji, int]
1523+
:param reason?: The reason of the deletion
1524+
:type reason?: Optional[str]
1525+
"""
1526+
if not self._client:
1527+
raise AttributeError("HTTPClient not found!")
1528+
emoji_id = emoji.id if isinstance(emoji, Emoji) else emoji
1529+
return await self._client.delete_guild_emoji(
1530+
guild_id=int(self.id),
1531+
emoji_id=emoji_id,
1532+
reason=reason,
1533+
)
1534+
14831535

14841536
class GuildPreview(DictSerializerMixin):
14851537
"""
@@ -1626,8 +1678,8 @@ def __init__(self, **kwargs):
16261678
else None
16271679
)
16281680
self.inviter = User(**self._json.get("inviter")) if self._json.get("inviter") else None
1629-
self.channel_id = int(self.channel_id) if self._json.get("channel_id") else None
1630-
self.guild_id = int(self.guild_id) if self._json.get("guild_id") else None
1681+
self.channel_id = Snowflake(self.channel_id) if self._json.get("channel_id") else None
1682+
self.guild_id = Snowflake(self.guild_id) if self._json.get("guild_id") else None
16311683
self.target_user = (
16321684
User(**self._json.get("target_user")) if self._json.get("target_user") else None
16331685
)

interactions/api/models/guild.pyi

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,16 @@ class Guild(DictSerializerMixin):
384384
reason: Optional[str] = None,
385385
) -> List[Role]: ...
386386
async def get_bans(self) -> List[dict]: ...
387+
async def get_emoji(
388+
self,
389+
emoji_id: int
390+
) -> Emoji: ...
391+
async def get_all_emojis(self) -> List[Emoji]: ...
392+
async def delete_emoji(
393+
self,
394+
emoji: Union[Emoji, int],
395+
reason: Optional[str] = None,
396+
) -> None: ...
387397

388398
class GuildPreview(DictSerializerMixin):
389399
_json: dict
@@ -403,7 +413,7 @@ class Invite(DictSerializerMixin):
403413
_client: HTTPClient
404414
type: str
405415
guild_id: Snowflake
406-
expires_at: str
416+
expires_at: Optional[datetime]
407417
code: str
408418
channel_id: Snowflake
409419
uses: int

interactions/api/models/message.py

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,6 @@ async def reply(
470470

471471
if not components or components is MISSING:
472472
_components = []
473-
# TODO: Break this obfuscation pattern down to a "builder" method.
474473
else:
475474
_components = _build_components(components=components)
476475

@@ -552,6 +551,97 @@ async def create_thread(
552551
)
553552
return Channel(**res, _client=self._client)
554553

554+
async def create_reaction(
555+
self,
556+
emoji: Union[str, "Emoji"],
557+
) -> None:
558+
"""
559+
Adds a reaction to the message.
560+
561+
:param emoji: The Emoji as object or formatted as `name:id`
562+
:type emoji: Union[str, Emoji]
563+
"""
564+
if not self._client:
565+
raise AttributeError("HTTPClient not found!")
566+
567+
_emoji = (
568+
emoji if not isinstance(emoji, Emoji) else f":{emoji.name.replace(':', '')}:{emoji.id}"
569+
)
570+
571+
return await self._client.create_reaction(
572+
channel_id=int(self.channel_id), message_id=int(self.id), emoji=_emoji
573+
)
574+
575+
async def remove_all_reactions(self) -> None:
576+
"""
577+
Removes all reactions of the message.
578+
"""
579+
if not self._client:
580+
raise AttributeError("HTTPClient not found!")
581+
582+
return await self._client.remove_all_reactions(
583+
channel_id=int(self.channel_id), message_id=int(self.id)
584+
)
585+
586+
async def remove_all_reactions_of(
587+
self,
588+
emoji: Union[str, "Emoji"],
589+
) -> None:
590+
"""
591+
Removes all reactions of one emoji of the message.
592+
593+
:param emoji: The Emoji as object or formatted as `name:id`
594+
:type emoji: Union[str, Emoji]
595+
"""
596+
if not self._client:
597+
raise AttributeError("HTTPClient not found!")
598+
599+
_emoji = (
600+
emoji if not isinstance(emoji, Emoji) else f":{emoji.name.replace(':', '')}:{emoji.id}"
601+
)
602+
return await self._client.remove_all_reactions_of_emoji(
603+
channel_id=int(self.channel_id), message_id=int(self.id), emoji=_emoji
604+
)
605+
606+
async def remove_own_reaction_of(
607+
self,
608+
emoji: Union[str, "Emoji"],
609+
) -> None:
610+
"""
611+
Removes the own reaction of an emoji of the message.
612+
613+
:param emoji: The Emoji as object or formatted as `name:id`
614+
:type emoji: Union[str, Emoji]
615+
"""
616+
if not self._client:
617+
raise AttributeError("HTTPClient not found!")
618+
619+
_emoji = (
620+
emoji if not isinstance(emoji, Emoji) else f"{emoji.name.replace(':', '')}:{emoji.id}"
621+
)
622+
return await self._client.remove_self_reaction(
623+
channel_id=int(self.channel_id), message_id=int(self.id), emoji=_emoji
624+
)
625+
626+
async def remove_reaction_from(
627+
self, emoji: Union[str, "Emoji"], user: Union[Member, User, int]
628+
) -> None:
629+
"""
630+
Removes another reaction of an emoji of the message.
631+
632+
:param emoji: The Emoji as object or formatted as `name:id`
633+
:type emoji: Union[str, Emoji]
634+
:param user: The user or user_id to remove the reaction of
635+
:type user: Union[Member, user, int]
636+
"""
637+
_emoji = (
638+
emoji if not isinstance(emoji, Emoji) else f":{emoji.name.replace(':', '')}:{emoji.id}"
639+
)
640+
_user_id = user if isinstance(user, int) else user.id
641+
return await self._client.remove_user_reaction(
642+
channel_id=int(self.channel_id), message_id=int(self.id), user_id=_user_id, emoji=_emoji
643+
)
644+
555645
@classmethod
556646
async def get_from_url(cls, url: str, client: "HTTPClient") -> "Message": # noqa,
557647
"""
@@ -590,6 +680,7 @@ class Emoji(DictSerializerMixin):
590680
"""
591681

592682
__slots__ = (
683+
"_client",
593684
"_json",
594685
"id",
595686
"name",
@@ -605,6 +696,66 @@ def __init__(self, **kwargs):
605696
super().__init__(**kwargs)
606697
self.id = Snowflake(self.id) if self._json.get("id") else None
607698

699+
@classmethod
700+
async def get(
701+
cls,
702+
guild_id: int,
703+
emoji_id: int,
704+
client: "HTTPClient", # noqa
705+
) -> "Emoji":
706+
"""
707+
Gets an emoji.
708+
709+
:param guild_id: The id of the guild of the emoji
710+
:type guild_id: int
711+
:param emoji_id: The id of the emoji
712+
:type emoji_id: int
713+
:param client: The HTTPClient of your bot. Equals to ``bot._http``
714+
:type client: HTTPClient
715+
:return: The Emoji as object
716+
:rtype: Emoji
717+
"""
718+
res = await client.get_guild_emoji(guild_id=guild_id, emoji_id=emoji_id)
719+
return cls(**res, _client=client)
720+
721+
@classmethod
722+
async def get_all_of_guild(
723+
cls,
724+
guild_id: int,
725+
client: "HTTPClient", # noqa
726+
) -> List["Emoji"]:
727+
"""
728+
Gets all emoji of a guild.
729+
730+
:param guild_id: The id of the guild to get the emojis of
731+
:type guild_id: int
732+
:param client: The HTTPClient of your bot. Equals to ``bot._http``
733+
:type client: HTTPClient
734+
:return: The Emoji as list
735+
:rtype: List[Emoji]
736+
"""
737+
res = await client.get_all_emoji(guild_id=guild_id)
738+
return [cls(**emoji, _client=client) for emoji in res]
739+
740+
async def delete(
741+
self,
742+
guild_id: int,
743+
reason: Optional[str] = None,
744+
) -> None:
745+
"""
746+
Deletes the emoji.
747+
748+
:param guild_id: The guild id to delete the emoji from
749+
:type guild_id: int
750+
:param reason?: The reason of the deletion
751+
:type reason?: Optional[str]
752+
"""
753+
if not self._client:
754+
raise AttributeError("HTTPClient not found!")
755+
return await self._client.delete_guild_emoji(
756+
guild_id=guild_id, emoji_id=int(self.id), reason=reason
757+
)
758+
608759

609760
class ReactionObject(DictSerializerMixin):
610761
"""The reaction object.

interactions/api/models/message.pyi

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,33 @@ class Message(DictSerializerMixin):
145145
invitable: Optional[bool] = MISSING,
146146
reason: Optional[str] = None,
147147
) -> Channel: ...
148+
async def create_reaction(
149+
self,
150+
emoji: Union[str, "Emoji"],
151+
) -> None: ...
152+
async def remove_all_reactions(self) -> None: ...
153+
async def remove_all_reactions_of(
154+
self,
155+
emoji: Union[str, "Emoji"],
156+
) -> None: ...
157+
async def remove_own_reaction_of(
158+
self,
159+
emoji: Union[str, "Emoji"],
160+
) -> None: ...
161+
async def remove_reaction_from(
162+
self,
163+
emoji: Union[str, "Emoji"],
164+
user: Union[Member, User, int]
165+
) -> None: ...
148166
@classmethod
149167
async def get_from_url(
150168
cls,
151169
url: str,
152170
client: HTTPClient,
153171
) -> "Message": ...
154172

155-
156173
class Emoji(DictSerializerMixin):
174+
_client: HTTPClient
157175
_json: dict
158176
id: Optional[Snowflake]
159177
name: Optional[str]
@@ -164,6 +182,24 @@ class Emoji(DictSerializerMixin):
164182
animated: Optional[bool]
165183
available: Optional[bool]
166184
def __init__(self, **kwargs): ...
185+
@classmethod
186+
async def get(
187+
cls,
188+
guild_id: int,
189+
emoji_id: int,
190+
client: "HTTPClient", # noqa
191+
) -> "Emoji": ...
192+
@classmethod
193+
async def get_all_of_guild(
194+
cls,
195+
guild_id: int,
196+
client: "HTTPClient", # noqa
197+
) -> List["Emoji"]: ...
198+
async def delete(
199+
self,
200+
guild_id: int,
201+
reason: Optional[str] = None,
202+
) -> None: ...
167203

168204
class ReactionObject(DictSerializerMixin):
169205
_json: dict

0 commit comments

Comments
 (0)