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: ForumChannel default_reaction_emoji attribute #2178

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -72,6 +72,9 @@ These changes are available on the `master` branch, but have not yet been releas
- Added `suppress` and `allowed_mentions` parameters to `Webhook` and
`InteractionResponse` edit methods.
([#2138](https://github.com/Pycord-Development/pycord/pull/2138))
- Added `Guild.create_forum_channel` parameter and `ForumChannel` attribute:
`default_reaction_emoji`.
Lulalaby marked this conversation as resolved.
Show resolved Hide resolved
([#2178](https://github.com/Pycord-Development/pycord/pull/2178))

### Changed

Expand Down
23 changes: 23 additions & 0 deletions discord/abc.py
Expand Up @@ -50,6 +50,7 @@
from .invite import Invite
from .iterators import HistoryIterator
from .mentions import AllowedMentions
from .partial_emoji import PartialEmoji, _EmojiTag
from .permissions import PermissionOverwrite, Permissions
from .role import Role
from .scheduled_events import ScheduledEvent
Expand Down Expand Up @@ -507,6 +508,28 @@ async def _edit(
raise InvalidArgument("type field must be of type ChannelType")
options["type"] = ch_type.value

try:
default_reaction_emoji = options["default_reaction_emoji"]
except KeyError:
pass
else:
if isinstance(default_reaction_emoji, _EmojiTag): # Emoji, PartialEmoji
default_reaction_emoji = default_reaction_emoji._to_partial()
elif isinstance(default_reaction_emoji, int):
default_reaction_emoji = PartialEmoji(
name=None, id=default_reaction_emoji
)
elif isinstance(default_reaction_emoji, str):
default_reaction_emoji = PartialEmoji.from_str(default_reaction_emoji)
else:
raise InvalidArgument(
"default_reaction_emoji must be of type: Emoji | int | str"
)

options[
"default_reaction_emoji"
] = default_reaction_emoji._to_forum_reaction_payload()

if options:
return await self._state.http.edit_channel(
self.id, reason=reason, **options
Expand Down
25 changes: 23 additions & 2 deletions discord/channel.py
Expand Up @@ -32,6 +32,7 @@

from . import utils
from .asset import Asset
from .emoji import Emoji
from .enums import (
ChannelType,
EmbeddedActivity,
Expand Down Expand Up @@ -171,7 +172,7 @@ def to_dict(self) -> dict[str, Any]:
payload: dict[str, Any] = {
"name": self.name,
"moderated": self.moderated,
} | self.emoji._to_forum_tag_payload()
} | self.emoji._to_forum_reaction_payload()

if self.id:
payload["id"] = self.id
Expand All @@ -195,6 +196,7 @@ class _TextChannel(discord.abc.GuildChannel, Hashable):
"last_message_id",
"default_auto_archive_duration",
"default_thread_slowmode_delay",
"default_reaction_emoji",
"default_sort_order",
"available_tags",
"flags",
Expand Down Expand Up @@ -228,7 +230,6 @@ def _update(
self.name: str = data["name"]
self.category_id: int | None = utils._get_as_snowflake(data, "parent_id")
self._type: int = data["type"]

# This data may be missing depending on how this object is being created/updated
if not data.pop("_invoke_flag", False):
self.topic: str | None = data.get("topic")
Expand Down Expand Up @@ -1008,6 +1009,10 @@ 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`]
The default forum reaction emoji.

.. versionadded:: 2.5
"""

def __init__(
Expand All @@ -1022,6 +1027,15 @@ def _update(self, guild: Guild, data: ForumChannelPayload) -> None:
for tag in (data.get("available_tags") or [])
]
self.default_sort_order: SortOrder | None = data.get("default_sort_order", None)
reaction_emoji_ctx: dict = data.get("default_reaction_emoji")
if reaction_emoji_ctx is not None:
emoji_name = reaction_emoji_ctx.get("emoji_name")
if emoji_name is not None:
self.default_reaction_emoji = reaction_emoji_ctx["emoji_name"]
else:
self.default_reaction_emoji = self._state.get_emoji(
utils._get_as_snowflake(reaction_emoji_ctx, "emoji_id")
)

@property
def guidelines(self) -> str | None:
Expand Down Expand Up @@ -1061,6 +1075,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 = ...,
available_tags: list[ForumTag] = ...,
require_tag: bool = ...,
overwrites: Mapping[Role | Member | Snowflake, PermissionOverwrite] = ...,
Expand Down Expand Up @@ -1113,6 +1128,12 @@ 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`]
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>').

.. versionadded:: 2.5
available_tags: List[:class:`ForumTag`]
The set of tags that can be used in this channel. Must be less than `20`.

Expand Down
29 changes: 27 additions & 2 deletions discord/guild.py
Expand Up @@ -47,7 +47,7 @@
from .channel import *
from .channel import _guild_channel_factory, _threaded_guild_channel_factory
from .colour import Colour
from .emoji import Emoji
from .emoji import Emoji, PartialEmoji, _EmojiTag
from .enums import (
AuditLogAction,
AutoModEventType,
Expand Down Expand Up @@ -1395,6 +1395,7 @@ async def create_forum_channel(
slowmode_delay: int = MISSING,
nsfw: bool = MISSING,
overwrites: dict[Role | Member, PermissionOverwrite] = MISSING,
default_reaction_emoji: Emoji | int | str = MISSING,
) -> ForumChannel:
"""|coro|

Expand Down Expand Up @@ -1436,6 +1437,12 @@ async def create_forum_channel(
To mark the channel as NSFW or not.
reason: Optional[:class:`str`]
The reason for creating this channel. Shows up on the audit log.
default_reaction_emoji: Optional[:class:`Emoji` | :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>').

.. versionadded:: v2.5

Returns
-------
Expand All @@ -1449,7 +1456,7 @@ async def create_forum_channel(
HTTPException
Creating the channel failed.
InvalidArgument
The permission overwrite information is not in proper form.
The argument is not in proper form.

Examples
--------
Expand Down Expand Up @@ -1485,6 +1492,24 @@ async def create_forum_channel(
if nsfw is not MISSING:
options["nsfw"] = nsfw

if default_reaction_emoji is not MISSING:
if isinstance(default_reaction_emoji, _EmojiTag): # Emoji, PartialEmoji
default_reaction_emoji = default_reaction_emoji._to_partial()
elif isinstance(default_reaction_emoji, int):
default_reaction_emoji = PartialEmoji(
name=None, id=default_reaction_emoji
)
elif isinstance(default_reaction_emoji, str):
default_reaction_emoji = PartialEmoji.from_str(default_reaction_emoji)
else:
raise InvalidArgument(
"default_reaction_emoji must be of type: Emoji | int | str"
)

options[
"default_reaction_emoji"
] = default_reaction_emoji._to_forum_reaction_payload()

data = await self._create_channel(
name,
overwrites=overwrites,
Expand Down
1 change: 1 addition & 0 deletions discord/http.py
Expand Up @@ -1093,6 +1093,7 @@ def create_channel(
"rtc_region",
"video_quality_mode",
"auto_archive_duration",
"default_reaction_emoji",
)
payload.update(
{k: v for k, v in options.items() if k in valid_keys and v is not None}
Expand Down
8 changes: 4 additions & 4 deletions discord/partial_emoji.py
Expand Up @@ -160,11 +160,11 @@ def to_dict(self) -> dict[str, Any]:
def _to_partial(self) -> PartialEmoji:
return self

def _to_forum_tag_payload(
def _to_forum_reaction_payload(
self,
) -> TypedDict("TagPayload", {"emoji_id": int, "emoji_name": None}) | TypedDict(
"TagPayload", {"emoji_id": None, "emoji_name": str}
):
) -> TypedDict(
"ReactionPayload", {"emoji_id": int, "emoji_name": None}
) | TypedDict("ReactionPayload", {"emoji_id": None, "emoji_name": str}):
if self.id is None:
return {"emoji_id": None, "emoji_name": self.name}
else:
Expand Down