diff --git a/CHANGELOG.md b/CHANGELOG.md index fdfdc6d896..10e1c4532e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2714](https://github.com/Pycord-Development/pycord/pull/2714)) - Added the ability to pass a `datetime.time` object to `format_dt`. ([#2747](https://github.com/Pycord-Development/pycord/pull/2747)) +- Added various missing channel parameters and allow `default_reaction_emoji` to be + `None`. ([#2772](https://github.com/Pycord-Development/pycord/pull/2772)) - Added `discord.Interaction.created_at`. ([#2801](https://github.com/Pycord-Development/pycord/pull/2801)) @@ -147,6 +149,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2501](https://github.com/Pycord-Development/pycord/pull/2501)) - Deprecated `Interaction.cached_channel` in favor of `Interaction.channel`. ([#2658](https://github.com/Pycord-Development/pycord/pull/2658)) +- Deprecated `is_nsfw` for categories since it was never supported by the API. + ([#2772](https://github.com/Pycord-Development/pycord/pull/2772)) ### Removed diff --git a/discord/channel.py b/discord/channel.py index be6c68b38a..10beeca59e 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -812,7 +812,7 @@ async def edit(self, *, reason=None, **options): position: :class:`int` The new channel's position. nsfw: :class:`bool` - To mark the channel as NSFW or not. + Whether the channel is marked as NSFW. sync_permissions: :class:`bool` Whether to sync permissions with the channel's new or pre-existing category. Defaults to ``False``. @@ -1039,6 +1039,8 @@ def _update(self, guild: Guild, data: ForumChannelPayload) -> None: if self.default_sort_order is not None: self.default_sort_order = try_enum(SortOrder, self.default_sort_order) + self.default_reaction_emoji = 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") @@ -1113,7 +1115,7 @@ async def edit(self, *, reason=None, **options): position: :class:`int` The new channel's position. nsfw: :class:`bool` - To mark the channel as NSFW or not. + Whether the channel is marked as NSFW. sync_permissions: :class:`bool` Whether to sync permissions with the channel's new or pre-existing category. Defaults to ``False``. @@ -1476,7 +1478,7 @@ async def edit(self, *, reason=None, **options): position: :class:`int` The new channel's position. nsfw: :class:`bool` - To mark the channel as NSFW or not. + Whether the channel is marked as NSFW. sync_permissions: :class:`bool` Whether to sync permissions with the channel's new or pre-existing category. Defaults to ``False``. @@ -1724,6 +1726,11 @@ class VoiceChannel(discord.abc.Messageable, VocalGuildChannel): Extra features of the channel. .. versionadded:: 2.0 + + nsfw: :class:`bool` + Whether the channel is marked as NSFW. + + .. versionadded:: 2.7 """ def __init__( @@ -2042,6 +2049,7 @@ async def edit( rtc_region: VoiceRegion | None = ..., video_quality_mode: VideoQualityMode = ..., slowmode_delay: int = ..., + nsfw: bool = ..., reason: str | None = ..., ) -> VoiceChannel | None: ... @@ -2092,6 +2100,15 @@ async def edit(self, *, reason=None, **options): .. versionadded:: 2.0 + slowmode_delay: :class:`int` + Specifies the slowmode rate limit for user in this channel, in seconds. + A value of `0` disables slowmode. The maximum value possible is `21600`. + + nsfw: :class:`bool` + Whether the channel is marked as NSFW. + + .. versionadded:: 2.7 + Returns ------- Optional[:class:`.VoiceChannel`] @@ -2250,6 +2267,15 @@ class StageChannel(discord.abc.Messageable, VocalGuildChannel): last_message_id: Optional[:class:`int`] The ID of the last message sent to this channel. It may not always point to an existing or valid message. .. versionadded:: 2.5 + + slowmode_delay: :class:`int` + Specifies the slowmode rate limit for user in this channel, in seconds. + The maximum value possible is `21600`. + + nsfw: :class:`bool` + Whether the channel is marked as NSFW. + + .. versionadded:: 2.7 """ __slots__ = ("topic",) @@ -2734,6 +2760,16 @@ async def edit(self, *, reason=None, **options): .. versionadded:: 2.0 + bitrate: :class:`int` + The channel's preferred audio bitrate in bits per second. + + user_limit: :class:`int` + The channel's limit for number of members that can be in a voice channel. + + slowmode_delay: :class:`int` + Specifies the slowmode rate limit for user in this channel, in seconds. + A value of `0` disables slowmode. The maximum value possible is `21600`. + Returns ------- Optional[:class:`.StageChannel`] @@ -2790,12 +2826,9 @@ class CategoryChannel(discord.abc.GuildChannel, Hashable): position: Optional[:class:`int`] The position in the category list. This is a number that starts at 0. e.g. the top category is position 0. Can be ``None`` if the channel was received in an interaction. - nsfw: :class:`bool` - If the channel is marked as "not safe for work". .. note:: - To check if the channel or the guild of that channel are marked as NSFW, consider :meth:`is_nsfw` instead. flags: :class:`ChannelFlags` Extra features of the channel. @@ -2823,8 +2856,7 @@ def __init__( def __repr__(self) -> str: return ( - "" + f" None: @@ -2832,10 +2864,10 @@ def _update(self, guild: Guild, data: CategoryChannelPayload) -> None: self.guild: Guild = guild self.name: str = data["name"] self.category_id: int | None = utils._get_as_snowflake(data, "parent_id") + self.nsfw = False # This data may be missing depending on how this object is being created/updated if not data.pop("_invoke_flag", False): - self.nsfw: bool = data.get("nsfw", False) self.position: int = data.get("position") self.flags: ChannelFlags = ChannelFlags._from_value(data.get("flags", 0)) self._fill_overwrites(data) @@ -2849,15 +2881,11 @@ def type(self) -> ChannelType: """The channel's Discord type.""" return ChannelType.category - def is_nsfw(self) -> bool: - """Checks if the category is NSFW.""" - return self.nsfw - @utils.copy_doc(discord.abc.GuildChannel.clone) async def clone( self, *, name: str | None = None, reason: str | None = None ) -> CategoryChannel: - return await self._clone_impl({"nsfw": self.nsfw}, name=name, reason=reason) + return await self._clone_impl({}, name=name, reason=reason) @overload async def edit( @@ -2865,7 +2893,6 @@ async def edit( *, name: str = ..., position: int = ..., - nsfw: bool = ..., overwrites: Mapping[Role | Member, PermissionOverwrite] = ..., reason: str | None = ..., ) -> CategoryChannel | None: ... @@ -2893,8 +2920,6 @@ async def edit(self, *, reason=None, **options): The new category's name. position: :class:`int` The new category's position. - nsfw: :class:`bool` - To mark the category as NSFW or not. reason: Optional[:class:`str`] The reason for editing this category. Shows up on the audit log. overwrites: Dict[Union[:class:`Role`, :class:`Member`, :class:`~discord.abc.Snowflake`], :class:`PermissionOverwrite`] @@ -3042,6 +3067,16 @@ async def create_forum_channel(self, name: str, **options: Any) -> ForumChannel: """ return await self.guild.create_forum_channel(name, category=self, **options) + @utils.deprecated( + since="2.7", + removed="3.0", + reference="Category NSFW was never supported by the API.", + ) + def is_nsfw(self) -> bool: + return False + + # TODO: Remove in 3.0 + DMC = TypeVar("DMC", bound="DMChannel") diff --git a/discord/guild.py b/discord/guild.py index 6a9d54537a..4bf8a1d054 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -1130,6 +1130,8 @@ async def create_text_channel( slowmode_delay: int = MISSING, nsfw: bool = MISSING, overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, + default_thread_slowmode_delay: int | None = MISSING, + default_auto_archive_duration: int = MISSING, ) -> TextChannel: """|coro| @@ -1166,12 +1168,22 @@ async def create_text_channel( The new channel's topic. slowmode_delay: :class:`int` Specifies the slowmode rate limit for user in this channel, in seconds. - The maximum value possible is `21600`. + A value of `0` disables slowmode. The maximum value possible is `21600`. nsfw: :class:`bool` - To mark the channel as NSFW or not. + Whether the channel is marked as NSFW. reason: Optional[:class:`str`] The reason for creating this channel. Shows up on the audit log. + default_thread_slowmode_delay: Optional[:class:`int`] + The initial slowmode delay to set on newly created threads in this channel. + + .. versionadded:: 2.7 + + default_auto_archive_duration: :class:`int` + The default auto archive duration in minutes for threads created in this channel. + + .. versionadded:: 2.7 + Returns ------- :class:`TextChannel` @@ -1220,6 +1232,12 @@ async def create_text_channel( if nsfw is not MISSING: options["nsfw"] = nsfw + if default_thread_slowmode_delay is not MISSING: + options["default_thread_slowmode_delay"] = default_thread_slowmode_delay + + if default_auto_archive_duration is not MISSING: + options["default_auto_archive_duration"] = default_auto_archive_duration + data = await self._create_channel( name, overwrites=overwrites, @@ -1246,6 +1264,8 @@ async def create_voice_channel( rtc_region: VoiceRegion | None = MISSING, video_quality_mode: VideoQualityMode = MISSING, overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, + slowmode_delay: int = MISSING, + nsfw: bool = MISSING, ) -> VoiceChannel: """|coro| @@ -1280,6 +1300,17 @@ async def create_voice_channel( reason: Optional[:class:`str`] The reason for creating this channel. Shows up on the audit log. + slowmode_delay: :class:`int` + Specifies the slowmode rate limit for user in this channel, in seconds. + A value of `0` disables slowmode. The maximum value possible is `21600`. + + .. versionadded:: 2.7 + + nsfw: :class:`bool` + Whether the channel is marked as NSFW. + + .. versionadded:: 2.7 + Returns ------- :class:`VoiceChannel` @@ -1310,6 +1341,12 @@ async def create_voice_channel( if video_quality_mode is not MISSING: options["video_quality_mode"] = video_quality_mode.value + if slowmode_delay is not MISSING: + options["rate_limit_per_user"] = slowmode_delay + + if nsfw is not MISSING: + options["nsfw"] = nsfw + data = await self._create_channel( name, overwrites=overwrites, @@ -1333,6 +1370,12 @@ async def create_stage_channel( overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, category: CategoryChannel | None = None, reason: str | None = None, + bitrate: int = MISSING, + user_limit: int = MISSING, + rtc_region: VoiceRegion | None = MISSING, + video_quality_mode: VideoQualityMode = MISSING, + slowmode_delay: int = MISSING, + nsfw: bool = MISSING, ) -> StageChannel: """|coro| @@ -1358,6 +1401,38 @@ async def create_stage_channel( reason: Optional[:class:`str`] The reason for creating this channel. Shows up on the audit log. + bitrate: :class:`int` + The channel's preferred audio bitrate in bits per second. + + .. versionadded:: 2.7 + + user_limit: :class:`int` + The channel's limit for number of members that can be in a voice channel. + + .. versionadded:: 2.7 + + rtc_region: Optional[:class:`VoiceRegion`] + The region for the voice channel's voice communication. + A value of ``None`` indicates automatic voice region detection. + + .. versionadded:: 2.7 + + video_quality_mode: :class:`VideoQualityMode` + The camera video quality for the voice channel's participants. + + .. versionadded:: 2.7 + + slowmode_delay: :class:`int` + Specifies the slowmode rate limit for user in this channel, in seconds. + A value of `0` disables slowmode. The maximum value possible is `21600`. + + .. versionadded:: 2.7 + + nsfw: :class:`bool` + Whether the channel is marked as NSFW. + + .. versionadded:: 2.7 + Returns ------- :class:`StageChannel` @@ -1379,6 +1454,24 @@ async def create_stage_channel( if position is not MISSING: options["position"] = position + if bitrate is not MISSING: + options["bitrate"] = bitrate + + if user_limit is not MISSING: + options["user_limit"] = user_limit + + if rtc_region is not MISSING: + options["rtc_region"] = None if rtc_region is None else str(rtc_region) + + if video_quality_mode is not MISSING: + options["video_quality_mode"] = video_quality_mode.value + + if slowmode_delay is not MISSING: + options["rate_limit_per_user"] = slowmode_delay + + if nsfw is not MISSING: + options["nsfw"] = nsfw + data = await self._create_channel( name, overwrites=overwrites, @@ -1405,6 +1498,10 @@ async def create_forum_channel( nsfw: bool = MISSING, overwrites: dict[Role | Member, PermissionOverwrite] = MISSING, default_reaction_emoji: GuildEmoji | int | str = MISSING, + available_tags: list[ForumTag] = MISSING, + default_sort_order: SortOrder | None = MISSING, + default_thread_slowmode_delay: int | None = MISSING, + default_auto_archive_duration: int = MISSING, ) -> ForumChannel: """|coro| @@ -1441,9 +1538,9 @@ async def create_forum_channel( The new channel's topic. slowmode_delay: :class:`int` Specifies the slowmode rate limit for user in this channel, in seconds. - The maximum value possible is `21600`. + A value of `0` disables slowmode. The maximum value possible is `21600`. nsfw: :class:`bool` - To mark the channel as NSFW or not. + Whether the channel is marked as NSFW. reason: Optional[:class:`str`] The reason for creating this channel. Shows up on the audit log. default_reaction_emoji: Optional[:class:`GuildEmoji` | :class:`int` | :class:`str`] @@ -1453,6 +1550,26 @@ async def create_forum_channel( .. versionadded:: v2.5 + available_tags: List[:class:`ForumTag`] + The set of tags that can be used in a forum channel. + + .. versionadded:: 2.7 + + default_sort_order: Optional[:class:`SortOrder`] + The default sort order type used to order posts in this channel. + + .. versionadded:: 2.7 + + default_thread_slowmode_delay: Optional[:class:`int`] + The initial slowmode delay to set on newly created threads in this channel. + + .. versionadded:: 2.7 + + default_auto_archive_duration: :class:`int` + The default auto archive duration in minutes for threads created in this channel. + + .. versionadded:: 2.7 + Returns ------- :class:`ForumChannel` @@ -1501,6 +1618,20 @@ async def create_forum_channel( if nsfw is not MISSING: options["nsfw"] = nsfw + if available_tags is not MISSING: + options["available_tags"] = [tag.to_dict() for tag in available_tags] + + if default_sort_order is not MISSING: + options["default_sort_order"] = ( + default_sort_order.value if default_sort_order else None + ) + + if default_thread_slowmode_delay is not MISSING: + options["default_thread_slowmode_delay"] = default_thread_slowmode_delay + + if default_auto_archive_duration is not MISSING: + options["default_auto_archive_duration"] = default_auto_archive_duration + if default_reaction_emoji is not MISSING: if isinstance( default_reaction_emoji, _EmojiTag @@ -1512,13 +1643,17 @@ async def create_forum_channel( ) elif isinstance(default_reaction_emoji, str): default_reaction_emoji = PartialEmoji.from_str(default_reaction_emoji) + elif default_reaction_emoji is None: + pass else: raise InvalidArgument( - "default_reaction_emoji must be of type: GuildEmoji | int | str" + "default_reaction_emoji must be of type: GuildEmoji | int | str | None" ) options["default_reaction_emoji"] = ( default_reaction_emoji._to_forum_reaction_payload() + if default_reaction_emoji + else None ) data = await self._create_channel(