discordrb 3.4.3 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +13 -0
- data/.devcontainer/devcontainer.json +29 -0
- data/.devcontainer/postcreate.sh +4 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -1
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -1
- data/.github/workflows/ci.yml +78 -0
- data/.github/workflows/codeql.yml +65 -0
- data/.github/workflows/deploy.yml +54 -0
- data/.github/workflows/release.yml +45 -0
- data/.markdownlint.json +4 -0
- data/.rubocop.yml +58 -2
- data/CHANGELOG.md +485 -225
- data/LICENSE.txt +1 -1
- data/README.md +38 -26
- data/discordrb-webhooks.gemspec +4 -1
- data/discordrb.gemspec +18 -10
- data/lib/discordrb/api/application.rb +278 -0
- data/lib/discordrb/api/channel.rb +222 -18
- data/lib/discordrb/api/interaction.rb +63 -0
- data/lib/discordrb/api/invite.rb +2 -2
- data/lib/discordrb/api/server.rb +123 -66
- data/lib/discordrb/api/user.rb +20 -5
- data/lib/discordrb/api/webhook.rb +72 -0
- data/lib/discordrb/api.rb +35 -25
- data/lib/discordrb/bot.rb +437 -66
- data/lib/discordrb/cache.rb +41 -22
- data/lib/discordrb/commands/command_bot.rb +13 -21
- data/lib/discordrb/commands/container.rb +1 -1
- data/lib/discordrb/commands/parser.rb +7 -7
- data/lib/discordrb/commands/rate_limiter.rb +1 -1
- data/lib/discordrb/container.rb +178 -3
- data/lib/discordrb/data/activity.rb +1 -1
- data/lib/discordrb/data/application.rb +1 -0
- data/lib/discordrb/data/attachment.rb +38 -3
- data/lib/discordrb/data/audit_logs.rb +3 -3
- data/lib/discordrb/data/avatar_decoration.rb +26 -0
- data/lib/discordrb/data/call.rb +22 -0
- data/lib/discordrb/data/channel.rb +299 -30
- data/lib/discordrb/data/collectibles.rb +45 -0
- data/lib/discordrb/data/component.rb +229 -0
- data/lib/discordrb/data/embed.rb +10 -3
- data/lib/discordrb/data/emoji.rb +20 -1
- data/lib/discordrb/data/integration.rb +45 -3
- data/lib/discordrb/data/interaction.rb +937 -0
- data/lib/discordrb/data/invite.rb +1 -1
- data/lib/discordrb/data/member.rb +236 -44
- data/lib/discordrb/data/message.rb +278 -51
- data/lib/discordrb/data/overwrite.rb +15 -7
- data/lib/discordrb/data/primary_server.rb +60 -0
- data/lib/discordrb/data/profile.rb +2 -7
- data/lib/discordrb/data/reaction.rb +2 -1
- data/lib/discordrb/data/recipient.rb +1 -1
- data/lib/discordrb/data/role.rb +204 -18
- data/lib/discordrb/data/server.rb +194 -118
- data/lib/discordrb/data/server_preview.rb +68 -0
- data/lib/discordrb/data/snapshot.rb +110 -0
- data/lib/discordrb/data/user.rb +132 -12
- data/lib/discordrb/data/voice_region.rb +1 -0
- data/lib/discordrb/data/webhook.rb +99 -9
- data/lib/discordrb/data.rb +9 -0
- data/lib/discordrb/errors.rb +47 -3
- data/lib/discordrb/events/await.rb +1 -1
- data/lib/discordrb/events/channels.rb +38 -1
- data/lib/discordrb/events/generic.rb +2 -0
- data/lib/discordrb/events/guilds.rb +6 -1
- data/lib/discordrb/events/interactions.rb +575 -0
- data/lib/discordrb/events/invites.rb +2 -0
- data/lib/discordrb/events/members.rb +19 -2
- data/lib/discordrb/events/message.rb +42 -8
- data/lib/discordrb/events/presence.rb +23 -14
- data/lib/discordrb/events/raw.rb +1 -0
- data/lib/discordrb/events/reactions.rb +2 -1
- data/lib/discordrb/events/roles.rb +2 -0
- data/lib/discordrb/events/threads.rb +100 -0
- data/lib/discordrb/events/typing.rb +1 -0
- data/lib/discordrb/events/voice_server_update.rb +1 -0
- data/lib/discordrb/events/voice_state_update.rb +1 -0
- data/lib/discordrb/events/webhooks.rb +1 -0
- data/lib/discordrb/gateway.rb +57 -28
- data/lib/discordrb/paginator.rb +3 -3
- data/lib/discordrb/permissions.rb +71 -35
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +2 -2
- data/lib/discordrb/voice/network.rb +18 -7
- data/lib/discordrb/voice/sodium.rb +3 -1
- data/lib/discordrb/voice/voice_bot.rb +3 -3
- data/lib/discordrb/webhooks.rb +2 -0
- data/lib/discordrb/websocket.rb +0 -10
- data/lib/discordrb.rb +54 -5
- metadata +87 -25
- data/.circleci/config.yml +0 -126
- data/.codeclimate.yml +0 -16
- data/.travis.yml +0 -32
- data/bin/travis_build_docs.sh +0 -17
|
@@ -64,38 +64,20 @@ module Discordrb
|
|
|
64
64
|
# @!visibility private
|
|
65
65
|
def initialize(data, bot)
|
|
66
66
|
@bot = bot
|
|
67
|
-
@owner_id = data['owner_id'].to_i
|
|
68
67
|
@id = data['id'].to_i
|
|
69
|
-
|
|
70
|
-
process_channels(data['channels'])
|
|
71
|
-
update_data(data)
|
|
72
|
-
|
|
73
|
-
@large = data['large']
|
|
74
|
-
@member_count = data['member_count']
|
|
75
|
-
@splash_id = nil
|
|
76
|
-
@banner_id = nil
|
|
77
|
-
@features = data['features'].map { |element| element.downcase.to_sym }
|
|
78
68
|
@members = {}
|
|
79
69
|
@voice_states = {}
|
|
80
70
|
@emoji = {}
|
|
81
71
|
|
|
82
|
-
|
|
83
|
-
process_emoji(data['emojis'])
|
|
84
|
-
process_members(data['members'])
|
|
85
|
-
process_presences(data['presences'])
|
|
86
|
-
process_voice_states(data['voice_states'])
|
|
72
|
+
update_data(data)
|
|
87
73
|
|
|
88
74
|
# Whether this server's members have been chunked (resolved using op 8 and GUILD_MEMBERS_CHUNK) yet
|
|
89
75
|
@chunked = false
|
|
90
|
-
@processed_chunk_members = 0
|
|
91
|
-
|
|
92
|
-
@booster_count = data['premium_subscription_count'] || 0
|
|
93
|
-
@boost_level = data['premium_tier']
|
|
94
76
|
end
|
|
95
77
|
|
|
96
78
|
# @return [Member] The server owner.
|
|
97
79
|
def owner
|
|
98
|
-
|
|
80
|
+
member(@owner_id)
|
|
99
81
|
end
|
|
100
82
|
|
|
101
83
|
# The default channel is the text channel on this server with the highest position
|
|
@@ -143,10 +125,15 @@ module Discordrb
|
|
|
143
125
|
end
|
|
144
126
|
|
|
145
127
|
# @return [Array<Member>] an array of all the members on this server.
|
|
128
|
+
# @raise [RuntimeError] if the bot was not started with the :server_member intent
|
|
146
129
|
def members
|
|
147
130
|
return @members.values if @chunked
|
|
148
131
|
|
|
149
132
|
@bot.debug("Members for server #{@id} not chunked yet - initiating")
|
|
133
|
+
|
|
134
|
+
# If the SERVER_MEMBERS intent flag isn't set, the gateway won't respond when we ask for members.
|
|
135
|
+
raise 'The :server_members intent is required to get server members' if @bot.gateway.intents.nobits?(INTENTS[:server_members])
|
|
136
|
+
|
|
150
137
|
@bot.request_chunks(@id)
|
|
151
138
|
sleep 0.05 until @chunked
|
|
152
139
|
@members.values
|
|
@@ -189,78 +176,73 @@ module Discordrb
|
|
|
189
176
|
AuditLogs.new(self, @bot, JSON.parse(API::Server.audit_logs(@bot.token, @id, limit, user, action, before)))
|
|
190
177
|
end
|
|
191
178
|
|
|
192
|
-
# Cache @
|
|
179
|
+
# Cache @widget
|
|
193
180
|
# @note For internal use only
|
|
194
181
|
# @!visibility private
|
|
195
|
-
def
|
|
196
|
-
data = JSON.parse(API::Server.
|
|
197
|
-
@
|
|
198
|
-
@
|
|
182
|
+
def cache_widget_data
|
|
183
|
+
data = JSON.parse(API::Server.widget(@bot.token, @id))
|
|
184
|
+
@widget_enabled = data['enabled']
|
|
185
|
+
@widget_channel_id = data['channel_id']
|
|
199
186
|
end
|
|
200
187
|
|
|
201
188
|
# @return [true, false] whether or not the server has widget enabled
|
|
202
|
-
def
|
|
203
|
-
|
|
204
|
-
@
|
|
189
|
+
def widget_enabled?
|
|
190
|
+
cache_widget_data if @widget_enabled.nil?
|
|
191
|
+
@widget_enabled
|
|
205
192
|
end
|
|
206
|
-
alias_method :
|
|
207
|
-
alias_method :
|
|
208
|
-
alias_method :embed?, :
|
|
193
|
+
alias_method :widget?, :widget_enabled?
|
|
194
|
+
alias_method :embed_enabled, :widget_enabled?
|
|
195
|
+
alias_method :embed?, :widget_enabled?
|
|
209
196
|
|
|
210
|
-
# @return [Channel, nil] the channel the server
|
|
211
|
-
def
|
|
212
|
-
|
|
213
|
-
@bot.channel(@
|
|
197
|
+
# @return [Channel, nil] the channel the server widget will make an invite for.
|
|
198
|
+
def widget_channel
|
|
199
|
+
cache_widget_data if @widget_enabled.nil?
|
|
200
|
+
@bot.channel(@widget_channel_id) if @widget_channel_id
|
|
214
201
|
end
|
|
215
|
-
alias_method :
|
|
202
|
+
alias_method :embed_channel, :widget_channel
|
|
216
203
|
|
|
217
|
-
# Sets whether this server's
|
|
204
|
+
# Sets whether this server's widget is enabled
|
|
218
205
|
# @param value [true, false]
|
|
219
|
-
def
|
|
220
|
-
|
|
206
|
+
def widget_enabled=(value)
|
|
207
|
+
modify_widget(value, widget_channel)
|
|
221
208
|
end
|
|
209
|
+
alias_method :embed_enabled=, :widget_enabled=
|
|
222
210
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
# Sets whether this server's embed (widget) is enabled
|
|
211
|
+
# Sets whether this server's widget is enabled
|
|
226
212
|
# @param value [true, false]
|
|
227
213
|
# @param reason [String, nil] the reason to be shown in the audit log for this action
|
|
228
|
-
def
|
|
229
|
-
|
|
214
|
+
def set_widget_enabled(value, reason = nil)
|
|
215
|
+
modify_widget(value, widget_channel, reason)
|
|
230
216
|
end
|
|
217
|
+
alias_method :set_embed_enabled, :set_widget_enabled
|
|
231
218
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
def embed_channel=(channel)
|
|
237
|
-
modify_embed(embed?, channel)
|
|
219
|
+
# Changes the channel on the server's widget
|
|
220
|
+
# @param channel [Channel, String, Integer] the channel, or its ID, to be referenced by the widget
|
|
221
|
+
def widget_channel=(channel)
|
|
222
|
+
modify_widget(widget?, channel)
|
|
238
223
|
end
|
|
224
|
+
alias_method :embed_channel=, :widget_channel=
|
|
239
225
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# Changes the channel on the server's embed (widget)
|
|
243
|
-
# @param channel [Channel, String, Integer] the channel, or its ID, to be referenced by the embed
|
|
226
|
+
# Changes the channel on the server's widget
|
|
227
|
+
# @param channel [Channel, String, Integer] the channel, or its ID, to be referenced by the widget
|
|
244
228
|
# @param reason [String, nil] the reason to be shown in the audit log for this action
|
|
245
|
-
def
|
|
246
|
-
|
|
229
|
+
def set_widget_channel(channel, reason = nil)
|
|
230
|
+
modify_widget(widget?, channel, reason)
|
|
247
231
|
end
|
|
232
|
+
alias_method :set_embed_channel, :set_widget_channel
|
|
248
233
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
#
|
|
252
|
-
# @param enabled [true, false] whether the embed (widget) is enabled
|
|
253
|
-
# @param channel [Channel, String, Integer] the channel, or its ID, to be referenced by the embed
|
|
234
|
+
# Changes the channel on the server's widget, and sets whether it is enabled.
|
|
235
|
+
# @param enabled [true, false] whether the widget is enabled
|
|
236
|
+
# @param channel [Channel, String, Integer] the channel, or its ID, to be referenced by the widget
|
|
254
237
|
# @param reason [String, nil] the reason to be shown in the audit log for this action
|
|
255
|
-
def
|
|
256
|
-
|
|
257
|
-
channel_id = channel ? channel.resolve_id : @
|
|
258
|
-
response = JSON.parse(API::Server.
|
|
259
|
-
@
|
|
260
|
-
@
|
|
238
|
+
def modify_widget(enabled, channel, reason = nil)
|
|
239
|
+
cache_widget_data if @widget_enabled.nil?
|
|
240
|
+
channel_id = channel ? channel.resolve_id : @widget_channel_id
|
|
241
|
+
response = JSON.parse(API::Server.modify_widget(@bot.token, @id, enabled, channel_id, reason))
|
|
242
|
+
@widget_enabled = response['enabled']
|
|
243
|
+
@widget_channel_id = response['channel_id']
|
|
261
244
|
end
|
|
262
|
-
|
|
263
|
-
alias_method :modify_widget, :modify_embed
|
|
245
|
+
alias_method :modify_embed, :modify_widget
|
|
264
246
|
|
|
265
247
|
# @param include_idle [true, false] Whether to count idle members as online.
|
|
266
248
|
# @param include_bots [true, false] Whether to include bot accounts in the count.
|
|
@@ -338,6 +320,11 @@ module Discordrb
|
|
|
338
320
|
@channels.reject { |c| c.parent || c.category? }
|
|
339
321
|
end
|
|
340
322
|
|
|
323
|
+
# @return [ServerPreview] the preview of this server shown in the discovery page.
|
|
324
|
+
def preview
|
|
325
|
+
@bot.server_preview(@id)
|
|
326
|
+
end
|
|
327
|
+
|
|
341
328
|
# @return [String, nil] the widget URL to the server that displays the amount of online members in a
|
|
342
329
|
# stylish way. `nil` if the widget is not enabled.
|
|
343
330
|
def widget_url
|
|
@@ -410,7 +397,7 @@ module Discordrb
|
|
|
410
397
|
# @!visibility private
|
|
411
398
|
def delete_role(role_id)
|
|
412
399
|
@roles.reject! { |r| r.id == role_id }
|
|
413
|
-
@members.
|
|
400
|
+
@members.each_value do |member|
|
|
414
401
|
new_roles = member.roles.reject { |r| r.id == role_id }
|
|
415
402
|
member.update_roles(new_roles)
|
|
416
403
|
end
|
|
@@ -444,7 +431,7 @@ module Discordrb
|
|
|
444
431
|
# @!visibility private
|
|
445
432
|
def delete_member(user_id)
|
|
446
433
|
@members.delete(user_id)
|
|
447
|
-
@member_count -= 1
|
|
434
|
+
@member_count -= 1 unless @member_count <= 0
|
|
448
435
|
end
|
|
449
436
|
|
|
450
437
|
# Checks whether a member is cached
|
|
@@ -520,14 +507,19 @@ module Discordrb
|
|
|
520
507
|
# Creates a role on this server which can then be modified. It will be initialized
|
|
521
508
|
# with the regular role defaults the client uses unless specified, i.e. name is "new role",
|
|
522
509
|
# permissions are the default, colour is the default etc.
|
|
523
|
-
# @param name [String] Name of the role to create
|
|
524
|
-
# @param colour [Integer, ColourRGB, #combined] The
|
|
525
|
-
# @param hoist [true, false]
|
|
526
|
-
# @param mentionable [true, false]
|
|
510
|
+
# @param name [String] Name of the role to create.
|
|
511
|
+
# @param colour [Integer, ColourRGB, #combined] The primary colour of the role to create.
|
|
512
|
+
# @param hoist [true, false] whether members of this role should be displayed seperately in the members list.
|
|
513
|
+
# @param mentionable [true, false] whether this role can mentioned by anyone in the server.
|
|
527
514
|
# @param permissions [Integer, Array<Symbol>, Permissions, #bits] The permissions to write to the new role.
|
|
515
|
+
# @param icon [String, #read, nil] The base64 encoded image data, or a file like object that responds to #read.
|
|
516
|
+
# @param unicode_emoji [String, nil] The unicode emoji of the role to create, or nil.
|
|
517
|
+
# @param display_icon [String, File, #read, nil] The icon to display for the role. Overrides the **icon** and **unicode_emoji** parameters if passed.
|
|
528
518
|
# @param reason [String] The reason the for the creation of this role.
|
|
519
|
+
# @param secondary_colour [Integer, ColourRGB, nil] The secondary colour of the role to create.
|
|
520
|
+
# @param tertiary_colour [Integer, ColourRGB, nil] The tertiary colour of the role to create.
|
|
529
521
|
# @return [Role] the created role.
|
|
530
|
-
def create_role(name: 'new role', colour: 0, hoist: false, mentionable: false, permissions: 104_324_161, reason: nil)
|
|
522
|
+
def create_role(name: 'new role', colour: 0, hoist: false, mentionable: false, permissions: 104_324_161, secondary_colour: nil, tertiary_colour: nil, icon: nil, unicode_emoji: nil, display_icon: nil, reason: nil)
|
|
531
523
|
colour = colour.respond_to?(:combined) ? colour.combined : colour
|
|
532
524
|
|
|
533
525
|
permissions = if permissions.is_a?(Array)
|
|
@@ -538,7 +530,21 @@ module Discordrb
|
|
|
538
530
|
permissions
|
|
539
531
|
end
|
|
540
532
|
|
|
541
|
-
|
|
533
|
+
icon = icon.respond_to?(:read) ? Discordrb.encode64(icon) : icon
|
|
534
|
+
|
|
535
|
+
colours = {
|
|
536
|
+
primary_color: colour&.to_i,
|
|
537
|
+
tertiary_color: tertiary_colour&.to_i,
|
|
538
|
+
secondary_color: secondary_colour&.to_i
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if display_icon.is_a?(String)
|
|
542
|
+
unicode_emoji = display_icon
|
|
543
|
+
elsif display_icon.respond_to?(:read)
|
|
544
|
+
icon = Discordrb.encode64(display_icon)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
response = API::Server.create_role(@bot.token, @id, name, nil, hoist, mentionable, permissions&.to_s, reason, colours, icon, unicode_emoji)
|
|
542
548
|
|
|
543
549
|
role = Role.new(JSON.parse(response), @bot, self)
|
|
544
550
|
@roles << role
|
|
@@ -552,13 +558,9 @@ module Discordrb
|
|
|
552
558
|
# @param reason [String] The reason the for the creation of this emoji.
|
|
553
559
|
# @return [Emoji] The emoji that has been added.
|
|
554
560
|
def add_emoji(name, image, roles = [], reason: nil)
|
|
555
|
-
|
|
556
|
-
if image.respond_to? :read
|
|
557
|
-
image_string = 'data:image/jpg;base64,'
|
|
558
|
-
image_string += Base64.strict_encode64(image.read)
|
|
559
|
-
end
|
|
561
|
+
image = image.respond_to?(:read) ? Discordrb.encode64(image) : image
|
|
560
562
|
|
|
561
|
-
data = JSON.parse(API::Server.add_emoji(@bot.token, @id,
|
|
563
|
+
data = JSON.parse(API::Server.add_emoji(@bot.token, @id, image, name, roles.map(&:resolve_id), reason))
|
|
562
564
|
new_emoji = Emoji.new(data, @bot, self)
|
|
563
565
|
@emoji[new_emoji.id] = new_emoji
|
|
564
566
|
end
|
|
@@ -586,7 +588,7 @@ module Discordrb
|
|
|
586
588
|
# The amount of emoji the server can have, based on its current Nitro Boost Level.
|
|
587
589
|
# @return [Integer] the max amount of emoji
|
|
588
590
|
def max_emoji
|
|
589
|
-
case @
|
|
591
|
+
case @boost_level
|
|
590
592
|
when 1
|
|
591
593
|
100
|
|
592
594
|
when 2
|
|
@@ -598,9 +600,24 @@ module Discordrb
|
|
|
598
600
|
end
|
|
599
601
|
end
|
|
600
602
|
|
|
603
|
+
# Searches a server for members that matches a username or a nickname.
|
|
604
|
+
# @param name [String] The username or nickname to search for.
|
|
605
|
+
# @param limit [Integer] The maximum number of members between 1-1000 to return. Returns 1 member by default.
|
|
606
|
+
# @return [Array<Member>, nil] An array of member objects that match the given parameters, or nil for no members.
|
|
607
|
+
def search_members(name:, limit: nil)
|
|
608
|
+
response = JSON.parse(API::Server.search_guild_members(@bot.token, @id, name, limit))
|
|
609
|
+
return nil if response.empty?
|
|
610
|
+
|
|
611
|
+
response.map { |mem| Member.new(mem, self, @bot) }
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
# Retrieve banned users from this server.
|
|
615
|
+
# @param limit [Integer] Number of users to return (up to maximum 1000, default 1000).
|
|
616
|
+
# @param before_id [Integer] Consider only users before given user id.
|
|
617
|
+
# @param after_id [Integer] Consider only users after given user id.
|
|
601
618
|
# @return [Array<ServerBan>] a list of banned users on this server and the reason they were banned.
|
|
602
|
-
def bans
|
|
603
|
-
response = JSON.parse(API::Server.bans(@bot.token, @id))
|
|
619
|
+
def bans(limit: nil, before_id: nil, after_id: nil)
|
|
620
|
+
response = JSON.parse(API::Server.bans(@bot.token, @id, limit, before_id, after_id))
|
|
604
621
|
response.map do |e|
|
|
605
622
|
ServerBan.new(self, User.new(e['user'], @bot), e['reason'])
|
|
606
623
|
end
|
|
@@ -608,10 +625,17 @@ module Discordrb
|
|
|
608
625
|
|
|
609
626
|
# Bans a user from this server.
|
|
610
627
|
# @param user [User, String, Integer] The user to ban.
|
|
611
|
-
# @param message_days [Integer] How many days worth of messages sent by the user should be deleted.
|
|
628
|
+
# @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.
|
|
629
|
+
# @param message_seconds [Integer] How many seconds of messages sent by the user should be deleted.
|
|
612
630
|
# @param reason [String] The reason the user is being banned.
|
|
613
|
-
def ban(user, message_days = 0, reason: nil)
|
|
614
|
-
|
|
631
|
+
def ban(user, message_days = 0, message_seconds: nil, reason: nil)
|
|
632
|
+
delete_messages = if message_days != 0 && message_days
|
|
633
|
+
message_days * 86_400
|
|
634
|
+
else
|
|
635
|
+
message_seconds || 0
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
API::Server.ban_user!(@bot.token, @id, user.resolve_id, delete_messages, reason)
|
|
615
639
|
end
|
|
616
640
|
|
|
617
641
|
# Unbans a previously banned user from this server.
|
|
@@ -621,6 +645,20 @@ module Discordrb
|
|
|
621
645
|
API::Server.unban_user(@bot.token, @id, user.resolve_id, reason)
|
|
622
646
|
end
|
|
623
647
|
|
|
648
|
+
# Ban up to 200 users from this server in one go.
|
|
649
|
+
# @param users [Array<User, String, Integer>] Array of up to 200 users to ban.
|
|
650
|
+
# @param message_seconds [Integer] How many seconds of messages sent by the users should be deleted.
|
|
651
|
+
# @param reason [String] The reason these users are being banned.
|
|
652
|
+
# @return [BulkBan]
|
|
653
|
+
def bulk_ban(users:, message_seconds: 0, reason: nil)
|
|
654
|
+
raise ArgumentError, 'Can only ban between 1 and 200 users!' unless users.size.between?(1, 200)
|
|
655
|
+
|
|
656
|
+
return ban(users.first, 0, message_seconds: message_seconds, reason: reason) if users.size == 1
|
|
657
|
+
|
|
658
|
+
response = API::Server.bulk_ban(@bot.token, @id, users.map(&:resolve_id), message_seconds, reason)
|
|
659
|
+
BulkBan.new(JSON.parse(response), self, reason)
|
|
660
|
+
end
|
|
661
|
+
|
|
624
662
|
# Kicks a user from this server.
|
|
625
663
|
# @param user [User, String, Integer] The user to kick.
|
|
626
664
|
# @param reason [String] The reason the user is being kicked.
|
|
@@ -628,16 +666,12 @@ module Discordrb
|
|
|
628
666
|
API::Server.remove_member(@bot.token, @id, user.resolve_id, reason)
|
|
629
667
|
end
|
|
630
668
|
|
|
631
|
-
# Forcibly moves a user into a different voice channel.
|
|
669
|
+
# Forcibly moves a user into a different voice channel.
|
|
670
|
+
# Only works if the bot has the permission needed and if the user is already connected to some voice channel on this server.
|
|
632
671
|
# @param user [User, String, Integer] The user to move.
|
|
633
|
-
# @param channel [Channel, String, Integer] The voice channel to move into.
|
|
672
|
+
# @param channel [Channel, String, Integer, nil] The voice channel to move into. (If nil, the user is disconnected from the voice channel)
|
|
634
673
|
def move(user, channel)
|
|
635
|
-
API::Server.update_member(@bot.token, @id, user.resolve_id, channel_id: channel
|
|
636
|
-
end
|
|
637
|
-
|
|
638
|
-
# Deletes this server. Be aware that this is permanent and impossible to undo, so be careful!
|
|
639
|
-
def delete
|
|
640
|
-
API::Server.delete(@bot.token, @id)
|
|
674
|
+
API::Server.update_member(@bot.token, @id, user.resolve_id, channel_id: channel&.resolve_id)
|
|
641
675
|
end
|
|
642
676
|
|
|
643
677
|
# Leave the server.
|
|
@@ -645,12 +679,6 @@ module Discordrb
|
|
|
645
679
|
API::User.leave_server(@bot.token, @id)
|
|
646
680
|
end
|
|
647
681
|
|
|
648
|
-
# Transfers server ownership to another user.
|
|
649
|
-
# @param user [User, String, Integer] The user who should become the new owner.
|
|
650
|
-
def owner=(user)
|
|
651
|
-
API::Server.transfer_ownership(@bot.token, @id, user.resolve_id)
|
|
652
|
-
end
|
|
653
|
-
|
|
654
682
|
# Sets the server's name.
|
|
655
683
|
# @param name [String] The new server name.
|
|
656
684
|
def name=(name)
|
|
@@ -682,10 +710,8 @@ module Discordrb
|
|
|
682
710
|
# Sets the server's icon.
|
|
683
711
|
# @param icon [String, #read] The new icon, in base64-encoded JPG format.
|
|
684
712
|
def icon=(icon)
|
|
685
|
-
if icon.respond_to?
|
|
686
|
-
|
|
687
|
-
icon_string += Base64.strict_encode64(icon.read)
|
|
688
|
-
update_server_data(icon_id: icon_string)
|
|
713
|
+
if icon.respond_to?(:read)
|
|
714
|
+
update_server_data(icon_id: Discordrb.encode64(icon))
|
|
689
715
|
else
|
|
690
716
|
update_server_data(icon_id: icon)
|
|
691
717
|
end
|
|
@@ -805,19 +831,16 @@ module Discordrb
|
|
|
805
831
|
# Processes a GUILD_MEMBERS_CHUNK packet, specifically the members field
|
|
806
832
|
# @note For internal use only
|
|
807
833
|
# @!visibility private
|
|
808
|
-
def process_chunk(members)
|
|
834
|
+
def process_chunk(members, chunk_index, chunk_count)
|
|
809
835
|
process_members(members)
|
|
810
|
-
@
|
|
811
|
-
LOGGER.debug("Processed one chunk on server #{@id} - length #{members.length}")
|
|
836
|
+
LOGGER.debug("Processed chunk #{chunk_index + 1}/#{chunk_count} server #{@id} - index #{chunk_index} - length #{members.length}")
|
|
812
837
|
|
|
813
|
-
|
|
814
|
-
return unless @processed_chunk_members == @member_count
|
|
838
|
+
return if chunk_index + 1 < chunk_count
|
|
815
839
|
|
|
816
840
|
LOGGER.debug("Finished chunking server #{@id}")
|
|
817
841
|
|
|
818
842
|
# Reset everything to normal
|
|
819
843
|
@chunked = true
|
|
820
|
-
@processed_chunk_members = 0
|
|
821
844
|
end
|
|
822
845
|
|
|
823
846
|
# @return [Channel, nil] the AFK voice channel of this server, or `nil` if none is set.
|
|
@@ -841,18 +864,35 @@ module Discordrb
|
|
|
841
864
|
@afk_timeout = new_data[:afk_timeout] || new_data['afk_timeout'] || @afk_timeout
|
|
842
865
|
|
|
843
866
|
afk_channel_id = new_data[:afk_channel_id] || new_data['afk_channel_id'] || @afk_channel
|
|
844
|
-
@afk_channel_id = afk_channel_id
|
|
845
|
-
|
|
846
|
-
@
|
|
867
|
+
@afk_channel_id = afk_channel_id&.resolve_id
|
|
868
|
+
widget_channel_id = new_data[:widget_channel_id] || new_data['widget_channel_id'] || @widget_channel
|
|
869
|
+
@widget_channel_id = widget_channel_id&.resolve_id
|
|
847
870
|
system_channel_id = new_data[:system_channel_id] || new_data['system_channel_id'] || @system_channel
|
|
848
|
-
@system_channel_id = system_channel_id
|
|
871
|
+
@system_channel_id = system_channel_id&.resolve_id
|
|
849
872
|
|
|
850
|
-
@
|
|
873
|
+
@widget_enabled = new_data[:widget_enabled] || new_data['widget_enabled']
|
|
851
874
|
@splash = new_data[:splash_id] || new_data['splash_id'] || @splash_id
|
|
852
875
|
|
|
853
876
|
@verification_level = new_data[:verification_level] || new_data['verification_level'] || @verification_level
|
|
854
877
|
@explicit_content_filter = new_data[:explicit_content_filter] || new_data['explicit_content_filter'] || @explicit_content_filter
|
|
855
878
|
@default_message_notifications = new_data[:default_message_notifications] || new_data['default_message_notifications'] || @default_message_notifications
|
|
879
|
+
|
|
880
|
+
@large = new_data.key?('large') ? new_data['large'] : @large
|
|
881
|
+
@member_count = new_data['member_count'] || @member_count || 0
|
|
882
|
+
@splash_id = new_data['splash'] || @splash_id
|
|
883
|
+
@banner_id = new_data['banner'] || @banner_id
|
|
884
|
+
@features = new_data['features'] ? new_data['features'].map { |element| element.downcase.to_sym } : @features || []
|
|
885
|
+
@booster_count = new_data['premium_subscription_count'] || @booster_count || 0
|
|
886
|
+
@boost_level = new_data['premium_tier'] || @boost_level
|
|
887
|
+
@owner_id = new_data['owner_id'].to_i
|
|
888
|
+
|
|
889
|
+
process_channels(new_data['channels']) if new_data['channels']
|
|
890
|
+
process_roles(new_data['roles']) if new_data['roles']
|
|
891
|
+
process_emoji(new_data['emojis']) if new_data['emojis']
|
|
892
|
+
process_members(new_data['members']) if new_data['members']
|
|
893
|
+
process_presences(new_data['presences']) if new_data['presences']
|
|
894
|
+
process_voice_states(new_data['voice_states']) if new_data['voice_states']
|
|
895
|
+
process_active_threads(new_data['threads']) if new_data['threads']
|
|
856
896
|
end
|
|
857
897
|
|
|
858
898
|
# Adds a channel to this server's cache
|
|
@@ -970,6 +1010,19 @@ module Discordrb
|
|
|
970
1010
|
update_voice_state(element)
|
|
971
1011
|
end
|
|
972
1012
|
end
|
|
1013
|
+
|
|
1014
|
+
def process_active_threads(threads)
|
|
1015
|
+
@channels ||= []
|
|
1016
|
+
@channels_by_id ||= {}
|
|
1017
|
+
|
|
1018
|
+
return unless threads
|
|
1019
|
+
|
|
1020
|
+
threads.each do |element|
|
|
1021
|
+
thread = @bot.ensure_channel(element, self)
|
|
1022
|
+
@channels << thread
|
|
1023
|
+
@channels_by_id[thread.id] = thread
|
|
1024
|
+
end
|
|
1025
|
+
end
|
|
973
1026
|
end
|
|
974
1027
|
|
|
975
1028
|
# A ban entry on a server
|
|
@@ -999,4 +1052,27 @@ module Discordrb
|
|
|
999
1052
|
alias_method :unban, :remove
|
|
1000
1053
|
alias_method :lift, :remove
|
|
1001
1054
|
end
|
|
1055
|
+
|
|
1056
|
+
# A bulk ban entry on a server
|
|
1057
|
+
class BulkBan
|
|
1058
|
+
# @return [Server] The server this bulk ban belongs to.
|
|
1059
|
+
attr_reader :server
|
|
1060
|
+
|
|
1061
|
+
# @return [String, nil] The reason these users were banned.
|
|
1062
|
+
attr_reader :reason
|
|
1063
|
+
|
|
1064
|
+
# @return [Array<Integer>] Array of user IDs that were banned.
|
|
1065
|
+
attr_reader :banned_users
|
|
1066
|
+
|
|
1067
|
+
# @return [Array<Integer>] Array of user IDs that couldn't be banned.
|
|
1068
|
+
attr_reader :failed_users
|
|
1069
|
+
|
|
1070
|
+
# @!visibility private
|
|
1071
|
+
def initialize(data, server, reason)
|
|
1072
|
+
@server = server
|
|
1073
|
+
@reason = reason
|
|
1074
|
+
@banned_users = data['banned_users']&.map(&:resolve_id) || []
|
|
1075
|
+
@failed_users = data['failed_users']&.map(&:resolve_id) || []
|
|
1076
|
+
end
|
|
1077
|
+
end
|
|
1002
1078
|
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Discordrb
|
|
4
|
+
# Publicly accessible information about a discoverable server.
|
|
5
|
+
class ServerPreview
|
|
6
|
+
include IDObject
|
|
7
|
+
include ServerAttributes
|
|
8
|
+
|
|
9
|
+
# @return [String, nil] the ID of the server's invite splash screen.
|
|
10
|
+
# @see #splash_url
|
|
11
|
+
attr_reader :splash_id
|
|
12
|
+
|
|
13
|
+
# @return [String, nil] the ID of the server's discovery splash screen.
|
|
14
|
+
# @see #discovery_splash_url
|
|
15
|
+
attr_reader :discovery_splash_id
|
|
16
|
+
|
|
17
|
+
# @return [Hash<Integer => Emoji>] a hash of all the emojis usable on this server.
|
|
18
|
+
attr_reader :emojis
|
|
19
|
+
|
|
20
|
+
# @return [Array<Symbol>] the features of this server, e.g. `:banner` or `:verified`.
|
|
21
|
+
attr_reader :features
|
|
22
|
+
|
|
23
|
+
# @return [Integer] the approximate number of members on this server, offline or not.
|
|
24
|
+
attr_reader :member_count
|
|
25
|
+
|
|
26
|
+
# @return [Integer] the approximate number of members that aren't offline on this server.
|
|
27
|
+
attr_reader :presence_count
|
|
28
|
+
|
|
29
|
+
# @return [String, nil] the description of this server that's shown in the discovery tab.
|
|
30
|
+
attr_reader :description
|
|
31
|
+
|
|
32
|
+
# @!visibility private
|
|
33
|
+
def initialize(data, bot)
|
|
34
|
+
@bot = bot
|
|
35
|
+
@id = data['id'].to_i
|
|
36
|
+
@name = data['name']
|
|
37
|
+
@icon_id = data['icon']
|
|
38
|
+
@splash_id = data['splash']
|
|
39
|
+
@description = data['description']
|
|
40
|
+
@discovery_splash_id = data['discovery_splash']
|
|
41
|
+
@member_count = data['approximate_member_count']
|
|
42
|
+
@presence_count = data['approximate_presence_count']
|
|
43
|
+
@features = data['features'].map { |feature| feature.downcase.to_sym }
|
|
44
|
+
@emojis = data['emojis'].to_h { |emoji| [emoji['id'].to_i, Emoji.new(emoji, bot)] }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get the server associated with this server preview.
|
|
48
|
+
# @return [Server] the server associated with this server preview.
|
|
49
|
+
# @raise [Discordrb::Errors::NoPermission] this can happen when the bot is not in the associated server.
|
|
50
|
+
def server
|
|
51
|
+
@bot.server(@id)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Utility method to get a server preview's splash URL.
|
|
55
|
+
# @param format [String] the URL will default to `webp`. You can otherwise specify one of `jpg` or `png` to override this.
|
|
56
|
+
# @return [String, nil] the URL to the server's splash image, or `nil` if the server doesn't have a splash image.
|
|
57
|
+
def splash_url(format = 'webp')
|
|
58
|
+
API.splash_url(@id, @splash_id, format) if @splash_id
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Utility method to get a server preview's discovery splash URL.
|
|
62
|
+
# @param format [String] the URL will default to `webp`. You can otherwise specify one of `jpg` or `png` to override this.
|
|
63
|
+
# @return [String, nil] the URL to the server's discovery splash image, or `nil` if the server doesn't have a discovery splash image.
|
|
64
|
+
def discovery_splash_url(format = 'webp')
|
|
65
|
+
API.discovery_splash_url(@id, @discovery_splash_id, format) if @discovery_splash_id
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|