discordrb 3.3.0 → 3.4.3

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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +126 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  5. data/.github/pull_request_template.md +37 -0
  6. data/.rubocop.yml +34 -37
  7. data/.travis.yml +5 -6
  8. data/CHANGELOG.md +504 -347
  9. data/Gemfile +2 -0
  10. data/LICENSE.txt +1 -1
  11. data/README.md +61 -79
  12. data/Rakefile +2 -0
  13. data/bin/console +1 -0
  14. data/discordrb-webhooks.gemspec +6 -6
  15. data/discordrb.gemspec +18 -18
  16. data/lib/discordrb/allowed_mentions.rb +36 -0
  17. data/lib/discordrb/api/channel.rb +62 -39
  18. data/lib/discordrb/api/invite.rb +3 -3
  19. data/lib/discordrb/api/server.rb +57 -50
  20. data/lib/discordrb/api/user.rb +9 -8
  21. data/lib/discordrb/api/webhook.rb +6 -6
  22. data/lib/discordrb/api.rb +40 -15
  23. data/lib/discordrb/await.rb +0 -1
  24. data/lib/discordrb/bot.rb +175 -73
  25. data/lib/discordrb/cache.rb +4 -2
  26. data/lib/discordrb/colour_rgb.rb +43 -0
  27. data/lib/discordrb/commands/command_bot.rb +30 -9
  28. data/lib/discordrb/commands/container.rb +20 -23
  29. data/lib/discordrb/commands/parser.rb +18 -18
  30. data/lib/discordrb/commands/rate_limiter.rb +3 -2
  31. data/lib/discordrb/container.rb +77 -17
  32. data/lib/discordrb/data/activity.rb +271 -0
  33. data/lib/discordrb/data/application.rb +50 -0
  34. data/lib/discordrb/data/attachment.rb +56 -0
  35. data/lib/discordrb/data/audit_logs.rb +345 -0
  36. data/lib/discordrb/data/channel.rb +849 -0
  37. data/lib/discordrb/data/embed.rb +251 -0
  38. data/lib/discordrb/data/emoji.rb +82 -0
  39. data/lib/discordrb/data/integration.rb +83 -0
  40. data/lib/discordrb/data/invite.rb +137 -0
  41. data/lib/discordrb/data/member.rb +297 -0
  42. data/lib/discordrb/data/message.rb +334 -0
  43. data/lib/discordrb/data/overwrite.rb +102 -0
  44. data/lib/discordrb/data/profile.rb +91 -0
  45. data/lib/discordrb/data/reaction.rb +33 -0
  46. data/lib/discordrb/data/recipient.rb +34 -0
  47. data/lib/discordrb/data/role.rb +191 -0
  48. data/lib/discordrb/data/server.rb +1002 -0
  49. data/lib/discordrb/data/user.rb +204 -0
  50. data/lib/discordrb/data/voice_region.rb +45 -0
  51. data/lib/discordrb/data/voice_state.rb +41 -0
  52. data/lib/discordrb/data/webhook.rb +145 -0
  53. data/lib/discordrb/data.rb +25 -4180
  54. data/lib/discordrb/errors.rb +2 -1
  55. data/lib/discordrb/events/bans.rb +7 -5
  56. data/lib/discordrb/events/channels.rb +2 -0
  57. data/lib/discordrb/events/guilds.rb +16 -9
  58. data/lib/discordrb/events/invites.rb +125 -0
  59. data/lib/discordrb/events/members.rb +6 -2
  60. data/lib/discordrb/events/message.rb +69 -27
  61. data/lib/discordrb/events/presence.rb +14 -4
  62. data/lib/discordrb/events/raw.rb +1 -3
  63. data/lib/discordrb/events/reactions.rb +49 -3
  64. data/lib/discordrb/events/typing.rb +6 -4
  65. data/lib/discordrb/events/voice_server_update.rb +47 -0
  66. data/lib/discordrb/events/voice_state_update.rb +15 -10
  67. data/lib/discordrb/events/webhooks.rb +9 -6
  68. data/lib/discordrb/gateway.rb +72 -57
  69. data/lib/discordrb/id_object.rb +39 -0
  70. data/lib/discordrb/light/integrations.rb +1 -1
  71. data/lib/discordrb/light/light_bot.rb +1 -1
  72. data/lib/discordrb/logger.rb +4 -4
  73. data/lib/discordrb/paginator.rb +57 -0
  74. data/lib/discordrb/permissions.rb +103 -8
  75. data/lib/discordrb/version.rb +1 -1
  76. data/lib/discordrb/voice/encoder.rb +16 -7
  77. data/lib/discordrb/voice/network.rb +84 -43
  78. data/lib/discordrb/voice/sodium.rb +96 -0
  79. data/lib/discordrb/voice/voice_bot.rb +34 -26
  80. data/lib/discordrb.rb +73 -0
  81. metadata +98 -60
  82. /data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
@@ -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,14 +39,15 @@ 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
46
46
  # `false` as the value.
47
- # @option attributes [String] :command_doesnt_exist_message The message that should be displayed if a user attempts
47
+ # @option attributes [String, #call] :command_doesnt_exist_message The message that should be displayed if a user attempts
48
48
  # to use a command that does not exist. If none is specified, no message will be displayed. In the message, you
49
- # can use the string '%command%' that will be replaced with the name of the command.
49
+ # can use the string '%command%' that will be replaced with the name of the command. Anything responding to call
50
+ # such as a proc will be called with the event, and is expected to return a String or nil.
50
51
  # @option attributes [String] :no_permission_message The message to be displayed when `NoPermission` error is raised.
51
52
  # @option attributes [true, false] :spaces_allowed Whether spaces are allowed to occur between the prefix and the
52
53
  # command. Default is false.
@@ -83,7 +84,9 @@ module Discordrb::Commands
83
84
  num_shards: attributes[:num_shards],
84
85
  redact_token: attributes.key?(:redact_token) ? attributes[:redact_token] : true,
85
86
  ignore_bots: attributes[:ignore_bots],
86
- compress_mode: attributes[:compress_mode])
87
+ compress_mode: attributes[:compress_mode],
88
+ intents: attributes[:intents]
89
+ )
87
90
 
88
91
  @prefix = attributes[:prefix]
89
92
  @attributes = {
@@ -140,6 +143,7 @@ module Discordrb::Commands
140
143
  }
141
144
 
142
145
  return unless @attributes[:help_command]
146
+
143
147
  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
148
  if command_name
145
149
  command = @commands[command_name.to_sym]
@@ -148,6 +152,7 @@ module Discordrb::Commands
148
152
  command_name = command.name
149
153
  end
150
154
  return "The command `#{command_name}` does not exist!" unless command
155
+
151
156
  desc = command.attributes[:description] || '*No description available*'
152
157
  usage = command.attributes[:usage]
153
158
  parameters = command.attributes[:parameters]
@@ -206,15 +211,22 @@ module Discordrb::Commands
206
211
  def execute_command(name, event, arguments, chained = false, check_permissions = true)
207
212
  debug("Executing command #{name} with arguments #{arguments}")
208
213
  return unless @commands
214
+
209
215
  command = @commands[name]
210
216
  command = command.aliased_command if command.is_a?(CommandAlias)
211
217
  return unless !check_permissions || channels?(event.channel, @attributes[:channels]) ||
212
218
  (command && !command.attributes[:channels].nil?)
219
+
213
220
  unless command
214
- event.respond @attributes[:command_doesnt_exist_message].gsub('%command%', name.to_s) if @attributes[:command_doesnt_exist_message]
221
+ if @attributes[:command_doesnt_exist_message]
222
+ message = @attributes[:command_doesnt_exist_message]
223
+ message = message.call(event) if message.respond_to?(:call)
224
+ event.respond message.gsub('%command%', name.to_s) if message
225
+ end
215
226
  return
216
227
  end
217
228
  return unless !check_permissions || channels?(event.channel, command.attributes[:channels])
229
+
218
230
  arguments = arg_check(arguments, command.attributes[:arg_types], event.server) if check_permissions
219
231
  if (check_permissions &&
220
232
  permission?(event.author, command.attributes[:permission_level], event.server) &&
@@ -238,11 +250,13 @@ module Discordrb::Commands
238
250
  # For example, `['1', '10..14']` with types `[Integer, Range]` would turn into `[1, 10..14]`.
239
251
  def arg_check(args, types = nil, server = nil)
240
252
  return args unless types
253
+
241
254
  args.each_with_index.map do |arg, i|
242
255
  next arg if types[i].nil? || types[i] == String
256
+
243
257
  if types[i] == Integer
244
258
  begin
245
- Integer(arg)
259
+ Integer(arg, 10)
246
260
  rescue ArgumentError
247
261
  nil
248
262
  end
@@ -304,7 +318,7 @@ module Discordrb::Commands
304
318
  elsif types[i].respond_to?(:from_argument)
305
319
  begin
306
320
  types[i].from_argument arg
307
- rescue
321
+ rescue StandardError
308
322
  nil
309
323
  end
310
324
  else
@@ -319,6 +333,7 @@ module Discordrb::Commands
319
333
  # @return [String, nil] the command's result, if there is any.
320
334
  def simple_execute(chain, event)
321
335
  return nil if chain.empty?
336
+
322
337
  args = chain.split(' ')
323
338
  execute_command(args[0].to_sym, event, args[1..-1])
324
339
  end
@@ -369,6 +384,7 @@ module Discordrb::Commands
369
384
  # @param channel [String, Integer, Channel] The channel name, integer ID, or `Channel` object to be added
370
385
  def add_channel(channel)
371
386
  return if @attributes[:channels].find { |c| channel.resolve_id == c.resolve_id }
387
+
372
388
  @attributes[:channels] << channel
373
389
  end
374
390
 
@@ -426,6 +442,7 @@ module Discordrb::Commands
426
442
 
427
443
  def standard_prefix_trigger(message, prefix)
428
444
  return nil unless message.start_with? prefix
445
+
429
446
  message[prefix.length..-1]
430
447
  end
431
448
 
@@ -437,11 +454,13 @@ module Discordrb::Commands
437
454
 
438
455
  def required_roles?(member, required)
439
456
  return true if member.webhook? || member.is_a?(Discordrb::Recipient) || required.nil? || required.empty?
457
+
440
458
  required.is_a?(Array) ? check_multiple_roles(member, required) : member.role?(role)
441
459
  end
442
460
 
443
461
  def allowed_roles?(member, required)
444
462
  return true if member.webhook? || member.is_a?(Discordrb::Recipient) || required.nil? || required.empty?
463
+
445
464
  required.is_a?(Array) ? check_multiple_roles(member, required, false) : member.role?(role)
446
465
  end
447
466
 
@@ -459,9 +478,11 @@ module Discordrb::Commands
459
478
 
460
479
  def channels?(channel, channels)
461
480
  return true if channels.nil? || channels.empty?
481
+
462
482
  channels.any? do |c|
463
483
  # if c is string, make sure to remove the "#" from channel names in case it was specified
464
484
  return true if c.is_a?(String) && c.delete('#') == channel.name
485
+
465
486
  c.resolve_id == channel.resolve_id
466
487
  end
467
488
  end
@@ -480,7 +501,7 @@ module Discordrb::Commands
480
501
  else
481
502
  event.respond result unless result.nil? || result.empty?
482
503
  end
483
- rescue => e
504
+ rescue StandardError => e
484
505
  log_exception(e)
485
506
  ensure
486
507
  @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