From 43419fc5d7bf29b45b483150bb8b9cd5f549e473 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:08:55 +0100 Subject: [PATCH 01/16] guild bulk ban --- discord/guild.py | 49 +++++++++++++++++++++++++++++++++--------- discord/http.py | 28 ++++++++++++++++++++++++ discord/types/guild.py | 4 ++++ 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 2b6ff7a382..6ed7faffbb 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3073,7 +3073,7 @@ async def kick(self, user: Snowflake, *, reason: str | None = None) -> None: async def ban( self, - user: Snowflake, + *users: Snowflake, *, delete_message_seconds: int | None = None, delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None, @@ -3081,17 +3081,17 @@ async def ban( ) -> None: """|coro| - Bans a user from the guild. + Bans users from the guild. - The user must meet the :class:`abc.Snowflake` abc. + The users must meet the :class:`abc.Snowflake` abc. You must have the :attr:`~Permissions.ban_members` permission to do this. Parameters ---------- - user: :class:`abc.Snowflake` - The user to ban from their guild. + \*users: :class:`abc.Snowflake` + An argument list of users to ban from the guild, up to 200. delete_message_seconds: Optional[:class:`int`] The number of seconds worth of messages to delete from the user in the guild. The minimum is 0 and the maximum @@ -3100,14 +3100,32 @@ async def ban( ***Deprecated parameter***, same as ``delete_message_seconds`` but is used for days instead. reason: Optional[:class:`str`] - The reason the user got banned. + The reason the users got banned. + + Returns + ------- + Optional[List[List[:class:`Snowflake`], List[:class:`Snowflake`]]] + If banning a single member, returns nothing. Otherwise, returns two lists; Raises ------ + ValueError + You tried to ban more than 200 users. Forbidden You do not have the proper permissions to ban. HTTPException - Banning failed. + No users were banned. + + Example Usage: :: + + # Ban a single member + await guild.ban(member, reason="Spam") + + # Ban multiple members + successes, failures = await guild.ban(member1, member2, member3, ..., reason="Raid") + + # Ban a list of members + successes, failures = await guild.ban(*members, reason="Hacked") """ if delete_message_seconds and delete_message_days: raise TypeError( @@ -3120,10 +3138,21 @@ async def ban( raise TypeError( "delete_message_seconds must be between 0 and 604800 seconds." ) + + if len(users) == 1: + await self._state.http.ban( + users[0].id, self.id, delete_message_seconds, delete_message_days, reason=reason + ) + elif len(users) > 200: + raise ValueError("You may only bulk ban up to 200 members.") + else: + data = await self._state.http.bulk_ban( + [u.id for u in users], self.id, delete_message_seconds, delete_message_days, reason=reason + ) + banned = [u for u in users if u.id in data["banned_users"]] + failed = [u for u in users if u.id in data["failed_users"]] + return banned, failed - await self._state.http.ban( - user.id, self.id, delete_message_seconds, delete_message_days, reason=reason - ) async def unban(self, user: Snowflake, *, reason: str | None = None) -> None: """|coro| diff --git a/discord/http.py b/discord/http.py index e79d6120b7..ec03f472c1 100644 --- a/discord/http.py +++ b/discord/http.py @@ -931,6 +931,34 @@ def ban( return self.request(r, params=params, reason=reason) + def bulk_ban( + self, + user_ids: list[Snowflake], + guild_id: Snowflake, + delete_message_seconds: int = None, + reason: str | None = None, + ) -> Response[guild.GuildBulkBan]: + r = Route( + "PUT", + "/guilds/{guild_id}/bulk-ban", + guild_id=guild_id, + ) + params = { + "user_ids": user_ids, + } + if delete_message_seconds: + params["delete_message_seconds"] = delete_message_seconds + elif delete_message_days: + warn_deprecated( + "delete_message_days", + "delete_message_seconds", + "2.2", + reference="https://github.com/discord/discord-api-docs/pull/5219", + ) + params["delete_message_days"] = delete_message_days + + return self.request(r, params=params, reason=reason) + def unban( self, user_id: Snowflake, guild_id: Snowflake, *, reason: str | None = None ) -> Response[None]: diff --git a/discord/types/guild.py b/discord/types/guild.py index be417a726d..47e0eca3a2 100644 --- a/discord/types/guild.py +++ b/discord/types/guild.py @@ -185,3 +185,7 @@ class RolePositionUpdate(TypedDict, total=False): class GuildMFAModify(TypedDict): level: Literal[0, 1] + +class GuildBulkBan(TypedDict): + banned_users: list[Snowflake] + failed_users: list[Snowflake] \ No newline at end of file From 221b8bcd1fb9577c3a51d3043ab3c2b93e3a7131 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:11:54 +0000 Subject: [PATCH 02/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/guild.py | 6 +++--- discord/types/guild.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 6ed7faffbb..80fb67845f 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3079,7 +3079,7 @@ async def ban( delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None, reason: str | None = None, ) -> None: - """|coro| + r"""|coro| Bans users from the guild. @@ -3105,7 +3105,7 @@ async def ban( Returns ------- Optional[List[List[:class:`Snowflake`], List[:class:`Snowflake`]]] - If banning a single member, returns nothing. Otherwise, returns two lists; + If banning a single member, returns nothing. Otherwise, returns two lists; Raises ------ @@ -3138,7 +3138,7 @@ async def ban( raise TypeError( "delete_message_seconds must be between 0 and 604800 seconds." ) - + if len(users) == 1: await self._state.http.ban( users[0].id, self.id, delete_message_seconds, delete_message_days, reason=reason diff --git a/discord/types/guild.py b/discord/types/guild.py index 47e0eca3a2..cac645b272 100644 --- a/discord/types/guild.py +++ b/discord/types/guild.py @@ -186,6 +186,7 @@ class RolePositionUpdate(TypedDict, total=False): class GuildMFAModify(TypedDict): level: Literal[0, 1] + class GuildBulkBan(TypedDict): banned_users: list[Snowflake] - failed_users: list[Snowflake] \ No newline at end of file + failed_users: list[Snowflake] From 8283620c23ca950f721cabaaee25c50999181a17 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:19:36 +0100 Subject: [PATCH 03/16] fixes --- discord/guild.py | 1 - discord/http.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/guild.py b/discord/guild.py index 80fb67845f..720599027d 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3074,7 +3074,6 @@ async def kick(self, user: Snowflake, *, reason: str | None = None) -> None: async def ban( self, *users: Snowflake, - *, delete_message_seconds: int | None = None, delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None, reason: str | None = None, diff --git a/discord/http.py b/discord/http.py index ec03f472c1..d804785fe9 100644 --- a/discord/http.py +++ b/discord/http.py @@ -936,6 +936,7 @@ def bulk_ban( user_ids: list[Snowflake], guild_id: Snowflake, delete_message_seconds: int = None, + delete_message_days: int = None, reason: str | None = None, ) -> Response[guild.GuildBulkBan]: r = Route( From 6158e5ea3e89011d03163ba21d77e6cd46e21338 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:19:57 +0000 Subject: [PATCH 04/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/guild.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 720599027d..5ad0b31305 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3140,19 +3140,26 @@ async def ban( if len(users) == 1: await self._state.http.ban( - users[0].id, self.id, delete_message_seconds, delete_message_days, reason=reason + users[0].id, + self.id, + delete_message_seconds, + delete_message_days, + reason=reason, ) elif len(users) > 200: raise ValueError("You may only bulk ban up to 200 members.") else: data = await self._state.http.bulk_ban( - [u.id for u in users], self.id, delete_message_seconds, delete_message_days, reason=reason + [u.id for u in users], + self.id, + delete_message_seconds, + delete_message_days, + reason=reason, ) banned = [u for u in users if u.id in data["banned_users"]] failed = [u for u in users if u.id in data["failed_users"]] return banned, failed - async def unban(self, user: Snowflake, *, reason: str | None = None) -> None: """|coro| From ca7578138dd372ba5f82a9bfb26db867a337ad2d Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:23:33 +0100 Subject: [PATCH 05/16] change method --- discord/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/http.py b/discord/http.py index d804785fe9..ae6ad633ed 100644 --- a/discord/http.py +++ b/discord/http.py @@ -940,7 +940,7 @@ def bulk_ban( reason: str | None = None, ) -> Response[guild.GuildBulkBan]: r = Route( - "PUT", + "POST", "/guilds/{guild_id}/bulk-ban", guild_id=guild_id, ) From 86db7df16f9144fc088b3019c31d1a5912bcbd6c Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:27:09 +0100 Subject: [PATCH 06/16] payload --- discord/guild.py | 4 ++-- discord/http.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 5ad0b31305..652e6c429c 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3156,8 +3156,8 @@ async def ban( delete_message_days, reason=reason, ) - banned = [u for u in users if u.id in data["banned_users"]] - failed = [u for u in users if u.id in data["failed_users"]] + banned = [u for u in users if str(u.id) in data["banned_users"]] + failed = [u for u in users if str(u.id) in data["failed_users"]] return banned, failed async def unban(self, user: Snowflake, *, reason: str | None = None) -> None: diff --git a/discord/http.py b/discord/http.py index ae6ad633ed..5d33ebb2d8 100644 --- a/discord/http.py +++ b/discord/http.py @@ -944,11 +944,11 @@ def bulk_ban( "/guilds/{guild_id}/bulk-ban", guild_id=guild_id, ) - params = { + payload = { "user_ids": user_ids, } if delete_message_seconds: - params["delete_message_seconds"] = delete_message_seconds + payload["delete_message_seconds"] = delete_message_seconds elif delete_message_days: warn_deprecated( "delete_message_days", @@ -956,9 +956,9 @@ def bulk_ban( "2.2", reference="https://github.com/discord/discord-api-docs/pull/5219", ) - params["delete_message_days"] = delete_message_days + payload["delete_message_days"] = delete_message_days - return self.request(r, params=params, reason=reason) + return self.request(r, json=payload, reason=reason) def unban( self, user_id: Snowflake, guild_id: Snowflake, *, reason: str | None = None From 6590ac204ca97203470641a3ea6b436a7d645894 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:32:15 +0100 Subject: [PATCH 07/16] cl --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ae1911b88..6030730ac3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2417](https://github.com/Pycord-Development/pycord/pull/2417)) - Added `Guild.search_members`. ([#2418](https://github.com/Pycord-Development/pycord/pull/2418)) +- Added bulk banning up to 200 users through `Guild.ban` + ([#2421](https://github.com/Pycord-Development/pycord/pull/2421)) ### Fixed From c46833b7af463d8da83c18dbeca76bfce758b8d3 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 18:40:52 +0100 Subject: [PATCH 08/16] Update CHANGELOG.md Co-authored-by: plun1331 Signed-off-by: UK <41271523+NeloBlivion@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6030730ac3..5170280f9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ These changes are available on the `master` branch, but have not yet been releas ([#2417](https://github.com/Pycord-Development/pycord/pull/2417)) - Added `Guild.search_members`. ([#2418](https://github.com/Pycord-Development/pycord/pull/2418)) -- Added bulk banning up to 200 users through `Guild.ban` +- Added bulk banning up to 200 users through `Guild.ban`. ([#2421](https://github.com/Pycord-Development/pycord/pull/2421)) ### Fixed From c8c3f6e2897b3919f3fe3aed61f3dbeef9381e7f Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 18:52:35 +0100 Subject: [PATCH 09/16] fixes --- discord/guild.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 652e6c429c..62008f8344 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3077,16 +3077,27 @@ async def ban( delete_message_seconds: int | None = None, delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None, reason: str | None = None, - ) -> None: + ) -> list[list[Snowflake], list[Snowflake]] | None: r"""|coro| - Bans users from the guild. + Bans user(s) from the guild. - The users must meet the :class:`abc.Snowflake` abc. + The user(s) must meet the :class:`abc.Snowflake` abc. You must have the :attr:`~Permissions.ban_members` permission to do this. + Example Usage: :: + + # Ban a single user + await guild.ban(user, reason="Spam") + + # Ban multiple users + successes, failures = await guild.ban(user1, user2, user3, ..., reason="Raid") + + # Ban a list of users + successes, failures = await guild.ban(*users) + Parameters ---------- \*users: :class:`abc.Snowflake` @@ -3114,17 +3125,6 @@ async def ban( You do not have the proper permissions to ban. HTTPException No users were banned. - - Example Usage: :: - - # Ban a single member - await guild.ban(member, reason="Spam") - - # Ban multiple members - successes, failures = await guild.ban(member1, member2, member3, ..., reason="Raid") - - # Ban a list of members - successes, failures = await guild.ban(*members, reason="Hacked") """ if delete_message_seconds and delete_message_days: raise TypeError( @@ -3147,7 +3147,7 @@ async def ban( reason=reason, ) elif len(users) > 200: - raise ValueError("You may only bulk ban up to 200 members.") + raise ValueError("The number of users to be banned must be between 1 and 200.") else: data = await self._state.http.bulk_ban( [u.id for u in users], From bf5469a30771b9db09911c3f11f4aea52c5dd77a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 17:52:57 +0000 Subject: [PATCH 10/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/guild.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/discord/guild.py b/discord/guild.py index 62008f8344..0573f5668c 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3147,7 +3147,9 @@ async def ban( reason=reason, ) elif len(users) > 200: - raise ValueError("The number of users to be banned must be between 1 and 200.") + raise ValueError( + "The number of users to be banned must be between 1 and 200." + ) else: data = await self._state.http.bulk_ban( [u.id for u in users], From e556df1b2dd4c94fa5e3c267296d36959c58616f Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Sat, 13 Apr 2024 22:57:00 +0100 Subject: [PATCH 11/16] docs --- discord/guild.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 0573f5668c..b331489a55 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3114,8 +3114,8 @@ async def ban( Returns ------- - Optional[List[List[:class:`Snowflake`], List[:class:`Snowflake`]]] - If banning a single member, returns nothing. Otherwise, returns two lists; + Optional[List[List[:class:`abc.Snowflake`], List[:class:`abc.Snowflake`]]] + If banning a single member, returns nothing. Otherwise, returns two lists: the first contains members that were successfully banned, while the second is members that could not be banned. Raises ------ From 4a37187dc5a12592c3930ee54d63c5ceb136bb40 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:05:46 +0100 Subject: [PATCH 12/16] split into bulk_ban, remove delete_message_days and update examples --- CHANGELOG.md | 6 ++ discord/guild.py | 135 +++++++++++++++++++-------------- discord/http.py | 18 ----- discord/member.py | 2 - docs/ext/commands/commands.rst | 9 +-- 5 files changed, 88 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edaeca343e..39df9290f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,12 @@ These changes are available on the `master` branch, but have not yet been releas - `Guild.query_members` now accepts `limit=None` to retrieve all members. ([#2419](https://github.com/Pycord-Development/pycord/pull/2419)) +### Removed + +- Removed the `delete_message_days` parameter from ban methods. Please use + `delete_message_seconds` instead. + ([#2421](https://github.com/Pycord-Development/pycord/pull/2421)) + ## [2.5.0] - 2024-03-02 ### Added diff --git a/discord/guild.py b/discord/guild.py index 764a06773d..aa961f2074 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3071,27 +3071,69 @@ async def kick(self, user: Snowflake, *, reason: str | None = None) -> None: """ await self._state.http.kick(user.id, self.id, reason=reason) + async def ban( + self, + user: Snowflake, + *, + delete_message_seconds: int | None = None, + reason: str | None = None, + ) -> None: + """|coro| + + Bans a user from the guild. + + The user must meet the :class:`abc.Snowflake` abc. + + You must have the :attr:`~Permissions.ban_members` permission to + do this. + + Parameters + ---------- + user: :class:`abc.Snowflake` + The user to ban from their guild. + delete_message_seconds: Optional[:class:`int`] + The number of seconds worth of messages to delete from + the user in the guild. The minimum is 0 and the maximum + is 604800 (i.e. 7 days). The default is 0. + reason: Optional[:class:`str`] + The reason the user got banned. + + Raises + ------ + Forbidden + You do not have the proper permissions to ban. + HTTPException + Banning failed. + """ + + if delete_message_seconds is not None and not ( + 0 <= delete_message_seconds <= 604800 + ): + raise TypeError( + "delete_message_seconds must be between 0 and 604800 seconds." + ) + + await self._state.http.ban( + user.id, self.id, delete_message_seconds, reason=reason + ) + async def ban( self, *users: Snowflake, delete_message_seconds: int | None = None, - delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None, reason: str | None = None, ) -> list[list[Snowflake], list[Snowflake]] | None: r"""|coro| - Bans user(s) from the guild. + Bulk ban users from the guild. - The user(s) must meet the :class:`abc.Snowflake` abc. + The users must meet the :class:`abc.Snowflake` abc. You must have the :attr:`~Permissions.ban_members` permission to do this. Example Usage: :: - # Ban a single user - await guild.ban(user, reason="Spam") - # Ban multiple users successes, failures = await guild.ban(user1, user2, user3, ..., reason="Raid") @@ -3106,16 +3148,13 @@ async def ban( The number of seconds worth of messages to delete from the user in the guild. The minimum is 0 and the maximum is 604800 (i.e. 7 days). The default is 0. - delete_message_days: Optional[:class:`int`] - ***Deprecated parameter***, same as ``delete_message_seconds`` but - is used for days instead. reason: Optional[:class:`str`] - The reason the users got banned. + The reason the users were banned. Returns ------- - Optional[List[List[:class:`abc.Snowflake`], List[:class:`abc.Snowflake`]]] - If banning a single member, returns nothing. Otherwise, returns two lists: the first contains members that were successfully banned, while the second is members that could not be banned. + List[List[:class:`abc.Snowflake`], List[:class:`abc.Snowflake`]] + Returns two lists: the first contains members that were successfully banned, while the second is members that could not be banned. Raises ------ @@ -3126,10 +3165,6 @@ async def ban( HTTPException No users were banned. """ - if delete_message_seconds and delete_message_days: - raise TypeError( - "delete_message_seconds and delete_message_days are mutually exclusive." - ) if delete_message_seconds is not None and not ( 0 <= delete_message_seconds <= 604800 @@ -3137,30 +3172,21 @@ async def ban( raise TypeError( "delete_message_seconds must be between 0 and 604800 seconds." ) - - if len(users) == 1: - await self._state.http.ban( - users[0].id, - self.id, - delete_message_seconds, - delete_message_days, - reason=reason, - ) - elif len(users) > 200: + + if len(users) > 200 or len(users) < 1: raise ValueError( "The number of users to be banned must be between 1 and 200." ) - else: - data = await self._state.http.bulk_ban( - [u.id for u in users], - self.id, - delete_message_seconds, - delete_message_days, - reason=reason, - ) - banned = [u for u in users if str(u.id) in data["banned_users"]] - failed = [u for u in users if str(u.id) in data["failed_users"]] - return banned, failed + + data = await self._state.http.bulk_ban( + [u.id for u in users], + self.id, + delete_message_seconds, + reason=reason, + ) + banned = [u for u in users if str(u.id) in data["banned_users"]] + failed = [u for u in users if str(u.id) in data["failed_users"]] + return banned, failed async def unban(self, user: Snowflake, *, reason: str | None = None) -> None: """|coro| @@ -3398,7 +3424,7 @@ async def query_members( self, query: str | None = None, *, - limit: int | None = 5, + limit: int = 5, user_ids: list[int] | None = None, presences: bool = False, cache: bool = True, @@ -3416,14 +3442,10 @@ async def query_members( ---------- query: Optional[:class:`str`] The string that the username's start with. - user_ids: Optional[List[:class:`int`]] - List of user IDs to search for. If the user ID is not in the guild then it won't be returned. - - .. versionadded:: 1.4 - limit: Optional[:class:`int`] - The maximum number of members to send back. If no query is passed, passing ``None`` returns all members. - If a ``query`` or ``user_ids`` is passed, must be between 1 and 100. Defaults to 5. - presences: Optional[:class:`bool`] + limit: :class:`int` + The maximum number of members to send back. This must be + a number between 5 and 100. + presences: :class:`bool` Whether to request for presences to be provided. This defaults to ``False``. @@ -3431,7 +3453,11 @@ async def query_members( cache: :class:`bool` Whether to cache the members internally. This makes operations - such as :meth:`get_member` work for those that matched. Defaults to ``True``. + such as :meth:`get_member` work for those that matched. + user_ids: Optional[List[:class:`int`]] + List of user IDs to search for. If the user ID is not in the guild then it won't be returned. + + .. versionadded:: 1.4 Returns ------- @@ -3451,18 +3477,12 @@ async def query_members( if presences and not self._state._intents.presences: raise ClientException("Intents.presences must be enabled to use this.") - if not limit or limit > 100 or limit < 1: - if query or user_ids: - raise ValueError( - "limit must be between 1 and 100 when using query or user_ids" - ) - if not limit: - query = "" - limit = 0 - if query is None: + if query == "": + raise ValueError("Cannot pass empty query string.") + if user_ids is None: - raise ValueError("Must pass query or user_ids, or set limit to None") + raise ValueError("Must pass either query or user_ids") if user_ids is not None and query is not None: raise ValueError("Cannot pass both query and user_ids") @@ -3470,6 +3490,7 @@ async def query_members( if user_ids is not None and not user_ids: raise ValueError("user_ids must contain at least 1 value") + limit = min(100, limit or 5) return await self._state.query_members( self, query=query, diff --git a/discord/http.py b/discord/http.py index 5d33ebb2d8..3622afc2bd 100644 --- a/discord/http.py +++ b/discord/http.py @@ -907,7 +907,6 @@ def ban( user_id: Snowflake, guild_id: Snowflake, delete_message_seconds: int = None, - delete_message_days: int = None, reason: str | None = None, ) -> Response[None]: r = Route( @@ -920,14 +919,6 @@ def ban( if delete_message_seconds: params["delete_message_seconds"] = delete_message_seconds - elif delete_message_days: - warn_deprecated( - "delete_message_days", - "delete_message_seconds", - "2.2", - reference="https://github.com/discord/discord-api-docs/pull/5219", - ) - params["delete_message_days"] = delete_message_days return self.request(r, params=params, reason=reason) @@ -936,7 +927,6 @@ def bulk_ban( user_ids: list[Snowflake], guild_id: Snowflake, delete_message_seconds: int = None, - delete_message_days: int = None, reason: str | None = None, ) -> Response[guild.GuildBulkBan]: r = Route( @@ -949,14 +939,6 @@ def bulk_ban( } if delete_message_seconds: payload["delete_message_seconds"] = delete_message_seconds - elif delete_message_days: - warn_deprecated( - "delete_message_days", - "delete_message_seconds", - "2.2", - reference="https://github.com/discord/discord-api-docs/pull/5219", - ) - payload["delete_message_days"] = delete_message_days return self.request(r, json=payload, reason=reason) diff --git a/discord/member.py b/discord/member.py index fecb9b9dfa..c7b06a1990 100644 --- a/discord/member.py +++ b/discord/member.py @@ -684,7 +684,6 @@ async def ban( self, *, delete_message_seconds: int | None = None, - delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None, reason: str | None = None, ) -> None: """|coro| @@ -695,7 +694,6 @@ async def ban( self, reason=reason, delete_message_seconds=delete_message_seconds, - delete_message_days=delete_message_days, ) async def unban(self, *, reason: str | None = None) -> None: diff --git a/docs/ext/commands/commands.rst b/docs/ext/commands/commands.rst index 793c3a64e4..c907e2a1b4 100644 --- a/docs/ext/commands/commands.rst +++ b/docs/ext/commands/commands.rst @@ -573,11 +573,10 @@ When mixed with the :data:`typing.Optional` converter you can provide simple and @bot.command() async def ban(ctx, members: commands.Greedy[discord.Member], - delete_days: typing.Optional[int] = 0, *, + delete_seconds: typing.Optional[int] = 0, *, reason: str): - """Mass bans members with an optional delete_days parameter""" - for member in members: - await member.ban(delete_message_days=delete_days, reason=reason) + """Bulk bans members with an optional delete_seconds parameter""" + await ctx.guild.bulk_ban(*members, delete_message_seconds=delete_seconds, reason=reason) This command can be invoked any of the following ways: @@ -707,7 +706,7 @@ For example, augmenting the example above: @commands.command() async def ban(ctx, *, flags: BanFlags): for member in flags.members: - await member.ban(reason=flags.reason, delete_message_days=flags.days) + await member.ban(reason=flags.reason, delete_message_seconds=flags.days * 60 * 24) members = ', '.join(str(member) for member in flags.members) plural = f'{flags.days} days' if flags.days != 1 else f'{flags.days} day' From c9d02bf76a306be7a6cc9dabeade45e207ae1a38 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 01:06:06 +0000 Subject: [PATCH 13/16] style(pre-commit): auto fixes from pre-commit.com hooks --- discord/guild.py | 3 +-- discord/member.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index aa961f2074..3acb104cf1 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -32,7 +32,6 @@ Any, ClassVar, List, - Literal, NamedTuple, Optional, Sequence, @@ -3172,7 +3171,7 @@ async def ban( raise TypeError( "delete_message_seconds must be between 0 and 604800 seconds." ) - + if len(users) > 200 or len(users) < 1: raise ValueError( "The number of users to be banned must be between 1 and 200." diff --git a/discord/member.py b/discord/member.py index c7b06a1990..c854e12979 100644 --- a/discord/member.py +++ b/discord/member.py @@ -30,7 +30,7 @@ import itertools import sys from operator import attrgetter -from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union +from typing import TYPE_CHECKING, Any, TypeVar, Union import discord.abc From f2add452d870f2d95f965944ad0818a8fc3fb8cb Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:08:16 +0100 Subject: [PATCH 14/16] oops rename --- discord/guild.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/guild.py b/discord/guild.py index 3acb104cf1..8674283fb1 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3116,7 +3116,7 @@ async def ban( user.id, self.id, delete_message_seconds, reason=reason ) - async def ban( + async def bulk_ban( self, *users: Snowflake, delete_message_seconds: int | None = None, From 96976c8f0ea4a0d880bc2c5bf84ec3df1ce32033 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:10:21 +0100 Subject: [PATCH 15/16] typehint --- discord/guild.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/guild.py b/discord/guild.py index 8674283fb1..35f592284e 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3121,7 +3121,7 @@ async def bulk_ban( *users: Snowflake, delete_message_seconds: int | None = None, reason: str | None = None, - ) -> list[list[Snowflake], list[Snowflake]] | None: + ) -> list[list[Snowflake], list[Snowflake]]: r"""|coro| Bulk ban users from the guild. From 342fdd99d1d753ac1a28956398f88c45d55af6a6 Mon Sep 17 00:00:00 2001 From: UK <41271523+NeloBlivion@users.noreply.github.com> Date: Mon, 22 Apr 2024 02:15:01 +0100 Subject: [PATCH 16/16] somehow desynced with master --- discord/guild.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/discord/guild.py b/discord/guild.py index 35f592284e..f015048f08 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -3423,7 +3423,7 @@ async def query_members( self, query: str | None = None, *, - limit: int = 5, + limit: int | None = 5, user_ids: list[int] | None = None, presences: bool = False, cache: bool = True, @@ -3441,10 +3441,14 @@ async def query_members( ---------- query: Optional[:class:`str`] The string that the username's start with. - limit: :class:`int` - The maximum number of members to send back. This must be - a number between 5 and 100. - presences: :class:`bool` + user_ids: Optional[List[:class:`int`]] + List of user IDs to search for. If the user ID is not in the guild then it won't be returned. + + .. versionadded:: 1.4 + limit: Optional[:class:`int`] + The maximum number of members to send back. If no query is passed, passing ``None`` returns all members. + If a ``query`` or ``user_ids`` is passed, must be between 1 and 100. Defaults to 5. + presences: Optional[:class:`bool`] Whether to request for presences to be provided. This defaults to ``False``. @@ -3452,11 +3456,7 @@ async def query_members( cache: :class:`bool` Whether to cache the members internally. This makes operations - such as :meth:`get_member` work for those that matched. - user_ids: Optional[List[:class:`int`]] - List of user IDs to search for. If the user ID is not in the guild then it won't be returned. - - .. versionadded:: 1.4 + such as :meth:`get_member` work for those that matched. Defaults to ``True``. Returns ------- @@ -3476,12 +3476,18 @@ async def query_members( if presences and not self._state._intents.presences: raise ClientException("Intents.presences must be enabled to use this.") - if query is None: - if query == "": - raise ValueError("Cannot pass empty query string.") + if not limit or limit > 100 or limit < 1: + if query or user_ids: + raise ValueError( + "limit must be between 1 and 100 when using query or user_ids" + ) + if not limit: + query = "" + limit = 0 + if query is None: if user_ids is None: - raise ValueError("Must pass either query or user_ids") + raise ValueError("Must pass query or user_ids, or set limit to None") if user_ids is not None and query is not None: raise ValueError("Cannot pass both query and user_ids") @@ -3489,7 +3495,6 @@ async def query_members( if user_ids is not None and not user_ids: raise ValueError("user_ids must contain at least 1 value") - limit = min(100, limit or 5) return await self._state.query_members( self, query=query,