Browse Source

Add support for application emojis

Co-authored-by: DA344 <[email protected]>
Co-authored-by: Danny <[email protected]>
pull/9932/head
Soheab 8 months ago
committed by GitHub
parent
commit
463b4bd570
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 102
      discord/client.py
  2. 49
      discord/emoji.py
  3. 57
      discord/http.py
  4. 5
      discord/types/appinfo.py

102
discord/client.py

@ -366,7 +366,13 @@ class Client:
@property @property
def emojis(self) -> Sequence[Emoji]: def emojis(self) -> Sequence[Emoji]:
"""Sequence[:class:`.Emoji`]: The emojis that the connected client has.""" """Sequence[:class:`.Emoji`]: The emojis that the connected client has.
.. note::
This not include the emojis that are owned by the application.
Use :meth:`.fetch_application_emoji` to get those.
"""
return self._connection.emojis return self._connection.emojis
@property @property
@ -3073,3 +3079,97 @@ class Client:
.. versionadded:: 2.0 .. versionadded:: 2.0
""" """
return self._connection.persistent_views return self._connection.persistent_views
async def create_application_emoji(
self,
*,
name: str,
image: bytes,
) -> Emoji:
"""|coro|
Create an emoji for the current application.
.. versionadded:: 2.5
Parameters
----------
name: :class:`str`
The emoji name. Must be at least 2 characters.
image: :class:`bytes`
The :term:`py:bytes-like object` representing the image data to use.
Only JPG, PNG and GIF images are supported.
Raises
------
MissingApplicationID
The application ID could not be found.
HTTPException
Creating the emoji failed.
Returns
-------
:class:`.Emoji`
The emoji that was created.
"""
if self.application_id is None:
raise MissingApplicationID
img = utils._bytes_to_base64_data(image)
data = await self.http.create_application_emoji(self.application_id, name, img)
return Emoji(guild=Object(0), state=self._connection, data=data)
async def fetch_application_emoji(self, emoji_id: int, /) -> Emoji:
"""|coro|
Retrieves an emoji for the current application.
.. versionadded:: 2.5
Parameters
----------
emoji_id: :class:`int`
The emoji ID to retrieve.
Raises
------
MissingApplicationID
The application ID could not be found.
HTTPException
Retrieving the emoji failed.
Returns
-------
:class:`.Emoji`
The emoji requested.
"""
if self.application_id is None:
raise MissingApplicationID
data = await self.http.get_application_emoji(self.application_id, emoji_id)
return Emoji(guild=Object(0), state=self._connection, data=data)
async def fetch_application_emojis(self) -> List[Emoji]:
"""|coro|
Retrieves all emojis for the current application.
.. versionadded:: 2.5
Raises
-------
MissingApplicationID
The application ID could not be found.
HTTPException
Retrieving the emojis failed.
Returns
-------
List[:class:`.Emoji`]
The list of emojis for the current application.
"""
if self.application_id is None:
raise MissingApplicationID
data = await self.http.get_application_emojis(self.application_id)
return [Emoji(guild=Object(0), state=self._connection, data=emoji) for emoji in data['items']]

49
discord/emoji.py

@ -29,6 +29,8 @@ from .asset import Asset, AssetMixin
from .utils import SnowflakeList, snowflake_time, MISSING from .utils import SnowflakeList, snowflake_time, MISSING
from .partial_emoji import _EmojiTag, PartialEmoji from .partial_emoji import _EmojiTag, PartialEmoji
from .user import User from .user import User
from .app_commands.errors import MissingApplicationID
from .object import Object
# fmt: off # fmt: off
__all__ = ( __all__ = (
@ -93,6 +95,10 @@ class Emoji(_EmojiTag, AssetMixin):
user: Optional[:class:`User`] user: Optional[:class:`User`]
The user that created the emoji. This can only be retrieved using :meth:`Guild.fetch_emoji` and The user that created the emoji. This can only be retrieved using :meth:`Guild.fetch_emoji` and
having :attr:`~Permissions.manage_emojis`. having :attr:`~Permissions.manage_emojis`.
Or if :meth:`.is_application_owned` is ``True``, this is the team member that uploaded
the emoji, or the bot user if it was uploaded using the API and this can
only be retrieved using :meth:`~discord.Client.fetch_application_emoji` or :meth:`~discord.Client.fetch_application_emojis`.
""" """
__slots__: Tuple[str, ...] = ( __slots__: Tuple[str, ...] = (
@ -108,7 +114,7 @@ class Emoji(_EmojiTag, AssetMixin):
'available', 'available',
) )
def __init__(self, *, guild: Guild, state: ConnectionState, data: EmojiPayload) -> None: def __init__(self, *, guild: Snowflake, state: ConnectionState, data: EmojiPayload) -> None:
self.guild_id: int = guild.id self.guild_id: int = guild.id
self._state: ConnectionState = state self._state: ConnectionState = state
self._from_data(data) self._from_data(data)
@ -196,20 +202,32 @@ class Emoji(_EmojiTag, AssetMixin):
Deletes the custom emoji. Deletes the custom emoji.
You must have :attr:`~Permissions.manage_emojis` to do this. You must have :attr:`~Permissions.manage_emojis` to do this if
:meth:`.is_application_owned` is ``False``.
Parameters Parameters
----------- -----------
reason: Optional[:class:`str`] reason: Optional[:class:`str`]
The reason for deleting this emoji. Shows up on the audit log. The reason for deleting this emoji. Shows up on the audit log.
This does not apply if :meth:`.is_application_owned` is ``True``.
Raises Raises
------- -------
Forbidden Forbidden
You are not allowed to delete emojis. You are not allowed to delete emojis.
HTTPException HTTPException
An error occurred deleting the emoji. An error occurred deleting the emoji.
MissingApplicationID
The emoji is owned by an application but the application ID is missing.
""" """
if self.is_application_owned():
application_id = self._state.application_id
if application_id is None:
raise MissingApplicationID
await self._state.http.delete_application_emoji(application_id, self.id)
return
await self._state.http.delete_custom_emoji(self.guild_id, self.id, reason=reason) await self._state.http.delete_custom_emoji(self.guild_id, self.id, reason=reason)
@ -231,15 +249,22 @@ class Emoji(_EmojiTag, AssetMixin):
The new emoji name. The new emoji name.
roles: List[:class:`~discord.abc.Snowflake`] roles: List[:class:`~discord.abc.Snowflake`]
A list of roles that can use this emoji. An empty list can be passed to make it available to everyone. A list of roles that can use this emoji. An empty list can be passed to make it available to everyone.
This does not apply if :meth:`.is_application_owned` is ``True``.
reason: Optional[:class:`str`] reason: Optional[:class:`str`]
The reason for editing this emoji. Shows up on the audit log. The reason for editing this emoji. Shows up on the audit log.
This does not apply if :meth:`.is_application_owned` is ``True``.
Raises Raises
------- -------
Forbidden Forbidden
You are not allowed to edit emojis. You are not allowed to edit emojis.
HTTPException HTTPException
An error occurred editing the emoji. An error occurred editing the emoji.
MissingApplicationID
The emoji is owned by an application but the application ID is missing
Returns Returns
-------- --------
@ -253,5 +278,25 @@ class Emoji(_EmojiTag, AssetMixin):
if roles is not MISSING: if roles is not MISSING:
payload['roles'] = [role.id for role in roles] payload['roles'] = [role.id for role in roles]
if self.is_application_owned():
application_id = self._state.application_id
if application_id is None:
raise MissingApplicationID
payload.pop('roles', None)
data = await self._state.http.edit_application_emoji(
application_id,
self.id,
payload=payload,
)
return Emoji(guild=Object(0), data=data, state=self._state)
data = await self._state.http.edit_custom_emoji(self.guild_id, self.id, payload=payload, reason=reason) data = await self._state.http.edit_custom_emoji(self.guild_id, self.id, payload=payload, reason=reason)
return Emoji(guild=self.guild, data=data, state=self._state) # type: ignore # if guild is None, the http request would have failed return Emoji(guild=self.guild, data=data, state=self._state) # type: ignore # if guild is None, the http request would have failed
def is_application_owned(self) -> bool:
""":class:`bool`: Whether the emoji is owned by an application.
.. versionadded:: 2.5
"""
return self.guild_id == 0

57
discord/http.py

@ -2515,7 +2515,7 @@ class HTTPClient:
), ),
) )
# Misc # Application
def application_info(self) -> Response[appinfo.AppInfo]: def application_info(self) -> Response[appinfo.AppInfo]:
return self.request(Route('GET', '/oauth2/applications/@me')) return self.request(Route('GET', '/oauth2/applications/@me'))
@ -2536,6 +2536,59 @@ class HTTPClient:
payload = {k: v for k, v in payload.items() if k in valid_keys} payload = {k: v for k, v in payload.items() if k in valid_keys}
return self.request(Route('PATCH', '/applications/@me'), json=payload, reason=reason) return self.request(Route('PATCH', '/applications/@me'), json=payload, reason=reason)
def get_application_emojis(self, application_id: Snowflake) -> Response[appinfo.ListAppEmojis]:
return self.request(Route('GET', '/applications/{application_id}/emojis', application_id=application_id))
def get_application_emoji(self, application_id: Snowflake, emoji_id: Snowflake) -> Response[emoji.Emoji]:
return self.request(
Route(
'GET', '/applications/{application_id}/emojis/{emoji_id}', application_id=application_id, emoji_id=emoji_id
)
)
def create_application_emoji(
self,
application_id: Snowflake,
name: str,
image: str,
) -> Response[emoji.Emoji]:
payload = {
'name': name,
'image': image,
}
return self.request(
Route('POST', '/applications/{application_id}/emojis', application_id=application_id), json=payload
)
def edit_application_emoji(
self,
application_id: Snowflake,
emoji_id: Snowflake,
*,
payload: Dict[str, Any],
) -> Response[emoji.Emoji]:
r = Route(
'PATCH', '/applications/{application_id}/emojis/{emoji_id}', application_id=application_id, emoji_id=emoji_id
)
return self.request(r, json=payload)
def delete_application_emoji(
self,
application_id: Snowflake,
emoji_id: Snowflake,
) -> Response[None]:
return self.request(
Route(
'DELETE',
'/applications/{application_id}/emojis/{emoji_id}',
application_id=application_id,
emoji_id=emoji_id,
)
)
# Poll
def get_poll_answer_voters( def get_poll_answer_voters(
self, self,
channel_id: Snowflake, channel_id: Snowflake,
@ -2573,6 +2626,8 @@ class HTTPClient:
) )
) )
# Misc
async def get_gateway(self, *, encoding: str = 'json', zlib: bool = True) -> str: async def get_gateway(self, *, encoding: str = 'json', zlib: bool = True) -> str:
try: try:
data = await self.request(Route('GET', '/gateway')) data = await self.request(Route('GET', '/gateway'))

5
discord/types/appinfo.py

@ -30,6 +30,7 @@ from typing_extensions import NotRequired
from .user import User from .user import User
from .team import Team from .team import Team
from .snowflake import Snowflake from .snowflake import Snowflake
from .emoji import Emoji
class InstallParams(TypedDict): class InstallParams(TypedDict):
@ -79,3 +80,7 @@ class PartialAppInfo(BaseAppInfo, total=False):
class GatewayAppInfo(TypedDict): class GatewayAppInfo(TypedDict):
id: Snowflake id: Snowflake
flags: int flags: int
class ListAppEmojis(TypedDict):
items: List[Emoji]

Loading…
Cancel
Save