discordrb 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of discordrb might be problematic. Click here for more details.

Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +126 -0
  3. data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  6. data/.github/pull_request_template.md +37 -0
  7. data/.rubocop.yml +34 -37
  8. data/.travis.yml +5 -6
  9. data/CHANGELOG.md +472 -347
  10. data/Gemfile +2 -0
  11. data/LICENSE.txt +1 -1
  12. data/README.md +61 -79
  13. data/Rakefile +2 -0
  14. data/bin/console +1 -0
  15. data/discordrb-webhooks.gemspec +6 -6
  16. data/discordrb.gemspec +17 -17
  17. data/lib/discordrb.rb +73 -0
  18. data/lib/discordrb/allowed_mentions.rb +36 -0
  19. data/lib/discordrb/api.rb +40 -15
  20. data/lib/discordrb/api/channel.rb +57 -39
  21. data/lib/discordrb/api/invite.rb +3 -3
  22. data/lib/discordrb/api/server.rb +55 -50
  23. data/lib/discordrb/api/user.rb +8 -8
  24. data/lib/discordrb/api/webhook.rb +6 -6
  25. data/lib/discordrb/await.rb +0 -1
  26. data/lib/discordrb/bot.rb +164 -72
  27. data/lib/discordrb/cache.rb +4 -2
  28. data/lib/discordrb/colour_rgb.rb +43 -0
  29. data/lib/discordrb/commands/command_bot.rb +22 -6
  30. data/lib/discordrb/commands/container.rb +20 -23
  31. data/lib/discordrb/commands/parser.rb +18 -18
  32. data/lib/discordrb/commands/rate_limiter.rb +3 -2
  33. data/lib/discordrb/container.rb +77 -17
  34. data/lib/discordrb/data.rb +25 -4180
  35. data/lib/discordrb/data/activity.rb +264 -0
  36. data/lib/discordrb/data/application.rb +50 -0
  37. data/lib/discordrb/data/attachment.rb +56 -0
  38. data/lib/discordrb/data/audit_logs.rb +345 -0
  39. data/lib/discordrb/data/channel.rb +849 -0
  40. data/lib/discordrb/data/embed.rb +251 -0
  41. data/lib/discordrb/data/emoji.rb +82 -0
  42. data/lib/discordrb/data/integration.rb +83 -0
  43. data/lib/discordrb/data/invite.rb +137 -0
  44. data/lib/discordrb/data/member.rb +297 -0
  45. data/lib/discordrb/data/message.rb +334 -0
  46. data/lib/discordrb/data/overwrite.rb +102 -0
  47. data/lib/discordrb/data/profile.rb +91 -0
  48. data/lib/discordrb/data/reaction.rb +33 -0
  49. data/lib/discordrb/data/recipient.rb +34 -0
  50. data/lib/discordrb/data/role.rb +191 -0
  51. data/lib/discordrb/data/server.rb +1002 -0
  52. data/lib/discordrb/data/user.rb +204 -0
  53. data/lib/discordrb/data/voice_region.rb +45 -0
  54. data/lib/discordrb/data/voice_state.rb +41 -0
  55. data/lib/discordrb/data/webhook.rb +145 -0
  56. data/lib/discordrb/errors.rb +2 -1
  57. data/lib/discordrb/events/bans.rb +7 -5
  58. data/lib/discordrb/events/channels.rb +2 -0
  59. data/lib/discordrb/events/guilds.rb +16 -9
  60. data/lib/discordrb/events/invites.rb +125 -0
  61. data/lib/discordrb/events/members.rb +6 -2
  62. data/lib/discordrb/events/message.rb +69 -27
  63. data/lib/discordrb/events/presence.rb +14 -4
  64. data/lib/discordrb/events/raw.rb +1 -3
  65. data/lib/discordrb/events/reactions.rb +49 -3
  66. data/lib/discordrb/events/typing.rb +6 -4
  67. data/lib/discordrb/events/voice_server_update.rb +47 -0
  68. data/lib/discordrb/events/voice_state_update.rb +15 -10
  69. data/lib/discordrb/events/webhooks.rb +9 -6
  70. data/lib/discordrb/gateway.rb +72 -57
  71. data/lib/discordrb/id_object.rb +39 -0
  72. data/lib/discordrb/light/integrations.rb +1 -1
  73. data/lib/discordrb/light/light_bot.rb +1 -1
  74. data/lib/discordrb/logger.rb +4 -4
  75. data/lib/discordrb/paginator.rb +57 -0
  76. data/lib/discordrb/permissions.rb +103 -8
  77. data/lib/discordrb/version.rb +1 -1
  78. data/lib/discordrb/voice/encoder.rb +3 -3
  79. data/lib/discordrb/voice/network.rb +84 -43
  80. data/lib/discordrb/voice/sodium.rb +96 -0
  81. data/lib/discordrb/voice/voice_bot.rb +34 -26
  82. metadata +93 -55
@@ -134,6 +134,7 @@ module Discordrb
134
134
  def pm_channel(id)
135
135
  id = id.resolve_id
136
136
  return @pm_channels[id] if @pm_channels[id]
137
+
137
138
  debug("Creating pm channel with user id #{id}")
138
139
  response = API::User.create_pm(token, id)
139
140
  channel = Channel.new(JSON.parse(response), self)
@@ -187,7 +188,7 @@ module Discordrb
187
188
  #
188
189
  # * An {Invite} object
189
190
  # * The code for an invite
190
- # * A fully qualified invite URL (e.g. `https://discordapp.com/invite/0A37aN7fasF7n83q`)
191
+ # * A fully qualified invite URL (e.g. `https://discord.com/invite/0A37aN7fasF7n83q`)
191
192
  # * A short invite URL with protocol (e.g. `https://discord.gg/0A37aN7fasF7n83q`)
192
193
  # * A short invite URL without protocol (e.g. `discord.gg/0A37aN7fasF7n83q`)
193
194
  # @return [String] Only the code for the invite.
@@ -219,7 +220,7 @@ module Discordrb
219
220
  return [channel(id)]
220
221
  end
221
222
 
222
- @servers.values.each do |server|
223
+ @servers.each_value do |server|
223
224
  server.channels.each do |channel|
224
225
  results << channel if channel.name == channel_name && (server_name || server.name) == server.name && (!type || (channel.type == type))
225
226
  end
@@ -248,6 +249,7 @@ module Discordrb
248
249
  def find_user(username, discrim = nil)
249
250
  users = @users.values.find_all { |e| e.username == username }
250
251
  return users.find { |u| u.discrim == discrim } if discrim
252
+
251
253
  users
252
254
  end
253
255
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discordrb
4
+ # A colour (red, green and blue values). Used for role colours. If you prefer the American spelling, the alias
5
+ # {ColorRGB} is also available.
6
+ class ColourRGB
7
+ # @return [Integer] the red part of this colour (0-255).
8
+ attr_reader :red
9
+
10
+ # @return [Integer] the green part of this colour (0-255).
11
+ attr_reader :green
12
+
13
+ # @return [Integer] the blue part of this colour (0-255).
14
+ attr_reader :blue
15
+
16
+ # @return [Integer] the colour's RGB values combined into one integer.
17
+ attr_reader :combined
18
+ alias_method :to_i, :combined
19
+
20
+ # Make a new colour from the combined value.
21
+ # @param combined [String, Integer] The colour's RGB values combined into one integer or a hexadecimal string
22
+ # @example Initialize a with a base 10 integer
23
+ # ColourRGB.new(7506394) #=> ColourRGB
24
+ # ColourRGB.new(0x7289da) #=> ColourRGB
25
+ # @example Initialize a with a hexadecimal string
26
+ # ColourRGB.new('7289da') #=> ColourRGB
27
+ def initialize(combined)
28
+ @combined = combined.is_a?(String) ? combined.to_i(16) : combined
29
+ @red = (@combined >> 16) & 0xFF
30
+ @green = (@combined >> 8) & 0xFF
31
+ @blue = @combined & 0xFF
32
+ end
33
+
34
+ # @return [String] the colour as a hexadecimal.
35
+ def hex
36
+ @combined.to_s(16)
37
+ end
38
+ alias_method :hexadecimal, :hex
39
+ end
40
+
41
+ # Alias for the class {ColourRGB}
42
+ ColorRGB = ColourRGB
43
+ end
@@ -24,7 +24,7 @@ module Discordrb::Commands
24
24
 
25
25
  # Creates a new CommandBot and logs in to Discord.
26
26
  # @param attributes [Hash] The attributes to initialize the CommandBot with.
27
- # @see {Discordrb::Bot#initialize} for other attributes that should be used to create the underlying regular bot.
27
+ # @see Discordrb::Bot#initialize Discordrb::Bot#initialize for other attributes that should be used to create the underlying regular bot.
28
28
  # @option attributes [String, Array<String>, #call] :prefix The prefix that should trigger this bot's commands. It
29
29
  # can be:
30
30
  #
@@ -39,7 +39,7 @@ module Discordrb::Commands
39
39
  # complicated dynamic prefixes (e. g. based on server), or even something else entirely (suffixes, or most
40
40
  # adventurous, infixes).
41
41
  # @option attributes [true, false] :advanced_functionality Whether to enable advanced functionality (very powerful
42
- # way to nest commands into chains, see https://github.com/meew0/discordrb/wiki/Commands#command-chain-syntax
42
+ # way to nest commands into chains, see https://github.com/shardlab/discordrb/wiki/Commands#command-chain-syntax
43
43
  # for info. Default is false.
44
44
  # @option attributes [Symbol, Array<Symbol>, false] :help_command The name of the command that displays info for
45
45
  # other commands. Use an array if you want to have aliases. Default is "help". If none should be created, use
@@ -83,7 +83,9 @@ module Discordrb::Commands
83
83
  num_shards: attributes[:num_shards],
84
84
  redact_token: attributes.key?(:redact_token) ? attributes[:redact_token] : true,
85
85
  ignore_bots: attributes[:ignore_bots],
86
- compress_mode: attributes[:compress_mode])
86
+ compress_mode: attributes[:compress_mode],
87
+ intents: attributes[:intents]
88
+ )
87
89
 
88
90
  @prefix = attributes[:prefix]
89
91
  @attributes = {
@@ -140,6 +142,7 @@ module Discordrb::Commands
140
142
  }
141
143
 
142
144
  return unless @attributes[:help_command]
145
+
143
146
  command(@attributes[:help_command], max_args: 1, description: 'Shows a list of all the commands available or displays help for a specific command.', usage: 'help [command name]') do |event, command_name|
144
147
  if command_name
145
148
  command = @commands[command_name.to_sym]
@@ -148,6 +151,7 @@ module Discordrb::Commands
148
151
  command_name = command.name
149
152
  end
150
153
  return "The command `#{command_name}` does not exist!" unless command
154
+
151
155
  desc = command.attributes[:description] || '*No description available*'
152
156
  usage = command.attributes[:usage]
153
157
  parameters = command.attributes[:parameters]
@@ -206,15 +210,18 @@ module Discordrb::Commands
206
210
  def execute_command(name, event, arguments, chained = false, check_permissions = true)
207
211
  debug("Executing command #{name} with arguments #{arguments}")
208
212
  return unless @commands
213
+
209
214
  command = @commands[name]
210
215
  command = command.aliased_command if command.is_a?(CommandAlias)
211
216
  return unless !check_permissions || channels?(event.channel, @attributes[:channels]) ||
212
217
  (command && !command.attributes[:channels].nil?)
218
+
213
219
  unless command
214
220
  event.respond @attributes[:command_doesnt_exist_message].gsub('%command%', name.to_s) if @attributes[:command_doesnt_exist_message]
215
221
  return
216
222
  end
217
223
  return unless !check_permissions || channels?(event.channel, command.attributes[:channels])
224
+
218
225
  arguments = arg_check(arguments, command.attributes[:arg_types], event.server) if check_permissions
219
226
  if (check_permissions &&
220
227
  permission?(event.author, command.attributes[:permission_level], event.server) &&
@@ -238,11 +245,13 @@ module Discordrb::Commands
238
245
  # For example, `['1', '10..14']` with types `[Integer, Range]` would turn into `[1, 10..14]`.
239
246
  def arg_check(args, types = nil, server = nil)
240
247
  return args unless types
248
+
241
249
  args.each_with_index.map do |arg, i|
242
250
  next arg if types[i].nil? || types[i] == String
251
+
243
252
  if types[i] == Integer
244
253
  begin
245
- Integer(arg)
254
+ Integer(arg, 10)
246
255
  rescue ArgumentError
247
256
  nil
248
257
  end
@@ -304,7 +313,7 @@ module Discordrb::Commands
304
313
  elsif types[i].respond_to?(:from_argument)
305
314
  begin
306
315
  types[i].from_argument arg
307
- rescue
316
+ rescue StandardError
308
317
  nil
309
318
  end
310
319
  else
@@ -319,6 +328,7 @@ module Discordrb::Commands
319
328
  # @return [String, nil] the command's result, if there is any.
320
329
  def simple_execute(chain, event)
321
330
  return nil if chain.empty?
331
+
322
332
  args = chain.split(' ')
323
333
  execute_command(args[0].to_sym, event, args[1..-1])
324
334
  end
@@ -369,6 +379,7 @@ module Discordrb::Commands
369
379
  # @param channel [String, Integer, Channel] The channel name, integer ID, or `Channel` object to be added
370
380
  def add_channel(channel)
371
381
  return if @attributes[:channels].find { |c| channel.resolve_id == c.resolve_id }
382
+
372
383
  @attributes[:channels] << channel
373
384
  end
374
385
 
@@ -426,6 +437,7 @@ module Discordrb::Commands
426
437
 
427
438
  def standard_prefix_trigger(message, prefix)
428
439
  return nil unless message.start_with? prefix
440
+
429
441
  message[prefix.length..-1]
430
442
  end
431
443
 
@@ -437,11 +449,13 @@ module Discordrb::Commands
437
449
 
438
450
  def required_roles?(member, required)
439
451
  return true if member.webhook? || member.is_a?(Discordrb::Recipient) || required.nil? || required.empty?
452
+
440
453
  required.is_a?(Array) ? check_multiple_roles(member, required) : member.role?(role)
441
454
  end
442
455
 
443
456
  def allowed_roles?(member, required)
444
457
  return true if member.webhook? || member.is_a?(Discordrb::Recipient) || required.nil? || required.empty?
458
+
445
459
  required.is_a?(Array) ? check_multiple_roles(member, required, false) : member.role?(role)
446
460
  end
447
461
 
@@ -459,9 +473,11 @@ module Discordrb::Commands
459
473
 
460
474
  def channels?(channel, channels)
461
475
  return true if channels.nil? || channels.empty?
476
+
462
477
  channels.any? do |c|
463
478
  # if c is string, make sure to remove the "#" from channel names in case it was specified
464
479
  return true if c.is_a?(String) && c.delete('#') == channel.name
480
+
465
481
  c.resolve_id == channel.resolve_id
466
482
  end
467
483
  end
@@ -480,7 +496,7 @@ module Discordrb::Commands
480
496
  else
481
497
  event.respond result unless result.nil? || result.empty?
482
498
  end
483
- rescue => e
499
+ rescue StandardError => e
484
500
  log_exception(e)
485
501
  ensure
486
502
  @event_threads.delete(t)
@@ -9,22 +9,25 @@ module Discordrb::Commands
9
9
  module CommandContainer
10
10
  include RateLimiter
11
11
 
12
- # @return [Hash<Symbol, Command>] hash of command names and commands this container has.
12
+ # @return [Hash<Symbol, Command, CommandAlias>] hash of command names and commands this container has.
13
13
  attr_reader :commands
14
14
 
15
15
  # Adds a new command to the container.
16
- # @param name [Symbol, Array<Symbol>] The name of the command to add, or an array of multiple names for the command
16
+ # @param name [Symbol] The name of the command to add.
17
17
  # @param attributes [Hash] The attributes to initialize the command with.
18
+ # @option attributes [Array<Symbol>] :aliases A list of additional names for this command. This in effect
19
+ # creates {CommandAlias} objects in the container ({#commands}) that refer to the newly created command.
20
+ # Additionally, the default help command will identify these command names as an alias where applicable.
18
21
  # @option attributes [Integer] :permission_level The minimum permission level that can use this command, inclusive.
19
22
  # See {CommandBot#set_user_permission} and {CommandBot#set_role_permission}.
20
23
  # @option attributes [String, false] :permission_message Message to display when a user does not have sufficient
21
24
  # permissions to execute a command. %name% in the message will be replaced with the name of the command. Disable
22
25
  # the message by setting this option to false.
23
26
  # @option attributes [Array<Symbol>] :required_permissions Discord action permissions (e.g. `:kick_members`) that
24
- # should be required to use this command. See {Discordrb::Permissions::Flags} for a list.
25
- # @option attributes [Array<Role>, Array<#resolve_id>] :required_roles Roles that user must have to use this command
27
+ # should be required to use this command. See {Discordrb::Permissions::FLAGS} for a list.
28
+ # @option attributes [Array<Role>, Array<String, Integer>] :required_roles Roles, or their IDs, that user must have to use this command
26
29
  # (user must have all of them).
27
- # @option attributes [Array<Role>, Array<#resolve_id>] :allowed_roles Roles that user should have to use this command
30
+ # @option attributes [Array<Role>, Array<String, Integer>] :allowed_roles Roles, or their IDs, that user should have to use this command
28
31
  # (user should have at least one of them).
29
32
  # @option attributes [Array<String, Integer, Channel>] :channels The channels that this command can be used on. An
30
33
  # empty array indicates it can be used on any channel. Supersedes the command bot attribute.
@@ -55,26 +58,22 @@ module Discordrb::Commands
55
58
  # @note `LocalJumpError`s are rescued from internally, giving bots the opportunity to use `return` or `break` in
56
59
  # their blocks without propagating an exception.
57
60
  # @return [Command] The command that was added.
58
- # @deprecated The command name argument will no longer support arrays in the next release.
59
- # Use the `aliases` attribute instead.
60
61
  def command(name, attributes = {}, &block)
61
62
  @commands ||= {}
62
- if name.is_a? Array
63
- new_command = nil
64
63
 
65
- name.each do |e|
66
- new_command = Command.new(e, attributes, &block)
67
- @commands[e] = new_command
68
- end
64
+ # TODO: Remove in 4.0
65
+ if name.is_a?(Array)
66
+ name, *aliases = name
67
+ attributes[:aliases] = aliases if attributes[:aliases].nil?
68
+ Discordrb::LOGGER.warn("While registering command #{name.inspect}")
69
+ Discordrb::LOGGER.warn('Arrays for command aliases is removed. Please use `aliases` argument instead.')
70
+ end
69
71
 
70
- new_command
71
- else
72
- new_command = Command.new(name, attributes, &block)
73
- new_command.attributes[:aliases].each do |aliased_name|
74
- @commands[aliased_name] = CommandAlias.new(aliased_name, new_command)
75
- end
76
- @commands[name] = new_command
72
+ new_command = Command.new(name, attributes, &block)
73
+ new_command.attributes[:aliases].each do |aliased_name|
74
+ @commands[aliased_name] = CommandAlias.new(aliased_name, new_command)
77
75
  end
76
+ @commands[name] = new_command
78
77
  end
79
78
 
80
79
  # Removes a specific command from this container.
@@ -100,9 +99,7 @@ module Discordrb::Commands
100
99
  container_modules = container.singleton_class.included_modules
101
100
 
102
101
  # If the container is an EventContainer and we can include it, then do that
103
- if container_modules.include?(Discordrb::EventContainer) && respond_to?(:include_events)
104
- include_events(container)
105
- end
102
+ include_events(container) if container_modules.include?(Discordrb::EventContainer) && respond_to?(:include_events)
106
103
 
107
104
  if container_modules.include? Discordrb::Commands::CommandContainer
108
105
  include_commands(container)
@@ -81,45 +81,43 @@ module Discordrb::Commands
81
81
  # @return [String] the result of the execution.
82
82
  def call(event, arguments, chained = false, check_permissions = true)
83
83
  if arguments.length < @attributes[:min_args]
84
- event.respond "Too few arguments for command `#{name}`!"
85
- event.respond "Usage: `#{@attributes[:usage]}`" if @attributes[:usage]
84
+ response = "Too few arguments for command `#{name}`!"
85
+ response += "\nUsage: `#{@attributes[:usage]}`" if @attributes[:usage]
86
+ event.respond(response)
86
87
  return
87
88
  end
88
89
  if @attributes[:max_args] >= 0 && arguments.length > @attributes[:max_args]
89
- event.respond "Too many arguments for command `#{name}`!"
90
- event.respond "Usage: `#{@attributes[:usage]}`" if @attributes[:usage]
90
+ response = "Too many arguments for command `#{name}`!"
91
+ response += "\nUsage: `#{@attributes[:usage]}`" if @attributes[:usage]
92
+ event.respond(response)
91
93
  return
92
94
  end
93
- unless @attributes[:chain_usable]
94
- if chained
95
- event.respond "Command `#{name}` cannot be used in a command chain!"
96
- return
97
- end
95
+ unless @attributes[:chain_usable] && !chained
96
+ event.respond "Command `#{name}` cannot be used in a command chain!"
97
+ return
98
98
  end
99
99
 
100
100
  if check_permissions
101
101
  rate_limited = event.bot.rate_limited?(@attributes[:bucket], event.author)
102
102
  if @attributes[:bucket] && rate_limited
103
- if @attributes[:rate_limit_message]
104
- event.respond @attributes[:rate_limit_message].gsub('%time%', rate_limited.round(2).to_s)
105
- end
103
+ event.respond @attributes[:rate_limit_message].gsub('%time%', rate_limited.round(2).to_s) if @attributes[:rate_limit_message]
106
104
  return
107
105
  end
108
106
  end
109
107
 
110
108
  result = @block.call(event, *arguments)
111
109
  event.drain_into(result)
112
- rescue LocalJumpError => ex # occurs when breaking
113
- result = ex.exit_value
110
+ rescue LocalJumpError => e # occurs when breaking
111
+ result = e.exit_value
114
112
  event.drain_into(result)
115
- rescue => exception # Something went wrong inside our @block!
113
+ rescue StandardError => e # Something went wrong inside our @block!
116
114
  rescue_value = @attributes[:rescue] || event.bot.attributes[:rescue]
117
115
  if rescue_value
118
- event.respond(rescue_value.gsub('%exception%', exception.message)) if rescue_value.is_a?(String)
119
- rescue_value.call(event, exception) if rescue_value.respond_to?(:call)
116
+ event.respond(rescue_value.gsub('%exception%', e.message)) if rescue_value.is_a?(String)
117
+ rescue_value.call(event, e) if rescue_value.respond_to?(:call)
120
118
  end
121
119
 
122
- raise exception
120
+ raise e
123
121
  end
124
122
  end
125
123
 
@@ -209,8 +207,10 @@ module Discordrb::Commands
209
207
  result += char if b_level <= 0
210
208
 
211
209
  next unless char == @attributes[:sub_chain_end] && !quoted
210
+
212
211
  b_level -= 1
213
212
  next unless b_level.zero?
213
+
214
214
  nested = @chain[b_start + 1..index - 1]
215
215
  subchain = CommandChain.new(nested, @bot, true)
216
216
  result += subchain.execute(event)
@@ -35,7 +35,7 @@ module Discordrb::Commands
35
35
  end
36
36
 
37
37
  # Performs a rate limiting request
38
- # @param thing [#resolve_id, Integer, Symbol] The particular thing that should be rate-limited (usually a user/channel, but you can also choose arbitrary integers or symbols)
38
+ # @param thing [String, Integer, Symbol] The particular thing that should be rate-limited (usually a user/channel, but you can also choose arbitrary integers or symbols)
39
39
  # @param rate_limit_time [Time] The time to base the rate limiting on, only useful for testing.
40
40
  # @param increment [Integer] How much to increment the rate-limit counter. Default is 1.
41
41
  # @return [Integer, false] the waiting time until the next request, in seconds, or false if the request succeeded
@@ -83,6 +83,7 @@ module Discordrb::Commands
83
83
  def resolve_key(thing)
84
84
  return thing.resolve_id if thing.respond_to?(:resolve_id) && !thing.is_a?(String)
85
85
  return thing if thing.is_a?(Integer) || thing.is_a?(Symbol)
86
+
86
87
  raise ArgumentError, "Cannot use a #{thing.class} as a rate limiting key!"
87
88
  end
88
89
  end
@@ -104,7 +105,7 @@ module Discordrb::Commands
104
105
 
105
106
  # Performs a rate limit request.
106
107
  # @param key [Symbol] Which bucket to perform the request for.
107
- # @param thing [#resolve_id, Integer, Symbol] What should be rate-limited.
108
+ # @param thing [String, Integer, Symbol] What should be rate-limited.
108
109
  # @param increment (see Bucket#rate_limited?)
109
110
  # @see Bucket#rate_limited?
110
111
  # @return [Integer, false] How much time to wait or false if the request succeeded.
@@ -5,6 +5,7 @@ require 'discordrb/events/typing'
5
5
  require 'discordrb/events/lifetime'
6
6
  require 'discordrb/events/presence'
7
7
  require 'discordrb/events/voice_state_update'
8
+ require 'discordrb/events/voice_server_update'
8
9
  require 'discordrb/events/channels'
9
10
  require 'discordrb/events/members'
10
11
  require 'discordrb/events/roles'
@@ -89,7 +90,7 @@ module Discordrb
89
90
 
90
91
  # This **event** is raised when a message is edited in a channel.
91
92
  # @param attributes [Hash] The event's attributes.
92
- # @option attributes [#resolve_id] :id Matches the ID of the message that was edited.
93
+ # @option attributes [String, Integer] :id Matches the ID of the message that was edited.
93
94
  # @option attributes [String, Integer, Channel] :in Matches the channel the message was edited in.
94
95
  # @yield The block is executed when the event is raised.
95
96
  # @yieldparam event [MessageEditEvent] The event that was raised.
@@ -100,7 +101,7 @@ module Discordrb
100
101
 
101
102
  # This **event** is raised when a message is deleted in a channel.
102
103
  # @param attributes [Hash] The event's attributes.
103
- # @option attributes [#resolve_id] :id Matches the ID of the message that was deleted.
104
+ # @option attributes [String, Integer] :id Matches the ID of the message that was deleted.
104
105
  # @option attributes [String, Integer, Channel] :in Matches the channel the message was deleted in.
105
106
  # @yield The block is executed when the event is raised.
106
107
  # @yieldparam event [MessageDeleteEvent] The event that was raised.
@@ -109,9 +110,26 @@ module Discordrb
109
110
  register_event(MessageDeleteEvent, attributes, block)
110
111
  end
111
112
 
113
+ # This **event** is raised whenever a message is updated. Message updates can be triggered from
114
+ # a user editing their own message, or from Discord automatically attaching embeds to the
115
+ # user's message for URLs contained in the message's content. If you only want to listen
116
+ # for users editing their own messages, use the {message_edit} handler instead.
117
+ # @param attributes [Hash] The event's attributes.
118
+ # @option attributes [String, Integer] :id Matches the ID of the message that was updated.
119
+ # @option attributes [String, Integer, Channel] :in Matches the channel the message was updated in.
120
+ # @yield The block is executed when the event is raised.
121
+ # @yieldparam event [MessageUpdateEvent] The event that was raised.
122
+ # @return [MessageUpdateEventHandler] the event handler that was registered.
123
+ def message_update(attributes = {}, &block)
124
+ register_event(MessageUpdateEvent, attributes, block)
125
+ end
126
+
112
127
  # This **event** is raised when somebody reacts to a message.
113
128
  # @param attributes [Hash] The event's attributes.
114
- # @option attributes [Integer, String] :emoji Matches the ID of the emoji that was reacted with, or its name.
129
+ # @option attributes [String, Integer] :emoji Matches the ID of the emoji that was reacted with, or its name.
130
+ # @option attributes [String, Integer, User] :from Matches the user who added the reaction.
131
+ # @option attributes [String, Integer, Message] :message Matches the message to which the reaction was added.
132
+ # @option attributes [String, Integer, Channel] :in Matches the channel the reaction was added in.
115
133
  # @yield The block is executed when the event is raised.
116
134
  # @yieldparam event [ReactionAddEvent] The event that was raised.
117
135
  # @return [ReactionAddEventHandler] The event handler that was registered.
@@ -121,8 +139,11 @@ module Discordrb
121
139
 
122
140
  # This **event** is raised when somebody removes a reaction from a message.
123
141
  # @param attributes [Hash] The event's attributes.
124
- # @option attributes [Integer, String] :emoji Matches the ID of the emoji that was removed from the reactions, or
142
+ # @option attributes [String, Integer] :emoji Matches the ID of the emoji that was removed from the reactions, or
125
143
  # its name.
144
+ # @option attributes [String, Integer, User] :from Matches the user who removed the reaction.
145
+ # @option attributes [String, Integer, Message] :message Matches the message to which the reaction was removed.
146
+ # @option attributes [String, Integer, Channel] :in Matches the channel the reaction was removed in.
126
147
  # @yield The block is executed when the event is raised.
127
148
  # @yieldparam event [ReactionRemoveEvent] The event that was raised.
128
149
  # @return [ReactionRemoveEventHandler] The event handler that was registered.
@@ -132,6 +153,9 @@ module Discordrb
132
153
 
133
154
  # This **event** is raised when somebody removes all reactions from a message.
134
155
  # @param attributes [Hash] The event's attributes.
156
+ # @option attributes [Hash] The event's attributes.
157
+ # @option attributes [String, Integer, Message] :message Matches the message to which the reactions were removed.
158
+ # @option attributes [String, Integer, Channel] :in Matches the channel the reactions were removed in.
135
159
  # @yield The block is executed when the event is raised.
136
160
  # @yieldparam event [ReactionRemoveAllEvent] The event that was raised.
137
161
  # @return [ReactionRemoveAllEventHandler] The event handler that was registered.
@@ -143,6 +167,8 @@ module Discordrb
143
167
  # @param attributes [Hash] The event's attributes.
144
168
  # @option attributes [String, Integer, User] :from Matches the user whose status changed.
145
169
  # @option attributes [:offline, :idle, :online] :status Matches the status the user has now.
170
+ # @option attributes [Hash<Symbol, Symbol>] :client_status Matches the current online status (`:online`, `:idle` or `:dnd`) of the user
171
+ # on various device types (`:desktop`, `:mobile`, or `:web`). The value will be `nil` when the user is offline or invisible
146
172
  # @yield The block is executed when the event is raised.
147
173
  # @yieldparam event [PresenceEvent] The event that was raised.
148
174
  # @return [PresenceEventHandler] the event handler that was registered.
@@ -216,8 +242,8 @@ module Discordrb
216
242
  # This **event** is raised when a recipient is added to a group channel.
217
243
  # @param attributes [Hash] The event's attributes.
218
244
  # @option attributes [String] :name Matches the name of the group channel that the recipient is added to.
219
- # @option attributes [#resolve_id] :owner_id Matches the id of the group channel's owner.
220
- # @option attributes [#resolve_id] :id Matches the id of the recipient added to the group channel.
245
+ # @option attributes [String, Integer] :owner_id Matches the ID of the group channel's owner.
246
+ # @option attributes [String, Integer] :id Matches the ID of the recipient added to the group channel.
221
247
  # @yield The block is executed when the event is raised.
222
248
  # @yieldparam event [ChannelRecipientAddEvent] The event that was raised.
223
249
  # @return [ChannelRecipientAddHandler] the event handler that was registered.
@@ -228,8 +254,8 @@ module Discordrb
228
254
  # This **event** is raised when a recipient is removed from a group channel.
229
255
  # @param attributes [Hash] The event's attributes.
230
256
  # @option attributes [String] :name Matches the name of the group channel that the recipient is added to.
231
- # @option attributes [#resolve_id] :owner_id Matches the id of the group channel's owner.
232
- # @option attributes [#resolve_id] :id Matches the id of the recipient removed from the group channel.
257
+ # @option attributes [String, Integer] :owner_id Matches the ID of the group channel's owner.
258
+ # @option attributes [String, Integer] :id Matches the ID of the recipient removed from the group channel.
233
259
  # @yield The block is executed when the event is raised.
234
260
  # @yieldparam event [ChannelRecipientRemoveEvent] The event that was raised.
235
261
  # @return [ChannelRecipientRemoveHandler] the event handler that was registered.
@@ -254,6 +280,16 @@ module Discordrb
254
280
  register_event(VoiceStateUpdateEvent, attributes, block)
255
281
  end
256
282
 
283
+ # This **event** is raised when first connecting to a server's voice channel.
284
+ # @param attributes [Hash] The event's attributes.
285
+ # @option attributes [String, Integer, User] :from Matches the server that the update is for.
286
+ # @yield The block is executed when the event is raised.
287
+ # @yieldparam event [VoiceServerUpdateEvent] The event that was raised.
288
+ # @return [VoiceServerUpdateEventHandler] The event handler that was registered.
289
+ def voice_server_update(attributes = {}, &block)
290
+ register_event(VoiceServerUpdateEvent, attributes, block)
291
+ end
292
+
257
293
  # This **event** is raised when a new user joins a server.
258
294
  # @param attributes [Hash] The event's attributes.
259
295
  # @option attributes [String] :username Matches the username of the joined user.
@@ -352,7 +388,7 @@ module Discordrb
352
388
  # This **event** is raised when an emoji is created.
353
389
  # @param attributes [Hash] The event's attributes.
354
390
  # @option attributes [String, Integer, Server] :server Matches the server.
355
- # @option attributes [String, Integer] :id Matches the id of the emoji.
391
+ # @option attributes [String, Integer] :id Matches the ID of the emoji.
356
392
  # @option attributes [String] :name Matches the name of the emoji.
357
393
  # @yield The block is executed when the event is raised.
358
394
  # @yieldparam event [ServerEmojiCreateEvent] The event that was raised.
@@ -364,7 +400,7 @@ module Discordrb
364
400
  # This **event** is raised when an emoji is deleted.
365
401
  # @param attributes [Hash] The event's attributes.
366
402
  # @option attributes [String, Integer, Server] :server Matches the server.
367
- # @option attributes [String, Integer] :id Matches the id of the emoji.
403
+ # @option attributes [String, Integer] :id Matches the ID of the emoji.
368
404
  # @option attributes [String] :name Matches the name of the emoji.
369
405
  # @yield The block is executed when the event is raised.
370
406
  # @yieldparam event [ServerEmojiDeleteEvent] The event that was raised.
@@ -376,7 +412,7 @@ module Discordrb
376
412
  # This **event** is raised when an emoji is updated.
377
413
  # @param attributes [Hash] The event's attributes.
378
414
  # @option attributes [String, Integer, Server] :server Matches the server.
379
- # @option attributes [String, Integer] :id Matches the id of the emoji.
415
+ # @option attributes [String, Integer] :id Matches the ID of the emoji.
380
416
  # @option attributes [String] :name Matches the name of the emoji.
381
417
  # @option attributes [String] :old_name Matches the name of the emoji before the update.
382
418
  # @yield The block is executed when the event is raised.
@@ -398,7 +434,7 @@ module Discordrb
398
434
 
399
435
  # This **event** is raised when a role is deleted.
400
436
  # @param attributes [Hash] The event's attributes.
401
- # @option attributes [#resolve_id] :id Matches the role id.
437
+ # @option attributes [String, Integer] :id Matches the role ID.
402
438
  # @yield The block is executed when the event is raised.
403
439
  # @yieldparam event [ServerRoleDeleteEvent] The event that was raised.
404
440
  # @return [ServerRoleDeleteEventHandler] the event handler that was registered.
@@ -418,9 +454,9 @@ module Discordrb
418
454
 
419
455
  # This **event** is raised when a webhook is updated.
420
456
  # @param attributes [Hash] The event's attributes.
421
- # @option attributes [String, Integer, Server] :server Matches the server by name, id or instance.
422
- # @option attributes [String, Integer, Channel] :channel Matches the channel by name, id or instance.
423
- # @option attribute [String, Integer, Webhook] :webhook Matches the webhook by name, id or instance.
457
+ # @option attributes [String, Integer, Server] :server Matches the server by name, ID or instance.
458
+ # @option attributes [String, Integer, Channel] :channel Matches the channel by name, ID or instance.
459
+ # @option attribute [String, Integer, Webhook] :webhook Matches the webhook by name, ID or instance.
424
460
  # @yield The block is executed when the event is raised.
425
461
  # @yieldparam event [WebhookUpdateEvent] The event that was raised.
426
462
  # @return [WebhookUpdateEventHandler] the event handler that was registered.
@@ -462,6 +498,30 @@ module Discordrb
462
498
  alias_method :direct_message, :pm
463
499
  alias_method :dm, :pm
464
500
 
501
+ # This **event** is raised when an invite is created.
502
+ # @param attributes [Hash] The event's attributes.
503
+ # @option attributes [String, Integer, User] :inviter Matches the user that created the invite.
504
+ # @option attributes [String, Integer, Channel] :channel Matches the channel the invite was created for.
505
+ # @option attributes [String, Integer, Server] :server Matches the server the invite was created for.
506
+ # @option attributes [true, false] :temporary Matches whether the invite is temporary or not.
507
+ # @yield The block is executed when the event is raised.
508
+ # @yieldparam event [InviteCreateEvent] The event that was raised.
509
+ # @return [InviteCreateEventHandler] The event handler that was registered.
510
+ def invite_create(attributes = {}, &block)
511
+ register_event(InviteCreateEvent, attributes, block)
512
+ end
513
+
514
+ # This **event** is raised when an invite is deleted.
515
+ # @param attributes [Hash] The event's attributes.
516
+ # @option attributes [String, Integer, Channel] :channel Matches the channel the deleted invite was for.
517
+ # @option attributes [String, Integer, Server] :server Matches the server the deleted invite was for.
518
+ # @yield The block is executed when the event is raised
519
+ # @yieldparam event [InviteDeleteEvent] The event that was raised.
520
+ # @return [InviteDeleteEventHandler] The event handler that was registered.
521
+ def invite_delete(attributes = {}, &block)
522
+ register_event(InviteDeleteEvent, attributes, block)
523
+ end
524
+
465
525
  # This **event** is raised for every dispatch received over the gateway, whether supported by discordrb or not.
466
526
  # @param attributes [Hash] The event's attributes.
467
527
  # @option attributes [String, Symbol, Regexp] :type Matches the event type of the dispatch.
@@ -494,7 +554,7 @@ module Discordrb
494
554
 
495
555
  # Removes all events from this event handler.
496
556
  def clear!
497
- @event_handlers.clear if @event_handlers
557
+ @event_handlers&.clear
498
558
  end
499
559
 
500
560
  # Adds an event handler to this container. Usually, it's more expressive to just use one of the shorthand adder
@@ -525,7 +585,7 @@ module Discordrb
525
585
  # @param event_class [Class] The event type
526
586
  # @return [Class] the handler type
527
587
  def self.handler_class(event_class)
528
- class_from_string(event_class.to_s + 'Handler')
588
+ class_from_string("#{event_class}Handler")
529
589
  end
530
590
 
531
591
  # Returns the event class for a handler class type