stuff
253 removals
526 lines
122 additions
404 lines
diff --git a/discord/client.py b/discord/client.py
diff --git a/disnake/client.py b/disnake/client.py
--- a/discord/client.py
--- a/disnake/client.py
+++ b/discord/client.py
+++ b/disnake/client.py
-from .emoji import Emoji
-from .emoji import Emoji
+from .emoji import AppEmoji, GuildEmoji
+from .emoji import ApplicationEmoji, GuildEmoji
+ cache_app_emojis: :class:`bool`
+ cache_app_emojis: bool = False,
+ Whether to automatically fetch and cache the application's emojis on startup and when fetching. Defaults to ``False``.
+ cache_app_emojis=cache_app_emojis,
+
+ cache_app_emojis: bool,
+ .. warning::
+ cache_app_emojis=cache_app_emojis,
+
- def emojis(self) -> List[Emoji]:
+ There are no events related to application emojis - if any are created/deleted on the
- """List[:class:`.Emoji`]: The emojis that the connected client has."""
+ Developer Dashboard while the client is running, the cache will not be updated until you manually
+ def emojis(self) -> List[Union[GuildEmoji, ApplicationEmoji]]:
+ run :func:`fetch_emojis`.
+
+ .. versionadded:: 2.7
- def emojis(self) -> list[Emoji]:
- """The emojis that the connected client has."""
+ def emojis(self) -> list[GuildEmoji | AppEmoji]:
+ """The emojis that the connected client has.
+ """The emojis that the connected client has.
+
+
+ .. note::
+ .. note::
+
+ This only includes the application's emojis if :attr:`~Client.cache_app_emojis` is
+ This only includes the application's emojis if :attr:`~Client.cache_app_emojis` is ``True``.
+ ``True``.
+ """
+ """
- def get_emoji(self, id: int, /) -> Emoji | None:
- def get_emoji(self, id: int, /) -> Optional[Emoji]:
+ def get_emoji(self, id: int, /) -> GuildEmoji | AppEmoji | None:
+ def get_emoji(self, id: int, /) -> Optional[Union[GuildEmoji, ApplicationEmoji]]:
- Optional[:class:`.Emoji`]
+ Optional[:class:`.GuildEmoji` | :class:`.AppEmoji`]
+
+
+ async def fetch_emojis(self) -> list[AppEmoji]:
+ async def fetch_application_emojis(self) -> list[ApplicationEmoji]:
+ r"""|coro|
+ r"""|coro|
+
+ Retrieves all custom :class:`ApplicationEmoji`\s from the application.
+ Retrieves all custom :class:`AppEmoji`\s from the application.
+
+
+ Raises
+ Raises
+ ---------
+ ------
+ HTTPException
+ HTTPException
+ An error occurred fetching the emojis.
+ An error occurred fetching the emojis.
+
+
+ Returns
+ Returns
+ --------
+ -------
+ List[:class:`AppEmoji`]
+ List[:class:`ApplicationEmoji`]
+ The retrieved emojis.
+ The retrieved emojis.
+ """
+ """
+ data = await self._state.http.get_all_application_emojis(self.application_id)
+ data = await self._connection.http.get_all_application_emojis(self.application_id)
+ return [
+ return [
+ self._state.maybe_store_app_emoji(self.application_id, d)
+ self._connection.store_application_emoji(self.application_id, d) for d in data["items"]
+ for d in data["items"]
+ ]
+ ]
+
+
+ async def fetch_emoji(self, emoji_id: int, /) -> AppEmoji:
+ async def fetch_application_emoji(self, emoji_id: int, /) -> ApplicationEmoji:
+ """|coro|
+ """|coro|
+
+ Retrieves a custom :class:`ApplicationEmoji` from the application.
+ Retrieves a custom :class:`AppEmoji` from the application.
+
+
+ Parameters
+ Parameters
+ ----------
+ ----------
+ emoji_id: :class:`int`
+ emoji_id: :class:`int`
+ The emoji's ID.
+ The emoji's ID.
+
+
+ Returns
+ Returns
+ -------
+ -------
+ :class:`AppEmoji`
+ :class:`ApplicationEmoji`
+ The retrieved emoji.
+ The retrieved emoji.
+
+
+ Raises
+ Raises
+ ------
+ ------
+ NotFound
+ NotFound
+ The emoji requested could not be found.
+ The emoji requested could not be found.
+ HTTPException
+ HTTPException
+ An error occurred fetching the emoji.
+ An error occurred fetching the emoji.
+ """
+ """
+ data = await self._state.http.get_application_emoji(
+ data = await self._connection.http.get_application_emoji(self.application_id, emoji_id)
+ self.application_id, emoji_id
+ return self._connection.store_application_emoji(self.application_id, data)
+ )
+ return self._state.maybe_store_app_emoji(self.application_id, data)
+
+
+ async def create_emoji(
+ async def create_application_emoji(
+ self,
+ self,
+ *,
+ *,
+ name: str,
+ name: str,
+ image: bytes,
+ image: bytes,
+ ) -> AppEmoji:
+ ) -> ApplicationEmoji:
+ r"""|coro|
+ r"""|coro|
+
+ Creates a custom :class:`ApplicationEmoji` for the application.
+ Creates a custom :class:`AppEmoji` for the application.
+
+ There is currently a limit of 2000 emojis per application.
+ There is currently a limit of 2000 emojis per application.
+
+
+ Parameters
+ Parameters
+ -----------
+ ----------
+ name: :class:`str`
+ name: :class:`str`
+ The emoji name. Must be at least 2 characters.
+ The emoji name. Must be at least 2 characters.
+ image: :class:`bytes`
+ image: :class:`bytes`
+ The :term:`py:bytes-like object` representing the image data to use.
+ The :term:`py:bytes-like object` representing the image data to use.
+ Only JPG, PNG and GIF images are supported.
+ Only JPG, PNG and GIF images are supported.
+
+
+ Raises
+ Raises
+ -------
+ ------
+ Forbidden
+ Forbidden
+ You are not allowed to create emojis.
+ You are not allowed to create emojis.
+ HTTPException
+ HTTPException
+ An error occurred creating an emoji.
+ An error occurred creating an emoji.
+
+
+ Returns
+ Returns
+ --------
+ -------
+ :class:`AppEmoji`
+ :class:`ApplicationEmoji`
+ The created emoji.
+ The created emoji.
+ """
+ """
+
+ img = utils._bytes_to_base64_data(image)
+ img = utils._bytes_to_base64_data(image)
+ data = await self._state.http.create_application_emoji(
+ data = await self._connection.http.create_application_emoji(self.application_id, name, img)
+ self.application_id, name, img
+ return self._connection.store_application_emoji(self.application_id, data)
+ )
diff --git a/disnake/emoji.py b/disnake/emoji.py
+ return self._state.maybe_store_app_emoji(self.application_id, data)
--- a/disnake/emoji.py
+
+++ b/disnake/emoji.py
+ async def delete_emoji(
-from typing import TYPE_CHECKING, Any, Iterator, List, Optional, Tuple, Union
+ self, emoji: Snowflake, *, reason: str | None = None
+from typing import TYPE_CHECKING, Any, Iterator, List, Optional, Tuple
+ ) -> None:
+ """|coro|
+
+ Deletes the custom :class:`AppEmoji` from the application.
+
+ Parameters
+ ----------
+ emoji: :class:`abc.Snowflake`
+ The emoji you are deleting.
+
+ Raises
+ ------
+ HTTPException
+ An error occurred deleting the emoji.
+ """
+
+ await self._state.http.delete_application_emoji(self.application_id, emoji.id)
+ if self._state.cache_app_emojis and self._state.get_emoji(emoji.id):
+ self._state.remove_emoji(emoji)
diff --git a/discord/emoji.py b/discord/emoji.py
--- a/discord/emoji.py
+++ b/discord/emoji.py
-__all__ = ("Emoji",)
-__all__ = ("Emoji",)
+__all__ = (
+__all__ = ("Emoji", "GuildEmoji", "ApplicationEmoji")
+ "Emoji",
- from .guild_preview import GuildPreview
+ "GuildEmoji",
+ "AppEmoji",
+)
-class Emoji(_EmojiTag, AssetMixin):
-class Emoji(_EmojiTag, AssetMixin):
- """Represents a custom emoji.
-
- Depending on the way this object was created, some attributes can
- have a value of ``None``.
-
- .. container:: operations
-
- .. describe:: x == y
-
- Checks if two emoji are the same.
-
- .. describe:: x != y
-
- Checks if two emoji are not the same.
-
- .. describe:: hash(x)
-
- Return the emoji's hash.
-
- .. describe:: iter(x)
-
- Returns an iterator of ``(field, value)`` pairs. This allows this class
- to be used as an iterable in list/dict/etc constructions.
-
- .. describe:: str(x)
-
- Returns the emoji rendered for discord.
-
- Attributes
- ----------
- name: :class:`str`
- The name of the emoji.
- id: :class:`int`
- The emoji's ID.
- require_colons: :class:`bool`
- If colons are required to use this emoji in the client (:PJSalt: vs PJSalt).
- animated: :class:`bool`
- Whether an emoji is animated or not.
- managed: :class:`bool`
- If this emoji is managed by a Twitch integration.
- guild_id: :class:`int`
- The guild ID the emoji belongs to.
- available: :class:`bool`
- Whether the emoji is available for use.
- user: Optional[:class:`User`]
- The user that created the emoji. This can only be retrieved using :meth:`Guild.fetch_emoji` and
- having the :attr:`~Permissions.manage_emojis` permission.
- """
+class BaseEmoji(_EmojiTag, AssetMixin):
+class BaseEmoji(_EmojiTag, AssetMixin):
+ "application_id",
+ "application_id",
- def __init__(self, *, guild: Guild, state: ConnectionState, data: EmojiPayload):
- def __init__(
- self, *, guild: Union[Guild, GuildPreview], state: ConnectionState, data: EmojiPayload
- ) -> None:
- self.guild_id: int = guild.id
- self.guild_id: int = guild.id
+ def __init__(self, *, state: ConnectionState, data: EmojiPayload):
+ def __init__(self, *, state: ConnectionState, data: EmojiPayload) -> None:
- "<Emoji"
- return f"<Emoji id={self.id} name={self.name!r} animated={self.animated} managed={self.managed}>"
- f" id={self.id} name={self.name!r} animated={self.animated} managed={self.managed}>"
+ return f"<BaseEmoji id={self.id} name={self.name!r} animated={self.animated}>"
+ "<BaseEmoji" f" id={self.id} name={self.name!r} animated={self.animated}>"
+
+
+class GuildEmoji(BaseEmoji):
+class GuildEmoji(BaseEmoji):
+ """Represents a custom emoji in a guild.
+ """Represents a custom emoji in a guild.
+
+
+ Depending on the way this object was created, some attributes can
+ Depending on the way this object was created, some of the attributes can
+ have a value of ``None``.
+ have a value of ``None``.
+
+
+ .. container:: operations
+ .. collapse:: operations
+
+
+ .. describe:: x == y
+ .. describe:: x == y
+
+
+ Checks if two emoji are the same.
+ Checks if two emoji are the same.
+
+
+ .. describe:: x != y
+ .. describe:: x != y
+
+
+ Checks if two emoji are not the same.
+ Checks if two emoji are not the same.
+
+
+ .. describe:: hash(x)
+ .. describe:: hash(x)
+
+
+ Return the emoji's hash.
+ Return the emoji's hash.
+
+
+ .. describe:: iter(x)
+ .. describe:: iter(x)
+
+
+ Returns an iterator of ``(field, value)`` pairs. This allows this class
+ Returns an iterator of ``(field, value)`` pairs. This allows this class
+ to be used as an iterable in list/dict/etc constructions.
+ to be used as an iterable in list/dict/etc constructions.
+
+
+ .. describe:: str(x)
+ .. describe:: str(x)
+
+
+ Returns the emoji rendered for discord.
+ Returns the emoji rendered for Discord.
+
+
+ Attributes
+ Attributes
+ ----------
+ ----------
+ name: :class:`str`
+ name: :class:`str`
+ The name of the emoji.
+ The emoji's name.
+ id: :class:`int`
+ id: :class:`int`
+ The emoji's ID.
+ The emoji's ID.
+ require_colons: :class:`bool`
+ require_colons: :class:`bool`
+ If colons are required to use this emoji in the client (:PJSalt: vs PJSalt).
+ Whether colons are required to use this emoji in the client (:PJSalt: vs PJSalt).
+ animated: :class:`bool`
+ animated: :class:`bool`
+ Whether an emoji is animated or not.
+ Whether the emoji is animated or not.
+ managed: :class:`bool`
+ managed: :class:`bool`
+ If this emoji is managed by a Twitch integration.
+ Whether the emoji is managed by a Twitch integration.
+ guild_id: :class:`int`
+ guild_id: :class:`int`
+ The guild ID the emoji belongs to.
+ The guild ID the emoji belongs to.
+ available: :class:`bool`
+ available: :class:`bool`
+ Whether the emoji is available for use.
+ Whether the emoji is available for use.
+ 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 this emoji. This can only be retrieved using
+ having the :attr:`~Permissions.manage_emojis` permission.
+ :meth:`Guild.fetch_emoji`/:meth:`Guild.fetch_emojis` while
+ having the :attr:`~Permissions.manage_guild_expressions` permission.
+ """
+ """
+
+
+ def __init__(self, *, guild: Guild, state: ConnectionState, data: EmojiPayload):
+ def __init__(self, *, guild: Guild, state: ConnectionState, data: EmojiPayload):
+ self.guild_id: int = guild.id
+ self.guild_id: int = guild.id
+ super().__init__(state, data)
+ super().__init__(state=state, data=data)
+
+
+ def __repr__(self) -> str:
+ def __repr__(self) -> str:
+ return (
+ return f"<GuildEmoji id={self.id} name={self.name!r} animated={self.animated} managed={self.managed}>"
+ "<GuildEmoji"
+ f" id={self.id} name={self.name!r} animated={self.animated} managed={self.managed}>"
+ )
+
+
- ) -> Emoji:
- ) -> Emoji:
+ ) -> GuildEmoji:
+ ) -> GuildEmoji:
- :class:`Emoji`
- :class:`Emoji`
+ :class:`GuildEmoji`
+ :class:`GuildEmoji`
- return Emoji(guild=self.guild, data=data, state=self._state)
- return Emoji(guild=self.guild, data=data, state=self._state)
+ return GuildEmoji(guild=self.guild, data=data, state=self._state)
+ return GuildEmoji(guild=self.guild, data=data, state=self._state)
+
+
+
+
+Emoji = GuildEmoji
+Emoji = GuildEmoji
+
+
+
+
+class AppEmoji(BaseEmoji):
+class ApplicationEmoji(BaseEmoji):
+ """Represents a custom emoji from an application.
+ """Represents a custom emoji from an application.
+
+
+ Depending on the way this object was created, some attributes can
+ Depending on the way this object was created, some attributes can
+ have a value of ``None``.
+ have a value of ``None``.
+
+
+ .. versionadded:: 2.7
+
+ .. container:: operations
+ .. container:: operations
+
+
+ .. describe:: x == y
+ .. describe:: x == y
+
+
+ Checks if two emoji are the same.
+ Checks if two emoji are the same.
+
+
+ .. describe:: x != y
+ .. describe:: x != y
+
+
+ Checks if two emoji are not the same.
+ Checks if two emoji are not the same.
+
+
+ .. describe:: hash(x)
+ .. describe:: hash(x)
+
+
+ Return the emoji's hash.
+ Return the emoji's hash.
+
+
+ .. describe:: iter(x)
+ .. describe:: iter(x)
+
+
+ Returns an iterator of ``(field, value)`` pairs. This allows this class
+ Returns an iterator of ``(field, value)`` pairs. This allows this class
+ to be used as an iterable in list/dict/etc constructions.
+ to be used as an iterable in list/dict/etc constructions.
+
+
+ .. describe:: str(x)
+ .. describe:: str(x)
+
+
+ Returns the emoji rendered for discord.
+ Returns the emoji rendered for discord.
+
+
+ Attributes
+ Attributes
+ ----------
+ ----------
+ name: :class:`str`
+ name: :class:`str`
+ The name of the emoji.
+ The name of the emoji.
+ id: :class:`int`
+ id: :class:`int`
+ The emoji's ID.
+ The emoji's ID.
+ require_colons: :class:`bool`
+ require_colons: :class:`bool`
+ If colons are required to use this emoji in the client (:PJSalt: vs PJSalt).
+ If colons are required to use this emoji in the client (:PJSalt: vs PJSalt).
+ animated: :class:`bool`
+ animated: :class:`bool`
+ Whether an emoji is animated or not.
+ Whether an emoji is animated or not.
+ managed: :class:`bool`
+ managed: :class:`bool`
+ If this emoji is managed by a Twitch integration.
+ If this emoji is managed by a Twitch integration.
+ application_id: Optional[:class:`int`]
+ application_id: Optional[:class:`int`]
+ The application ID the emoji belongs to, if available.
+ The application ID the emoji belongs to, if available.
+ available: :class:`bool`
+ available: :class:`bool`
+ Whether the emoji is available for use.
+ Whether the emoji is available for use.
+ user: Optional[:class:`User`]
+ user: Optional[:class:`User`]
+ The user that created the emoji.
+ The user that created the emoji.
+ """
+ """
+
+
+ def __init__(
+ def __init__(self, *, application_id: int, state: ConnectionState, data: EmojiPayload):
+ self, *, application_id: int, state: ConnectionState, data: EmojiPayload
+ ):
+ self.application_id: int = application_id
+ self.application_id: int = application_id
+ super().__init__(state, data)
+ super().__init__(state=state, data=data)
+
+ def __repr__(self) -> str:
+ return "<AppEmoji" f" id={self.id} name={self.name!r} animated={self.animated}>"
+
+ @property
+ def guild(self) -> Guild:
+ """The guild this emoji belongs to. This is always `None` for :class:`AppEmoji`."""
+ return None
+
+
+ @property
+ def __repr__(self):
+ def roles(self) -> list[Role]:
+ return f"<ApplicationEmoji id={self.id} name={self.name!r} animated={self.animated}>"
+ """A :class:`list` of roles that is allowed to use this emoji. This is always empty for :class:`AppEmoji`."""
+ return []
+
+
+ def is_usable(self) -> bool:
+ def is_usable(self) -> bool:
+ """Whether the bot can use this emoji."""
+ """Whether the bot can use this emoji."""
+ return self.application_id == self._state.application_id
+ return self.application_id == self._state.application_id
+
+
+ async def delete(self) -> None:
+ async def delete(self) -> None:
+ """|coro|
+ """|coro|
+
+ Deletes the application emoji.
+ Deletes the application emoji.
+
+ You must own the emoji to do this.
+ You must own the emoji to do this.
+
+
+ Raises
+ Raises
+ ------
+ ------
+ Forbidden
+ Forbidden
+ You are not allowed to delete the emoji.
+ You are not allowed to delete the emoji.
+ HTTPException
+ HTTPException
+ An error occurred deleting the emoji.
+ An error occurred deleting the emoji.
+ """
+ """
+
+ await self._state.http.delete_application_emoji(self.application_id, self.id)
+ await self._state.http.delete_application_emoji(self.application_id, self.id)
+ if self._state.cache_app_emojis and self._state.get_emoji(self.id):
+ if self._state.cache_app_emojis and self._state.get_emoji(self.id):
+ self._state._remove_emoji(self)
+ self._state._remove_emoji(self)
+
+
+ async def edit(
+ async def edit(
+ self,
+ self,
+ *,
+ *,
+ name: str = MISSING,
+ name: str = MISSING,
+ ) -> AppEmoji:
+ ) -> ApplicationEmoji:
+ r"""|coro|
+ r"""|coro|
+
+ Edits the application emoji.
+ Edits the application emoji.
+
+ You must own the emoji to do this.
+ You must own the emoji to do this.
+
+
+ Parameters
+ Parameters
+ -----------
+ ----------
+ name: :class:`str`
+ name: :class:`str`
+ The new emoji name.
+ The new emoji name.
+
+
+ Raises
+ Raises
+ -------
+ ------
+ Forbidden
+ Forbidden
+ You are not allowed to edit the emoji.
+ You are not allowed to edit the emoji.
+ HTTPException
+ HTTPException
+ An error occurred editing the emoji.
+ An error occurred editing the emoji.
+
+
+ Returns
+ Returns
+ --------
+ -------
+ :class:`AppEmoji`
+ :class:`ApplicationEmoji`
+ The newly updated emoji.
+ The newly updated emoji.
+ """
+ """
+
+ payload = {}
+ payload = {}
+ if name is not MISSING:
+ if name is not MISSING:
+ payload["name"] = name
+ payload["name"] = name
+
+
+ data = await self._state.http.edit_application_emoji(
+ data = await self._state.http.edit_application_emoji(
+ self.application_id, self.id, payload=payload
+ self.application_id, self.id, payload=payload
+ )
+ )
+ return self._state.maybe_store_app_emoji(self.application_id, data)
+ return self._state.store_application_emoji(self.application_id, data)
diff --git a/discord/http.py b/discord/http.py
diff --git a/disnake/ext/commands/bot.py b/disnake/ext/commands/bot.py
--- a/discord/http.py
--- a/disnake/ext/commands/bot.py
+++ b/discord/http.py
+++ b/disnake/ext/commands/bot.py
+ def get_all_application_emojis(
+
+ self, application_id: Snowflake
+ cache_app_emojis: :class:`bool`
+ ) -> Response[list[emoji.Emoji]]:
+ Whether to automatically fetch and cache the application's emojis on startup and when fetching.
+ Defaults to ``False``.
+ cache_app_emojis: bool = False,
+ cache_app_emojis: bool = False,
+
+ cache_app_emojis: :class:`bool`
+ Whether to automatically fetch and cache the application's emojis on startup and when fetching.
+ Defaults to ``False``.
+ cache_app_emojis: bool = False,
+ cache_app_emojis: bool = False,
diff --git a/disnake/http.py b/disnake/http.py
--- a/disnake/http.py
+++ b/disnake/http.py
+ def get_all_application_emojis(self, application_id: Snowflake) -> Response[List[emoji.Emoji]]:
+ return self.request(
+ return self.request(
+ Route(
+ Route("GET", "/applications/{application_id}/emojis", application_id=application_id)
+ "GET",
+ "/applications/{application_id}/emojis",
+ application_id=application_id,
+ )
+ )
+ )
+
+
+ def get_application_emoji(
+ def get_application_emoji(
+ self, application_id: Snowflake, emoji_id: Snowflake
+ self, application_id: Snowflake, emoji_id: Snowflake
+ ) -> Response[emoji.Emoji]:
+ ) -> Response[emoji.Emoji]:
+ return self.request(
+ return self.request(
+ Route(
+ Route(
+ "GET",
+ "GET",
+ "/applications/{application_id}/emojis/{emoji_id}",
+ "/applications/{application_id}/emojis/{emoji_id}",
+ application_id=application_id,
+ application_id=application_id,
+ emoji_id=emoji_id,
+ emoji_id=emoji_id,
+ )
+ )
+ )
+ )
+
+
+ def create_application_emoji(
+ def create_application_emoji(
+ self,
+ self,
+ application_id: Snowflake,
+ application_id: Snowflake,
+ name: str,
+ name: str,
+ image: bytes,
+ image: str,
+ ) -> Response[emoji.Emoji]:
+ ) -> Response[emoji.Emoji]:
+ payload = {
+ payload = {"name": name, "image": image}
+ "name": name,
+ r = Route("POST", "/applications/{application_id}/emojis", application_id=application_id)
+ "image": image,
+ }
+
+ r = Route(
+ "POST",
+ "/applications/{application_id}/emojis",
+ application_id=application_id,
+ )
+ return self.request(r, json=payload)
+ return self.request(r, json=payload)
+
+
+ def delete_application_emoji(
+ def delete_application_emoji(
+ self,
+ self,
+ application_id: Snowflake,
+ application_id: Snowflake,
+ emoji_id: Snowflake,
+ emoji_id: Snowflake,
+ ) -> Response[None]:
+ ) -> Response[None]:
+ r = Route(
+ r = Route(
+ "DELETE",
+ "DELETE",
+ "/applications/{application_id}/emojis/{emoji_id}",
+ "/applications/{application_id}/emojis/{emoji_id}",
+ application_id=application_id,
+ application_id=application_id,
+ emoji_id=emoji_id,
+ emoji_id=emoji_id,
+ )
+ )
+ return self.request(r)
+ return self.request(r)
+
+
+ def edit_application_emoji(
+ def edit_application_emoji(
+ self,
+ self,
+ application_id: Snowflake,
+ application_id: Snowflake,
+ emoji_id: Snowflake,
+ emoji_id: Snowflake,
+ *,
+ *,
+ payload: dict[str, Any],
+ payload: dict[str, Any],
+ ) -> Response[emoji.Emoji]:
+ ) -> Response[emoji.Emoji]:
+ r = Route(
+ r = Route(
+ "PATCH",
+ "PATCH",
+ "/applications/{application_id}/emojis/{emoji_id}",
+ "/applications/{application_id}/emojis/{emoji_id}",
+ application_id=application_id,
+ application_id=application_id,
+ emoji_id=emoji_id,
+ emoji_id=emoji_id,
+ )
+ )
+ return self.request(r, json=payload)
+ return self.request(r, json=payload)
+
+
diff --git a/discord/state.py b/discord/state.py
diff --git a/disnake/state.py b/disnake/state.py
--- a/discord/state.py
--- a/disnake/state.py
+++ b/discord/state.py
+++ b/disnake/state.py
-from .emoji import Emoji
-from .emoji import Emoji
+from .emoji import AppEmoji, Emoji, GuildEmoji
+from .emoji import ApplicationEmoji, Emoji, GuildEmoji
+ self.cache_app_emojis: bool = options.get("cache_app_emojis", False)
+ cache_app_emojis: bool = False,
+ self.cache_app_emojis: bool = cache_app_emojis
+
+
- self._emojis: Dict[int, Emoji] = {}
+ self._emojis: Dict[int, Emoji, ApplicationEmoji] = {}
- def store_emoji(self, guild: Guild, data: EmojiPayload) -> Emoji:
- def store_emoji(self, guild: Guild, data: EmojiPayload) -> Emoji:
+ def store_emoji(self, guild: Guild, data: EmojiPayload) -> GuildEmoji:
+ def store_emoji(self, guild: Guild, data: EmojiPayload) -> GuildEmoji:
- self._emojis[emoji_id] = emoji = Emoji(guild=guild, state=self, data=data)
- self._emojis[emoji_id] = emoji = Emoji(guild=guild, state=self, data=data)
+ self._emojis[emoji_id] = emoji = GuildEmoji(guild=guild, state=self, data=data)
+ self._emojis[emoji_id] = emoji = GuildEmoji(guild=guild, state=self, data=data)
+ return emoji
+ return emoji
+
+
+ def maybe_store_app_emoji(
+ def store_application_emoji(self, application_id: int, data: EmojiPayload) -> ApplicationEmoji:
+ self, application_id: int, data: EmojiPayload
+ emoji = ApplicationEmoji(application_id=application_id, state=self, data=data)
+ ) -> AppEmoji:
+ # the id will be present here
+ emoji = AppEmoji(application_id=application_id, state=self, data=data)
+ if self.cache_app_emojis:
+ if self.cache_app_emojis:
+ emoji_id = int(data["id"]) # type: ignore
+ emoji_id = int(data["id"]) # type: ignore
+ self._emojis[emoji_id] = emoji
+ self._emojis[emoji_id] = emoji
- self._emojis.pop(emoji.id, None)
- self._emojis.pop(emoji.id, None)
+ self._remove_emoji(emoji)
+ self._remove_emoji(emoji.id)
- def emojis(self) -> list[Emoji]:
- def emojis(self) -> List[Emoji]:
+ def emojis(self) -> list[GuildEmoji | AppEmoji]:
+ def emojis(self) -> List[Union[GuildEmoji, ApplicationEmoji]]:
- def get_emoji(self, emoji_id: int | None) -> Emoji | None:
- def get_emoji(self, emoji_id: Optional[int]) -> Optional[Emoji]:
+ def get_emoji(self, emoji_id: int | None) -> GuildEmoji | AppEmoji | None:
+ def get_emoji(self, emoji_id: Optional[int]) -> Optional[Union[GuildEmoji, ApplicationEmoji]]:
+ def _remove_emoji(self, emoji: GuildEmoji | AppEmoji) -> None:
+ def _remove_emoji(self, emoji: Union[GuildEmoji, ApplicationEmoji]) -> None:
+ self._emojis.pop(emoji.id, None)
+ self._emojis.pop(emoji.id, None)
+
+
+ if self.cache_app_emojis and self.application_id:
+ if self.cache_app_emojis and self.application_id:
+ data = await self.http.get_all_application_emojis(self.application_id)
+ data = await self.http.get_all_application_emojis(self.application_id)
+ for e in data.get("items", []):
+ for e in data.get("items", []):
+ self.maybe_store_app_emoji(self.application_id, e)
+ self.store_application_emoji(self.application_id, e)
+
diff --git a/docs/api/models.rst b/docs/api/models.rst
--- a/docs/api/models.rst
+++ b/docs/api/models.rst
-.. attributetable:: Emoji
+.. attributetable:: GuildEmoji
-.. autoclass:: Emoji()
+.. autoclass:: GuildEmoji()
+ :members:
+ :inherited-members:
+
+.. attributetable:: AppEmoji
+
+
+.. autoclass:: AppEmoji()