Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: app emojis #2501

Merged
merged 36 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
dc9fec5
add routes
NeloBlivion Jul 18, 2024
847cc4f
unfinished methods, needs rework
NeloBlivion Jul 18, 2024
b8c8dd2
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 19, 2024
607bc10
new classes
NeloBlivion Jul 19, 2024
f7a8f11
Merge branch 'master' into app_emojis
NeloBlivion Jul 19, 2024
833695d
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 19, 2024
79497e7
refinements
NeloBlivion Jul 19, 2024
6e5338e
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 19, 2024
90c4b55
Merge branch 'master' into app_emojis
NeloBlivion Jul 23, 2024
0aa1f8e
fix kwargs
NeloBlivion Jul 23, 2024
e9fae0f
_state -> _connection
NeloBlivion Jul 23, 2024
f2e81c7
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2024
3f04a98
cache on ready
NeloBlivion Jul 23, 2024
1244e4f
full cache
NeloBlivion Jul 23, 2024
5d389f9
remove delete reason
NeloBlivion Jul 23, 2024
42d3887
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2024
744a45f
Merge branch 'master' into app_emojis
Lulalaby Aug 16, 2024
82a5591
Merge branch 'master' into app_emojis
plun1331 Aug 28, 2024
70d23ba
Merge branch 'master' into app_emojis
NeloBlivion Sep 9, 2024
7b46217
adjust slots
NeloBlivion Sep 10, 2024
d14413f
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 10, 2024
c01e384
Update discord/emoji.py
plun1331 Sep 10, 2024
0381a6e
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 10, 2024
4ccf9b1
update all references to the Emoji class
NeloBlivion Sep 10, 2024
1bf8195
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 10, 2024
f2f0848
Merge branch 'master' into app_emojis
NeloBlivion Sep 10, 2024
b937eaa
misc
NeloBlivion Sep 10, 2024
9b018eb
cl
NeloBlivion Sep 10, 2024
ba5ffaf
Merge branch 'master' into app_emojis
NeloBlivion Oct 4, 2024
6f97d3a
style(pre-commit): auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 4, 2024
d8f7ee4
add deprecation
NeloBlivion Oct 4, 2024
5935ef9
Merge branch 'master' into app_emojis
plun1331 Oct 4, 2024
73d9336
Merge branch 'master' into app_emojis
plun1331 Oct 4, 2024
b27903a
Merge branch 'master' into app_emojis
NeloBlivion Oct 14, 2024
7872075
Merge branch 'master' into app_emojis
NeloBlivion Oct 17, 2024
2930699
Merge branch 'master' into app_emojis
NeloBlivion Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ These changes are available on the `master` branch, but have not yet been releas
`tags`. ([#2520](https://github.com/Pycord-Development/pycord/pull/2520))
- Added `Member.guild_banner` and `Member.display_banner` properties.
([#2556](https://github.com/Pycord-Development/pycord/pull/2556))
- Added support for Application Emojis.
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))
- Added `cache_app_emojis` parameter to `Client`.
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))
- Added optional `filter` parameter to `utils.basic_autocomplete()`.
([#2590](https://github.com/Pycord-Development/pycord/pull/2590))

Expand All @@ -48,11 +52,15 @@ These changes are available on the `master` branch, but have not yet been releas
([#2496](https://github.com/Pycord-Development/pycord/pull/2496))
- ⚠️ **Removed support for Python 3.8.**
([#2521](https://github.com/Pycord-Development/pycord/pull/2521))
- `Emoji` has been renamed to `GuildEmoji`.
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))

### Deprecated

- Deprecated `AppInfo.summary` in favor of `AppInfo.description`.
([#2520](https://github.com/Pycord-Development/pycord/pull/2520))
- Deprecated `Emoji` in favor of `GuildEmoji`
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))

## [2.6.1] - 2024-09-15

Expand Down
10 changes: 6 additions & 4 deletions discord/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,9 @@ async def _edit(
except KeyError:
pass
else:
if isinstance(default_reaction_emoji, _EmojiTag): # Emoji, PartialEmoji
if isinstance(
default_reaction_emoji, _EmojiTag
): # GuildEmoji, PartialEmoji
default_reaction_emoji = default_reaction_emoji._to_partial()
elif isinstance(default_reaction_emoji, int):
default_reaction_emoji = PartialEmoji(
Expand All @@ -523,7 +525,7 @@ async def _edit(
default_reaction_emoji = PartialEmoji.from_str(default_reaction_emoji)
else:
raise InvalidArgument(
"default_reaction_emoji must be of type: Emoji | int | str"
"default_reaction_emoji must be of type: GuildEmoji | int | str"
)

options["default_reaction_emoji"] = (
Expand Down Expand Up @@ -1792,7 +1794,7 @@ def can_send(self, *objects) -> bool:
"Message": "send_messages",
"Embed": "embed_links",
"File": "attach_files",
"Emoji": "use_external_emojis",
"GuildEmoji": "use_external_emojis",
"GuildSticker": "use_external_stickers",
}
# Can't use channel = await self._get_channel() since its async
Expand All @@ -1817,7 +1819,7 @@ def can_send(self, *objects) -> bool:
mapping.get(type(obj).__name__) or mapping[obj.__name__]
)

if type(obj).__name__ == "Emoji":
if type(obj).__name__ == "GuildEmoji":
if (
obj._to_partial().is_unicode_emoji
or obj.guild_id == channel.guild.id
Expand Down
6 changes: 3 additions & 3 deletions discord/audit_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
import datetime

from . import abc
from .emoji import Emoji
from .emoji import GuildEmoji
from .guild import Guild
from .member import Member
from .role import Role
Expand Down Expand Up @@ -617,7 +617,7 @@ def target(
| User
| Role
| Invite
| Emoji
| GuildEmoji
| StageInstance
| GuildSticker
| Thread
Expand Down Expand Up @@ -689,7 +689,7 @@ def _convert_target_invite(self, target_id: int) -> Invite:
pass
return obj

def _convert_target_emoji(self, target_id: int) -> Emoji | Object:
def _convert_target_emoji(self, target_id: int) -> GuildEmoji | Object:
return self._state.get_emoji(target_id) or Object(id=target_id)

def _convert_target_message(self, target_id: int) -> Member | User | None:
Expand Down
12 changes: 6 additions & 6 deletions discord/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

from . import utils
from .asset import Asset
from .emoji import Emoji
from .emoji import GuildEmoji
from .enums import (
ChannelType,
EmbeddedActivity,
Expand Down Expand Up @@ -143,7 +143,7 @@ def __init__(
self.emoji = PartialEmoji.from_str(emoji)
else:
raise TypeError(
"emoji must be a Emoji, PartialEmoji, or str and not"
"emoji must be a GuildEmoji, PartialEmoji, or str and not"
f" {emoji.__class__!r}"
)

Expand Down Expand Up @@ -1018,7 +1018,7 @@ class ForumChannel(_TextChannel):
The initial slowmode delay to set on newly created threads in this channel.

.. versionadded:: 2.3
default_reaction_emoji: Optional[:class:`str` | :class:`discord.Emoji`]
default_reaction_emoji: Optional[:class:`str` | :class:`discord.GuildEmoji`]
The default forum reaction emoji.

.. versionadded:: 2.5
Expand Down Expand Up @@ -1087,7 +1087,7 @@ async def edit(
default_auto_archive_duration: ThreadArchiveDuration = ...,
default_thread_slowmode_delay: int = ...,
default_sort_order: SortOrder = ...,
default_reaction_emoji: Emoji | int | str | None = ...,
default_reaction_emoji: GuildEmoji | int | str | None = ...,
available_tags: list[ForumTag] = ...,
require_tag: bool = ...,
overwrites: Mapping[Role | Member | Snowflake, PermissionOverwrite] = ...,
Expand Down Expand Up @@ -1138,10 +1138,10 @@ async def edit(self, *, reason=None, **options):
The default sort order type to use to order posts in this channel.

.. versionadded:: 2.3
default_reaction_emoji: Optional[:class:`discord.Emoji` | :class:`int` | :class:`str`]
default_reaction_emoji: Optional[:class:`discord.GuildEmoji` | :class:`int` | :class:`str`]
The default reaction emoji.
Can be a unicode emoji or a custom emoji in the forms:
:class:`Emoji`, snowflake ID, string representation (eg. '<a:emoji_name:emoji_id>').
:class:`GuildEmoji`, snowflake ID, string representation (eg. '<a:emoji_name:emoji_id>').

.. versionadded:: 2.5
available_tags: List[:class:`ForumTag`]
Expand Down
149 changes: 144 additions & 5 deletions discord/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from .application_role_connection import ApplicationRoleConnectionMetadata
from .backoff import ExponentialBackoff
from .channel import PartialMessageable, _threaded_channel_factory
from .emoji import Emoji
from .emoji import AppEmoji, GuildEmoji
from .enums import ChannelType, Status
from .errors import *
from .flags import ApplicationFlags, Intents
Expand Down Expand Up @@ -199,6 +199,16 @@ class Client:
To enable these events, this must be set to ``True``. Defaults to ``False``.

.. versionadded:: 2.0
cache_app_emojis: :class:`bool`
Whether to automatically fetch and cache the application's emojis on startup and when fetching. Defaults to ``False``.

.. warning::

There are no events related to application emojis - if any are created/deleted on the
Developer Dashboard while the client is running, the cache will not be updated until you manually
run :func:`fetch_emojis`.

.. versionadded:: 2.7

Attributes
-----------
Expand Down Expand Up @@ -330,10 +340,30 @@ def guilds(self) -> list[Guild]:
return self._connection.guilds

@property
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.

.. note::

This only includes the application's emojis if `cache_app_emojis` is ``True``.
"""
return self._connection.emojis

@property
def guild_emojis(self) -> list[GuildEmoji]:
"""The :class:`~discord.GuildEmoji` that the connected client has."""
return [e for e in self.emojis if isinstance(e, GuildEmoji)]

@property
def app_emojis(self) -> list[AppEmoji]:
"""The :class:`~discord.AppEmoji` that the connected client has.

.. note::

This is only available if `cache_app_emojis` is ``True``.
"""
return [e for e in self.emojis if isinstance(e, AppEmoji)]

@property
def stickers(self) -> list[GuildSticker]:
"""The stickers that the connected client has.
Expand Down Expand Up @@ -994,7 +1024,7 @@ def get_user(self, id: int, /) -> User | None:
"""
return self._connection.get_user(id)

def get_emoji(self, id: int, /) -> Emoji | None:
def get_emoji(self, id: int, /) -> GuildEmoji | AppEmoji | None:
"""Returns an emoji with the given ID.

Parameters
Expand All @@ -1004,7 +1034,7 @@ def get_emoji(self, id: int, /) -> Emoji | None:

Returns
-------
Optional[:class:`.Emoji`]
Optional[:class:`.GuildEmoji` | :class:`.AppEmoji`]
The custom emoji or ``None`` if not found.
"""
return self._connection.get_emoji(id)
Expand Down Expand Up @@ -2130,3 +2160,112 @@ def store_url(self) -> str:
.. versionadded:: 2.6
"""
return f"https://discord.com/application-directory/{self.application_id}/store"

async def fetch_emojis(self) -> list[AppEmoji]:
r"""|coro|

Retrieves all custom :class:`AppEmoji`\s from the application.

Raises
---------
HTTPException
An error occurred fetching the emojis.

Returns
--------
List[:class:`AppEmoji`]
The retrieved emojis.
"""
data = await self._connection.http.get_all_application_emojis(
self.application_id
)
return [
self._connection.maybe_store_app_emoji(self.application_id, d)
for d in data["items"]
]

async def fetch_emoji(self, emoji_id: int, /) -> AppEmoji:
"""|coro|

Retrieves a custom :class:`AppEmoji` from the application.

Parameters
----------
emoji_id: :class:`int`
The emoji's ID.

Returns
-------
:class:`AppEmoji`
The retrieved emoji.

Raises
------
NotFound
The emoji requested could not be found.
HTTPException
An error occurred fetching the emoji.
"""
data = await self._connection.http.get_application_emoji(
self.application_id, emoji_id
)
return self._connection.maybe_store_app_emoji(self.application_id, data)

async def create_emoji(
self,
*,
name: str,
image: bytes,
) -> AppEmoji:
r"""|coro|

Creates a custom :class:`AppEmoji` for the application.

There is currently a limit of 2000 emojis per application.

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
-------
HTTPException
An error occurred creating an emoji.

Returns
--------
:class:`AppEmoji`
The created emoji.
"""

img = utils._bytes_to_base64_data(image)
data = await self._connection.http.create_application_emoji(
self.application_id, name, img
)
return self._connection.maybe_store_app_emoji(self.application_id, data)

async def delete_emoji(self, emoji: Snowflake) -> 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._connection.http.delete_application_emoji(
self.application_id, emoji.id
)
if self._connection.cache_app_emojis and self._connection.get_emoji(emoji.id):
self._connection.remove_emoji(emoji)
8 changes: 4 additions & 4 deletions discord/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from .utils import MISSING, get_slots

if TYPE_CHECKING:
from .emoji import Emoji
from .emoji import AppEmoji, GuildEmoji
from .types.components import ActionRow as ActionRowPayload
from .types.components import ButtonComponent as ButtonComponentPayload
from .types.components import Component as ComponentPayload
Expand Down Expand Up @@ -412,7 +412,7 @@ def __init__(
label: str,
value: str = MISSING,
description: str | None = None,
emoji: str | Emoji | PartialEmoji | None = None,
emoji: str | GuildEmoji | AppEmoji | PartialEmoji | None = None,
default: bool = False,
) -> None:
if len(label) > 100:
Expand Down Expand Up @@ -444,7 +444,7 @@ def __str__(self) -> str:
return base

@property
def emoji(self) -> str | Emoji | PartialEmoji | None:
def emoji(self) -> str | GuildEmoji | AppEmoji | PartialEmoji | None:
"""The emoji of the option, if available."""
return self._emoji

Expand All @@ -457,7 +457,7 @@ def emoji(self, value) -> None:
value = value._to_partial()
else:
raise TypeError(
"expected emoji to be str, Emoji, or PartialEmoji not"
"expected emoji to be str, GuildEmoji, AppEmoji, or PartialEmoji, not"
f" {value.__class__}"
)

Expand Down
Loading