Skip to content

Commit a1439ba

Browse files
NeloBlivionpre-commit-ci[bot]plun1331Lulalaby
authored
feat: Support bulk banning in guilds (#2421)
Signed-off-by: UK <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: plun1331 <[email protected]> Co-authored-by: Lala Sabathil <[email protected]>
1 parent 0536899 commit a1439ba

File tree

6 files changed

+109
-26
lines changed

6 files changed

+109
-26
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ These changes are available on the `master` branch, but have not yet been releas
2020
([#2417](https://github.com/Pycord-Development/pycord/pull/2417))
2121
- Added `Guild.search_members`.
2222
([#2418](https://github.com/Pycord-Development/pycord/pull/2418))
23+
- Added bulk banning up to 200 users through `Guild.bulk_ban`.
24+
([#2421](https://github.com/Pycord-Development/pycord/pull/2421))
2325
- Added `member` data to the `raw_reaction_remove` event.
2426
([#2412](https://github.com/Pycord-Development/pycord/pull/2412))
2527

@@ -56,6 +58,12 @@ These changes are available on the `master` branch, but have not yet been releas
5658
- `Guild.query_members` now accepts `limit=None` to retrieve all members.
5759
([#2419](https://github.com/Pycord-Development/pycord/pull/2419))
5860

61+
### Removed
62+
63+
- Removed the `delete_message_days` parameter from ban methods. Please use
64+
`delete_message_seconds` instead.
65+
([#2421](https://github.com/Pycord-Development/pycord/pull/2421))
66+
5967
## [2.5.0] - 2024-03-02
6068

6169
### Added

discord/guild.py

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
Any,
3333
ClassVar,
3434
List,
35-
Literal,
3635
NamedTuple,
3736
Optional,
3837
Sequence,
@@ -3076,7 +3075,6 @@ async def ban(
30763075
user: Snowflake,
30773076
*,
30783077
delete_message_seconds: int | None = None,
3079-
delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None,
30803078
reason: str | None = None,
30813079
) -> None:
30823080
"""|coro|
@@ -3096,9 +3094,6 @@ async def ban(
30963094
The number of seconds worth of messages to delete from
30973095
the user in the guild. The minimum is 0 and the maximum
30983096
is 604800 (i.e. 7 days). The default is 0.
3099-
delete_message_days: Optional[:class:`int`]
3100-
***Deprecated parameter***, same as ``delete_message_seconds`` but
3101-
is used for days instead.
31023097
reason: Optional[:class:`str`]
31033098
The reason the user got banned.
31043099
@@ -3109,21 +3104,88 @@ async def ban(
31093104
HTTPException
31103105
Banning failed.
31113106
"""
3112-
if delete_message_seconds and delete_message_days:
3107+
3108+
if delete_message_seconds is not None and not (
3109+
0 <= delete_message_seconds <= 604800
3110+
):
31133111
raise TypeError(
3114-
"delete_message_seconds and delete_message_days are mutually exclusive."
3112+
"delete_message_seconds must be between 0 and 604800 seconds."
31153113
)
31163114

3115+
await self._state.http.ban(
3116+
user.id, self.id, delete_message_seconds, reason=reason
3117+
)
3118+
3119+
async def bulk_ban(
3120+
self,
3121+
*users: Snowflake,
3122+
delete_message_seconds: int | None = None,
3123+
reason: str | None = None,
3124+
) -> list[list[Snowflake], list[Snowflake]]:
3125+
r"""|coro|
3126+
3127+
Bulk ban users from the guild.
3128+
3129+
The users must meet the :class:`abc.Snowflake` abc.
3130+
3131+
You must have the :attr:`~Permissions.ban_members` permission to
3132+
do this.
3133+
3134+
Example Usage: ::
3135+
3136+
# Ban multiple users
3137+
successes, failures = await guild.ban(user1, user2, user3, ..., reason="Raid")
3138+
3139+
# Ban a list of users
3140+
successes, failures = await guild.ban(*users)
3141+
3142+
Parameters
3143+
----------
3144+
\*users: :class:`abc.Snowflake`
3145+
An argument list of users to ban from the guild, up to 200.
3146+
delete_message_seconds: Optional[:class:`int`]
3147+
The number of seconds worth of messages to delete from
3148+
the user in the guild. The minimum is 0 and the maximum
3149+
is 604800 (i.e. 7 days). The default is 0.
3150+
reason: Optional[:class:`str`]
3151+
The reason the users were banned.
3152+
3153+
Returns
3154+
-------
3155+
List[List[:class:`abc.Snowflake`], List[:class:`abc.Snowflake`]]
3156+
Returns two lists: the first contains members that were successfully banned, while the second is members that could not be banned.
3157+
3158+
Raises
3159+
------
3160+
ValueError
3161+
You tried to ban more than 200 users.
3162+
Forbidden
3163+
You do not have the proper permissions to ban.
3164+
HTTPException
3165+
No users were banned.
3166+
"""
3167+
31173168
if delete_message_seconds is not None and not (
31183169
0 <= delete_message_seconds <= 604800
31193170
):
31203171
raise TypeError(
31213172
"delete_message_seconds must be between 0 and 604800 seconds."
31223173
)
31233174

3124-
await self._state.http.ban(
3125-
user.id, self.id, delete_message_seconds, delete_message_days, reason=reason
3175+
if len(users) > 200 or len(users) < 1:
3176+
raise ValueError(
3177+
"The number of users to be banned must be between 1 and 200."
3178+
)
3179+
3180+
data = await self._state.http.bulk_ban(
3181+
[u.id for u in users],
3182+
self.id,
3183+
delete_message_seconds,
3184+
reason=reason,
31263185
)
3186+
banned = [u for u in users if str(u.id) in data["banned_users"]]
3187+
failed = [u for u in users if str(u.id) in data["failed_users"]]
3188+
return banned, failed
31273189

31283190
async def unban(self, user: Snowflake, *, reason: str | None = None) -> None:
31293191
"""|coro|

discord/http.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,6 @@ def ban(
907907
user_id: Snowflake,
908908
guild_id: Snowflake,
909909
delete_message_seconds: int = None,
910-
delete_message_days: int = None,
911910
reason: str | None = None,
912911
) -> Response[None]:
913912
r = Route(
@@ -920,17 +919,29 @@ def ban(
920919

921920
if delete_message_seconds:
922921
params["delete_message_seconds"] = delete_message_seconds
923-
elif delete_message_days:
924-
warn_deprecated(
925-
"delete_message_days",
926-
"delete_message_seconds",
927-
"2.2",
928-
reference="https://github.com/discord/discord-api-docs/pull/5219",
929-
)
930-
params["delete_message_days"] = delete_message_days
931922

932923
return self.request(r, params=params, reason=reason)
933924

925+
def bulk_ban(
926+
self,
927+
user_ids: list[Snowflake],
928+
guild_id: Snowflake,
929+
delete_message_seconds: int = None,
930+
reason: str | None = None,
931+
) -> Response[guild.GuildBulkBan]:
932+
r = Route(
933+
"POST",
934+
"/guilds/{guild_id}/bulk-ban",
935+
guild_id=guild_id,
936+
)
937+
payload = {
938+
"user_ids": user_ids,
939+
}
940+
if delete_message_seconds:
941+
payload["delete_message_seconds"] = delete_message_seconds
942+
943+
return self.request(r, json=payload, reason=reason)
944+
934945
def unban(
935946
self, user_id: Snowflake, guild_id: Snowflake, *, reason: str | None = None
936947
) -> Response[None]:

discord/member.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import itertools
3131
import sys
3232
from operator import attrgetter
33-
from typing import TYPE_CHECKING, Any, Literal, TypeVar, Union
33+
from typing import TYPE_CHECKING, Any, TypeVar, Union
3434

3535
import discord.abc
3636

@@ -684,7 +684,6 @@ async def ban(
684684
self,
685685
*,
686686
delete_message_seconds: int | None = None,
687-
delete_message_days: Literal[0, 1, 2, 3, 4, 5, 6, 7] | None = None,
688687
reason: str | None = None,
689688
) -> None:
690689
"""|coro|
@@ -695,7 +694,6 @@ async def ban(
695694
self,
696695
reason=reason,
697696
delete_message_seconds=delete_message_seconds,
698-
delete_message_days=delete_message_days,
699697
)
700698

701699
async def unban(self, *, reason: str | None = None) -> None:

discord/types/guild.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,8 @@ class RolePositionUpdate(TypedDict, total=False):
185185

186186
class GuildMFAModify(TypedDict):
187187
level: Literal[0, 1]
188+
189+
190+
class GuildBulkBan(TypedDict):
191+
banned_users: list[Snowflake]
192+
failed_users: list[Snowflake]

docs/ext/commands/commands.rst

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -573,11 +573,10 @@ When mixed with the :data:`typing.Optional` converter you can provide simple and
573573
574574
@bot.command()
575575
async def ban(ctx, members: commands.Greedy[discord.Member],
576-
delete_days: typing.Optional[int] = 0, *,
576+
delete_seconds: typing.Optional[int] = 0, *,
577577
reason: str):
578-
"""Mass bans members with an optional delete_days parameter"""
579-
for member in members:
580-
await member.ban(delete_message_days=delete_days, reason=reason)
578+
"""Bulk bans members with an optional delete_seconds parameter"""
579+
await ctx.guild.bulk_ban(*members, delete_message_seconds=delete_seconds, reason=reason)
581580
582581
583582
This command can be invoked any of the following ways:
@@ -707,7 +706,7 @@ For example, augmenting the example above:
707706
@commands.command()
708707
async def ban(ctx, *, flags: BanFlags):
709708
for member in flags.members:
710-
await member.ban(reason=flags.reason, delete_message_days=flags.days)
709+
await member.ban(reason=flags.reason, delete_message_seconds=flags.days * 60 * 24)
711710
712711
members = ', '.join(str(member) for member in flags.members)
713712
plural = f'{flags.days} days' if flags.days != 1 else f'{flags.days} day'

0 commit comments

Comments
 (0)