discorb 0.17.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint.yml +1 -3
  3. data/.github/workflows/validate.yml +21 -0
  4. data/Changelog.md +25 -0
  5. data/Gemfile +6 -0
  6. data/README.md +2 -1
  7. data/Rakefile +205 -98
  8. data/Steepfile +30 -0
  9. data/docs/application_command.md +1 -0
  10. data/docs/events.md +44 -8
  11. data/docs/tutorial.md +7 -7
  12. data/docs/voice_events.md +8 -8
  13. data/examples/commands/message.rb +12 -7
  14. data/examples/commands/permission.rb +2 -1
  15. data/examples/commands/slash.rb +23 -19
  16. data/examples/commands/user.rb +15 -12
  17. data/examples/components/authorization_button.rb +2 -1
  18. data/examples/components/select_menu.rb +4 -1
  19. data/examples/extension/main.rb +1 -0
  20. data/examples/extension/message_expander.rb +1 -0
  21. data/examples/sig/commands/message.rbs +5 -0
  22. data/examples/simple/eval.rb +1 -0
  23. data/examples/simple/ping_pong.rb +1 -0
  24. data/examples/simple/rolepanel.rb +16 -5
  25. data/examples/simple/shard.rb +2 -1
  26. data/examples/simple/wait_for_message.rb +3 -0
  27. data/exe/discorb +3 -3
  28. data/lib/discorb/allowed_mentions.rb +1 -1
  29. data/lib/discorb/app_command/command.rb +16 -13
  30. data/lib/discorb/app_command/handler.rb +21 -6
  31. data/lib/discorb/audit_logs.rb +6 -2
  32. data/lib/discorb/automod.rb +269 -0
  33. data/lib/discorb/channel/guild.rb +5 -4
  34. data/lib/discorb/channel/stage.rb +1 -1
  35. data/lib/discorb/channel/text.rb +14 -23
  36. data/lib/discorb/channel/thread.rb +15 -11
  37. data/lib/discorb/client.rb +15 -15
  38. data/lib/discorb/color.rb +37 -60
  39. data/lib/discorb/common.rb +1 -1
  40. data/lib/discorb/dictionary.rb +1 -1
  41. data/lib/discorb/embed.rb +5 -4
  42. data/lib/discorb/emoji.rb +4 -4
  43. data/lib/discorb/event.rb +2 -2
  44. data/lib/discorb/exe/about.rb +1 -1
  45. data/lib/discorb/exe/new.rb +1 -5
  46. data/lib/discorb/extension.rb +0 -4
  47. data/lib/discorb/flag.rb +2 -2
  48. data/lib/discorb/gateway.rb +38 -589
  49. data/lib/discorb/gateway_events.rb +638 -0
  50. data/lib/discorb/guild.rb +138 -19
  51. data/lib/discorb/guild_template.rb +3 -3
  52. data/lib/discorb/http.rb +47 -25
  53. data/lib/discorb/integration.rb +2 -2
  54. data/lib/discorb/intents.rb +27 -18
  55. data/lib/discorb/interaction/command.rb +14 -10
  56. data/lib/discorb/interaction/response.rb +150 -84
  57. data/lib/discorb/interaction/root.rb +139 -0
  58. data/lib/discorb/invite.rb +1 -1
  59. data/lib/discorb/member.rb +3 -3
  60. data/lib/discorb/message.rb +17 -15
  61. data/lib/discorb/message_meta.rb +2 -3
  62. data/lib/discorb/modules.rb +5 -4
  63. data/lib/discorb/permission.rb +3 -1
  64. data/lib/discorb/presence.rb +4 -2
  65. data/lib/discorb/reaction.rb +2 -2
  66. data/lib/discorb/role.rb +3 -3
  67. data/lib/discorb/shard.rb +1 -1
  68. data/lib/discorb/sticker.rb +5 -5
  69. data/lib/discorb/user.rb +2 -2
  70. data/lib/discorb/voice_state.rb +8 -8
  71. data/lib/discorb/webhook.rb +20 -11
  72. data/lib/discorb.rb +2 -2
  73. data/rbs_collection.lock.yaml +88 -96
  74. data/rbs_collection.yaml +21 -17
  75. data/sig/async.rbs +11 -5
  76. data/sig/discorb/activity.rbs +24 -0
  77. data/sig/discorb/allowed_mentions.rbs +45 -0
  78. data/sig/discorb/app_command/base.rbs +288 -0
  79. data/sig/discorb/app_command/handler.rbs +171 -0
  80. data/sig/discorb/application.rbs +146 -0
  81. data/sig/discorb/asset.rbs +34 -0
  82. data/sig/discorb/attachment.rbs +99 -0
  83. data/sig/discorb/audit_log.rbs +238 -0
  84. data/sig/discorb/automod.rbs +145 -0
  85. data/sig/discorb/avatar.rbs +27 -0
  86. data/sig/discorb/channel/base.rbs +186 -0
  87. data/sig/discorb/channel/category.rbs +57 -0
  88. data/sig/discorb/channel/container.rbs +33 -0
  89. data/sig/discorb/channel/dm.rbs +14 -0
  90. data/sig/discorb/channel/news.rbs +20 -0
  91. data/sig/discorb/channel/stage.rbs +81 -0
  92. data/sig/discorb/channel/text.rbs +158 -0
  93. data/sig/discorb/channel/thread.rbs +196 -0
  94. data/sig/discorb/channel/voice.rbs +43 -0
  95. data/sig/discorb/client.rbs +2496 -0
  96. data/sig/discorb/color.rbs +148 -0
  97. data/sig/discorb/component/base.rbs +29 -0
  98. data/sig/discorb/component/button.rbs +67 -0
  99. data/sig/discorb/component/select_menu.rbs +111 -0
  100. data/sig/discorb/component/text_input.rbs +70 -0
  101. data/sig/discorb/connectable.rbs +8 -0
  102. data/sig/discorb/custom_emoji.rbs +94 -0
  103. data/sig/discorb/dictionary.rbs +87 -0
  104. data/sig/discorb/discord_model.rbs +17 -0
  105. data/sig/discorb/embed.rbs +286 -0
  106. data/sig/discorb/emoji.rbs +14 -0
  107. data/sig/discorb/error.rbs +73 -0
  108. data/sig/discorb/event_handler.rbs +28 -0
  109. data/sig/discorb/extension.rbs +1735 -0
  110. data/sig/discorb/flag.rbs +74 -0
  111. data/sig/discorb/gateway.rbs +486 -0
  112. data/sig/discorb/guild.rbs +872 -0
  113. data/sig/discorb/guild_template.rbs +174 -0
  114. data/sig/discorb/http.rbs +150 -0
  115. data/sig/discorb/image.rbs +22 -0
  116. data/sig/discorb/integration.rbs +118 -0
  117. data/sig/discorb/intents.rbs +98 -0
  118. data/sig/discorb/interaction/autocomplete.rbs +9 -0
  119. data/sig/discorb/interaction/base.rbs +102 -0
  120. data/sig/discorb/interaction/command.rbs +66 -0
  121. data/sig/discorb/interaction/message_component.rbs +139 -0
  122. data/sig/discorb/interaction/modal.rbs +49 -0
  123. data/sig/discorb/interaction/responder.rbs +157 -0
  124. data/sig/discorb/invite.rbs +86 -0
  125. data/sig/discorb/member.rbs +189 -0
  126. data/sig/discorb/message.rbs +474 -0
  127. data/sig/discorb/messageable.rbs +150 -0
  128. data/sig/discorb/partial_emoji.rbs +38 -0
  129. data/sig/discorb/permissions.rbs +156 -0
  130. data/sig/discorb/presence.rbs +239 -0
  131. data/sig/discorb/reaction.rbs +37 -0
  132. data/sig/discorb/role.rbs +151 -0
  133. data/sig/discorb/scheduled_event.rbs +149 -0
  134. data/sig/discorb/shard.rbs +63 -0
  135. data/sig/discorb/snowflake.rbs +58 -0
  136. data/sig/discorb/stage_instance.rbs +69 -0
  137. data/sig/discorb/sticker.rbs +116 -0
  138. data/sig/discorb/system_channel_flag.rbs +17 -0
  139. data/sig/discorb/unicode_emoji.rbs +53 -0
  140. data/sig/discorb/user.rbs +95 -0
  141. data/sig/discorb/utils.rbs +8 -0
  142. data/sig/discorb/voice_region.rbs +30 -0
  143. data/sig/discorb/voice_state.rbs +71 -0
  144. data/sig/discorb/webhook.rbs +338 -0
  145. data/sig/discorb/welcome_screen.rbs +79 -0
  146. data/sig/discorb.rbs +5 -8661
  147. data/sig/manifest.yaml +3 -0
  148. data/sig/override.rbs +21 -0
  149. metadata +80 -3
@@ -9,6 +9,8 @@ module Discorb
9
9
  # A module for response with source.
10
10
  #
11
11
  module SourceResponder
12
+ # @type instance: Discorb::Interaction
13
+
12
14
  #
13
15
  # Response with `DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE`(`5`).
14
16
  #
@@ -46,6 +48,8 @@ module Discorb
46
48
  # @param [Discorb::Embed] embed The embed to send.
47
49
  # @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
48
50
  # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
51
+ # @param [Discorb::Attachment] attachment The attachment to send.
52
+ # @param [Array<Discorb::Attachment>] attachments The attachments to send. (max: 10)
49
53
  # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
50
54
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
51
55
  #
@@ -58,6 +62,8 @@ module Discorb
58
62
  embed: nil,
59
63
  embeds: nil,
60
64
  allowed_mentions: nil,
65
+ attachment: nil,
66
+ attachments: nil,
61
67
  components: nil,
62
68
  ephemeral: false
63
69
  )
@@ -70,23 +76,48 @@ module Discorb
70
76
  allowed_mentions&.to_hash(@client.allowed_mentions) || @client.allowed_mentions.to_hash
71
77
  payload[:components] = Component.to_payload(components) if components
72
78
  payload[:flags] = (ephemeral ? 1 << 6 : 0)
79
+ attachments ||= attachment ? [attachment] : []
80
+
81
+ payload[:attachments] = attachments.map.with_index do |a, i|
82
+ {
83
+ id: i,
84
+ filename: a.filename,
85
+ description: a.description,
86
+ }
87
+ end
73
88
 
74
89
  ret = if @responded
75
- _resp, data = @client.http.request(
76
- Route.new("/webhooks/#{@application_id}/#{@token}", "//webhooks/:webhook_id/:token", :post), payload
90
+ _resp, data = @client.http.multipart_request(
91
+ Route.new(
92
+ "/webhooks/#{@application_id}/#{@token}",
93
+ "//webhooks/:webhook_id/:token",
94
+ :post
95
+ ),
96
+ payload,
97
+ attachments
77
98
  ).wait
78
99
  webhook = Webhook::URLWebhook.new("/webhooks/#{@application_id}/#{@token}")
79
100
  Webhook::Message.new(webhook, data, @client)
80
101
  elsif @defered
81
- @client.http.request(
82
- Route.new("/webhooks/#{@application_id}/#{@token}/messages/@original",
83
- "//webhooks/:webhook_id/:token/messages/@original", :patch), payload
102
+ @client.http.multipart_request(
103
+ Route.new(
104
+ "/webhooks/#{@application_id}/#{@token}/messages/@original",
105
+ "//webhooks/:webhook_id/:token/messages/@original",
106
+ :patch
107
+ ),
108
+ payload,
109
+ attachments
84
110
  ).wait
85
111
  CallbackMessage.new(@client, payload, @application_id, @token)
86
112
  else
87
- @client.http.request(
88
- Route.new("/interactions/#{@id}/#{@token}/callback", "//interactions/:interaction_id/:token/callback",
89
- :post), { type: 4, data: payload }
113
+ @client.http.multipart_request(
114
+ Route.new(
115
+ "/interactions/#{@id}/#{@token}/callback",
116
+ "//interactions/:interaction_id/:token/callback",
117
+ :post
118
+ ),
119
+ { type: 4, data: payload },
120
+ attachments
90
121
  ).wait
91
122
  CallbackMessage.new(@client, payload, @application_id, @token)
92
123
  end
@@ -94,81 +125,86 @@ module Discorb
94
125
  ret
95
126
  end
96
127
  end
128
+ end
97
129
 
130
+ #
131
+ # Represents of a callback message of interaction.
132
+ #
133
+ class CallbackMessage
98
134
  #
99
- # Represents of a callback message of interaction.
100
- #
101
- class CallbackMessage
102
- #
103
- # Initializes a new instance of CallbackMessage.
104
- # @private
105
- #
106
- # @param [Client] client The client.
107
- # @param [Hash] data The payload.
108
- # @param [String] application_id The application ID.
109
- # @param [String] token The token.
110
- #
111
- def initialize(client, data, application_id, token)
112
- @client = client
113
- @data = data
114
- @application_id = application_id
115
- @token = token
116
- end
135
+ # Initializes a new instance of CallbackMessage.
136
+ # @private
137
+ #
138
+ # @param [Client] client The client.
139
+ # @param [Hash] data The payload.
140
+ # @param [String] application_id The application ID.
141
+ # @param [String] token The token.
142
+ #
143
+ def initialize(client, data, application_id, token)
144
+ @client = client
145
+ @data = data
146
+ @application_id = application_id
147
+ @token = token
148
+ end
117
149
 
118
- #
119
- # Edits the callback message.
120
- # @async
121
- # @macro edit
122
- #
123
- # @param [String] content The new content of the message.
124
- # @param [Discorb::Embed] embed The new embed of the message.
125
- # @param [Array<Discorb::Embed>] embeds The new embeds of the message.
126
- # @param [Array<Discorb::Attachment>] attachments The attachments to remain.
127
- # @param [Discorb::Attachment] file The file to send.
128
- # @param [Array<Discorb::Attachment>] files The files to send.
129
- #
130
- # @return [Async::Task<void>] The task.
131
- #
132
- def edit(
133
- content = Discorb::Unset,
134
- embed: Discorb::Unset, embeds: Discorb::Unset,
135
- file: Discorb::Unset, files: Discorb::Unset,
136
- attachments: Discorb::Unset
137
- )
138
- Async do
139
- payload = {}
140
- payload[:content] = content if content != Discorb::Unset
141
- payload[:embeds] = embed ? [embed.to_hash] : [] if embed != Discorb::Unset
142
- payload[:embeds] = embeds.map(&:to_hash) if embeds != Discorb::Unset
143
- payload[:attachments] = attachments.map(&:to_hash) if attachments != Discorb::Unset
144
- files = [file] if file != Discorb::Unset
145
- files = [] if files == Discorb::Unset
146
- @client.http.multipart_request(
147
- Route.new("/webhooks/#{@application_id}/#{@token}/messages/@original",
148
- "//webhooks/:webhook_id/:token/messages/@original", :patch), payload, files, headers: headers,
149
- ).wait
150
- end
150
+ #
151
+ # Edits the callback message.
152
+ # @async
153
+ # @macro edit
154
+ #
155
+ # @param [String] content The new content of the message.
156
+ # @param [Discorb::Embed] embed The new embed of the message.
157
+ # @param [Array<Discorb::Embed>] embeds The new embeds of the message.
158
+ # @param [Array<Discorb::Attachment>] attachments The attachments to remain.
159
+ # @param [Discorb::Attachment] file The file to send.
160
+ # @param [Array<Discorb::Attachment>] files The files to send.
161
+ #
162
+ # @return [Async::Task<void>] The task.
163
+ #
164
+ def edit(
165
+ content = Discorb::Unset,
166
+ embed: Discorb::Unset, embeds: Discorb::Unset,
167
+ file: Discorb::Unset, files: Discorb::Unset,
168
+ attachments: Discorb::Unset
169
+ )
170
+ Async do
171
+ payload = {}
172
+ payload[:content] = content if content != Discorb::Unset
173
+ payload[:embeds] = embed ? [embed.to_hash] : [] if embed != Discorb::Unset
174
+ payload[:embeds] = embeds.map(&:to_hash) if embeds != Discorb::Unset
175
+ payload[:attachments] = attachments.map(&:to_hash) if attachments != Discorb::Unset
176
+ files = [file] if file != Discorb::Unset
177
+ files = [] if files == Discorb::Unset
178
+ @client.http.multipart_request(
179
+ Route.new(
180
+ "/webhooks/#{@application_id}/#{@token}/messages/@original",
181
+ "//webhooks/:webhook_id/:token/messages/@original",
182
+ :patch
183
+ ),
184
+ payload,
185
+ files,
186
+ ).wait
151
187
  end
188
+ end
152
189
 
153
- alias modify edit
190
+ alias modify edit
154
191
 
155
- #
156
- # Deletes the callback message.
157
- # @async
158
- # @note This will fail if the message is ephemeral.
159
- #
160
- # @return [Async::Task<void>] The task.
161
- #
162
- def delete!
163
- Async do
164
- @client.http.request(Route.new("/webhooks/#{@application_id}/#{@token}/messages/@original",
165
- "//webhooks/:webhook_id/:token/messages/@original", :delete)).wait
166
- end
192
+ #
193
+ # Deletes the callback message.
194
+ # @async
195
+ # @note This will fail if the message is ephemeral.
196
+ #
197
+ # @return [Async::Task<void>] The task.
198
+ #
199
+ def delete
200
+ Async do
201
+ @client.http.request(Route.new("/webhooks/#{@application_id}/#{@token}/messages/@original",
202
+ "//webhooks/:webhook_id/:token/messages/@original", :delete)).wait
167
203
  end
204
+ end
168
205
 
169
- def inspect
170
- "#<#{self.class.name} application_id=#{@application_id}"
171
- end
206
+ def inspect
207
+ "#<#{self.class.name} application_id=#{@application_id}"
172
208
  end
173
209
  end
174
210
 
@@ -176,6 +212,8 @@ module Discorb
176
212
  # A module for response with update.
177
213
  #
178
214
  module UpdateResponder
215
+ # @type instance: Discorb::Interaction
216
+
179
217
  #
180
218
  # Response with `DEFERRED_UPDATE_MESSAGE`(`6`).
181
219
  # @async
@@ -211,12 +249,24 @@ module Discorb
211
249
  # @param [Discorb::Embed] embed The embed to send.
212
250
  # @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
213
251
  # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
252
+ # @param [Discorb::Attachment] attachment The attachment to send.
253
+ # @param [Array<Discorb::Attachment>] attachments The attachments to send. (max: 10)
214
254
  # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
215
255
  # @param [Boolean] ephemeral Whether to make the response ephemeral.
216
256
  #
217
257
  # @return [Async::Task<void>] The task.
218
258
  #
219
- def edit(content, tts: false, embed: nil, embeds: nil, allowed_mentions: nil, components: nil, ephemeral: false)
259
+ def edit(
260
+ content,
261
+ tts: false,
262
+ embed: nil,
263
+ embeds: nil,
264
+ allowed_mentions: nil,
265
+ attachment: nil,
266
+ attachments: nil,
267
+ components: nil,
268
+ ephemeral: false
269
+ )
220
270
  Async do
221
271
  payload = {}
222
272
  payload[:content] = content if content
@@ -231,9 +281,17 @@ module Discorb
231
281
  allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
232
282
  payload[:components] = Component.to_payload(components) if components
233
283
  payload[:flags] = (ephemeral ? 1 << 6 : 0)
234
- @client.http.request(
284
+ attachments ||= [attachment] if attachment
285
+ payload[:attachments] = attachments.map.with_index do |a, i|
286
+ {
287
+ id: i,
288
+ filename: a.filename,
289
+ description: a.description,
290
+ }
291
+ end
292
+ @client.http.multipart_request(
235
293
  Route.new("/interactions/#{@id}/#{@token}/callback", "//interactions/:interaction_id/:token/callback",
236
- :post), { type: 7, data: payload }
294
+ :post), { type: 7, data: payload }, attachments
237
295
  ).wait
238
296
  end
239
297
  end
@@ -243,6 +301,8 @@ module Discorb
243
301
  # A module for response with modal.
244
302
  #
245
303
  module ModalResponder
304
+ # @type instance: Discorb::Interaction
305
+
246
306
  #
247
307
  # Response with `MODAL`(`9`).
248
308
  #
@@ -253,17 +313,23 @@ module Discorb
253
313
  # @return [Async::Task<void>] The task.
254
314
  #
255
315
  def show_modal(title, custom_id, components)
256
- payload = { title: title, custom_id: custom_id, components: Component.to_payload(components) }
257
- @client.http.request(
258
- Route.new("/interactions/#{@id}/#{@token}/callback", "//interactions/:interaction_id/:token/callback", :post),
259
- { type: 9, data: payload }
260
- ).wait
316
+ Async do
317
+ payload = { title: title, custom_id: custom_id, components: Component.to_payload(components) }
318
+ @client.http.request(
319
+ Route.new(
320
+ "/interactions/#{@id}/#{@token}/callback",
321
+ "//interactions/:interaction_id/:token/callback",
322
+ :post
323
+ ),
324
+ { type: 9, data: payload }
325
+ ).wait
326
+ end
261
327
  end
262
328
  end
263
329
 
264
330
  private
265
331
 
266
- def _set_data(*)
332
+ def _set_data(_)
267
333
  nil
268
334
  end
269
335
  end
@@ -25,6 +25,8 @@ module Discorb
25
25
  # @return [Symbol] The locale of the guild that created the interaction.
26
26
  # @note This modifies the language code, `-` will be replaced with `_`.
27
27
  attr_reader :guild_locale
28
+ # @return [Discorb::Permission] The permissions of the bot.
29
+ attr_reader :app_permissions
28
30
 
29
31
  # @!attribute [r] guild
30
32
  # @macro client_cache
@@ -62,6 +64,7 @@ module Discorb
62
64
  @token = data[:token]
63
65
  @locale = data[:locale].to_s.gsub("-", "_").to_sym
64
66
  @guild_locale = data[:guild_locale].to_s.gsub("-", "_").to_sym
67
+ @app_permissions = data[:app_permissions] && Permission.new(data[:app_permissions].to_i)
65
68
  @version = data[:version]
66
69
  @defered = false
67
70
  @responded = false
@@ -80,6 +83,142 @@ module Discorb
80
83
  "#<#{self.class} id=#{@id}>"
81
84
  end
82
85
 
86
+ #
87
+ # Send followup message.
88
+ #
89
+ # @async
90
+ #
91
+ # @param [String] content The content of the response.
92
+ # @param [Boolean] tts Whether to send the message as text-to-speech.
93
+ # @param [Discorb::Embed] embed The embed to send.
94
+ # @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
95
+ # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
96
+ # @param [Discorb::Attachment] attachment The attachment to send.
97
+ # @param [Array<Discorb::Attachment>] attachments The attachments to send. (max: 10)
98
+ # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
99
+ # @param [Boolean] ephemeral Whether to make the response ephemeral.
100
+ #
101
+ # @return [Discorb::Webhook::Message] The message.
102
+ #
103
+ def post(
104
+ content = nil,
105
+ tts: false,
106
+ embed: nil,
107
+ embeds: nil,
108
+ allowed_mentions: nil,
109
+ attachment: nil,
110
+ attachments: nil,
111
+ components: nil,
112
+ ephemeral: false
113
+ )
114
+ Async do
115
+ payload = {}
116
+ payload[:content] = content if content
117
+ payload[:tts] = tts
118
+ payload[:embeds] = (embeds || [embed]).map { |e| e&.to_hash }.filter { _1 }
119
+ payload[:allowed_mentions] =
120
+ allowed_mentions&.to_hash(@client.allowed_mentions) || @client.allowed_mentions.to_hash
121
+ payload[:components] = Component.to_payload(components) if components
122
+ payload[:flags] = (ephemeral ? 1 << 6 : 0)
123
+ attachments ||= attachment ? [attachment] : []
124
+
125
+ payload[:attachments] = attachments.map.with_index do |a, i|
126
+ {
127
+ id: i,
128
+ filename: a.filename,
129
+ description: a.description,
130
+ }
131
+ end
132
+
133
+ _resp, data = @client.http.multipart_request(
134
+ Route.new(
135
+ "/webhooks/#{@application_id}/#{@token}",
136
+ "//webhooks/:webhook_id/:token",
137
+ :post
138
+ ),
139
+ payload,
140
+ attachments
141
+ ).wait
142
+ webhook = Webhook::URLWebhook.new("/webhooks/#{@application_id}/#{@token}")
143
+ Webhook::Message.new(webhook, data, @client)
144
+ ret
145
+ end
146
+ end
147
+
148
+ #
149
+ # Edit the original response message.
150
+ # This method is low-level.
151
+ #
152
+ # @async
153
+ #
154
+ # @param [String] content The content of the response.
155
+ # @param [Discorb::Embed] embed The embed to send.
156
+ # @param [Array<Discorb::Embed>] embeds The embeds to send. (max: 10)
157
+ # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions to send.
158
+ # @param [Discorb::Attachment] attachment The attachment to send.
159
+ # @param [Array<Discorb::Attachment>] attachments The attachments to send. (max: 10)
160
+ # @param [Array<Discorb::Component>, Array<Array<Discorb::Component>>] components The components to send.
161
+ #
162
+ # @return [Async::Task<void>] The task.
163
+ #
164
+ # @see CallbackMessage#edit
165
+ #
166
+ def edit_original_message(
167
+ content = nil,
168
+ embed: nil,
169
+ embeds: nil,
170
+ attachment: nil,
171
+ attachments: nil,
172
+ components: nil
173
+ )
174
+ Async do
175
+ payload = {}
176
+ payload[:content] = content if content
177
+ payload[:embeds] = (embeds || [embed]).map { |e| e&.to_hash }.filter { _1 }.then { _1.empty? ? nil : _1 }
178
+ payload[:components] = Component.to_payload(components) if components
179
+ attachments ||= attachment && [attachment]
180
+
181
+ payload[:attachments] = attachments&.map&.with_index do |a, i|
182
+ {
183
+ id: i,
184
+ filename: a.filename,
185
+ description: a.description,
186
+ }
187
+ end
188
+ payload.compact!
189
+
190
+ @client.http.multipart_request(
191
+ Route.new(
192
+ "/webhooks/#{@application_id}/#{@token}/messages/@original",
193
+ "//webhooks/:webhook_id/:token/messages/@original",
194
+ :patch
195
+ ),
196
+ payload,
197
+ attachments
198
+ ).wait
199
+ end
200
+ end
201
+
202
+ #
203
+ # Delete the original response message.
204
+ # This method is low-level.
205
+ #
206
+ # @async
207
+ #
208
+ # @return [Async::Task<void>] The task.
209
+ #
210
+ def delete_original_message
211
+ Async do
212
+ @client.http.request(
213
+ Route.new(
214
+ "/webhooks/#{@application_id}/#{@token}/messages/@original",
215
+ "//webhooks/:webhook_id/:token/messages/@original",
216
+ :delete
217
+ )
218
+ ).wait
219
+ end
220
+ end
221
+
83
222
  class << self
84
223
  # @private
85
224
  attr_reader :interaction_type, :interaction_name, :event_name
@@ -112,7 +112,7 @@ module Discorb
112
112
  # @async
113
113
  # @return [Async::Task<void>] The task.
114
114
  #
115
- def delete!(reason: nil)
115
+ def delete(reason: nil)
116
116
  Async do
117
117
  @client.http.request(Route.new("/invites/#{@code}", "//invites/:code", :delete), {}, audit_log_reason: reason)
118
118
  end
@@ -52,10 +52,10 @@ module Discorb
52
52
  # @return [Discorb::Presence] The presence of the member.
53
53
  # @!attribute [r] activity
54
54
  # @macro client_cache
55
- # @return [Discorb::Activity] The activity of the member. It's from the {#presence}.
55
+ # @return [Discorb::Presence::Activity] The activity of the member. It's from the {#presence}.
56
56
  # @!attribute [r] activities
57
57
  # @macro client_cache
58
- # @return [Array<Discorb::Activity>] The activities of the member. It's from the {#presence}.
58
+ # @return [Array<Discorb::Presence::Activity>] The activities of the member. It's from the {#presence}.
59
59
  # @!attribute [r] status
60
60
  # @macro client_cache
61
61
  # @return [Symbol] The status of the member. It's from the {#presence}.
@@ -303,7 +303,7 @@ module Discorb
303
303
  @deaf = member_data[:deaf]
304
304
  @custom_avatar = member_data[:avatar] && Asset.new(self, member_data[:avatar])
305
305
  super(user_data)
306
- @display_avatar = @avatar || @custom_avatar
306
+ @display_avatar = @custom_avatar || @avatar
307
307
  @client.guilds[@guild_id].members[@id] = self unless @guild_id.nil? || @client.guilds[@guild_id].nil?
308
308
  @_member_data.update(member_data)
309
309
  end
@@ -7,7 +7,7 @@ module Discorb
7
7
  class Message < DiscordModel
8
8
  # @return [Discorb::Snowflake] The ID of the message.
9
9
  attr_reader :id
10
- # @return [Discorb::User, Discorb::Member] The user that sent the message.
10
+ # @return [Discorb::User, Discorb::Member, Webhook::Message::Author] The user that sent the message.
11
11
  attr_reader :author
12
12
  # @return [String] The content of the message.
13
13
  attr_reader :content
@@ -217,8 +217,8 @@ module Discorb
217
217
  end
218
218
  if role
219
219
  ret.gsub!(/<@&(\d+)>/) do |_match|
220
- role = guild&.roles&.[]($1)
221
- role ? "@#{role.name}" : "@Unknown Role"
220
+ r = guild&.roles&.[]($1)
221
+ r ? "@#{r.name}" : "@Unknown Role"
222
222
  end
223
223
  end
224
224
  if emoji
@@ -282,9 +282,9 @@ module Discorb
282
282
  #
283
283
  # @return [Async::Task<void>] The task.
284
284
  #
285
- def delete!(reason: nil)
285
+ def delete(reason: nil)
286
286
  Async do
287
- channel.delete_message!(@id, reason: reason).wait
287
+ channel.delete_message(@id, reason: reason).wait
288
288
  end
289
289
  end
290
290
 
@@ -293,15 +293,17 @@ module Discorb
293
293
  #
294
294
  # @param [Boolean] fail_if_not_exists Whether to raise an error if the message does not exist.
295
295
  #
296
- # @return [Hash] The reference object.
296
+ # @return [Discorb::Message::Reference] The reference object.
297
297
  #
298
298
  def to_reference(fail_if_not_exists: true)
299
- {
300
- message_id: @id,
301
- channel_id: @channel_id,
302
- guild_id: @guild_id,
303
- fail_if_not_exists: fail_if_not_exists,
304
- }
299
+ Reference.from_hash(
300
+ {
301
+ message_id: @id,
302
+ channel_id: @channel_id,
303
+ guild_id: @guild_id,
304
+ fail_if_not_exists: fail_if_not_exists,
305
+ }
306
+ )
305
307
  end
306
308
 
307
309
  def embed
@@ -400,16 +402,16 @@ module Discorb
400
402
  # Fetch reacted users of reaction.
401
403
  # @async
402
404
  #
403
- # @param [Discorb::Emoji] emoji The emoji to fetch.
405
+ # @param [Discorb::Emoji, Discorb::PartialEmoji] emoji The emoji to fetch.
404
406
  # @param [Integer, nil] limit The maximum number of users to fetch. `nil` for no limit.
405
407
  # @param [Discorb::Snowflake, nil] after The ID of the user to start fetching from.
406
408
  #
407
409
  # @return [Async::Task<Array<Discorb::User>>] The users.
408
410
  #
409
- def fetch_reacted_users(emoji, limit: nil, after: 0)
411
+ def fetch_reacted_users(emoji, limit: nil, after: Discorb::Snowflake.new("0"))
410
412
  Async do
411
413
  if limit.nil? || !limit.positive?
412
- after = 0
414
+ after = Discorb::Snowflake.new("0")
413
415
  users = []
414
416
  loop do
415
417
  _resp, data = @client.http.request(
@@ -76,8 +76,6 @@ module Discorb
76
76
  }
77
77
  end
78
78
 
79
- alias to_reference to_hash
80
-
81
79
  #
82
80
  # Initialize a new reference from a hash.
83
81
  #
@@ -141,7 +139,8 @@ module Discorb
141
139
  def initialize(client, data)
142
140
  @id = Snowflake.new(data[:id])
143
141
  @name = data[:name]
144
- @type = Discorb::Interaction.descendants.find { |c| c.interaction_type == data[:type] }
142
+ @type = (Discorb::Interaction.descendants.find { |c| c.interaction_type == data[:type] } or
143
+ raise "Unknown interaction type: #{data[:type]}")
145
144
  @user = client.users[data[:user][:id]] || User.new(client, data[:user])
146
145
  end
147
146
 
@@ -44,7 +44,7 @@ module Discorb
44
44
  payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
45
45
  payload[:allowed_mentions] =
46
46
  allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
47
- payload[:message_reference] = reference.to_reference if reference
47
+ payload[:message_reference] = reference.to_reference.to_hash if reference
48
48
  payload[:components] = Component.to_payload(components) if components
49
49
  attachments ||= attachment ? [attachment] : []
50
50
 
@@ -135,7 +135,7 @@ module Discorb
135
135
  #
136
136
  # @return [Async::Task<void>] The task.
137
137
  #
138
- def delete_message!(message_id, reason: nil)
138
+ def delete_message(message_id, reason: nil)
139
139
  Async do
140
140
  @client.http.request(
141
141
  Route.new(
@@ -146,7 +146,7 @@ module Discorb
146
146
  end
147
147
  end
148
148
 
149
- alias destroy_message! delete_message!
149
+ alias destroy_message delete_message
150
150
 
151
151
  #
152
152
  # Fetch a message from ID.
@@ -265,10 +265,11 @@ module Discorb
265
265
  sleep(5)
266
266
  end
267
267
  end
268
- yield
268
+ ret = yield
269
269
  ensure
270
270
  post_task.stop
271
271
  end
272
+ ret
272
273
  else
273
274
  Async do |_task|
274
275
  @client.http.request(Route.new("/channels/#{@id}/typing", "//channels/:channel_id/typing", :post), {})
@@ -202,7 +202,9 @@ module Discorb
202
202
  def +(other)
203
203
  result = to_hash
204
204
  self.class.bits.each_key do |field|
205
- result[field] = other[field] unless other[field].nil?
205
+ unless other[field].nil?
206
+ result[field] = (other[field] || raise(KeyError, "field #{field} not found in #{other.inspect}"))
207
+ end
206
208
  end
207
209
  self.class.from_hash(result)
208
210
  end