From 1aa0bf33a214acb5462c17c07dfdb61f16318668 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 22 Feb 2023 17:54:51 +0000 Subject: [PATCH 1/6] Support for text in stage --- discord/abc.py | 5 +- discord/channel.py | 234 +++++++++++++++++++++++++++++++++++++++++++-- discord/message.py | 7 +- discord/state.py | 4 +- 4 files changed, 237 insertions(+), 13 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index 4ab10409c0..85fc4c7535 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -79,6 +79,7 @@ PartialMessageable, TextChannel, VoiceChannel, + StageChannel ) from .client import Client from .embeds import Embed @@ -97,7 +98,7 @@ from .user import ClientUser PartialMessageableChannel = Union[ - TextChannel, VoiceChannel, Thread, DMChannel, PartialMessageable + TextChannel, VoiceChannel, StageChannel, Thread, DMChannel, PartialMessageable ] MessageableChannel = Union[PartialMessageableChannel, GroupChannel] SnowflakeTime = Union["Snowflake", datetime] @@ -1292,6 +1293,8 @@ class Messageable: The following implement this ABC: - :class:`~discord.TextChannel` + - :class:`~discord.VoiceChannel` + - :class:`~discord.StageChannel` - :class:`~discord.DMChannel` - :class:`~discord.GroupChannel` - :class:`~discord.User` diff --git a/discord/channel.py b/discord/channel.py index 2efca7be02..925e891d50 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -1358,6 +1358,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha "video_quality_mode", "last_message_id", "flags", + "nsfw" ) def __init__( @@ -1401,6 +1402,7 @@ def _update( self.bitrate: int = data.get("bitrate") self.user_limit: int = data.get("user_limit") self.flags: ChannelFlags = ChannelFlags._from_value(data.get("flags", 0)) + self.nsfw: bool = data.get("nsfw", False) self._fill_overwrites(data) @property @@ -1510,11 +1512,8 @@ class VoiceChannel(discord.abc.Messageable, VocalGuildChannel): .. versionadded:: 2.0 """ - __slots__ = "nsfw" - def _update(self, guild: Guild, data: VoiceChannelPayload): super()._update(guild, data) - self.nsfw: bool = data.get("nsfw", False) def __repr__(self) -> str: attrs = [ @@ -1944,7 +1943,7 @@ async def create_activity_invite( ) -class StageChannel(VocalGuildChannel): +class StageChannel(discord.abc.Messageable, VocalGuildChannel): """Represents a Discord guild stage channel. .. versionadded:: 1.7 @@ -1997,10 +1996,17 @@ class StageChannel(VocalGuildChannel): Extra features of the channel. .. versionadded:: 2.0 + 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 """ __slots__ = ("topic",) + def _update(self, guild: Guild, data: StageChannelPayload) -> None: + super()._update(guild, data) + self.topic = data.get("topic") + def __repr__(self) -> str: attrs = [ ("id", self.id), @@ -2016,10 +2022,6 @@ def __repr__(self) -> str: joined = " ".join("%s=%r" % t for t in attrs) return f"<{self.__class__.__name__} {joined}>" - def _update(self, guild: Guild, data: StageChannelPayload) -> None: - super()._update(guild, data) - self.topic = data.get("topic") - @property def requesting_to_speak(self) -> list[Member]: """A list of members who are requesting to speak in the stage channel.""" @@ -2053,6 +2055,222 @@ def listeners(self) -> list[Member]: member for member in self.members if member.voice and member.voice.suppress ] + async def _get_channel(self): + return self + + @property + def last_message(self) -> Optional[Message]: + """Fetches the last message from this channel in cache. + The message might not be valid or point to an existing message. + .. admonition:: Reliable Fetching + :class: helpful + For a slightly more reliable method of fetching the + last message, consider using either :meth:`history` + or :meth:`fetch_message` with the :attr:`last_message_id` + attribute. + Returns + --------- + Optional[:class:`Message`] + The last message in this channel or ``None`` if not found. + """ + return self._state._get_message(self.last_message_id) if self.last_message_id else None + + def get_partial_message(self, message_id: int, /) -> PartialMessage: + """Creates a :class:`PartialMessage` from the message ID. + This is useful if you want to work with a message and only have its ID without + doing an unnecessary API call. + .. versionadded:: 1.6 + Parameters + ------------ + message_id: :class:`int` + The message ID to create a partial message for. + Returns + --------- + :class:`PartialMessage` + The partial message. + """ + + from .message import PartialMessage + + return PartialMessage(channel=self, id=message_id) + + async def delete_messages(self, messages: Iterable[Snowflake], *, reason: Optional[str] = None) -> None: + """|coro| + Deletes a list of messages. This is similar to :meth:`Message.delete` + except it bulk deletes multiple messages. + As a special case, if the number of messages is 0, then nothing + is done. If the number of messages is 1 then single message + delete is done. If it's more than two, then bulk delete is used. + You cannot bulk delete more than 100 messages or messages that + are older than 14 days old. + You must have the :attr:`~Permissions.manage_messages` permission to + use this. + Parameters + ----------- + messages: Iterable[:class:`abc.Snowflake`] + An iterable of messages denoting which ones to bulk delete. + reason: Optional[:class:`str`] + The reason for deleting the messages. Shows up on the audit log. + Raises + ------ + ClientException + The number of messages to delete was more than 100. + Forbidden + You do not have proper permissions to delete the messages. + NotFound + If single delete, then the message was already deleted. + HTTPException + Deleting the messages failed. + """ + if not isinstance(messages, (list, tuple)): + messages = list(messages) + + if len(messages) == 0: + return # do nothing + + if len(messages) == 1: + message_id: int = messages[0].id + await self._state.http.delete_message(self.id, message_id, reason=reason) + return + + if len(messages) > 100: + raise ClientException("Can only bulk delete messages up to 100 messages") + + message_ids: SnowflakeList = [m.id for m in messages] + await self._state.http.delete_messages(self.id, message_ids, reason=reason) + + async def purge( + self, + *, + limit: Optional[int] = 100, + check: Callable[[Message], bool] = MISSING, + before: Optional[SnowflakeTime] = None, + after: Optional[SnowflakeTime] = None, + around: Optional[SnowflakeTime] = None, + oldest_first: Optional[bool] = False, + bulk: bool = True, + reason: Optional[str] = None, + ) -> List[Message]: + """|coro| + Purges a list of messages that meet the criteria given by the predicate + ``check``. If a ``check`` is not provided then all messages are deleted + without discrimination. + You must have the :attr:`~Permissions.manage_messages` permission to + delete messages even if they are your own. + The :attr:`~Permissions.read_message_history` permission is + also needed to retrieve message history. + Examples + --------- + Deleting bot's messages :: + def is_me(m): + return m.author == client.user + deleted = await channel.purge(limit=100, check=is_me) + await channel.send(f'Deleted {len(deleted)} message(s)') + Parameters + ----------- + limit: Optional[:class:`int`] + The number of messages to search through. This is not the number + of messages that will be deleted, though it can be. + check: Callable[[:class:`Message`], :class:`bool`] + The function used to check if a message should be deleted. + It must take a :class:`Message` as its sole parameter. + before: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]] + Same as ``before`` in :meth:`history`. + after: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]] + Same as ``after`` in :meth:`history`. + around: Optional[Union[:class:`abc.Snowflake`, :class:`datetime.datetime`]] + Same as ``around`` in :meth:`history`. + oldest_first: Optional[:class:`bool`] + Same as ``oldest_first`` in :meth:`history`. + bulk: :class:`bool` + If ``True``, use bulk delete. Setting this to ``False`` is useful for mass-deleting + a bot's own messages without :attr:`Permissions.manage_messages`. When ``True``, will + fall back to single delete if messages are older than two weeks. + reason: Optional[:class:`str`] + The reason for deleting the messages. Shows up on the audit log. + Raises + ------- + Forbidden + You do not have proper permissions to do the actions required. + HTTPException + Purging the messages failed. + Returns + -------- + List[:class:`.Message`] + The list of messages that were deleted. + """ + return await discord.abc._purge_messages_helper( + self, + limit=limit, + check=check, + before=before, + after=after, + around=around, + oldest_first=oldest_first, + bulk=bulk, + reason=reason, + ) + + async def webhooks(self) -> List[Webhook]: + """|coro| + Gets the list of webhooks from this channel. + Requires :attr:`~.Permissions.manage_webhooks` permissions. + Raises + ------- + Forbidden + You don't have permissions to get the webhooks. + Returns + -------- + List[:class:`Webhook`] + The webhooks for this channel. + """ + + from .webhook import Webhook + + data = await self._state.http.channel_webhooks(self.id) + return [Webhook.from_state(d, state=self._state) for d in data] + + async def create_webhook( + self, *, name: str, avatar: Optional[bytes] = None, reason: Optional[str] = None + ) -> Webhook: + """|coro| + Creates a webhook for this channel. + Requires :attr:`~.Permissions.manage_webhooks` permissions. + .. versionchanged:: 1.1 + Added the ``reason`` keyword-only parameter. + Parameters + ------------- + name: :class:`str` + The webhook's name. + avatar: Optional[:class:`bytes`] + A :term:`py:bytes-like object` representing the webhook's default avatar. + This operates similarly to :meth:`~ClientUser.edit`. + reason: Optional[:class:`str`] + The reason for creating this webhook. Shows up in the audit logs. + Raises + ------- + HTTPException + Creating the webhook failed. + Forbidden + You do not have permissions to create a webhook. + Returns + -------- + :class:`Webhook` + The created webhook. + """ + + from .webhook import Webhook + + if avatar is not None: + avatar = utils._bytes_to_base64_data(avatar) # type: ignore + + data = await self._state.http.create_webhook(self.id, name=str(name), avatar=avatar, reason=reason) + return Webhook.from_state(data, state=self._state) + + def is_nsfw(self) -> bool: + """Checks if the channel is NSFW.""" + return self.nsfw + @property def moderators(self) -> list[Member]: """A list of members who are moderating the stage channel. diff --git a/discord/message.py b/discord/message.py index e299113369..69c7a79753 100644 --- a/discord/message.py +++ b/discord/message.py @@ -1798,6 +1798,8 @@ class PartialMessage(Hashable): - :meth:`TextChannel.get_partial_message` - :meth:`Thread.get_partial_message` - :meth:`DMChannel.get_partial_message` + - :meth:`VoiceChannel.get_partial_message` + - :meth:`StageChannel.get_partial_message` Note that this class is trimmed down and has no rich attributes. @@ -1819,7 +1821,7 @@ class PartialMessage(Hashable): Attributes ---------- - channel: Union[:class:`TextChannel`, :class:`Thread`, :class:`DMChannel`] + channel: Union[:class:`TextChannel`, :class:`Thread`, :class:`DMChannel`, :class:`VoiceChannel`, :class:`StageChannel`] The channel associated with this partial message. id: :class:`int` The message ID. @@ -1844,6 +1846,7 @@ def __init__(self, *, channel: PartialMessageableChannel, id: int): if channel.type not in ( ChannelType.text, ChannelType.voice, + ChannelType.stage_voice, ChannelType.news, ChannelType.private, ChannelType.news_thread, @@ -1851,7 +1854,7 @@ def __init__(self, *, channel: PartialMessageableChannel, id: int): ChannelType.private_thread, ): raise TypeError( - "Expected TextChannel, VoiceChannel, DMChannel or Thread not" + "Expected TextChannel, VoiceChannel, StageChannel, DMChannel or Thread not" f" {type(channel)!r}" ) diff --git a/discord/state.py b/discord/state.py index 744f63cabf..90e0c8dd22 100644 --- a/discord/state.py +++ b/discord/state.py @@ -672,8 +672,8 @@ def parse_message_create(self, data) -> None: self.dispatch("message", message) if self._messages is not None: self._messages.append(message) - # we ensure that the channel is either a TextChannel, VoiceChannel, or Thread - if channel and channel.__class__ in (TextChannel, VoiceChannel, Thread): + # we ensure that the channel is either a TextChannel, VoiceChannel, StageChannel, or Thread + if channel and channel.__class__ in (TextChannel, VoiceChannel, StageChannel, Thread): channel.last_message_id = message.id # type: ignore def parse_message_delete(self, data) -> None: From 848ae98d678275bb617abae339985efd3bf45d92 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 18:06:57 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- discord/abc.py | 2 +- discord/channel.py | 106 +++++++++++++++++++++++++++------------------ discord/state.py | 7 ++- 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/discord/abc.py b/discord/abc.py index 85fc4c7535..027ba96b18 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -77,9 +77,9 @@ DMChannel, GroupChannel, PartialMessageable, + StageChannel, TextChannel, VoiceChannel, - StageChannel ) from .client import Client from .embeds import Embed diff --git a/discord/channel.py b/discord/channel.py index 925e891d50..50d268c4f5 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -1358,7 +1358,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha "video_quality_mode", "last_message_id", "flags", - "nsfw" + "nsfw", ) def __init__( @@ -2068,24 +2068,31 @@ def last_message(self) -> Optional[Message]: last message, consider using either :meth:`history` or :meth:`fetch_message` with the :attr:`last_message_id` attribute. + Returns - --------- + ------- Optional[:class:`Message`] The last message in this channel or ``None`` if not found. """ - return self._state._get_message(self.last_message_id) if self.last_message_id else None + return ( + self._state._get_message(self.last_message_id) + if self.last_message_id + else None + ) def get_partial_message(self, message_id: int, /) -> PartialMessage: """Creates a :class:`PartialMessage` from the message ID. This is useful if you want to work with a message and only have its ID without doing an unnecessary API call. .. versionadded:: 1.6 + Parameters - ------------ + ---------- message_id: :class:`int` The message ID to create a partial message for. + Returns - --------- + ------- :class:`PartialMessage` The partial message. """ @@ -2094,7 +2101,9 @@ def get_partial_message(self, message_id: int, /) -> PartialMessage: return PartialMessage(channel=self, id=message_id) - async def delete_messages(self, messages: Iterable[Snowflake], *, reason: Optional[str] = None) -> None: + async def delete_messages( + self, messages: Iterable[Snowflake], *, reason: Optional[str] = None + ) -> None: """|coro| Deletes a list of messages. This is similar to :meth:`Message.delete` except it bulk deletes multiple messages. @@ -2105,12 +2114,14 @@ async def delete_messages(self, messages: Iterable[Snowflake], *, reason: Option are older than 14 days old. You must have the :attr:`~Permissions.manage_messages` permission to use this. + Parameters - ----------- + ---------- messages: Iterable[:class:`abc.Snowflake`] An iterable of messages denoting which ones to bulk delete. reason: Optional[:class:`str`] The reason for deleting the messages. Shows up on the audit log. + Raises ------ ClientException @@ -2140,16 +2151,16 @@ async def delete_messages(self, messages: Iterable[Snowflake], *, reason: Option await self._state.http.delete_messages(self.id, message_ids, reason=reason) async def purge( - self, - *, - limit: Optional[int] = 100, - check: Callable[[Message], bool] = MISSING, - before: Optional[SnowflakeTime] = None, - after: Optional[SnowflakeTime] = None, - around: Optional[SnowflakeTime] = None, - oldest_first: Optional[bool] = False, - bulk: bool = True, - reason: Optional[str] = None, + self, + *, + limit: Optional[int] = 100, + check: Callable[[Message], bool] = MISSING, + before: Optional[SnowflakeTime] = None, + after: Optional[SnowflakeTime] = None, + around: Optional[SnowflakeTime] = None, + oldest_first: Optional[bool] = False, + bulk: bool = True, + reason: Optional[str] = None, ) -> List[Message]: """|coro| Purges a list of messages that meet the criteria given by the predicate @@ -2159,15 +2170,9 @@ async def purge( delete messages even if they are your own. The :attr:`~Permissions.read_message_history` permission is also needed to retrieve message history. - Examples - --------- - Deleting bot's messages :: - def is_me(m): - return m.author == client.user - deleted = await channel.purge(limit=100, check=is_me) - await channel.send(f'Deleted {len(deleted)} message(s)') + Parameters - ----------- + ---------- limit: Optional[:class:`int`] The number of messages to search through. This is not the number of messages that will be deleted, though it can be. @@ -2188,16 +2193,26 @@ def is_me(m): fall back to single delete if messages are older than two weeks. reason: Optional[:class:`str`] The reason for deleting the messages. Shows up on the audit log. - Raises + + Returns ------- + List[:class:`.Message`] + The list of messages that were deleted. + + Raises + ------ Forbidden You do not have proper permissions to do the actions required. HTTPException Purging the messages failed. - Returns + + Examples -------- - List[:class:`.Message`] - The list of messages that were deleted. + Deleting bot's messages :: + def is_me(m): + return m.author == client.user + deleted = await channel.purge(limit=100, check=is_me) + await channel.send(f'Deleted {len(deleted)} message(s)') """ return await discord.abc._purge_messages_helper( self, @@ -2215,14 +2230,16 @@ async def webhooks(self) -> List[Webhook]: """|coro| Gets the list of webhooks from this channel. Requires :attr:`~.Permissions.manage_webhooks` permissions. - Raises - ------- - Forbidden - You don't have permissions to get the webhooks. + Returns - -------- + ------- List[:class:`Webhook`] The webhooks for this channel. + + Raises + ------ + Forbidden + You don't have permissions to get the webhooks. """ from .webhook import Webhook @@ -2231,15 +2248,16 @@ async def webhooks(self) -> List[Webhook]: return [Webhook.from_state(d, state=self._state) for d in data] async def create_webhook( - self, *, name: str, avatar: Optional[bytes] = None, reason: Optional[str] = None + self, *, name: str, avatar: Optional[bytes] = None, reason: Optional[str] = None ) -> Webhook: """|coro| Creates a webhook for this channel. Requires :attr:`~.Permissions.manage_webhooks` permissions. .. versionchanged:: 1.1 Added the ``reason`` keyword-only parameter. + Parameters - ------------- + ---------- name: :class:`str` The webhook's name. avatar: Optional[:class:`bytes`] @@ -2247,16 +2265,18 @@ async def create_webhook( This operates similarly to :meth:`~ClientUser.edit`. reason: Optional[:class:`str`] The reason for creating this webhook. Shows up in the audit logs. - Raises + + Returns ------- + :class:`Webhook` + The created webhook. + + Raises + ------ HTTPException Creating the webhook failed. Forbidden You do not have permissions to create a webhook. - Returns - -------- - :class:`Webhook` - The created webhook. """ from .webhook import Webhook @@ -2264,7 +2284,9 @@ async def create_webhook( if avatar is not None: avatar = utils._bytes_to_base64_data(avatar) # type: ignore - data = await self._state.http.create_webhook(self.id, name=str(name), avatar=avatar, reason=reason) + data = await self._state.http.create_webhook( + self.id, name=str(name), avatar=avatar, reason=reason + ) return Webhook.from_state(data, state=self._state) def is_nsfw(self) -> bool: diff --git a/discord/state.py b/discord/state.py index 90e0c8dd22..90fd97ab53 100644 --- a/discord/state.py +++ b/discord/state.py @@ -673,7 +673,12 @@ def parse_message_create(self, data) -> None: if self._messages is not None: self._messages.append(message) # we ensure that the channel is either a TextChannel, VoiceChannel, StageChannel, or Thread - if channel and channel.__class__ in (TextChannel, VoiceChannel, StageChannel, Thread): + if channel and channel.__class__ in ( + TextChannel, + VoiceChannel, + StageChannel, + Thread, + ): channel.last_message_id = message.id # type: ignore def parse_message_delete(self, data) -> None: From ffdd290f8eb6aea179dd5544569713b3a81c097d Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 22 Feb 2023 18:24:18 +0000 Subject: [PATCH 3/6] Updated type syntax --- discord/channel.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index 50d268c4f5..1a7e3f15ce 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -2059,7 +2059,7 @@ async def _get_channel(self): return self @property - def last_message(self) -> Optional[Message]: + def last_message(self) -> Message | None: """Fetches the last message from this channel in cache. The message might not be valid or point to an existing message. .. admonition:: Reliable Fetching @@ -2102,7 +2102,7 @@ def get_partial_message(self, message_id: int, /) -> PartialMessage: return PartialMessage(channel=self, id=message_id) async def delete_messages( - self, messages: Iterable[Snowflake], *, reason: Optional[str] = None + self, messages: Iterable[Snowflake], *, reason: str | None = None ) -> None: """|coro| Deletes a list of messages. This is similar to :meth:`Message.delete` @@ -2153,14 +2153,14 @@ async def delete_messages( async def purge( self, *, - limit: Optional[int] = 100, + limit: int | None = 100, check: Callable[[Message], bool] = MISSING, - before: Optional[SnowflakeTime] = None, - after: Optional[SnowflakeTime] = None, - around: Optional[SnowflakeTime] = None, - oldest_first: Optional[bool] = False, + before: SnowFlakeTime | None = None, + after: SnowFlakeTime | None = None, + around: SnowFlakeTime | None = None, + oldest_first: bool | None = False, bulk: bool = True, - reason: Optional[str] = None, + reason: str | None = None, ) -> List[Message]: """|coro| Purges a list of messages that meet the criteria given by the predicate From eb2dcb63efcdb8d169c6a7e91c6664937d28c30d Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Wed, 22 Feb 2023 18:37:46 +0000 Subject: [PATCH 4/6] fix again --- discord/channel.py | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/discord/channel.py b/discord/channel.py index 1a7e3f15ce..88ba717db5 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -2058,12 +2058,19 @@ def listeners(self) -> list[Member]: async def _get_channel(self): return self + def is_nsfw(self) -> bool: + """Checks if the channel is NSFW.""" + return self.nsfw + @property def last_message(self) -> Message | None: """Fetches the last message from this channel in cache. + The message might not be valid or point to an existing message. + .. admonition:: Reliable Fetching :class: helpful + For a slightly more reliable method of fetching the last message, consider using either :meth:`history` or :meth:`fetch_message` with the :attr:`last_message_id` @@ -2082,8 +2089,10 @@ def last_message(self) -> Message | None: def get_partial_message(self, message_id: int, /) -> PartialMessage: """Creates a :class:`PartialMessage` from the message ID. + This is useful if you want to work with a message and only have its ID without doing an unnecessary API call. + .. versionadded:: 1.6 Parameters @@ -2105,13 +2114,17 @@ async def delete_messages( self, messages: Iterable[Snowflake], *, reason: str | None = None ) -> None: """|coro| + Deletes a list of messages. This is similar to :meth:`Message.delete` except it bulk deletes multiple messages. + As a special case, if the number of messages is 0, then nothing is done. If the number of messages is 1 then single message delete is done. If it's more than two, then bulk delete is used. + You cannot bulk delete more than 100 messages or messages that are older than 14 days old. + You must have the :attr:`~Permissions.manage_messages` permission to use this. @@ -2155,17 +2168,19 @@ async def purge( *, limit: int | None = 100, check: Callable[[Message], bool] = MISSING, - before: SnowFlakeTime | None = None, - after: SnowFlakeTime | None = None, - around: SnowFlakeTime | None = None, + before: SnowflakeTime | None = None, + after: SnowflakeTime | None = None, + around: SnowflakeTime | None = None, oldest_first: bool | None = False, bulk: bool = True, reason: str | None = None, - ) -> List[Message]: + ) -> list[Message]: """|coro| + Purges a list of messages that meet the criteria given by the predicate ``check``. If a ``check`` is not provided then all messages are deleted without discrimination. + You must have the :attr:`~Permissions.manage_messages` permission to delete messages even if they are your own. The :attr:`~Permissions.read_message_history` permission is @@ -2208,9 +2223,12 @@ async def purge( Examples -------- + Deleting bot's messages :: + def is_me(m): return m.author == client.user + deleted = await channel.purge(limit=100, check=is_me) await channel.send(f'Deleted {len(deleted)} message(s)') """ @@ -2226,9 +2244,11 @@ def is_me(m): reason=reason, ) - async def webhooks(self) -> List[Webhook]: + async def webhooks(self) -> list[Webhook]: """|coro| + Gets the list of webhooks from this channel. + Requires :attr:`~.Permissions.manage_webhooks` permissions. Returns @@ -2248,11 +2268,14 @@ async def webhooks(self) -> List[Webhook]: return [Webhook.from_state(d, state=self._state) for d in data] async def create_webhook( - self, *, name: str, avatar: Optional[bytes] = None, reason: Optional[str] = None + self, *, name: str, avatar: bytes | None = None, reason: str | None = None ) -> Webhook: """|coro| + Creates a webhook for this channel. + Requires :attr:`~.Permissions.manage_webhooks` permissions. + .. versionchanged:: 1.1 Added the ``reason`` keyword-only parameter. @@ -2289,10 +2312,6 @@ async def create_webhook( ) return Webhook.from_state(data, state=self._state) - def is_nsfw(self) -> bool: - """Checks if the channel is NSFW.""" - return self.nsfw - @property def moderators(self) -> list[Member]: """A list of members who are moderating the stage channel. From 5a25fcfaa2358f06635de390fa52683710be50b6 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sun, 26 Feb 2023 14:35:09 +0000 Subject: [PATCH 5/6] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97d1d56853..66cdcdb156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ These changes are available on the `master` branch, but have not yet been releas - Added new events `on_bridge_command`, `on_bridge_command_completion`, and `on_bridge_command_error`. ([#1916](https://github.com/Pycord-Development/pycord/pull/1916)) +- Added support for text-related features in `StageChannel` ([#1936](https://github.com/Pycord-Development/pycord/pull/1936)) ### Fixed From a4c988d21ca2398a15026d3f5dbcbb53e7c0b00a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 26 Feb 2023 14:35:28 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66cdcdb156..8a284dbb68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ These changes are available on the `master` branch, but have not yet been releas - Added new events `on_bridge_command`, `on_bridge_command_completion`, and `on_bridge_command_error`. ([#1916](https://github.com/Pycord-Development/pycord/pull/1916)) -- Added support for text-related features in `StageChannel` ([#1936](https://github.com/Pycord-Development/pycord/pull/1936)) +- Added support for text-related features in `StageChannel` + ([#1936](https://github.com/Pycord-Development/pycord/pull/1936)) ### Fixed