onyxcord 1.1.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 (133) hide show
  1. checksums.yaml +7 -0
  2. data/.devcontainer/Dockerfile +13 -0
  3. data/.devcontainer/devcontainer.json +29 -0
  4. data/.devcontainer/postcreate.sh +4 -0
  5. data/.github/CONTRIBUTING.md +13 -0
  6. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  7. data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
  8. data/.github/pull_request_template.md +37 -0
  9. data/.github/workflows/ci.yml +78 -0
  10. data/.github/workflows/codeql.yml +65 -0
  11. data/.github/workflows/deploy.yml +54 -0
  12. data/.github/workflows/release.yml +51 -0
  13. data/.gitignore +16 -0
  14. data/.markdownlint.json +4 -0
  15. data/.overcommit.yml +7 -0
  16. data/.rspec +2 -0
  17. data/.rubocop.yml +129 -0
  18. data/.yardopts +1 -0
  19. data/CHANGELOG.md +0 -0
  20. data/Gemfile +7 -0
  21. data/LICENSE.txt +21 -0
  22. data/README.md +305 -0
  23. data/Rakefile +17 -0
  24. data/bin/console +15 -0
  25. data/bin/setup +7 -0
  26. data/lib/onyxcord/allowed_mentions.rb +43 -0
  27. data/lib/onyxcord/api/application.rb +316 -0
  28. data/lib/onyxcord/api/channel.rb +700 -0
  29. data/lib/onyxcord/api/interaction.rb +67 -0
  30. data/lib/onyxcord/api/invite.rb +44 -0
  31. data/lib/onyxcord/api/server.rb +775 -0
  32. data/lib/onyxcord/api/user.rb +158 -0
  33. data/lib/onyxcord/api/webhook.rb +163 -0
  34. data/lib/onyxcord/api.rb +335 -0
  35. data/lib/onyxcord/await.rb +51 -0
  36. data/lib/onyxcord/bot.rb +1971 -0
  37. data/lib/onyxcord/cache.rb +326 -0
  38. data/lib/onyxcord/colour_rgb.rb +43 -0
  39. data/lib/onyxcord/commands/command_bot.rb +511 -0
  40. data/lib/onyxcord/commands/container.rb +112 -0
  41. data/lib/onyxcord/commands/events.rb +11 -0
  42. data/lib/onyxcord/commands/parser.rb +327 -0
  43. data/lib/onyxcord/commands/rate_limiter.rb +144 -0
  44. data/lib/onyxcord/configuration.rb +125 -0
  45. data/lib/onyxcord/container.rb +988 -0
  46. data/lib/onyxcord/data/activity.rb +271 -0
  47. data/lib/onyxcord/data/application.rb +341 -0
  48. data/lib/onyxcord/data/attachment.rb +91 -0
  49. data/lib/onyxcord/data/audit_logs.rb +438 -0
  50. data/lib/onyxcord/data/avatar_decoration.rb +26 -0
  51. data/lib/onyxcord/data/call.rb +22 -0
  52. data/lib/onyxcord/data/channel.rb +1355 -0
  53. data/lib/onyxcord/data/channel_tag.rb +69 -0
  54. data/lib/onyxcord/data/collectibles.rb +47 -0
  55. data/lib/onyxcord/data/component.rb +583 -0
  56. data/lib/onyxcord/data/embed.rb +258 -0
  57. data/lib/onyxcord/data/emoji.rb +123 -0
  58. data/lib/onyxcord/data/install_params.rb +24 -0
  59. data/lib/onyxcord/data/integration.rb +144 -0
  60. data/lib/onyxcord/data/interaction.rb +1141 -0
  61. data/lib/onyxcord/data/invite.rb +137 -0
  62. data/lib/onyxcord/data/member.rb +528 -0
  63. data/lib/onyxcord/data/message.rb +612 -0
  64. data/lib/onyxcord/data/message_activity.rb +41 -0
  65. data/lib/onyxcord/data/overwrite.rb +109 -0
  66. data/lib/onyxcord/data/poll.rb +365 -0
  67. data/lib/onyxcord/data/primary_server.rb +60 -0
  68. data/lib/onyxcord/data/profile.rb +79 -0
  69. data/lib/onyxcord/data/reaction.rb +64 -0
  70. data/lib/onyxcord/data/recipient.rb +34 -0
  71. data/lib/onyxcord/data/role.rb +449 -0
  72. data/lib/onyxcord/data/role_connection_data.rb +69 -0
  73. data/lib/onyxcord/data/role_subscription.rb +41 -0
  74. data/lib/onyxcord/data/scheduled_event.rb +513 -0
  75. data/lib/onyxcord/data/server.rb +1614 -0
  76. data/lib/onyxcord/data/server_preview.rb +68 -0
  77. data/lib/onyxcord/data/snapshot.rb +112 -0
  78. data/lib/onyxcord/data/team.rb +98 -0
  79. data/lib/onyxcord/data/timestamp.rb +69 -0
  80. data/lib/onyxcord/data/user.rb +324 -0
  81. data/lib/onyxcord/data/voice_region.rb +46 -0
  82. data/lib/onyxcord/data/voice_state.rb +41 -0
  83. data/lib/onyxcord/data/webhook.rb +238 -0
  84. data/lib/onyxcord/data.rb +57 -0
  85. data/lib/onyxcord/errors.rb +246 -0
  86. data/lib/onyxcord/event_executor.rb +80 -0
  87. data/lib/onyxcord/events/await.rb +48 -0
  88. data/lib/onyxcord/events/bans.rb +60 -0
  89. data/lib/onyxcord/events/channels.rb +225 -0
  90. data/lib/onyxcord/events/generic.rb +129 -0
  91. data/lib/onyxcord/events/guilds.rb +269 -0
  92. data/lib/onyxcord/events/integrations.rb +100 -0
  93. data/lib/onyxcord/events/interactions.rb +624 -0
  94. data/lib/onyxcord/events/invites.rb +127 -0
  95. data/lib/onyxcord/events/lifetime.rb +31 -0
  96. data/lib/onyxcord/events/members.rb +110 -0
  97. data/lib/onyxcord/events/message.rb +399 -0
  98. data/lib/onyxcord/events/polls.rb +118 -0
  99. data/lib/onyxcord/events/presence.rb +131 -0
  100. data/lib/onyxcord/events/raw.rb +74 -0
  101. data/lib/onyxcord/events/reactions.rb +218 -0
  102. data/lib/onyxcord/events/roles.rb +87 -0
  103. data/lib/onyxcord/events/scheduled_events.rb +171 -0
  104. data/lib/onyxcord/events/threads.rb +100 -0
  105. data/lib/onyxcord/events/typing.rb +73 -0
  106. data/lib/onyxcord/events/voice_server_update.rb +48 -0
  107. data/lib/onyxcord/events/voice_state_update.rb +106 -0
  108. data/lib/onyxcord/events/webhooks.rb +65 -0
  109. data/lib/onyxcord/gateway.rb +890 -0
  110. data/lib/onyxcord/id_object.rb +39 -0
  111. data/lib/onyxcord/light/data.rb +62 -0
  112. data/lib/onyxcord/light/integrations.rb +73 -0
  113. data/lib/onyxcord/light/light_bot.rb +58 -0
  114. data/lib/onyxcord/light.rb +8 -0
  115. data/lib/onyxcord/logger.rb +120 -0
  116. data/lib/onyxcord/message_components.rb +70 -0
  117. data/lib/onyxcord/paginator.rb +60 -0
  118. data/lib/onyxcord/permissions.rb +255 -0
  119. data/lib/onyxcord/rate_limiter/gateway.rb +42 -0
  120. data/lib/onyxcord/rate_limiter/rest.rb +89 -0
  121. data/lib/onyxcord/version.rb +7 -0
  122. data/lib/onyxcord/voice/encoder.rb +115 -0
  123. data/lib/onyxcord/voice/network.rb +380 -0
  124. data/lib/onyxcord/voice/opcodes.rb +29 -0
  125. data/lib/onyxcord/voice/sodium.rb +157 -0
  126. data/lib/onyxcord/voice/timer.rb +19 -0
  127. data/lib/onyxcord/voice/voice_bot.rb +386 -0
  128. data/lib/onyxcord/webhooks.rb +14 -0
  129. data/lib/onyxcord/websocket.rb +62 -0
  130. data/lib/onyxcord.rb +180 -0
  131. data/onyxcord-webhooks.gemspec +30 -0
  132. data/onyxcord.gemspec +50 -0
  133. metadata +421 -0
@@ -0,0 +1,624 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'onyxcord/events/generic'
4
+ require 'onyxcord/data'
5
+
6
+ module OnyxCord::Events
7
+ # Generic subclass for interaction events
8
+ class InteractionCreateEvent < Event
9
+ # Struct to allow accessing data via [] or methods.
10
+ Resolved = Struct.new('Resolved', :channels, :members, :messages, :roles, :users, :attachments) # rubocop:disable Lint/StructNewOverride
11
+
12
+ # @return [Interaction] The interaction for this event.
13
+ attr_reader :interaction
14
+
15
+ # @!attribute [r] type
16
+ # @return [Integer]
17
+ # @see Interaction#type
18
+ # @!attribute [r] server
19
+ # @return [Server, nil]
20
+ # @see Interaction#server
21
+ # @!attribute [r] server_id
22
+ # @return [Integer]
23
+ # @see Interaction#server_id
24
+ # @!attribute [r] channel
25
+ # @return [Channel]
26
+ # @see Interaction#channel
27
+ # @!attribute [r] channel_id
28
+ # @return [Integer]
29
+ # @see Interaction#channel_id
30
+ # @!attribute [r] user
31
+ # @return [User]
32
+ # @see Interaction#user
33
+ # @!attribute [r] user_locale
34
+ # @return [String]
35
+ # @see Interaction#user_locale
36
+ # @!attribute [r] context
37
+ # @return [Integer]
38
+ # @see Interaction#context
39
+ # @!attribute [r] user_integration?
40
+ # @return [true, false]
41
+ # @see Interaction#user_integration?
42
+ # @!attribute [r] server_integration?
43
+ # @return [true, false]
44
+ # @see Interaction#server_integration?
45
+ delegate :type, :server, :server_id, :channel, :channel_id, :user, :user_locale, :context, :user_integration?, :server_integration?, to: :interaction
46
+
47
+ # @!visibility private
48
+ def initialize(data, bot)
49
+ @bot = bot
50
+ @interaction = OnyxCord::Interaction.new(data, @bot)
51
+ end
52
+
53
+ # @see Interaction#respond
54
+ def respond(...)
55
+ @interaction.respond(...)
56
+ end
57
+
58
+ # @see Interaction#defer
59
+ def defer(...)
60
+ @interaction.defer(...)
61
+ end
62
+
63
+ # @see Interaction#update_message
64
+ def update_message(...)
65
+ @interaction.update_message(...)
66
+ end
67
+
68
+ # @see Interaction#show_modal
69
+ def show_modal(...)
70
+ @interaction.show_modal(...)
71
+ end
72
+
73
+ # @see Interaction#edit_response
74
+ def edit_response(...)
75
+ @interaction.edit_response(...)
76
+ end
77
+
78
+ # @see Interaction#delete_response
79
+ def delete_response
80
+ @interaction.delete_response
81
+ end
82
+
83
+ # @see Interaction#send_message
84
+ def send_message(...)
85
+ @interaction.send_message(...)
86
+ end
87
+
88
+ # @see Interaction#edit_message
89
+ def edit_message(...)
90
+ @interaction.edit_message(...)
91
+ end
92
+
93
+ # @see Interaction#delete_message
94
+ def delete_message(...)
95
+ @interaction.delete_message(...)
96
+ end
97
+
98
+ # @see Interaction#defer_update
99
+ def defer_update
100
+ @interaction.defer_update
101
+ end
102
+
103
+ # @see Interaction#get_component
104
+ def get_component(...)
105
+ @interaction.get_component(...)
106
+ end
107
+
108
+ private
109
+
110
+ # @!visibility private
111
+ def process_resolved(resolved_data)
112
+ resolved_data['users']&.each do |id, data|
113
+ @resolved[:users][id.to_i] = @bot.ensure_user(data)
114
+ end
115
+
116
+ resolved_data['roles']&.each do |id, data|
117
+ @resolved[:roles][id.to_i] = OnyxCord::Role.new(data, @bot)
118
+ end
119
+
120
+ resolved_data['channels']&.each do |id, data|
121
+ data['guild_id'] = @interaction.server_id
122
+ @resolved[:channels][id.to_i] = OnyxCord::Channel.new(data, @bot)
123
+ end
124
+
125
+ resolved_data['members']&.each do |id, data|
126
+ data['user'] = resolved_data['users'][id]
127
+ data['guild_id'] = @interaction.server_id
128
+ @resolved[:members][id.to_i] = OnyxCord::Member.new(data, nil, @bot)
129
+ end
130
+
131
+ resolved_data['messages']&.each do |id, data|
132
+ @resolved[:messages][id.to_i] = OnyxCord::Message.new(data, @bot)
133
+ end
134
+
135
+ resolved_data['attachments']&.each do |id, data|
136
+ @resolved[:attachments][id.to_i] = OnyxCord::Attachment.new(data, nil, @bot)
137
+ end
138
+ end
139
+ end
140
+
141
+ # Event handler for INTERACTION_CREATE events.
142
+ class InteractionCreateEventHandler < EventHandler
143
+ # @!visibility private
144
+ def matches?(event)
145
+ return false unless event.is_a? InteractionCreateEvent
146
+
147
+ [
148
+ matches_all(@attributes[:type], event.type) do |a, e|
149
+ a == case a
150
+ when String, Symbol
151
+ OnyxCord::Interactions::TYPES[e.to_sym]
152
+ else
153
+ e
154
+ end
155
+ end,
156
+
157
+ matches_all(@attributes[:server], event.interaction) do |a, e|
158
+ a.resolve_id == e.server_id
159
+ end,
160
+
161
+ matches_all(@attributes[:channel], event.interaction) do |a, e|
162
+ a.resolve_id == e.channel_id
163
+ end,
164
+
165
+ matches_all(@attributes[:user], event.user) do |a, e|
166
+ a.resolve_id == e.id
167
+ end
168
+ ].reduce(true, &:&)
169
+ end
170
+ end
171
+
172
+ # Event for ApplicationCommand interactions.
173
+ class ApplicationCommandEvent < InteractionCreateEvent
174
+ # @return [Symbol] The name of the command.
175
+ attr_reader :command_name
176
+
177
+ # @return [Integer] The ID of the command.
178
+ attr_reader :command_id
179
+
180
+ # @return [Symbol, nil] The name of the subcommand group relevant to this event.
181
+ attr_reader :subcommand_group
182
+
183
+ # @return [Symbol, nil] The name of the subcommand relevant to this event.
184
+ attr_reader :subcommand
185
+
186
+ # @return [Resolved] The resolved channels, roles, users, members, and attachments for this event.
187
+ attr_reader :resolved
188
+
189
+ # @return [Hash<Symbol, Object>] Arguments provided to the command, mapped as `Name => Value`.
190
+ attr_reader :options
191
+
192
+ # @return [Integer, nil] The target of this command when it is a context command.
193
+ attr_reader :target_id
194
+
195
+ # @!visibility private
196
+ def initialize(data, bot)
197
+ super
198
+
199
+ command_data = data['data']
200
+
201
+ @command_id = command_data['id'].to_i
202
+ @command_name = command_data['name'].to_sym
203
+ @command_server_id = command_data['guild_id']
204
+
205
+ @target_id = command_data['target_id']&.to_i
206
+ @resolved = Resolved.new({}, {}, {}, {}, {}, {})
207
+ process_resolved(command_data['resolved']) if command_data['resolved']
208
+
209
+ options = command_data['options'] || []
210
+
211
+ if options.empty?
212
+ @options = {}
213
+ return
214
+ end
215
+
216
+ case options[0]['type']
217
+ when 2
218
+ options = options[0]
219
+ @subcommand_group = options['name'].to_sym
220
+ @subcommand = options['options'][0]['name'].to_sym
221
+ options = options['options'][0]['options']
222
+ when 1
223
+ options = options[0]
224
+ @subcommand = options['name'].to_sym
225
+ options = options['options']
226
+ end
227
+
228
+ @options = transform_options_hash(options || {})
229
+ end
230
+
231
+ # @return [true, false] Whether or not the application command that was executed
232
+ # has been registered globally. If this is false, then the application command
233
+ # that was executed is only available in the invoking server.
234
+ def global_command?
235
+ @command_server_id.nil?
236
+ end
237
+
238
+ # @return [Message, User, nil] The target of this command, for context commands.
239
+ def target
240
+ return nil unless @target_id
241
+
242
+ @resolved.find { |data| data.key?(@target_id) }[@target_id]
243
+ end
244
+
245
+ private
246
+
247
+ def transform_options_hash(hash)
248
+ hash.to_h { |opt| [opt['name'], opt['options'] || opt['value']] }
249
+ end
250
+ end
251
+
252
+ # Event handler for ApplicationCommandEvents.
253
+ class ApplicationCommandEventHandler < EventHandler
254
+ # @return [Hash]
255
+ attr_reader :subcommands
256
+
257
+ # @!visibility private
258
+ def initialize(attributes, block)
259
+ super
260
+
261
+ @subcommands = {}
262
+ end
263
+
264
+ # @param name [Symbol, String]
265
+ # @yieldparam [SubcommandBuilder]
266
+ # @return [ApplicationCommandEventHandler]
267
+ def group(name)
268
+ raise ArgumentError, 'Unable to mix subcommands and groups' if @subcommands.any? { |n, v| n == name && v.is_a?(Proc) }
269
+
270
+ builder = SubcommandBuilder.new(name)
271
+ yield builder
272
+
273
+ @subcommands.merge!(builder.to_h)
274
+ self
275
+ end
276
+
277
+ # @param name [String, Symbol]
278
+ # @yieldparam [SubcommandBuilder]
279
+ # @return [ApplicationCommandEventHandler]
280
+ def subcommand(name, &block)
281
+ raise ArgumentError, 'Unable to mix subcommands and groups' if @subcommands.any? { |n, v| n == name && v.is_a?(Hash) }
282
+
283
+ @subcommands[name.to_sym] = block
284
+
285
+ self
286
+ end
287
+
288
+ # @!visibility private
289
+ # @param event [Event]
290
+ def call(event)
291
+ return unless matches?(event)
292
+
293
+ if event.subcommand_group
294
+ unless (cmd = @subcommands.dig(event.subcommand_group, event.subcommand))
295
+ OnyxCord::LOGGER.debug("Received an event for an unhandled subcommand `#{event.command_name} #{event.subcommand_group} #{event.subcommand}'")
296
+ return
297
+ end
298
+
299
+ cmd.call(event)
300
+ elsif event.subcommand
301
+ unless (cmd = @subcommands[event.subcommand])
302
+ OnyxCord::LOGGER.debug("Received an event for an unhandled subcommand `#{event.command_name} #{event.subcommand}'")
303
+ return
304
+ end
305
+
306
+ cmd.call(event)
307
+ else
308
+ @block.call(event)
309
+ end
310
+ end
311
+
312
+ # @!visibility private
313
+ def matches?(event)
314
+ return false unless event.is_a? ApplicationCommandEvent
315
+
316
+ [
317
+ matches_all(@attributes[:name], event.command_name) do |a, e|
318
+ a.to_sym == e.to_sym
319
+ end
320
+ ].reduce(true, &:&)
321
+ end
322
+ end
323
+
324
+ # Builder for adding subcommands to an ApplicationCommandHandler
325
+ class SubcommandBuilder
326
+ # @!visibility private
327
+ # @param group [String, Symbol, nil]
328
+ def initialize(group = nil)
329
+ @group = group&.to_sym
330
+ @subcommands = {}
331
+ end
332
+
333
+ # @param name [Symbol, String]
334
+ # @yieldparam [ApplicationCommandEvent]
335
+ def subcommand(name, &block)
336
+ @subcommands[name.to_sym] = block
337
+ end
338
+
339
+ # @!visibility private
340
+ def to_h
341
+ @group ? { @group => @subcommands } : @subcommands
342
+ end
343
+ end
344
+
345
+ # An event for when a user interacts with a component.
346
+ class ComponentEvent < InteractionCreateEvent
347
+ # @return [String] User provided data for this button.
348
+ attr_reader :custom_id
349
+
350
+ # @return [Interactions::Message, nil] The message the button originates from.
351
+ attr_reader :message
352
+
353
+ # @!visibility private
354
+ def initialize(data, bot)
355
+ super
356
+
357
+ @message = @interaction.message
358
+ @custom_id = data['data']['custom_id']
359
+ end
360
+ end
361
+
362
+ # Generic handler for component events.
363
+ class ComponentEventHandler < InteractionCreateEventHandler
364
+ def matches?(event)
365
+ return false unless super
366
+ return false unless event.is_a? ComponentEvent
367
+
368
+ [
369
+ matches_all(@attributes[:custom_id], event.custom_id) do |a, e|
370
+ # Match regexp and strings
371
+ case a
372
+ when Regexp
373
+ a.match?(e)
374
+ else
375
+ a == e
376
+ end
377
+ end,
378
+ matches_all(@attributes[:message], event.message) do |a, e|
379
+ case a
380
+ when String, Integer
381
+ a.resolve_id == e.id
382
+ else
383
+ a.id == e.id
384
+ end
385
+ end
386
+ ].reduce(&:&)
387
+ end
388
+ end
389
+
390
+ # An event for when a user interacts with a button component.
391
+ class ButtonEvent < ComponentEvent
392
+ end
393
+
394
+ # Event handler for a Button interaction event.
395
+ class ButtonEventHandler < ComponentEventHandler
396
+ end
397
+
398
+ # Event for when a user interacts with a select string component.
399
+ class StringSelectEvent < ComponentEvent
400
+ # @return [Array<String>] Selected values.
401
+ attr_reader :values
402
+
403
+ # @!visibility private
404
+ def initialize(data, bot)
405
+ super
406
+
407
+ @values = data['data']['values']
408
+ end
409
+ end
410
+
411
+ # Event handler for a select string component.
412
+ class StringSelectEventHandler < ComponentEventHandler
413
+ end
414
+
415
+ # An event for when a user submits a modal.
416
+ class ModalSubmitEvent < ComponentEvent
417
+ # @return [Array<Component>] an array of partial component objects that were in the modal.
418
+ attr_reader :components
419
+
420
+ # @return [Resolved] The resolved channels, roles, users, members, and attachments for the modal.
421
+ attr_reader :resolved
422
+
423
+ # @!visibility private
424
+ def initialize(data, bot)
425
+ super
426
+
427
+ @components = @interaction.components
428
+ @resolved = Resolved.new({}, {}, {}, {}, {}, {})
429
+ process_resolved(data['data']['resolved']) if data['data']['resolved']
430
+ end
431
+
432
+ # Get the value of an input passed to the modal.
433
+ # @param custom_id [String] The custom ID of the component to look for.
434
+ # @return [String, nil] The selected value for the component.
435
+ def value(custom_id)
436
+ get_component(custom_id)&.value
437
+ end
438
+
439
+ # Get the selected values from a select menu or file upload component.
440
+ # @param custom_id [String] The custom ID of the component to look for.
441
+ # @return [Array<String>, nil] The values that were chosen for the component.
442
+ def values(custom_id)
443
+ get_component(custom_id)&.values
444
+ end
445
+
446
+ # Get the attachments that a user uploaded in this modal.
447
+ # @param custom_id [String] The custom ID of the file upload component to get attachments for.
448
+ # @return [Array<Attachment>] the attachments that were uploaded to the file upload component.
449
+ def attachments(custom_id)
450
+ values(custom_id)&.map { |id| @resolved[:attachments][id.to_i] } || []
451
+ end
452
+ end
453
+
454
+ # Event handler for a modal submission.
455
+ class ModalSubmitEventHandler < ComponentEventHandler
456
+ end
457
+
458
+ # Event for when a user interacts with a select user component.
459
+ class UserSelectEvent < ComponentEvent
460
+ # @return [Array<User>] Selected values.
461
+ attr_reader :values
462
+
463
+ # @!visibility private
464
+ def initialize(data, bot)
465
+ super
466
+
467
+ @values = data['data']['values'].map { |e| bot.user(e) }
468
+ end
469
+ end
470
+
471
+ # Event handler for a select user component.
472
+ class UserSelectEventHandler < ComponentEventHandler
473
+ end
474
+
475
+ # Event for when a user interacts with a select role component.
476
+ class RoleSelectEvent < ComponentEvent
477
+ # @return [Array<Role>] Selected values.
478
+ attr_reader :values
479
+
480
+ # @!visibility private
481
+ def initialize(data, bot)
482
+ super
483
+
484
+ @values = data['data']['values'].map { |e| bot.server(data['guild_id']).role(e) }
485
+ end
486
+ end
487
+
488
+ # Event handler for a select role component.
489
+ class RoleSelectEventHandler < ComponentEventHandler
490
+ end
491
+
492
+ # Event for when a user interacts with a select mentionable component.
493
+ class MentionableSelectEvent < ComponentEvent
494
+ # @return [Hash<Symbol => Array<User>, Symbol => Array<Role>>] Selected values.
495
+ attr_reader :values
496
+
497
+ # @!visibility private
498
+ def initialize(data, bot)
499
+ super
500
+
501
+ users = data['data']['resolved']['users'].map { |_, user| @bot.ensure_user(user) }
502
+ roles = data['data']['resolved']['roles'] ? data['data']['resolved']['roles'].keys.map { |e| bot.server(data['guild_id']).role(e) } : []
503
+ @values = { users: users, roles: roles }
504
+ end
505
+ end
506
+
507
+ # Event handler for a select mentionable component.
508
+ class MentionableSelectEventHandler < ComponentEventHandler
509
+ end
510
+
511
+ # Event for when a user interacts with a select channel component.
512
+ class ChannelSelectEvent < ComponentEvent
513
+ # @return [Array<Channel>] Selected values.
514
+ attr_reader :values
515
+
516
+ # @!visibility private
517
+ def initialize(data, bot)
518
+ super
519
+
520
+ @values = data['data']['values'].map { |e| bot.channel(e, bot.server(data['guild_id'])) }
521
+ end
522
+ end
523
+
524
+ # Event handler for a select channel component.
525
+ class ChannelSelectEventHandler < ComponentEventHandler
526
+ end
527
+
528
+ # Event handler for an autocomplete option choices.
529
+ class AutocompleteEventHandler < InteractionCreateEventHandler
530
+ def matches?(event)
531
+ return false unless super
532
+ return false unless event.is_a?(AutocompleteEvent)
533
+
534
+ [
535
+ matches_all(@attributes[:name], event.focused) { |a, e| a == e },
536
+ matches_all(@attributes[:command_id], event.command_id) { |a, e| a&.to_i == e },
537
+ matches_all(@attributes[:subcommand], event.subcommand) { |a, e| a&.to_sym == e },
538
+ matches_all(@attributes[:command_name], event.command_name) { |a, e| a&.to_sym == e },
539
+ matches_all(@attributes[:subcommand_group], event.subcommand_group) { |a, e| a&.to_sym == e },
540
+ matches_all(@attributes[:server], event.server_id) { |a, e| a&.resolve_id == e }
541
+ ].reduce(&:&)
542
+ end
543
+ end
544
+
545
+ # An event for an autocomplete option choice.
546
+ class AutocompleteEvent < ApplicationCommandEvent
547
+ # @return [String] Name of the currently focused option.
548
+ attr_reader :focused
549
+
550
+ # @return [Hash] An empty hash that can be used to return choices by adding K/V pairs.
551
+ attr_reader :choices
552
+
553
+ # @!visibility private
554
+ def initialize(data, bot)
555
+ super
556
+
557
+ @choices = {}
558
+
559
+ options = data['data']['options']
560
+
561
+ options = case options[0]['type']
562
+ when 1
563
+ options[0]['options']
564
+ when 2
565
+ options[0]['options'][0]['options']
566
+ else
567
+ options
568
+ end
569
+
570
+ @focused = options.find { |opt| opt.key?('focused') }['name']
571
+ end
572
+
573
+ # Respond to this interaction with autocomplete choices.
574
+ # @param choices [Array<Hash>, Hash, nil] Autocomplete choices to return.
575
+ def respond(choices:)
576
+ @interaction.show_autocomplete_choices(choices || [])
577
+ end
578
+ end
579
+
580
+ # An event for whenever an application command's permissions are updated.
581
+ class ApplicationCommandPermissionsUpdateEvent < Event
582
+ # @return [Integer] the ID of the server where the command permissions were updated.
583
+ attr_reader :server_id
584
+
585
+ # @return [Integer, nil] the ID of the application command that was updated.
586
+ attr_reader :command_id
587
+
588
+ # @return [Array<ApplicationCommand::Permission>] the permissions that were updated.
589
+ attr_reader :permissions
590
+
591
+ # @return [Integer] the ID of the application whose commands were updated.
592
+ attr_reader :application_id
593
+
594
+ # @!visibility private
595
+ def initialize(data, bot)
596
+ @bot = bot
597
+ @server_id = data['guild_id'].to_i
598
+ @application_id = data['application_id'].to_i
599
+ @command_id = data['id'].to_i if data['id'].to_i != @application_id
600
+ @permissions = data['permissions'].map do |permission|
601
+ OnyxCord::ApplicationCommand::Permission.new(permission, data, bot)
602
+ end
603
+ end
604
+
605
+ # @return [Server] the server where the command's permissions were updated.
606
+ def server
607
+ @bot.server(@server_id)
608
+ end
609
+ end
610
+
611
+ # Event handler for the APPLICATION_COMMAND_PERMISSIONS_UPDATE event.
612
+ class ApplicationCommandPermissionsUpdateEventHandler < EventHandler
613
+ # @!visibility private
614
+ def matches?(event)
615
+ return false unless event.is_a?(ApplicationCommandPermissionsUpdateEvent)
616
+
617
+ [
618
+ matches_all(@attributes[:server], event.server_id) { |a, e| a.resolve_id == e },
619
+ matches_all(@attributes[:command_id], event.command_id) { |a, e| a.resolve_id == e },
620
+ matches_all(@attributes[:application_id], event.application_id) { |a, e| a.resolve_id == e }
621
+ ].reduce(&:&)
622
+ end
623
+ end
624
+ end