diff --git a/lib/discordrb/api/server.rb b/lib/discordrb/api/server.rb index 9b383299e..857fd26f0 100644 --- a/lib/discordrb/api/server.rb +++ b/lib/discordrb/api/server.rb @@ -200,17 +200,18 @@ def bans(token, server_id, limit = nil, before = nil, after = nil) ) end - # Ban a user from a server and delete their messages from the last message_days days + # Ban a user from a server and delete their messages up to a given amount of time. # https://discord.com/developers/docs/resources/guild#create-guild-ban - def ban_user(token, server_id, user_id, message_days, reason = nil) - reason = URI.encode_www_form_component(reason) if reason + def ban_user(token, server_id, user_id, message_seconds, reason = nil) Discordrb::API.request( :guilds_sid_bans_uid, server_id, :put, - "#{Discordrb::API.api_base}/guilds/#{server_id}/bans/#{user_id}?delete_message_days=#{message_days}&reason=#{reason}", - nil, - Authorization: token + "#{Discordrb::API.api_base}/guilds/#{server_id}/bans/#{user_id}", + { delete_message_seconds: message_seconds }.to_json, + Authorization: token, + content_type: :json, + 'X-Audit-Log-Reason': reason ) end @@ -569,4 +570,19 @@ def add_member(token, server_id, user_id, access_token, nick = nil, roles = [], Authorization: token ) end + + # Ban multiple users in one go + # https://discord.com/developers/docs/resources/guild#bulk-guild-ban + def bulk_ban(token, server_id, users, message_seconds, reason = nil) + Discordrb::API.request( + :guilds_sid_bulk_bans, + server_id, + :post, + "#{Discordrb::API.api_base}/guilds/#{server_id}/bulk-ban", + { user_ids: users, delete_message_seconds: message_seconds }.to_json, + content_type: :json, + Authorization: token, + 'X-Audit-Log-Reason': reason + ) + end end diff --git a/lib/discordrb/data/member.rb b/lib/discordrb/data/member.rb index f2cc80b2f..35c639da6 100644 --- a/lib/discordrb/data/member.rb +++ b/lib/discordrb/data/member.rb @@ -247,10 +247,17 @@ def server_unmute end # Bans this member from the server. - # @param message_days [Integer] How many days worth of messages sent by the member should be deleted. + # @param message_days [Integer] How many days worth of messages sent by the member should be deleted. This parameter is deprecated and will be removed in 4.0. + # @param message_seconds [Integer] How many seconds worth of messages sent by the member should be deleted. # @param reason [String] The reason this member is being banned. - def ban(message_days = 0, reason: nil) - server.ban(@user, message_days, reason: reason) + def ban(message_days = 0, message_seconds: nil, reason: nil) + delete_messages = if message_days != 0 && message_days + message_days * 86_400 + else + message_seconds || 0 + end + + server.ban(@user, delete_messages, reason: reason) end # Unbans this member from the server. diff --git a/lib/discordrb/data/server.rb b/lib/discordrb/data/server.rb index 10a7ce02e..0e82b2020 100644 --- a/lib/discordrb/data/server.rb +++ b/lib/discordrb/data/server.rb @@ -610,10 +610,17 @@ def bans(limit: nil, before_id: nil, after_id: nil) # Bans a user from this server. # @param user [User, String, Integer] The user to ban. - # @param message_days [Integer] How many days worth of messages sent by the user should be deleted. + # @param message_days [Integer] How many days worth of messages sent by the user should be deleted. This is deprecated and will be removed in 4.0. + # @param message_seconds [Integer] How many seconds of messages sent by the user should be deleted. # @param reason [String] The reason the user is being banned. - def ban(user, message_days = 0, reason: nil) - API::Server.ban_user(@bot.token, @id, user.resolve_id, message_days, reason) + def ban(user, message_days = 0, message_seconds: nil, reason: nil) + delete_messages = if message_days != 0 && message_days + message_days * 86_400 + else + message_seconds || 0 + end + + API::Server.ban_user(@bot.token, @id, user.resolve_id, delete_messages, reason) end # Unbans a previously banned user from this server. @@ -623,6 +630,20 @@ def unban(user, reason = nil) API::Server.unban_user(@bot.token, @id, user.resolve_id, reason) end + # Ban up to 200 users from this server in one go. + # @param users [Array] Array of up to 200 users to ban. + # @param message_seconds [Integer] How many seconds of messages sent by the users should be deleted. + # @param reason [String] The reason these users are being banned. + # @return [nil, BulkBan] nil if only a single user was provided or a bulk ban object otherwise. + def bulk_ban(users, message_seconds: 0, reason: nil) + raise ArgumentError, 'Can only ban between 1 and 200 users!' unless users.size.between?(1, 200) + + return ban(users.first, 0, message_seconds: message_seconds, reason: reason) if users.size == 1 + + response = API::Server.bulk_ban(@bot.token, @id, users.map(&:resolve_id), message_seconds, reason) + BulkBan.new(JSON.parse(response), self, reason) + end + # Kicks a user from this server. # @param user [User, String, Integer] The user to kick. # @param reason [String] The reason the user is being kicked. @@ -1012,4 +1033,27 @@ def remove(reason = nil) alias_method :unban, :remove alias_method :lift, :remove end + + # A bulk ban entry on a server + class BulkBan + # @return [Server] The server this bulk ban belongs to. + attr_reader :server + + # @return [String, nil] The reason these users were banned. + attr_reader :reason + + # @return [Array] Array of IDs of banned users. + attr_reader :banned_users + + # @return [Array] Array of IDs of users who couldn't be banned. + attr_reader :failed_users + + # @!visibility private + def initialize(data, server, reason) + @server = server + @reason = reason + @banned_users = data['banned_users'].map(&:resolve_id) + @failed_users = data['failed_users'].map(&:resolve_id) + end + end end diff --git a/lib/discordrb/errors.rb b/lib/discordrb/errors.rb index c5fd1f96b..ee9b56006 100644 --- a/lib/discordrb/errors.rb +++ b/lib/discordrb/errors.rb @@ -174,6 +174,9 @@ def self.error_class_for(code) # Unauthorized Unauthorized = Unauthorised = Code(40_001) + # Unable to bulk ban any members + UnableToBulkBanMembers = Code(500_000) + # Missing Access MissingAccess = Code(50_001)