discordrb 3.5.0 → 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/workflows/ci.yml +78 -0
- data/.github/workflows/codeql.yml +3 -3
- data/.github/workflows/deploy.yml +54 -0
- data/.github/workflows/release.yml +45 -0
- data/.rubocop.yml +52 -2
- data/CHANGELOG.md +95 -0
- data/README.md +5 -5
- data/discordrb-webhooks.gemspec +1 -1
- data/discordrb.gemspec +16 -11
- data/lib/discordrb/api/application.rb +84 -8
- data/lib/discordrb/api/channel.rb +51 -13
- data/lib/discordrb/api/interaction.rb +15 -6
- data/lib/discordrb/api/invite.rb +1 -1
- data/lib/discordrb/api/server.rb +96 -60
- data/lib/discordrb/api/user.rb +12 -2
- data/lib/discordrb/api/webhook.rb +20 -5
- data/lib/discordrb/api.rb +16 -20
- data/lib/discordrb/bot.rb +139 -53
- data/lib/discordrb/cache.rb +15 -1
- data/lib/discordrb/commands/command_bot.rb +7 -17
- data/lib/discordrb/commands/parser.rb +7 -7
- data/lib/discordrb/container.rb +46 -0
- data/lib/discordrb/data/activity.rb +1 -1
- data/lib/discordrb/data/application.rb +1 -0
- data/lib/discordrb/data/attachment.rb +23 -3
- data/lib/discordrb/data/avatar_decoration.rb +26 -0
- data/lib/discordrb/data/call.rb +22 -0
- data/lib/discordrb/data/channel.rb +140 -15
- data/lib/discordrb/data/collectibles.rb +45 -0
- data/lib/discordrb/data/embed.rb +10 -3
- data/lib/discordrb/data/emoji.rb +20 -1
- data/lib/discordrb/data/integration.rb +3 -0
- data/lib/discordrb/data/interaction.rb +164 -27
- data/lib/discordrb/data/member.rb +145 -28
- data/lib/discordrb/data/message.rb +198 -51
- data/lib/discordrb/data/overwrite.rb +2 -0
- 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 +151 -22
- data/lib/discordrb/data/server.rb +115 -41
- data/lib/discordrb/data/server_preview.rb +68 -0
- data/lib/discordrb/data/snapshot.rb +110 -0
- data/lib/discordrb/data/user.rb +68 -8
- data/lib/discordrb/data/voice_region.rb +1 -0
- data/lib/discordrb/data/webhook.rb +2 -5
- data/lib/discordrb/data.rb +6 -0
- data/lib/discordrb/errors.rb +5 -2
- data/lib/discordrb/events/await.rb +1 -1
- data/lib/discordrb/events/channels.rb +37 -0
- data/lib/discordrb/events/generic.rb +2 -0
- data/lib/discordrb/events/guilds.rb +6 -1
- data/lib/discordrb/events/interactions.rb +135 -42
- data/lib/discordrb/events/invites.rb +2 -0
- data/lib/discordrb/events/members.rb +19 -2
- data/lib/discordrb/events/message.rb +39 -8
- data/lib/discordrb/events/presence.rb +2 -0
- data/lib/discordrb/events/raw.rb +1 -0
- data/lib/discordrb/events/reactions.rb +2 -0
- data/lib/discordrb/events/roles.rb +2 -0
- data/lib/discordrb/events/threads.rb +10 -6
- 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 +29 -13
- data/lib/discordrb/paginator.rb +3 -3
- data/lib/discordrb/permissions.rb +54 -43
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/websocket.rb +0 -10
- data/lib/discordrb.rb +17 -1
- metadata +53 -25
- data/.circleci/config.yml +0 -152
|
@@ -11,6 +11,7 @@ module Discordrb
|
|
|
11
11
|
ping: 1,
|
|
12
12
|
command: 2,
|
|
13
13
|
component: 3,
|
|
14
|
+
autocomplete: 4,
|
|
14
15
|
modal_submit: 5
|
|
15
16
|
}.freeze
|
|
16
17
|
|
|
@@ -22,6 +23,7 @@ module Discordrb
|
|
|
22
23
|
deferred_message: 5,
|
|
23
24
|
deferred_update: 6,
|
|
24
25
|
update_message: 7,
|
|
26
|
+
autocomplete: 8,
|
|
25
27
|
modal: 9
|
|
26
28
|
}.freeze
|
|
27
29
|
|
|
@@ -89,10 +91,11 @@ module Discordrb
|
|
|
89
91
|
# @param flags [Integer] Message flags.
|
|
90
92
|
# @param ephemeral [true, false] Whether this message should only be visible to the interaction initiator.
|
|
91
93
|
# @param wait [true, false] Whether this method should return a Message object of the interaction response.
|
|
92
|
-
# @param components [Array<#to_h>] An array of components
|
|
94
|
+
# @param components [Array<#to_h>] An array of components.
|
|
95
|
+
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`.
|
|
93
96
|
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data.
|
|
94
97
|
# @yieldparam view [Webhooks::View] A builder for creating interaction components.
|
|
95
|
-
def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil)
|
|
98
|
+
def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, attachments: nil)
|
|
96
99
|
flags |= 1 << 6 if ephemeral
|
|
97
100
|
|
|
98
101
|
builder = Discordrb::Webhooks::Builder.new
|
|
@@ -105,7 +108,7 @@ module Discordrb
|
|
|
105
108
|
components ||= view
|
|
106
109
|
data = builder.to_json_hash
|
|
107
110
|
|
|
108
|
-
Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:channel_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a)
|
|
111
|
+
Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:channel_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a, attachments)
|
|
109
112
|
|
|
110
113
|
return unless wait
|
|
111
114
|
|
|
@@ -157,10 +160,11 @@ module Discordrb
|
|
|
157
160
|
# @param flags [Integer] Message flags.
|
|
158
161
|
# @param ephemeral [true, false] Whether this message should only be visible to the interaction initiator.
|
|
159
162
|
# @param wait [true, false] Whether this method should return a Message object of the interaction response.
|
|
160
|
-
# @param components [Array<#to_h>] An array of components
|
|
163
|
+
# @param components [Array<#to_h>] An array of components.
|
|
164
|
+
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`.
|
|
161
165
|
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data.
|
|
162
166
|
# @yieldparam view [Webhooks::View] A builder for creating interaction components.
|
|
163
|
-
def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil)
|
|
167
|
+
def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, attachments: nil)
|
|
164
168
|
flags |= 1 << 6 if ephemeral
|
|
165
169
|
|
|
166
170
|
builder = Discordrb::Webhooks::Builder.new
|
|
@@ -172,7 +176,7 @@ module Discordrb
|
|
|
172
176
|
components ||= view
|
|
173
177
|
data = builder.to_json_hash
|
|
174
178
|
|
|
175
|
-
Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:update_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a)
|
|
179
|
+
Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:update_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a, attachments)
|
|
176
180
|
|
|
177
181
|
return unless wait
|
|
178
182
|
|
|
@@ -184,10 +188,11 @@ module Discordrb
|
|
|
184
188
|
# @param content [String] The content of the message.
|
|
185
189
|
# @param embeds [Array<Hash, Webhooks::Embed>] The embeds for the message.
|
|
186
190
|
# @param allowed_mentions [Hash, AllowedMentions] Mentions that can ping on this message.
|
|
187
|
-
# @param components [Array<#to_h>] An array of components
|
|
191
|
+
# @param components [Array<#to_h>] An array of components.
|
|
192
|
+
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`.
|
|
188
193
|
# @return [InteractionMessage] The updated response message.
|
|
189
194
|
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data.
|
|
190
|
-
def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: nil)
|
|
195
|
+
def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil)
|
|
191
196
|
builder = Discordrb::Webhooks::Builder.new
|
|
192
197
|
view = Discordrb::Webhooks::View.new
|
|
193
198
|
|
|
@@ -196,7 +201,7 @@ module Discordrb
|
|
|
196
201
|
|
|
197
202
|
components ||= view
|
|
198
203
|
data = builder.to_json_hash
|
|
199
|
-
resp = Discordrb::API::Interaction.edit_original_interaction_response(@token, @application_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a)
|
|
204
|
+
resp = Discordrb::API::Interaction.edit_original_interaction_response(@token, @application_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a, attachments)
|
|
200
205
|
|
|
201
206
|
Interactions::Message.new(JSON.parse(resp), @bot, @interaction)
|
|
202
207
|
end
|
|
@@ -212,8 +217,9 @@ module Discordrb
|
|
|
212
217
|
# @param allowed_mentions [Hash, AllowedMentions] Mentions that can ping on this message.
|
|
213
218
|
# @param flags [Integer] Message flags.
|
|
214
219
|
# @param ephemeral [true, false] Whether this message should only be visible to the interaction initiator.
|
|
220
|
+
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`.
|
|
215
221
|
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data.
|
|
216
|
-
def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, flags: 0, ephemeral: false, components: nil)
|
|
222
|
+
def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, flags: 0, ephemeral: false, components: nil, attachments: nil)
|
|
217
223
|
flags |= 64 if ephemeral
|
|
218
224
|
|
|
219
225
|
builder = Discordrb::Webhooks::Builder.new
|
|
@@ -226,7 +232,7 @@ module Discordrb
|
|
|
226
232
|
data = builder.to_json_hash
|
|
227
233
|
|
|
228
234
|
resp = Discordrb::API::Webhook.token_execute_webhook(
|
|
229
|
-
@token, @application_id, true, data[:content], nil, nil, tts, nil, data[:embeds], data[:allowed_mentions], flags, components.to_a
|
|
235
|
+
@token, @application_id, true, data[:content], nil, nil, tts, nil, data[:embeds], data[:allowed_mentions], flags, components.to_a, attachments
|
|
230
236
|
)
|
|
231
237
|
Interactions::Message.new(JSON.parse(resp), @bot, @interaction)
|
|
232
238
|
end
|
|
@@ -235,8 +241,9 @@ module Discordrb
|
|
|
235
241
|
# @param content [String] The message content.
|
|
236
242
|
# @param embeds [Array<Hash, Webhooks::Embed>] The embeds for the message.
|
|
237
243
|
# @param allowed_mentions [Hash, AllowedMentions] Mentions that can ping on this message.
|
|
244
|
+
# @param attachments [Array<File>] Files that can be referenced in embeds via `attachment://file.png`.
|
|
238
245
|
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data.
|
|
239
|
-
def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, components: nil)
|
|
246
|
+
def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil)
|
|
240
247
|
builder = Discordrb::Webhooks::Builder.new
|
|
241
248
|
view = Discordrb::Webhooks::View.new
|
|
242
249
|
|
|
@@ -247,7 +254,7 @@ module Discordrb
|
|
|
247
254
|
data = builder.to_json_hash
|
|
248
255
|
|
|
249
256
|
resp = Discordrb::API::Webhook.token_edit_message(
|
|
250
|
-
@token, @application_id, message.resolve_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a
|
|
257
|
+
@token, @application_id, message.resolve_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a, attachments
|
|
251
258
|
)
|
|
252
259
|
Interactions::Message.new(JSON.parse(resp), @bot, @interaction)
|
|
253
260
|
end
|
|
@@ -258,6 +265,14 @@ module Discordrb
|
|
|
258
265
|
nil
|
|
259
266
|
end
|
|
260
267
|
|
|
268
|
+
# Show autocomplete choices as a response.
|
|
269
|
+
# @param choices [Array<Hash>, Hash] Array of autocomplete choices to show the user.
|
|
270
|
+
def show_autocomplete_choices(choices)
|
|
271
|
+
choices = choices.map { |name, value| { name: name, value: value } } unless choices.is_a?(Array)
|
|
272
|
+
Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:autocomplete], nil, nil, nil, nil, nil, nil, nil, choices)
|
|
273
|
+
nil
|
|
274
|
+
end
|
|
275
|
+
|
|
261
276
|
# @return [Server, nil] This will be nil for interactions that occur in DM channels or servers where the bot
|
|
262
277
|
# does not have the `bot` scope.
|
|
263
278
|
def server
|
|
@@ -339,6 +354,9 @@ module Discordrb
|
|
|
339
354
|
# @return [Integer]
|
|
340
355
|
attr_reader :id
|
|
341
356
|
|
|
357
|
+
# @return [true, false]
|
|
358
|
+
attr_reader :nsfw
|
|
359
|
+
|
|
342
360
|
# @!visibility private
|
|
343
361
|
def initialize(data, bot, server_id = nil)
|
|
344
362
|
@bot = bot
|
|
@@ -350,6 +368,7 @@ module Discordrb
|
|
|
350
368
|
@description = data['description']
|
|
351
369
|
@default_permission = data['default_permission']
|
|
352
370
|
@options = data['options']
|
|
371
|
+
@nsfw = data['nsfw'] || false
|
|
353
372
|
end
|
|
354
373
|
|
|
355
374
|
# @param subcommand [String, nil] The subcommand to mention.
|
|
@@ -372,10 +391,11 @@ module Discordrb
|
|
|
372
391
|
# @param name [String] The name to use for this command.
|
|
373
392
|
# @param description [String] The description of this command.
|
|
374
393
|
# @param default_permission [true, false] Whether this command is available with default permissions.
|
|
394
|
+
# @param nsfw [true, false] Whether this command should be marked as age-restricted.
|
|
375
395
|
# @yieldparam (see Bot#edit_application_command)
|
|
376
396
|
# @return (see Bot#edit_application_command)
|
|
377
|
-
def edit(name: nil, description: nil, default_permission: nil, &block)
|
|
378
|
-
@bot.edit_application_command(@id, server_id: @server_id, name: name, description: description, default_permission: default_permission, &block)
|
|
397
|
+
def edit(name: nil, description: nil, default_permission: nil, nsfw: nil, &block)
|
|
398
|
+
@bot.edit_application_command(@id, server_id: @server_id, name: name, description: description, default_permission: default_permission, nsfw: nsfw, &block)
|
|
379
399
|
end
|
|
380
400
|
|
|
381
401
|
# Delete this application command.
|
|
@@ -383,6 +403,108 @@ module Discordrb
|
|
|
383
403
|
def delete
|
|
384
404
|
@bot.delete_application_command(@id, server_id: @server_id)
|
|
385
405
|
end
|
|
406
|
+
|
|
407
|
+
# Get the permission configuration for the this application command on a specific server.
|
|
408
|
+
# @param server_id [Integer, String, nil] The ID of the server to fetch command permissions for.
|
|
409
|
+
# @return [Array<Permission>] the permissions for this application command in the given server.
|
|
410
|
+
def permissions(server_id: nil)
|
|
411
|
+
raise ArgumentError, 'A server ID must be provided for global application commands' if @server_id.nil? && server_id.nil?
|
|
412
|
+
|
|
413
|
+
response = JSON.parse(API::Application.get_application_command_permissions(@bot.token, @bot.profile.id, @server_id || server_id&.resolve_id, @id))
|
|
414
|
+
response['permissions'].map { |permission| Permission.new(permission, response, @bot) }
|
|
415
|
+
rescue Discordrb::Errors::UnknownError
|
|
416
|
+
# If there aren't any explicit overwrites configured for the command, the response is a 400.
|
|
417
|
+
[]
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# An application command permission for a channel, member, or a role.
|
|
421
|
+
class Permission
|
|
422
|
+
# Map of permission types.
|
|
423
|
+
TYPES = {
|
|
424
|
+
role: 1,
|
|
425
|
+
member: 2,
|
|
426
|
+
channel: 3
|
|
427
|
+
}.freeze
|
|
428
|
+
|
|
429
|
+
# @return [Integer] the type of this permission.
|
|
430
|
+
# @see TYPES
|
|
431
|
+
attr_reader :type
|
|
432
|
+
|
|
433
|
+
# @return [Integer] the ID of the thing this permission is for.
|
|
434
|
+
attr_reader :target_id
|
|
435
|
+
|
|
436
|
+
# @return [Integer] the ID of the server this permission is for.
|
|
437
|
+
attr_reader :server_id
|
|
438
|
+
|
|
439
|
+
# @!visibility private
|
|
440
|
+
def initialize(data, command, bot)
|
|
441
|
+
@bot = bot
|
|
442
|
+
@type = data['type']
|
|
443
|
+
@target_id = data['id'].to_i
|
|
444
|
+
@overwrite = data['permission']
|
|
445
|
+
@command_id = command['id'].to_i
|
|
446
|
+
@server_id = command['guild_id'].to_i
|
|
447
|
+
@application_id = command['application_id'].to_i
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
# Whether this permission has been allowed, e.g has a green check in the UI.
|
|
451
|
+
# @return [true, false]
|
|
452
|
+
def allowed?
|
|
453
|
+
@overwrite == true
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Whether this permission has been denied, e.g has a red check in the UI.
|
|
457
|
+
# @return [true, false]
|
|
458
|
+
def denied?
|
|
459
|
+
@overwrite == false
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
# Whether this permission is applied to the everyone role in the server.
|
|
463
|
+
# @return [true, false]
|
|
464
|
+
def everyone?
|
|
465
|
+
@target_id == @server_id
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
# Whether this permission is the default for all commands that don't
|
|
469
|
+
# contain explicit permission oerwrites.
|
|
470
|
+
# @return [true, false]
|
|
471
|
+
def default?
|
|
472
|
+
@command_id == @application_id
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# Whether this permission is applied to every channel in the server.
|
|
476
|
+
# @return [true, false]
|
|
477
|
+
def all_channels?
|
|
478
|
+
@target_id == (@server_id - 1)
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
# Get the user, role, or channel(s) that this permission targets.
|
|
482
|
+
# @return [Array<Channel>, Role, Member]
|
|
483
|
+
def target
|
|
484
|
+
case @type
|
|
485
|
+
when TYPES[:role]
|
|
486
|
+
@bot.server(@server_id).role(@target_id)
|
|
487
|
+
when TYPES[:member]
|
|
488
|
+
@bot.server(@server_id).member(@target_id)
|
|
489
|
+
when TYPES[:channel]
|
|
490
|
+
all_channels ? @bot.server(@server_id).channels : [@bot.channel(@target_id)]
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
alias_method :targets, :target
|
|
495
|
+
|
|
496
|
+
# @!method role?
|
|
497
|
+
# @return [true, false] whether this permission is for a role.
|
|
498
|
+
# @!method member?
|
|
499
|
+
# @return [true, false] whether this permission is for a member.
|
|
500
|
+
# @!method channel?
|
|
501
|
+
# @return [true, false] whether this permission is for a channel.
|
|
502
|
+
TYPES.each do |name, value|
|
|
503
|
+
define_method("#{name}?") do
|
|
504
|
+
@type == value
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
end
|
|
386
508
|
end
|
|
387
509
|
|
|
388
510
|
# Objects specific to Interactions.
|
|
@@ -466,19 +588,27 @@ module Discordrb
|
|
|
466
588
|
# @param name [String, Symbol] The name of the argument.
|
|
467
589
|
# @param description [String] A description of the argument.
|
|
468
590
|
# @param required [true, false] Whether this option must be provided.
|
|
591
|
+
# @param min_length [Integer] A minimum length for option value.
|
|
592
|
+
# @param max_length [Integer] A maximum length for option value.
|
|
469
593
|
# @param choices [Hash, nil] Available choices, mapped as `Name => Value`.
|
|
594
|
+
# @param autocomplete [true, false] Whether this option can dynamically show choices.
|
|
470
595
|
# @return (see #option)
|
|
471
|
-
def string(name, description, required: nil, choices: nil)
|
|
472
|
-
option(TYPES[:string], name, description,
|
|
596
|
+
def string(name, description, required: nil, min_length: nil, max_length: nil, choices: nil, autocomplete: nil)
|
|
597
|
+
option(TYPES[:string], name, description,
|
|
598
|
+
required: required, min_length: min_length, max_length: max_length, choices: choices, autocomplete: autocomplete)
|
|
473
599
|
end
|
|
474
600
|
|
|
475
601
|
# @param name [String, Symbol] The name of the argument.
|
|
476
602
|
# @param description [String] A description of the argument.
|
|
477
603
|
# @param required [true, false] Whether this option must be provided.
|
|
604
|
+
# @param min_value [Integer] A minimum value for option.
|
|
605
|
+
# @param max_value [Integer] A maximum value for option.
|
|
478
606
|
# @param choices [Hash, nil] Available choices, mapped as `Name => Value`.
|
|
607
|
+
# @param autocomplete [true, false] Whether this option can dynamically show choices.
|
|
479
608
|
# @return (see #option)
|
|
480
|
-
def integer(name, description, required: nil, choices: nil)
|
|
481
|
-
option(TYPES[:integer], name, description,
|
|
609
|
+
def integer(name, description, required: nil, min_value: nil, max_value: nil, choices: nil, autocomplete: nil)
|
|
610
|
+
option(TYPES[:integer], name, description,
|
|
611
|
+
required: required, min_value: min_value, max_value: max_value, choices: choices, autocomplete: autocomplete)
|
|
482
612
|
end
|
|
483
613
|
|
|
484
614
|
# @param name [String, Symbol] The name of the argument.
|
|
@@ -526,10 +656,13 @@ module Discordrb
|
|
|
526
656
|
# @param name [String, Symbol] The name of the argument.
|
|
527
657
|
# @param description [String] A description of the argument.
|
|
528
658
|
# @param required [true, false] Whether this option must be provided.
|
|
659
|
+
# @param min_value [Float] A minimum value for option.
|
|
660
|
+
# @param max_value [Float] A maximum value for option.
|
|
661
|
+
# @param autocomplete [true, false] Whether this option can dynamically show choices.
|
|
529
662
|
# @return (see #option)
|
|
530
|
-
def number(name, description, required: nil, min_value: nil, max_value: nil, choices: nil)
|
|
663
|
+
def number(name, description, required: nil, min_value: nil, max_value: nil, choices: nil, autocomplete: nil)
|
|
531
664
|
option(TYPES[:number], name, description,
|
|
532
|
-
required: required, min_value: min_value, max_value: max_value, choices: choices)
|
|
665
|
+
required: required, min_value: min_value, max_value: max_value, choices: choices, autocomplete: autocomplete)
|
|
533
666
|
end
|
|
534
667
|
|
|
535
668
|
# @param name [String, Symbol] The name of the argument.
|
|
@@ -547,15 +680,19 @@ module Discordrb
|
|
|
547
680
|
# @param required [true, false] Whether this option must be provided.
|
|
548
681
|
# @param min_value [Integer, Float] A minimum value for integer and number options.
|
|
549
682
|
# @param max_value [Integer, Float] A maximum value for integer and number options.
|
|
683
|
+
# @param min_length [Integer] A minimum length for string option value.
|
|
684
|
+
# @param max_length [Integer] A maximum length for string option value.
|
|
550
685
|
# @param channel_types [Array<Integer>] Channel types that can be provides for channel options.
|
|
686
|
+
# @param autocomplete [true, false] Whether this option can dynamically show options.
|
|
551
687
|
# @return Hash
|
|
552
688
|
def option(type, name, description, required: nil, choices: nil, options: nil, min_value: nil, max_value: nil,
|
|
553
|
-
channel_types: nil)
|
|
689
|
+
min_length: nil, max_length: nil, channel_types: nil, autocomplete: nil)
|
|
554
690
|
opt = { type: type, name: name, description: description }
|
|
555
691
|
choices = choices.map { |option_name, value| { name: option_name, value: value } } if choices
|
|
556
692
|
|
|
557
693
|
opt.merge!({ required: required, choices: choices, options: options, min_value: min_value,
|
|
558
|
-
max_value: max_value,
|
|
694
|
+
max_value: max_value, min_length: min_length, max_length: max_length,
|
|
695
|
+
channel_types: channel_types, autocomplete: autocomplete }.compact)
|
|
559
696
|
|
|
560
697
|
@options << opt
|
|
561
698
|
opt
|
|
@@ -766,8 +903,8 @@ module Discordrb
|
|
|
766
903
|
# Respond to this message.
|
|
767
904
|
# @param (see Interaction#send_message)
|
|
768
905
|
# @yieldparam (see Interaction#send_message)
|
|
769
|
-
def respond(content: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: true, components: nil, &block)
|
|
770
|
-
@interaction.send_message(content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, &block)
|
|
906
|
+
def respond(content: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: true, components: nil, attachments: nil, &block)
|
|
907
|
+
@interaction.send_message(content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, attachments: attachments, &block)
|
|
771
908
|
end
|
|
772
909
|
|
|
773
910
|
# Delete this message.
|
|
@@ -780,8 +917,8 @@ module Discordrb
|
|
|
780
917
|
# @param embeds (see Interaction#send_message)
|
|
781
918
|
# @param allowed_mentions (see Interaction#send_message)
|
|
782
919
|
# @yieldparam (see Interaction#send_message)
|
|
783
|
-
def edit(content: nil, embeds: nil, allowed_mentions: nil, components: nil, &block)
|
|
784
|
-
@interaction.edit_message(@id, content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, &block)
|
|
920
|
+
def edit(content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil, &block)
|
|
921
|
+
@interaction.edit_message(@id, content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, attachments: attachments, &block)
|
|
785
922
|
end
|
|
786
923
|
|
|
787
924
|
# @return [Discordrb::Message]
|
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
module Discordrb
|
|
4
4
|
# Mixin for the attributes members and private members should have
|
|
5
5
|
module MemberAttributes
|
|
6
|
+
# Map of server member flags
|
|
7
|
+
MEMBER_FLAGS = {
|
|
8
|
+
rejoined: 1 << 0,
|
|
9
|
+
completed_onboarding: 1 << 1,
|
|
10
|
+
bypassed_verification: 1 << 2,
|
|
11
|
+
started_onboarding: 1 << 3,
|
|
12
|
+
guest: 1 << 4,
|
|
13
|
+
started_home_actions: 1 << 5,
|
|
14
|
+
completed_home_actions: 1 << 6,
|
|
15
|
+
automod_quarantined_username: 1 << 7,
|
|
16
|
+
dm_settings_upsell_acknowledged: 1 << 9
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
6
19
|
# @return [Time] when this member joined the server.
|
|
7
20
|
attr_reader :joined_at
|
|
8
21
|
|
|
@@ -22,6 +35,44 @@ module Discordrb
|
|
|
22
35
|
# @return [Time] When the user's timeout will expire.
|
|
23
36
|
attr_reader :communication_disabled_until
|
|
24
37
|
alias_method :timeout, :communication_disabled_until
|
|
38
|
+
|
|
39
|
+
# @return [Integer] the flags set on this member.
|
|
40
|
+
attr_reader :flags
|
|
41
|
+
|
|
42
|
+
# @return [true, false] whether the member has not yet passed the server's membership screening requirements.
|
|
43
|
+
attr_reader :pending
|
|
44
|
+
alias_method :pending?, :pending
|
|
45
|
+
|
|
46
|
+
# @return [String, nil] the ID of this user's current avatar, can be used to generate a server avatar URL.
|
|
47
|
+
# @see #server_avatar_url
|
|
48
|
+
attr_reader :server_avatar_id
|
|
49
|
+
|
|
50
|
+
# @return [String, nil] the ID of this user's current server banner, can be used to generate a banner URL.
|
|
51
|
+
# @see #server_banner_url
|
|
52
|
+
attr_reader :server_banner_id
|
|
53
|
+
|
|
54
|
+
# @return [AvatarDecoration, nil] the user's current server avatar decoration, or nil for no server avatar decoration.
|
|
55
|
+
attr_reader :server_avatar_decoration
|
|
56
|
+
|
|
57
|
+
# Utility method to get a member's server avatar URL.
|
|
58
|
+
# @param format [String, nil] If `nil`, the URL will default to `webp` for static avatars, and will detect if the member has a `gif` avatar. You can otherwise specify one of `webp`, `jpg`, `png`, or `gif` to override this.
|
|
59
|
+
# @return [String, nil] the URL to the avatar image, or nil if the member doesn't have one.
|
|
60
|
+
def server_avatar_url(format = nil)
|
|
61
|
+
API::Server.avatar_url(@server_id, @user.id, @server_avatar_id, format) if @server_avatar_id
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Utility method to get a member's server banner URL.
|
|
65
|
+
# @param format [String, nil] If `nil`, the URL will default to `webp` for static banners, and will detect if the member has a `gif` banner. You can otherwise specify one of `webp`, `jpg`, `png`, or `gif` to override this.
|
|
66
|
+
# @return [String, nil] the URL to the banner image, or nil if the member doesn't have one.
|
|
67
|
+
def server_banner_url(format = nil)
|
|
68
|
+
API::Server.banner_url(@server_id, @user.id, @server_banner_id, format) if @server_banner_id
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
MEMBER_FLAGS.each do |name, value|
|
|
72
|
+
define_method("#{name}?") do
|
|
73
|
+
@flags.anybits?(value)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
25
76
|
end
|
|
26
77
|
|
|
27
78
|
# A member is a user on a server. It differs from regular users in that it has roles, voice statuses and things like
|
|
@@ -64,7 +115,7 @@ module Discordrb
|
|
|
64
115
|
@bot = bot
|
|
65
116
|
|
|
66
117
|
@user = bot.ensure_user(data['user'])
|
|
67
|
-
super
|
|
118
|
+
super(@user) # Initialize the delegate class
|
|
68
119
|
|
|
69
120
|
@server = server
|
|
70
121
|
@server_id = server&.id || data['guild_id'].to_i
|
|
@@ -77,6 +128,11 @@ module Discordrb
|
|
|
77
128
|
timeout_until = data['communication_disabled_until']
|
|
78
129
|
@communication_disabled_until = timeout_until ? Time.parse(timeout_until) : nil
|
|
79
130
|
@permissions = Permissions.new(data['permissions']) if data['permissions']
|
|
131
|
+
@server_avatar_id = data['avatar']
|
|
132
|
+
@server_banner_id = data['banner']
|
|
133
|
+
@flags = data['flags'] || 0
|
|
134
|
+
@pending = data.key?('pending') ? data['pending'] : false
|
|
135
|
+
@server_avatar_decoration = process_avatar_decoration(data['avatar_decoration_data'])
|
|
80
136
|
end
|
|
81
137
|
|
|
82
138
|
# @return [Server] the server this member is on.
|
|
@@ -136,7 +192,7 @@ module Discordrb
|
|
|
136
192
|
def communication_disabled_until=(timeout_until)
|
|
137
193
|
raise ArgumentError, 'A time out cannot exceed 28 days' if timeout_until && timeout_until > (Time.now + 2_419_200)
|
|
138
194
|
|
|
139
|
-
|
|
195
|
+
update_member_data(communication_disabled_until: timeout_until&.iso8601)
|
|
140
196
|
end
|
|
141
197
|
|
|
142
198
|
alias_method :timeout=, :communication_disabled_until=
|
|
@@ -146,7 +202,7 @@ module Discordrb
|
|
|
146
202
|
# @param reason [String] The reason the user's roles are being changed.
|
|
147
203
|
def set_roles(role, reason = nil)
|
|
148
204
|
role_ids = role_id_array(role)
|
|
149
|
-
|
|
205
|
+
update_member_data(roles: role_ids, reason: reason)
|
|
150
206
|
end
|
|
151
207
|
|
|
152
208
|
# Adds and removes roles from a member.
|
|
@@ -163,7 +219,7 @@ module Discordrb
|
|
|
163
219
|
old_role_ids = resolve_role_ids
|
|
164
220
|
new_role_ids = (old_role_ids - remove_role_ids + add_role_ids).uniq
|
|
165
221
|
|
|
166
|
-
|
|
222
|
+
update_member_data(roles: new_role_ids, reason: reason)
|
|
167
223
|
end
|
|
168
224
|
|
|
169
225
|
# Adds one or more roles to this member.
|
|
@@ -172,12 +228,12 @@ module Discordrb
|
|
|
172
228
|
def add_role(role, reason = nil)
|
|
173
229
|
role_ids = role_id_array(role)
|
|
174
230
|
|
|
175
|
-
if role_ids.count
|
|
231
|
+
if role_ids.count.one?
|
|
176
232
|
API::Server.add_member_role(@bot.token, @server_id, @user.id, role_ids[0], reason)
|
|
177
233
|
else
|
|
178
234
|
old_role_ids = resolve_role_ids
|
|
179
235
|
new_role_ids = (old_role_ids + role_ids).uniq
|
|
180
|
-
|
|
236
|
+
update_member_data(roles: new_role_ids, reason: reason)
|
|
181
237
|
end
|
|
182
238
|
end
|
|
183
239
|
|
|
@@ -187,12 +243,12 @@ module Discordrb
|
|
|
187
243
|
def remove_role(role, reason = nil)
|
|
188
244
|
role_ids = role_id_array(role)
|
|
189
245
|
|
|
190
|
-
if role_ids.count
|
|
246
|
+
if role_ids.count.one?
|
|
191
247
|
API::Server.remove_member_role(@bot.token, @server_id, @user.id, role_ids[0], reason)
|
|
192
248
|
else
|
|
193
249
|
old_role_ids = resolve_role_ids
|
|
194
250
|
new_role_ids = old_role_ids.reject { |i| role_ids.include?(i) }
|
|
195
|
-
|
|
251
|
+
update_member_data(roles: new_role_ids, reason: reason)
|
|
196
252
|
end
|
|
197
253
|
end
|
|
198
254
|
|
|
@@ -216,6 +272,7 @@ module Discordrb
|
|
|
216
272
|
|
|
217
273
|
coloured_roles.max_by(&:position)
|
|
218
274
|
end
|
|
275
|
+
|
|
219
276
|
alias_method :color_role, :colour_role
|
|
220
277
|
|
|
221
278
|
# @return [ColourRGB, nil] the colour this member has.
|
|
@@ -224,33 +281,39 @@ module Discordrb
|
|
|
224
281
|
|
|
225
282
|
colour_role.color
|
|
226
283
|
end
|
|
284
|
+
|
|
227
285
|
alias_method :color, :colour
|
|
228
286
|
|
|
229
287
|
# Server deafens this member.
|
|
230
|
-
|
|
231
|
-
|
|
288
|
+
# @param reason [String, nil] The reason for defeaning this member.
|
|
289
|
+
def server_deafen(reason: nil)
|
|
290
|
+
update_member_data(deaf: true, reason: reason)
|
|
232
291
|
end
|
|
233
292
|
|
|
234
293
|
# Server undeafens this member.
|
|
235
|
-
|
|
236
|
-
|
|
294
|
+
# @param reason [String, nil] The reason for un-defeaning this member.
|
|
295
|
+
def server_undeafen(reason: nil)
|
|
296
|
+
update_member_data(deaf: false, reason: reason)
|
|
237
297
|
end
|
|
238
298
|
|
|
239
299
|
# Server mutes this member.
|
|
240
|
-
|
|
241
|
-
|
|
300
|
+
# @param reason [String, nil] The reason for muting this member.
|
|
301
|
+
def server_mute(reason: nil)
|
|
302
|
+
update_member_data(mute: true, reason: reason)
|
|
242
303
|
end
|
|
243
304
|
|
|
244
305
|
# Server unmutes this member.
|
|
245
|
-
|
|
246
|
-
|
|
306
|
+
# @param reason [String, nil] The reason for un-muting this member.
|
|
307
|
+
def server_unmute(reason: nil)
|
|
308
|
+
update_member_data(mute: false, reason: reason)
|
|
247
309
|
end
|
|
248
310
|
|
|
249
311
|
# Bans this member from the server.
|
|
250
|
-
# @param message_days [Integer] How many days worth of messages sent by the member should be deleted.
|
|
312
|
+
# @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.
|
|
313
|
+
# @param message_seconds [Integer] How many seconds worth of messages sent by the member should be deleted.
|
|
251
314
|
# @param reason [String] The reason this member is being banned.
|
|
252
|
-
def ban(message_days = 0, reason: nil)
|
|
253
|
-
server.ban(@user, message_days, reason: reason)
|
|
315
|
+
def ban(message_days = 0, message_seconds: nil, reason: nil)
|
|
316
|
+
server.ban(@user, message_days, message_seconds: message_seconds, reason: reason)
|
|
254
317
|
end
|
|
255
318
|
|
|
256
319
|
# Unbans this member from the server.
|
|
@@ -277,13 +340,10 @@ module Discordrb
|
|
|
277
340
|
# @param nick [String, nil] The string to set the nickname to, or nil if it should be reset.
|
|
278
341
|
# @param reason [String] The reason the user's nickname is being changed.
|
|
279
342
|
def set_nick(nick, reason = nil)
|
|
280
|
-
# Discord uses the empty string to signify 'no nickname' so we convert nil into that
|
|
281
|
-
nick ||= ''
|
|
282
|
-
|
|
283
343
|
if @user.current_bot?
|
|
284
|
-
|
|
344
|
+
update_current_member_data(nick: nick, reason: reason)
|
|
285
345
|
else
|
|
286
|
-
|
|
346
|
+
update_member_data(nick: nick, reason: reason)
|
|
287
347
|
end
|
|
288
348
|
end
|
|
289
349
|
|
|
@@ -294,6 +354,29 @@ module Discordrb
|
|
|
294
354
|
nickname || global_name || username
|
|
295
355
|
end
|
|
296
356
|
|
|
357
|
+
# @param format [String, nil] If `nil`, the URL will default to `webp` for static avatars, and will detect if the member has a `gif` avatar. You can otherwise specify one of `webp`, `jpg`, `png`, or `gif` to override this.
|
|
358
|
+
# @return [String, nil] the avatar that the user has displayed (server avatar if they have one, user avatar if they have one, nil otherwise)
|
|
359
|
+
def display_avatar_url(format = nil)
|
|
360
|
+
server_avatar_url(format) || avatar_url(format)
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
# @param format [String, nil] If `nil`, the URL will default to `webp` for static banners, and will detect if the member has a `gif` banner. You can otherwise specify one of `webp`, `jpg`, `png`, or `gif` to override this.
|
|
364
|
+
# @return [String, nil] the banner that the user has displayed (server banner if they have one, user banner if they have one, nil otherwise)
|
|
365
|
+
def display_banner_url(format = nil)
|
|
366
|
+
server_banner_url(format) || banner_url(format)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# @return [AvatarDecoration, nil] the avatar decoration that the user displays (server avatar decoration if they have one, user avatar decoration if they have one, nil otherwise)
|
|
370
|
+
def display_avatar_decoration
|
|
371
|
+
server_avatar_decoration || avatar_decoration
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
# Set the flags for this member.
|
|
375
|
+
# @param flags [Integer, nil] The new bitwise value of flags for this member, or nil.
|
|
376
|
+
def flags=(flags)
|
|
377
|
+
update_member_data(flags: flags)
|
|
378
|
+
end
|
|
379
|
+
|
|
297
380
|
# Update this member's roles
|
|
298
381
|
# @note For internal use only.
|
|
299
382
|
# @!visibility private
|
|
@@ -332,20 +415,41 @@ module Discordrb
|
|
|
332
415
|
# @!visibility private
|
|
333
416
|
def update_data(data)
|
|
334
417
|
update_roles(data['roles']) if data['roles']
|
|
335
|
-
|
|
418
|
+
@nick = data['nick'] if data.key?('nick')
|
|
336
419
|
@mute = data['mute'] if data.key?('mute')
|
|
337
420
|
@deaf = data['deaf'] if data.key?('deaf')
|
|
421
|
+
@server_avatar_id = data['avatar'] if data.key?('avatar')
|
|
422
|
+
@server_banner_id = data['banner'] if data.key?('banner')
|
|
423
|
+
@flags = data['flags'] if data.key?('flags')
|
|
424
|
+
@pending = data['pending'] if data.key?('pending')
|
|
338
425
|
|
|
339
426
|
@joined_at = Time.parse(data['joined_at']) if data['joined_at']
|
|
340
|
-
|
|
341
|
-
|
|
427
|
+
|
|
428
|
+
if data.key?('communication_disabled_until')
|
|
429
|
+
timeout_until = data['communication_disabled_until']
|
|
430
|
+
@communication_disabled_until = timeout_until ? Time.parse(timeout_until) : nil
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
if data.key('premium_since')
|
|
434
|
+
@boosting_since = data['premium_since'] ? Time.parse(data['premium_since']) : nil
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
if (user = data['user'])
|
|
438
|
+
@user.update_global_name(user['global_name']) if user['global_name']
|
|
439
|
+
@user.avatar_id = user['avatar'] if user.key('avatar')
|
|
440
|
+
@user.update_avatar_decoration(user['avatar_decoration_data']) if user.key?('avatar_decoration_data')
|
|
441
|
+
@user.update_collectibles(user['collectibles']) if user.key?('collectibles')
|
|
442
|
+
@user.update_primary_server(user['primary_guild']) if user.key?('primary_guild')
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
@server_avatar_decoration = process_avatar_decoration(data['avatar_decoration_data']) if data.key?('avatar_decoration_data')
|
|
342
446
|
end
|
|
343
447
|
|
|
344
448
|
include PermissionCalculator
|
|
345
449
|
|
|
346
450
|
# Overwriting inspect for debug purposes
|
|
347
451
|
def inspect
|
|
348
|
-
"<Member user=#{@user.inspect} server=#{@server&.inspect || @server_id} joined_at=#{@joined_at} roles=#{@roles&.inspect || @role_ids} voice_channel=#{
|
|
452
|
+
"<Member user=#{@user.inspect} server=#{@server&.inspect || @server_id} joined_at=#{@joined_at} roles=#{@roles&.inspect || @role_ids} voice_channel=#{voice_channel.inspect} mute=#{mute} deaf=#{deaf} self_mute=#{self_mute} self_deaf=#{self_deaf}>"
|
|
349
453
|
end
|
|
350
454
|
|
|
351
455
|
private
|
|
@@ -365,8 +469,21 @@ module Discordrb
|
|
|
365
469
|
voice_state&.send name
|
|
366
470
|
end
|
|
367
471
|
|
|
472
|
+
# @!visibility private
|
|
368
473
|
def resolve_role_ids
|
|
369
474
|
@roles ? @roles.collect(&:id) : @role_ids
|
|
370
475
|
end
|
|
476
|
+
|
|
477
|
+
# @!visibility private
|
|
478
|
+
def update_member_data(new_data)
|
|
479
|
+
update_data(JSON.parse(API::Server.update_member(@bot.token, @server_id, @user.id, **new_data)))
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# @!visibility private
|
|
483
|
+
def update_current_member_data(new_data)
|
|
484
|
+
update_data(JSON.parse(API::Server.update_current_member(@bot.token, @server_id,
|
|
485
|
+
new_data.key?(:nick) ? new_data[:nick] : :undef,
|
|
486
|
+
new_data[:reason])))
|
|
487
|
+
end
|
|
371
488
|
end
|
|
372
489
|
end
|