discorb 0.13.1 → 0.14.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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/build_version.yml +3 -3
  4. data/.github/workflows/codeql-analysis.yml +70 -0
  5. data/.github/workflows/lint-push.yml +18 -0
  6. data/.github/workflows/lint.yml +16 -0
  7. data/.rubocop.yml +70 -0
  8. data/CODE_OF_CONDUCT.md +128 -0
  9. data/Changelog.md +33 -0
  10. data/Gemfile +7 -3
  11. data/README.md +1 -1
  12. data/Rakefile +35 -35
  13. data/discorb.gemspec +13 -1
  14. data/examples/commands/bookmarker.rb +2 -1
  15. data/examples/commands/hello.rb +1 -0
  16. data/examples/commands/inspect.rb +3 -2
  17. data/examples/components/authorization_button.rb +2 -1
  18. data/examples/components/select_menu.rb +2 -1
  19. data/examples/extension/main.rb +1 -0
  20. data/examples/extension/message_expander.rb +1 -0
  21. data/examples/simple/eval.rb +3 -2
  22. data/examples/simple/ping_pong.rb +1 -0
  23. data/examples/simple/rolepanel.rb +1 -0
  24. data/examples/simple/wait_for_message.rb +4 -3
  25. data/exe/discorb +8 -7
  26. data/lib/discorb/allowed_mentions.rb +64 -0
  27. data/lib/discorb/app_command/command.rb +274 -0
  28. data/lib/discorb/app_command/handler.rb +168 -0
  29. data/lib/discorb/app_command.rb +2 -404
  30. data/lib/discorb/asset.rb +3 -1
  31. data/lib/discorb/audit_logs.rb +3 -3
  32. data/lib/discorb/channel.rb +89 -53
  33. data/lib/discorb/client.rb +36 -33
  34. data/lib/discorb/common.rb +28 -21
  35. data/lib/discorb/components/button.rb +106 -0
  36. data/lib/discorb/components/select_menu.rb +157 -0
  37. data/lib/discorb/components/text_input.rb +96 -0
  38. data/lib/discorb/components.rb +11 -276
  39. data/lib/discorb/dictionary.rb +13 -2
  40. data/lib/discorb/embed.rb +2 -2
  41. data/lib/discorb/emoji.rb +21 -5
  42. data/lib/discorb/emoji_table.rb +1 -1
  43. data/lib/discorb/error.rb +4 -6
  44. data/lib/discorb/event.rb +13 -11
  45. data/lib/discorb/exe/about.rb +1 -0
  46. data/lib/discorb/exe/irb.rb +4 -3
  47. data/lib/discorb/exe/new.rb +6 -7
  48. data/lib/discorb/exe/run.rb +2 -1
  49. data/lib/discorb/exe/setup.rb +8 -5
  50. data/lib/discorb/exe/show.rb +1 -0
  51. data/lib/discorb/extend.rb +19 -14
  52. data/lib/discorb/extension.rb +5 -1
  53. data/lib/discorb/gateway.rb +75 -27
  54. data/lib/discorb/guild.rb +58 -80
  55. data/lib/discorb/guild_template.rb +5 -5
  56. data/lib/discorb/http.rb +34 -169
  57. data/lib/discorb/integration.rb +32 -3
  58. data/lib/discorb/intents.rb +1 -1
  59. data/lib/discorb/interaction/autocomplete.rb +5 -4
  60. data/lib/discorb/interaction/command.rb +34 -9
  61. data/lib/discorb/interaction/components.rb +5 -2
  62. data/lib/discorb/interaction/modal.rb +33 -0
  63. data/lib/discorb/interaction/response.rb +41 -12
  64. data/lib/discorb/interaction/root.rb +1 -0
  65. data/lib/discorb/interaction.rb +2 -1
  66. data/lib/discorb/invite.rb +1 -1
  67. data/lib/discorb/log.rb +4 -3
  68. data/lib/discorb/member.rb +4 -6
  69. data/lib/discorb/message.rb +31 -282
  70. data/lib/discorb/message_meta.rb +205 -0
  71. data/lib/discorb/modules.rb +11 -11
  72. data/lib/discorb/permission.rb +2 -2
  73. data/lib/discorb/presence.rb +6 -3
  74. data/lib/discorb/rate_limit.rb +15 -21
  75. data/lib/discorb/role.rb +3 -3
  76. data/lib/discorb/sticker.rb +2 -2
  77. data/lib/discorb/user.rb +3 -3
  78. data/lib/discorb/utils/colored_puts.rb +1 -0
  79. data/lib/discorb/voice_state.rb +7 -2
  80. data/lib/discorb/webhook.rb +8 -5
  81. data/lib/discorb.rb +1 -0
  82. data/template-replace/scripts/arrow.rb +1 -0
  83. data/template-replace/scripts/favicon.rb +1 -0
  84. data/template-replace/scripts/index.rb +2 -1
  85. data/template-replace/scripts/locale_ja.rb +5 -4
  86. data/template-replace/scripts/sidebar.rb +1 -0
  87. data/template-replace/scripts/version.rb +7 -10
  88. data/template-replace/scripts/yard_replace.rb +5 -4
  89. metadata +29 -4
@@ -1,406 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
- module Discorb
4
- #
5
- # Handles application commands.
6
- #
7
- module ApplicationCommand
8
- #
9
- # Module to handle application commands.
10
- #
11
- module Handler
12
- #
13
- # Add new top-level command.
14
- #
15
- # @param [String] command_name Command name.
16
- # @param [String] description Command description.
17
- # @param [Hash{String => Hash{:description => String, :optional => Boolean, :type => Object}}] options Command options.
18
- # The key is the option name, the value is a hash with the following keys:
19
- #
20
- # | Key | Type | Description |
21
- # | --- | --- | --- |
22
- # | `:description` | `String` | Description of the option. |
23
- # | `:required` | Whether the argument is required. `optional` will be used if not specified. |
24
- # | `:optional` | Whether the argument is optional. `required` will be used if not specified. |
25
- # | `:type` | `Object` | Type of the option. |
26
- # | `:choice` | `Hash{String => String, Integer, Float}` | Type of the option. |
27
- # | `:default` | `Object` | Default value of the option. |
28
- # | `:channel_types` | `Array<Class<Discorb::Channel>>` | Type of the channel option. |
29
- # | `:autocomplete` | `Proc` | Autocomplete function. |
30
- # | `:range` | `Range` | Range of the option. Only valid for numeric options. (`:int`, `:float`) |
31
- #
32
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
33
- # @param [Proc] block Command block.
34
- #
35
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] Command object.
36
- #
37
- # @see file:docs/application_command.md#register-slash-command Application Comamnds: Register Slash Command
38
- # @see file:docs/cli/setup.md CLI: setup
39
- #
40
- def slash(command_name, description, options = {}, guild_ids: nil, &block)
41
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, guild_ids, block, 1, "")
42
- @commands << command
43
- @bottom_commands << command
44
- command
45
- end
46
-
47
- #
48
- # Add new command with group.
49
- #
50
- # @param [String] command_name Command name.
51
- # @param [String] description Command description.
52
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
53
- #
54
- # @yield Block to yield with the command.
55
- # @yieldparam [Discorb::ApplicationCommand::Command::GroupCommand] group Group command.
56
- #
57
- # @return [Discorb::ApplicationCommand::Command::GroupCommand] Command object.
58
- #
59
- # @see file:docs/application_command.md Application Commands
60
- # @see file:docs/cli/setup.md CLI: setup
61
- #
62
- def slash_group(command_name, description, guild_ids: nil, &block)
63
- command = Discorb::ApplicationCommand::Command::GroupCommand.new(command_name, description, guild_ids, nil, self)
64
- command.yield_self(&block) if block_given?
65
- @commands << command
66
- command
67
- end
68
-
69
- #
70
- # Add message context menu command.
71
- #
72
- # @param [String] command_name Command name.
73
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
74
- # @param [Proc] block Command block.
75
- # @yield [interaction, message] Block to execute.
76
- # @yieldparam [Discorb::CommandInteraction::UserMenuCommand] interaction Interaction object.
77
- # @yieldparam [Discorb::Message] message Message object.
78
- #
79
- # @return [Discorb::ApplicationCommand::Command] Command object.
80
- #
81
- def message_command(command_name, guild_ids: nil, &block)
82
- command = Discorb::ApplicationCommand::Command.new(command_name, guild_ids, block, 3)
83
- @commands << command
84
- command
85
- end
86
-
87
- #
88
- # Add user context menu command.
89
- #
90
- # @param [String] command_name Command name.
91
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
92
- # @param [Proc] block Command block.
93
- # @yield [interaction, user] Block to execute.
94
- # @yieldparam [Discorb::CommandInteraction::UserMenuCommand] interaction Interaction object.
95
- # @yieldparam [Discorb::User] user User object.
96
- #
97
- # @return [Discorb::ApplicationCommand::Command] Command object.
98
- #
99
- def user_command(command_name, guild_ids: nil, &block)
100
- command = Discorb::ApplicationCommand::Command.new(command_name, guild_ids, block, 2)
101
- @commands << command
102
- command
103
- end
104
-
105
- #
106
- # Setup commands.
107
- # @async
108
- # @see Client#initialize
109
- #
110
- # @param [String] token Bot token.
111
- # @param [Array<#to_s>, false, nil] guild_ids Guild IDs to use as default. If `false` is given, it will be global command.
112
- #
113
- # @note `token` parameter only required if you don't run client.
114
- #
115
- def setup_commands(token = nil, guild_ids: nil)
116
- Async do
117
- @token ||= token
118
- @http = HTTP.new(self)
119
- global_commands = @commands.select { |c| c.guild_ids == false or c.guild_ids == [] }
120
- local_commands = @commands.select { |c| c.guild_ids.is_a?(Array) and c.guild_ids.any? }
121
- default_commands = @commands.select { |c| c.guild_ids.nil? }
122
- if guild_ids.is_a?(Array)
123
- default_commands.each do |command|
124
- command.instance_variable_set(:@guild_ids, guild_ids)
125
- end
126
- local_commands += default_commands
127
- else
128
- global_commands += default_commands
129
- end
130
- final_guild_ids = local_commands.map(&:guild_ids).flatten.map(&:to_s).uniq
131
- app_info = fetch_application.wait
132
- http.put("/applications/#{app_info.id}/commands", global_commands.map(&:to_hash)).wait unless global_commands.empty?
133
- final_guild_ids.each do |guild_id|
134
- commands = local_commands.select { |c| c.guild_ids.include?(guild_id) }
135
- http.put("/applications/#{app_info.id}/guilds/#{guild_id}/commands", commands.map(&:to_hash)).wait
136
- end unless final_guild_ids.empty?
137
- @log.info "Successfully setup commands"
138
- end
139
- end
140
- end
141
-
142
- #
143
- # Represents a application command.
144
- # @abstract
145
- #
146
- class Command < DiscordModel
147
- # @return [String] The name of the command.
148
- attr_reader :name
149
- # @return [Array<#to_s>] The guild ids that the command is enabled in.
150
- attr_reader :guild_ids
151
- # @return [Proc] The block of the command.
152
- attr_reader :block
153
- # @return [:chat_input, :user, :message] The type of the command.
154
- attr_reader :type
155
- # @return [Integer] The raw type of the command.
156
- attr_reader :type_raw
157
- # @return [Discorb::Dictionary{Discorb::Snowflake, :global => Discorb::Snowflake}] The ID mapping.
158
- attr_reader :id_map
159
-
160
- @types = {
161
- 1 => :chat_input,
162
- 2 => :user,
163
- 3 => :message,
164
- }.freeze
165
-
166
- # @private
167
- def initialize(name, guild_ids, block, type)
168
- @name = name
169
- @guild_ids = guild_ids&.map(&:to_s)
170
- @block = block
171
- @raw_type = type
172
- @type = Discorb::ApplicationCommand::Command.types[type]
173
- @type_raw = type
174
- @id_map = Discorb::Dictionary.new
175
- end
176
-
177
- # @private
178
- def replace_block(instance)
179
- current_block = @block.dup
180
- @block = Proc.new do |*args|
181
- instance.instance_exec(*args, &current_block)
182
- end
183
- end
184
-
185
- # @private
186
- def to_hash
187
- {
188
- name: @name,
189
- default_permission: @default_permission,
190
- type: @type_raw,
191
- }
192
- end
193
-
194
- #
195
- # Represents the slash command.
196
- #
197
- class SlashCommand < Command
198
- # @return [String] The description of the command.
199
- attr_reader :description
200
- # @return [Hash{String => Hash}] The options of the command.
201
- attr_reader :options
202
-
203
- # @private
204
- def initialize(name, description, options, guild_ids, block, type, parent)
205
- super(name, guild_ids, block, type)
206
- @description = description
207
- @options = options
208
- @id = nil
209
- @parent = parent
210
- @id_map = Discorb::Dictionary.new
211
- end
212
-
213
- #
214
- # Returns the commands name.
215
- #
216
- # @return [String] The name of the command.
217
- #
218
- def to_s
219
- (@parent + " " + @name).strip
220
- end
221
-
222
- # @private
223
- def to_hash
224
- options_payload = options.map do |name, value|
225
- ret = {
226
- type: case value[:type]
227
- when String, :string, :str
228
- 3
229
- when Integer, :integer, :int
230
- 4
231
- when TrueClass, FalseClass, :boolean, :bool
232
- 5
233
- when Discorb::User, Discorb::Member, :user, :member
234
- 6
235
- when Discorb::Channel, :channel
236
- 7
237
- when Discorb::Role, :role
238
- 8
239
- when :mentionable
240
- 9
241
- when Float, :float
242
- 10
243
- else
244
- raise ArgumentError, "Invalid option type: #{value[:type]}"
245
- end,
246
- name: name,
247
- description: value[:description],
248
- required: value[:required].nil? ? !value[:optional] : value[:required],
249
- }
250
-
251
- ret[:choices] = value[:choices].map { |t| { name: t[0], value: t[1] } } if value[:choices]
252
-
253
- ret[:channel_types] = value[:channel_types].map(&:channel_type) if value[:channel_types]
254
-
255
- ret[:autocomplete] = !!value[:autocomplete] if value[:autocomplete]
256
- if value[:range]
257
- ret[:min_value] = value[:range].begin
258
- ret[:max_value] = value[:range].end
259
- end
260
- ret
261
- end
262
- {
263
- name: @name,
264
- default_permission: true,
265
- description: @description,
266
- options: options_payload,
267
- }
268
- end
269
- end
270
-
271
- #
272
- # Represents the command with subcommands.
273
- #
274
- class GroupCommand < Command
275
- # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand, Discorb::ApplicationCommand::Command::SubcommandGroup>] The subcommands of the command.
276
- attr_reader :commands
277
- # @return [String] The description of the command.
278
- attr_reader :description
279
-
280
- # @private
281
- def initialize(name, description, guild_ids, type, client)
282
- super(name, guild_ids, block, type)
283
- @description = description
284
- @commands = []
285
- @client = client
286
- @id_map = Discorb::Dictionary.new
287
- end
288
-
289
- #
290
- # Add new subcommand.
291
- #
292
- # @param (see Discorb::ApplicationCommand::Handler#slash)
293
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] The added subcommand.
294
- #
295
- def slash(command_name, description, options = {}, &block)
296
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, [], block, 1, @name)
297
- @client.bottom_commands << command
298
- @commands << command
299
- command
300
- end
301
-
302
- #
303
- # Add new subcommand group.
304
- #
305
- # @param [String] command_name Group name.
306
- # @param [String] description Group description.
307
- #
308
- # @yield Block to yield with the command.
309
- # @yieldparam [Discorb::ApplicationCommand::Command::SubcommandGroup] group Group command.
310
- #
311
- # @return [Discorb::ApplicationCommand::Command::SubcommandGroup] Command object.
312
- #
313
- # @see file:docs/application_command.md Application Commands
314
- #
315
- def group(command_name, description, &block)
316
- command = Discorb::ApplicationCommand::Command::SubcommandGroup.new(command_name, description, @name, @client)
317
- command.yield_self(&block) if block_given?
318
- @commands << command
319
- command
320
- end
321
-
322
- #
323
- # Returns the command name.
324
- #
325
- # @return [String] The command name.
326
- #
327
- def to_s
328
- @name
329
- end
330
-
331
- # @private
332
- def block_replace(instance)
333
- super
334
- @commands.each { |c| c.replace_block(instance) }
335
- end
336
-
337
- # @private
338
- def to_hash
339
- options_payload = @commands.map do |command|
340
- if command.is_a?(SlashCommand)
341
- {
342
- name: command.name,
343
- description: command.description,
344
- default_permission: true,
345
- type: 1,
346
- options: command.to_hash[:options],
347
- }
348
- else
349
- {
350
- name: command.name,
351
- description: command.description,
352
- default_permission: true,
353
- type: 2,
354
- options: command.commands.map { |c| c.to_hash.merge(type: 1) },
355
- }
356
- end
357
- end
358
-
359
- {
360
- name: @name,
361
- default_permission: @enabled,
362
- description: @description,
363
- options: options_payload,
364
- }
365
- end
366
- end
367
-
368
- #
369
- # Represents the subcommand group.
370
- #
371
- class SubcommandGroup < GroupCommand
372
- # @return [Array<Discorb::ApplicationCommand::Command::SlashCommand>] The subcommands of the command.
373
- attr_reader :commands
374
-
375
- # @private
376
- def initialize(name, description, parent, client)
377
- super(name, description, [], 1, client)
378
-
379
- @commands = []
380
- @parent = parent
381
- end
382
-
383
- def to_s
384
- @parent + " " + @name
385
- end
386
-
387
- #
388
- # Add new subcommand.
389
- # @param (see Discorb::ApplicationCommand::Handler#slash)
390
- # @return [Discorb::ApplicationCommand::Command::SlashCommand] The added subcommand.
391
- #
392
- def slash(command_name, description, options = {}, &block)
393
- command = Discorb::ApplicationCommand::Command::SlashCommand.new(command_name, description, options, [], block, 1, @parent + " " + @name)
394
- @commands << command
395
- @client.bottom_commands << command
396
- command
397
- end
398
- end
399
-
400
- class << self
401
- # @private
402
- attr_reader :types
403
- end
404
- end
405
- end
2
+ %w[command handler].each do |file|
3
+ require_relative "app_command/#{file}.rb"
406
4
  end
data/lib/discorb/asset.rb CHANGED
@@ -47,7 +47,7 @@ module Discorb
47
47
  "avatars"
48
48
  when Guild, IncomingWebhook::Guild
49
49
  "icons"
50
- when Application
50
+ when Application, Integration::Application
51
51
  "app-icons"
52
52
  when Application::Team
53
53
  "team-icons"
@@ -80,7 +80,9 @@ module Discorb
80
80
  #
81
81
  # @return [String] URL of the avatar.
82
82
  #
83
+ # rubocop: disable Lint/UnusedMethodArgument
83
84
  def url(image_format: nil, size: 1024)
85
+ # rubocop: enable Lint/UnusedMethodArgument
84
86
  "https://cdn.discordapp.com/embed/avatars/#{@discriminator.to_i % 5}.png"
85
87
  end
86
88
 
@@ -226,7 +226,7 @@ module Discorb
226
226
  # @private
227
227
  #
228
228
  def initialize(data)
229
- @data = data.map { |d| [d[:key].to_sym, d] }.to_h
229
+ @data = data.to_h { |d| [d[:key].to_sym, d] }
230
230
  @data.each do |k, v|
231
231
  define_singleton_method(k) { Change.new(v) }
232
232
  end
@@ -287,8 +287,8 @@ module Discorb
287
287
  else
288
288
  ->(v) { v }
289
289
  end
290
- @old_value = method.(data[:old_value])
291
- @new_value = method.(data[:new_value])
290
+ @old_value = method.call(data[:old_value])
291
+ @new_value = method.call(data[:new_value])
292
292
  end
293
293
 
294
294
  #