Skip to content

Commit 654b38e

Browse files
authored
Merge branch 'master' into python-3.13
2 parents d4650d4 + 9a6cbff commit 654b38e

26 files changed

+604
-183
lines changed

CHANGELOG.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ These changes are available on the `master` branch, but have not yet been releas
2222
`tags`. ([#2520](https://github.com/Pycord-Development/pycord/pull/2520))
2323
- Added `Member.guild_banner` and `Member.display_banner` properties.
2424
([#2556](https://github.com/Pycord-Development/pycord/pull/2556))
25+
- Added support for Application Emojis.
26+
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))
27+
- Added `cache_app_emojis` parameter to `Client`.
28+
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))
2529
- Added `elapsed` method to `VoiceClient`.
2630
([#2587](https://github.com/Pycord-Development/pycord/pull/2587/))
2731
- Added optional `filter` parameter to `utils.basic_autocomplete()`.
@@ -42,8 +46,8 @@ These changes are available on the `master` branch, but have not yet been releas
4246
- Fixed `Guild.create_test_entitlement()` and `User.create_test_entitlement()` using the
4347
guild/user ID instead of the application ID.
4448
([#2595](https://github.com/Pycord-Development/pycord/pull/2595))
45-
- Fixed commands with `BucketType.cagegory` cooldown causing issues in private channels.
46-
([#2603](https://github.com/Pycord-Development/pycord/pull/2603))
49+
- Fixed `BucketType.category` cooldown commands not functioning correctly in private
50+
channels. ([#2603](https://github.com/Pycord-Development/pycord/pull/2603))
4751

4852
### Changed
4953

@@ -52,6 +56,8 @@ These changes are available on the `master` branch, but have not yet been releas
5256
([#2496](https://github.com/Pycord-Development/pycord/pull/2496))
5357
- ⚠️ **Removed support for Python 3.8.**
5458
([#2521](https://github.com/Pycord-Development/pycord/pull/2521))
59+
- `Emoji` has been renamed to `GuildEmoji`.
60+
([#2501](https://github.com/Pycord-Development/pycord/pull/2501))
5561
- Replaced audioop (deprecated module) implementation of `PCMVolumeTransformer.read`
5662
method with a pure Python equivalent.
5763
([#2176](https://github.com/Pycord-Development/pycord/pull/2176))
@@ -60,6 +66,8 @@ These changes are available on the `master` branch, but have not yet been releas
6066

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

6472
## [2.6.1] - 2024-09-15
6573

@@ -81,9 +89,9 @@ These changes are available on the `master` branch, but have not yet been releas
8189
`SortOrder`. ([#2500](https://github.com/Pycord-Development/pycord/pull/2500))
8290
- Fixed `PartialMessage` causing errors when created from `PartialMessageable`.
8391
([#2568](https://github.com/Pycord-Development/pycord/pull/2500))
84-
- Fixed the `guild` attribute of `Member`s recieved from a `UserCommand` being `None`.
92+
- Fixed the `guild` attribute of `Member`s received from a `UserCommand` being `None`.
8593
([#2573](https://github.com/Pycord-Development/pycord/pull/2573))
86-
- Fixed `Webhook.send` not including attachment data.
94+
- Fixed `Webhook.send`, which did not include attachment data.
8795
([#2513](https://github.com/Pycord-Development/pycord/pull/2513))
8896
- Fixed inverted type hints in `CheckAnyFailure`.
8997
([#2502](https://github.com/Pycord-Development/pycord/pull/2502))
@@ -140,7 +148,7 @@ These changes are available on the `master` branch, but have not yet been releas
140148
([#2407](https://github.com/Pycord-Development/pycord/pull/2407))
141149
- Fixed invalid data being passed to `Interaction._guild` in certain cases.
142150
([#2411](https://github.com/Pycord-Development/pycord/pull/2411))
143-
- Fixed option typehints being ignored when using `parameter_name`.
151+
- Fixed option type hints being ignored when using `parameter_name`.
144152
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
145153
- Fixed parameter `embed=None` causing `AttributeError` on `PartialMessage.edit`.
146154
([#2446](https://github.com/Pycord-Development/pycord/pull/2446))
@@ -165,7 +173,7 @@ These changes are available on the `master` branch, but have not yet been releas
165173

166174
- Changed the type of `Guild.bitrate_limit` to `int`.
167175
([#2387](https://github.com/Pycord-Development/pycord/pull/2387))
168-
- HTTP requests that fail with a 503 status are now re-tried.
176+
- HTTP requests that fail with a 503 status are now retried.
169177
([#2395](https://github.com/Pycord-Development/pycord/pull/2395))
170178
- `option` decorator now accepts `input_type`.
171179
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
@@ -374,7 +382,7 @@ These changes are available on the `master` branch, but have not yet been releas
374382
([#2145](https://github.com/Pycord-Development/pycord/pull/2145))
375383
- Fixed `Thread.applied_tags` not being updated.
376384
([#2146](https://github.com/Pycord-Development/pycord/pull/2146))
377-
- Fixed type hinting of `author` property of `ApplicationContext` to include
385+
- Fixed type-hinting of `author` property of `ApplicationContext` to include
378386
type-hinting of `User` or `Member`.
379387
([#2148](https://github.com/Pycord-Development/pycord/pull/2148))
380388
- Fixed missing `delete_after` parameter in overload type-hinting for `Webhook.send()`.

discord/abc.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,9 @@ async def _edit(
513513
except KeyError:
514514
pass
515515
else:
516-
if isinstance(default_reaction_emoji, _EmojiTag): # Emoji, PartialEmoji
516+
if isinstance(
517+
default_reaction_emoji, _EmojiTag
518+
): # GuildEmoji, PartialEmoji
517519
default_reaction_emoji = default_reaction_emoji._to_partial()
518520
elif isinstance(default_reaction_emoji, int):
519521
default_reaction_emoji = PartialEmoji(
@@ -523,7 +525,7 @@ async def _edit(
523525
default_reaction_emoji = PartialEmoji.from_str(default_reaction_emoji)
524526
else:
525527
raise InvalidArgument(
526-
"default_reaction_emoji must be of type: Emoji | int | str"
528+
"default_reaction_emoji must be of type: GuildEmoji | int | str"
527529
)
528530

529531
options["default_reaction_emoji"] = (
@@ -1792,7 +1794,7 @@ def can_send(self, *objects) -> bool:
17921794
"Message": "send_messages",
17931795
"Embed": "embed_links",
17941796
"File": "attach_files",
1795-
"Emoji": "use_external_emojis",
1797+
"GuildEmoji": "use_external_emojis",
17961798
"GuildSticker": "use_external_stickers",
17971799
}
17981800
# Can't use channel = await self._get_channel() since its async
@@ -1817,7 +1819,7 @@ def can_send(self, *objects) -> bool:
18171819
mapping.get(type(obj).__name__) or mapping[obj.__name__]
18181820
)
18191821

1820-
if type(obj).__name__ == "Emoji":
1822+
if type(obj).__name__ == "GuildEmoji":
18211823
if (
18221824
obj._to_partial().is_unicode_emoji
18231825
or obj.guild_id == channel.guild.id

discord/audit_logs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
import datetime
4848

4949
from . import abc
50-
from .emoji import Emoji
50+
from .emoji import GuildEmoji
5151
from .guild import Guild
5252
from .member import Member
5353
from .role import Role
@@ -617,7 +617,7 @@ def target(
617617
| User
618618
| Role
619619
| Invite
620-
| Emoji
620+
| GuildEmoji
621621
| StageInstance
622622
| GuildSticker
623623
| Thread
@@ -689,7 +689,7 @@ def _convert_target_invite(self, target_id: int) -> Invite:
689689
pass
690690
return obj
691691

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

695695
def _convert_target_message(self, target_id: int) -> Member | User | None:

discord/channel.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
from . import utils
3434
from .asset import Asset
35-
from .emoji import Emoji
35+
from .emoji import GuildEmoji
3636
from .enums import (
3737
ChannelType,
3838
EmbeddedActivity,
@@ -143,7 +143,7 @@ def __init__(
143143
self.emoji = PartialEmoji.from_str(emoji)
144144
else:
145145
raise TypeError(
146-
"emoji must be a Emoji, PartialEmoji, or str and not"
146+
"emoji must be a GuildEmoji, PartialEmoji, or str and not"
147147
f" {emoji.__class__!r}"
148148
)
149149

@@ -1018,7 +1018,7 @@ class ForumChannel(_TextChannel):
10181018
The initial slowmode delay to set on newly created threads in this channel.
10191019
10201020
.. versionadded:: 2.3
1021-
default_reaction_emoji: Optional[:class:`str` | :class:`discord.Emoji`]
1021+
default_reaction_emoji: Optional[:class:`str` | :class:`discord.GuildEmoji`]
10221022
The default forum reaction emoji.
10231023
10241024
.. versionadded:: 2.5
@@ -1087,7 +1087,7 @@ async def edit(
10871087
default_auto_archive_duration: ThreadArchiveDuration = ...,
10881088
default_thread_slowmode_delay: int = ...,
10891089
default_sort_order: SortOrder = ...,
1090-
default_reaction_emoji: Emoji | int | str | None = ...,
1090+
default_reaction_emoji: GuildEmoji | int | str | None = ...,
10911091
available_tags: list[ForumTag] = ...,
10921092
require_tag: bool = ...,
10931093
overwrites: Mapping[Role | Member | Snowflake, PermissionOverwrite] = ...,
@@ -1138,10 +1138,10 @@ async def edit(self, *, reason=None, **options):
11381138
The default sort order type to use to order posts in this channel.
11391139
11401140
.. versionadded:: 2.3
1141-
default_reaction_emoji: Optional[:class:`discord.Emoji` | :class:`int` | :class:`str`]
1141+
default_reaction_emoji: Optional[:class:`discord.GuildEmoji` | :class:`int` | :class:`str`]
11421142
The default reaction emoji.
11431143
Can be a unicode emoji or a custom emoji in the forms:
1144-
:class:`Emoji`, snowflake ID, string representation (eg. '<a:emoji_name:emoji_id>').
1144+
:class:`GuildEmoji`, snowflake ID, string representation (eg. '<a:emoji_name:emoji_id>').
11451145
11461146
.. versionadded:: 2.5
11471147
available_tags: List[:class:`ForumTag`]

discord/client.py

Lines changed: 145 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from .application_role_connection import ApplicationRoleConnectionMetadata
4242
from .backoff import ExponentialBackoff
4343
from .channel import PartialMessageable, _threaded_channel_factory
44-
from .emoji import Emoji
44+
from .emoji import AppEmoji, GuildEmoji
4545
from .enums import ChannelType, Status
4646
from .errors import *
4747
from .flags import ApplicationFlags, Intents
@@ -199,6 +199,16 @@ class Client:
199199
To enable these events, this must be set to ``True``. Defaults to ``False``.
200200
201201
.. versionadded:: 2.0
202+
cache_app_emojis: :class:`bool`
203+
Whether to automatically fetch and cache the application's emojis on startup and when fetching. Defaults to ``False``.
204+
205+
.. warning::
206+
207+
There are no events related to application emojis - if any are created/deleted on the
208+
Developer Dashboard while the client is running, the cache will not be updated until you manually
209+
run :func:`fetch_emojis`.
210+
211+
.. versionadded:: 2.7
202212
203213
Attributes
204214
-----------
@@ -330,10 +340,30 @@ def guilds(self) -> list[Guild]:
330340
return self._connection.guilds
331341

332342
@property
333-
def emojis(self) -> list[Emoji]:
334-
"""The emojis that the connected client has."""
343+
def emojis(self) -> list[GuildEmoji | AppEmoji]:
344+
"""The emojis that the connected client has.
345+
346+
.. note::
347+
348+
This only includes the application's emojis if `cache_app_emojis` is ``True``.
349+
"""
335350
return self._connection.emojis
336351

352+
@property
353+
def guild_emojis(self) -> list[GuildEmoji]:
354+
"""The :class:`~discord.GuildEmoji` that the connected client has."""
355+
return [e for e in self.emojis if isinstance(e, GuildEmoji)]
356+
357+
@property
358+
def app_emojis(self) -> list[AppEmoji]:
359+
"""The :class:`~discord.AppEmoji` that the connected client has.
360+
361+
.. note::
362+
363+
This is only available if `cache_app_emojis` is ``True``.
364+
"""
365+
return [e for e in self.emojis if isinstance(e, AppEmoji)]
366+
337367
@property
338368
def stickers(self) -> list[GuildSticker]:
339369
"""The stickers that the connected client has.
@@ -684,6 +714,7 @@ async def close(self) -> None:
684714
if self._closed:
685715
return
686716

717+
await self.http.close()
687718
self._closed = True
688719

689720
for voice in self.voice_clients:
@@ -696,7 +727,6 @@ async def close(self) -> None:
696727
if self.ws is not None and self.ws.open:
697728
await self.ws.close(code=1000)
698729

699-
await self.http.close()
700730
self._ready.clear()
701731

702732
def clear(self) -> None:
@@ -994,7 +1024,7 @@ def get_user(self, id: int, /) -> User | None:
9941024
"""
9951025
return self._connection.get_user(id)
9961026

997-
def get_emoji(self, id: int, /) -> Emoji | None:
1027+
def get_emoji(self, id: int, /) -> GuildEmoji | AppEmoji | None:
9981028
"""Returns an emoji with the given ID.
9991029
10001030
Parameters
@@ -1004,7 +1034,7 @@ def get_emoji(self, id: int, /) -> Emoji | None:
10041034
10051035
Returns
10061036
-------
1007-
Optional[:class:`.Emoji`]
1037+
Optional[:class:`.GuildEmoji` | :class:`.AppEmoji`]
10081038
The custom emoji or ``None`` if not found.
10091039
"""
10101040
return self._connection.get_emoji(id)
@@ -2130,3 +2160,112 @@ def store_url(self) -> str:
21302160
.. versionadded:: 2.6
21312161
"""
21322162
return f"https://discord.com/application-directory/{self.application_id}/store"
2163+
2164+
async def fetch_emojis(self) -> list[AppEmoji]:
2165+
r"""|coro|
2166+
2167+
Retrieves all custom :class:`AppEmoji`\s from the application.
2168+
2169+
Raises
2170+
---------
2171+
HTTPException
2172+
An error occurred fetching the emojis.
2173+
2174+
Returns
2175+
--------
2176+
List[:class:`AppEmoji`]
2177+
The retrieved emojis.
2178+
"""
2179+
data = await self._connection.http.get_all_application_emojis(
2180+
self.application_id
2181+
)
2182+
return [
2183+
self._connection.maybe_store_app_emoji(self.application_id, d)
2184+
for d in data["items"]
2185+
]
2186+
2187+
async def fetch_emoji(self, emoji_id: int, /) -> AppEmoji:
2188+
"""|coro|
2189+
2190+
Retrieves a custom :class:`AppEmoji` from the application.
2191+
2192+
Parameters
2193+
----------
2194+
emoji_id: :class:`int`
2195+
The emoji's ID.
2196+
2197+
Returns
2198+
-------
2199+
:class:`AppEmoji`
2200+
The retrieved emoji.
2201+
2202+
Raises
2203+
------
2204+
NotFound
2205+
The emoji requested could not be found.
2206+
HTTPException
2207+
An error occurred fetching the emoji.
2208+
"""
2209+
data = await self._connection.http.get_application_emoji(
2210+
self.application_id, emoji_id
2211+
)
2212+
return self._connection.maybe_store_app_emoji(self.application_id, data)
2213+
2214+
async def create_emoji(
2215+
self,
2216+
*,
2217+
name: str,
2218+
image: bytes,
2219+
) -> AppEmoji:
2220+
r"""|coro|
2221+
2222+
Creates a custom :class:`AppEmoji` for the application.
2223+
2224+
There is currently a limit of 2000 emojis per application.
2225+
2226+
Parameters
2227+
-----------
2228+
name: :class:`str`
2229+
The emoji name. Must be at least 2 characters.
2230+
image: :class:`bytes`
2231+
The :term:`py:bytes-like object` representing the image data to use.
2232+
Only JPG, PNG and GIF images are supported.
2233+
2234+
Raises
2235+
-------
2236+
HTTPException
2237+
An error occurred creating an emoji.
2238+
2239+
Returns
2240+
--------
2241+
:class:`AppEmoji`
2242+
The created emoji.
2243+
"""
2244+
2245+
img = utils._bytes_to_base64_data(image)
2246+
data = await self._connection.http.create_application_emoji(
2247+
self.application_id, name, img
2248+
)
2249+
return self._connection.maybe_store_app_emoji(self.application_id, data)
2250+
2251+
async def delete_emoji(self, emoji: Snowflake) -> None:
2252+
"""|coro|
2253+
2254+
Deletes the custom :class:`AppEmoji` from the application.
2255+
2256+
Parameters
2257+
----------
2258+
emoji: :class:`abc.Snowflake`
2259+
The emoji you are deleting.
2260+
2261+
Raises
2262+
------
2263+
HTTPException
2264+
An error occurred deleting the emoji.
2265+
"""
2266+
2267+
await self._connection.http.delete_application_emoji(
2268+
self.application_id, emoji.id
2269+
)
2270+
if self._connection.cache_app_emojis and self._connection.get_emoji(emoji.id):
2271+
self._connection.remove_emoji(emoji)

0 commit comments

Comments
 (0)