discordrb 3.4.3 → 3.6.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +13 -0
  3. data/.devcontainer/devcontainer.json +29 -0
  4. data/.devcontainer/postcreate.sh +4 -0
  5. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -1
  6. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -1
  7. data/.github/workflows/ci.yml +78 -0
  8. data/.github/workflows/codeql.yml +65 -0
  9. data/.github/workflows/deploy.yml +54 -0
  10. data/.github/workflows/release.yml +45 -0
  11. data/.markdownlint.json +4 -0
  12. data/.rubocop.yml +58 -2
  13. data/CHANGELOG.md +485 -225
  14. data/LICENSE.txt +1 -1
  15. data/README.md +38 -26
  16. data/discordrb-webhooks.gemspec +4 -1
  17. data/discordrb.gemspec +18 -10
  18. data/lib/discordrb/api/application.rb +278 -0
  19. data/lib/discordrb/api/channel.rb +222 -18
  20. data/lib/discordrb/api/interaction.rb +63 -0
  21. data/lib/discordrb/api/invite.rb +2 -2
  22. data/lib/discordrb/api/server.rb +123 -66
  23. data/lib/discordrb/api/user.rb +20 -5
  24. data/lib/discordrb/api/webhook.rb +72 -0
  25. data/lib/discordrb/api.rb +35 -25
  26. data/lib/discordrb/bot.rb +437 -66
  27. data/lib/discordrb/cache.rb +41 -22
  28. data/lib/discordrb/commands/command_bot.rb +13 -21
  29. data/lib/discordrb/commands/container.rb +1 -1
  30. data/lib/discordrb/commands/parser.rb +7 -7
  31. data/lib/discordrb/commands/rate_limiter.rb +1 -1
  32. data/lib/discordrb/container.rb +178 -3
  33. data/lib/discordrb/data/activity.rb +1 -1
  34. data/lib/discordrb/data/application.rb +1 -0
  35. data/lib/discordrb/data/attachment.rb +38 -3
  36. data/lib/discordrb/data/audit_logs.rb +3 -3
  37. data/lib/discordrb/data/avatar_decoration.rb +26 -0
  38. data/lib/discordrb/data/call.rb +22 -0
  39. data/lib/discordrb/data/channel.rb +299 -30
  40. data/lib/discordrb/data/collectibles.rb +45 -0
  41. data/lib/discordrb/data/component.rb +229 -0
  42. data/lib/discordrb/data/embed.rb +10 -3
  43. data/lib/discordrb/data/emoji.rb +20 -1
  44. data/lib/discordrb/data/integration.rb +45 -3
  45. data/lib/discordrb/data/interaction.rb +937 -0
  46. data/lib/discordrb/data/invite.rb +1 -1
  47. data/lib/discordrb/data/member.rb +236 -44
  48. data/lib/discordrb/data/message.rb +278 -51
  49. data/lib/discordrb/data/overwrite.rb +15 -7
  50. data/lib/discordrb/data/primary_server.rb +60 -0
  51. data/lib/discordrb/data/profile.rb +2 -7
  52. data/lib/discordrb/data/reaction.rb +2 -1
  53. data/lib/discordrb/data/recipient.rb +1 -1
  54. data/lib/discordrb/data/role.rb +204 -18
  55. data/lib/discordrb/data/server.rb +194 -118
  56. data/lib/discordrb/data/server_preview.rb +68 -0
  57. data/lib/discordrb/data/snapshot.rb +110 -0
  58. data/lib/discordrb/data/user.rb +132 -12
  59. data/lib/discordrb/data/voice_region.rb +1 -0
  60. data/lib/discordrb/data/webhook.rb +99 -9
  61. data/lib/discordrb/data.rb +9 -0
  62. data/lib/discordrb/errors.rb +47 -3
  63. data/lib/discordrb/events/await.rb +1 -1
  64. data/lib/discordrb/events/channels.rb +38 -1
  65. data/lib/discordrb/events/generic.rb +2 -0
  66. data/lib/discordrb/events/guilds.rb +6 -1
  67. data/lib/discordrb/events/interactions.rb +575 -0
  68. data/lib/discordrb/events/invites.rb +2 -0
  69. data/lib/discordrb/events/members.rb +19 -2
  70. data/lib/discordrb/events/message.rb +42 -8
  71. data/lib/discordrb/events/presence.rb +23 -14
  72. data/lib/discordrb/events/raw.rb +1 -0
  73. data/lib/discordrb/events/reactions.rb +2 -1
  74. data/lib/discordrb/events/roles.rb +2 -0
  75. data/lib/discordrb/events/threads.rb +100 -0
  76. data/lib/discordrb/events/typing.rb +1 -0
  77. data/lib/discordrb/events/voice_server_update.rb +1 -0
  78. data/lib/discordrb/events/voice_state_update.rb +1 -0
  79. data/lib/discordrb/events/webhooks.rb +1 -0
  80. data/lib/discordrb/gateway.rb +57 -28
  81. data/lib/discordrb/paginator.rb +3 -3
  82. data/lib/discordrb/permissions.rb +71 -35
  83. data/lib/discordrb/version.rb +1 -1
  84. data/lib/discordrb/voice/encoder.rb +2 -2
  85. data/lib/discordrb/voice/network.rb +18 -7
  86. data/lib/discordrb/voice/sodium.rb +3 -1
  87. data/lib/discordrb/voice/voice_bot.rb +3 -3
  88. data/lib/discordrb/webhooks.rb +2 -0
  89. data/lib/discordrb/websocket.rb +0 -10
  90. data/lib/discordrb.rb +54 -5
  91. metadata +87 -25
  92. data/.circleci/config.yml +0 -126
  93. data/.codeclimate.yml +0 -16
  94. data/.travis.yml +0 -32
  95. data/bin/travis_build_docs.sh +0 -17
@@ -4,20 +4,6 @@
4
4
  module Discordrb::API::Server
5
5
  module_function
6
6
 
7
- # Create a server
8
- # https://discord.com/developers/docs/resources/guild#create-guild
9
- def create(token, name, region = :'eu-central')
10
- Discordrb::API.request(
11
- :guilds,
12
- nil,
13
- :post,
14
- "#{Discordrb::API.api_base}/guilds",
15
- { name: name, region: region.to_s }.to_json,
16
- Authorization: token,
17
- content_type: :json
18
- )
19
- end
20
-
21
7
  # Get a server's data
22
8
  # https://discord.com/developers/docs/resources/guild#get-guild
23
9
  def resolve(token, server_id, with_counts = nil)
@@ -45,33 +31,6 @@ module Discordrb::API::Server
45
31
  )
46
32
  end
47
33
 
48
- # Transfer server ownership
49
- # https://discord.com/developers/docs/resources/guild#modify-guild
50
- def transfer_ownership(token, server_id, user_id, reason = nil)
51
- Discordrb::API.request(
52
- :guilds_sid,
53
- server_id,
54
- :patch,
55
- "#{Discordrb::API.api_base}/guilds/#{server_id}",
56
- { owner_id: user_id }.to_json,
57
- Authorization: token,
58
- content_type: :json,
59
- 'X-Audit-Log-Reason': reason
60
- )
61
- end
62
-
63
- # Delete a server
64
- # https://discord.com/developers/docs/resources/guild#delete-guild
65
- def delete(token, server_id)
66
- Discordrb::API.request(
67
- :guilds_sid,
68
- server_id,
69
- :delete,
70
- "#{Discordrb::API.api_base}/guilds/#{server_id}",
71
- Authorization: token
72
- )
73
- end
74
-
75
34
  # Get a server's channels list
76
35
  # https://discord.com/developers/docs/resources/guild#get-guild-channels
77
36
  def channels(token, server_id)
@@ -99,6 +58,18 @@ module Discordrb::API::Server
99
58
  )
100
59
  end
101
60
 
61
+ # Get the preview of a server.
62
+ # https://discord.com/developers/docs/resources/guild#get-guild-preview
63
+ def preview(token, server_id)
64
+ Discordrb::API.request(
65
+ :guilds_sid_preview,
66
+ server_id,
67
+ :get,
68
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/preview",
69
+ Authorization: token
70
+ )
71
+ end
72
+
102
73
  # Update a channels position
103
74
  # https://discord.com/developers/docs/resources/guild#modify-guild-channel-positions
104
75
  def update_channel_positions(token, server_id, positions)
@@ -128,18 +99,33 @@ module Discordrb::API::Server
128
99
  # Gets members from the server
129
100
  # https://discord.com/developers/docs/resources/guild#list-guild-members
130
101
  def resolve_members(token, server_id, limit, after = nil)
102
+ query_string = URI.encode_www_form({ limit: limit, after: after }.compact)
131
103
  Discordrb::API.request(
132
104
  :guilds_sid_members,
133
105
  server_id,
134
106
  :get,
135
- "#{Discordrb::API.api_base}/guilds/#{server_id}/members?limit=#{limit}#{"&after=#{after}" if after}",
107
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/members?#{query_string}",
108
+ Authorization: token
109
+ )
110
+ end
111
+
112
+ # Search for a guild member
113
+ # https://discord.com/developers/docs/resources/guild#search-guild-members
114
+ def search_guild_members(token, server_id, query, limit)
115
+ query_string = URI.encode_www_form({ query: query, limit: limit }.compact)
116
+ Discordrb::API.request(
117
+ :guilds_sid_members,
118
+ server_id,
119
+ :get,
120
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/members/search?#{query_string}",
136
121
  Authorization: token
137
122
  )
138
123
  end
139
124
 
140
125
  # Update a user properties
141
126
  # https://discord.com/developers/docs/resources/guild#modify-guild-member
142
- def update_member(token, server_id, user_id, nick: nil, roles: nil, mute: nil, deaf: nil, channel_id: nil, reason: nil)
127
+ def update_member(token, server_id, user_id, nick: :undef, roles: :undef, mute: :undef, deaf: :undef, channel_id: :undef,
128
+ communication_disabled_until: :undef, flags: :undef, reason: nil)
143
129
  Discordrb::API.request(
144
130
  :guilds_sid_members_uid,
145
131
  server_id,
@@ -149,8 +135,25 @@ module Discordrb::API::Server
149
135
  nick: nick,
150
136
  mute: mute,
151
137
  deaf: deaf,
152
- channel_id: channel_id
153
- }.compact.to_json,
138
+ channel_id: channel_id,
139
+ communication_disabled_until: communication_disabled_until,
140
+ flags: flags
141
+ }.reject { |_, v| v == :undef }.to_json,
142
+ Authorization: token,
143
+ content_type: :json,
144
+ 'X-Audit-Log-Reason': reason
145
+ )
146
+ end
147
+
148
+ # Update the current member's properties.
149
+ # https://discord.com/developers/docs/resources/guild#modify-current-member
150
+ def update_current_member(token, server_id, nick = :undef, reason = nil)
151
+ Discordrb::API.request(
152
+ :guilds_sid_members_me,
153
+ server_id,
154
+ :patch,
155
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/members/@me",
156
+ { nick: nick }.reject { |_, v| v == :undef }.to_json,
154
157
  Authorization: token,
155
158
  content_type: :json,
156
159
  'X-Audit-Log-Reason': reason
@@ -173,27 +176,35 @@ module Discordrb::API::Server
173
176
 
174
177
  # Get a server's banned users
175
178
  # https://discord.com/developers/docs/resources/guild#get-guild-bans
176
- def bans(token, server_id)
179
+ def bans(token, server_id, limit = nil, before = nil, after = nil)
180
+ query_string = URI.encode_www_form({ limit: limit, before: before, after: after }.compact)
177
181
  Discordrb::API.request(
178
182
  :guilds_sid_bans,
179
183
  server_id,
180
184
  :get,
181
- "#{Discordrb::API.api_base}/guilds/#{server_id}/bans",
185
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/bans?#{query_string}",
182
186
  Authorization: token
183
187
  )
184
188
  end
185
189
 
186
- # Ban a user from a server and delete their messages from the last message_days days
190
+ # @deprecated Please use {ban_user!} instead.
187
191
  # https://discord.com/developers/docs/resources/guild#create-guild-ban
188
192
  def ban_user(token, server_id, user_id, message_days, reason = nil)
189
- reason = URI.encode_www_form_component(reason) if reason
193
+ ban_user!(token, server_id, user_id, message_days * 86_400, reason)
194
+ end
195
+
196
+ # Ban a user from a server and delete their messages up to a given amount of time.
197
+ # https://discord.com/developers/docs/resources/guild#create-guild-ban
198
+ def ban_user!(token, server_id, user_id, message_seconds, reason = nil)
190
199
  Discordrb::API.request(
191
200
  :guilds_sid_bans_uid,
192
201
  server_id,
193
202
  :put,
194
- "#{Discordrb::API.api_base}/guilds/#{server_id}/bans/#{user_id}?delete-message-days=#{message_days}&reason=#{reason}",
195
- nil,
196
- Authorization: token
203
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/bans/#{user_id}",
204
+ { delete_message_seconds: message_seconds }.to_json,
205
+ Authorization: token,
206
+ content_type: :json,
207
+ 'X-Audit-Log-Reason': reason
197
208
  )
198
209
  end
199
210
 
@@ -227,13 +238,13 @@ module Discordrb::API::Server
227
238
  # sending TTS messages, embedding links, sending files, reading the history, mentioning everybody,
228
239
  # connecting to voice, speaking and voice activity (push-to-talk isn't mandatory)
229
240
  # https://discord.com/developers/docs/resources/guild#get-guild-roles
230
- def create_role(token, server_id, name, colour, hoist, mentionable, packed_permissions, reason = nil)
241
+ def create_role(token, server_id, name, colour, hoist, mentionable, packed_permissions, reason = nil, colours = nil, icon = nil, unicode_emoji = nil)
231
242
  Discordrb::API.request(
232
243
  :guilds_sid_roles,
233
244
  server_id,
234
245
  :post,
235
246
  "#{Discordrb::API.api_base}/guilds/#{server_id}/roles",
236
- { color: colour, name: name, hoist: hoist, mentionable: mentionable, permissions: packed_permissions }.to_json,
247
+ { color: colour, name: name, hoist: hoist, mentionable: mentionable, permissions: packed_permissions, colors: colours, icon: icon, unicode_emoji: unicode_emoji }.compact.to_json,
237
248
  Authorization: token,
238
249
  content_type: :json,
239
250
  'X-Audit-Log-Reason': reason
@@ -245,13 +256,22 @@ module Discordrb::API::Server
245
256
  # sending TTS messages, embedding links, sending files, reading the history, mentioning everybody,
246
257
  # connecting to voice, speaking and voice activity (push-to-talk isn't mandatory)
247
258
  # https://discord.com/developers/docs/resources/guild#batch-modify-guild-role
248
- def update_role(token, server_id, role_id, name, colour, hoist = false, mentionable = false, packed_permissions = 104_324_161, reason = nil)
259
+ # @param icon [:undef, File]
260
+ def update_role(token, server_id, role_id, name, colour, hoist = false, mentionable = false, packed_permissions = 104_324_161, reason = nil, icon = :undef, unicode_emoji = :undef, colours = :undef)
261
+ data = { color: colour, name: name, hoist: hoist, mentionable: mentionable, permissions: packed_permissions, colors: colours, unicode_emoji: unicode_emoji }
262
+
263
+ if icon != :undef && icon
264
+ data[:icon] = Discordrb.encode64(icon)
265
+ elsif icon.nil?
266
+ data[:icon] = nil
267
+ end
268
+
249
269
  Discordrb::API.request(
250
270
  :guilds_sid_roles_rid,
251
271
  server_id,
252
272
  :patch,
253
273
  "#{Discordrb::API.api_base}/guilds/#{server_id}/roles/#{role_id}",
254
- { color: colour, name: name, hoist: hoist, mentionable: mentionable, permissions: packed_permissions }.to_json,
274
+ data.reject { |_, value| value == :undef }.to_json,
255
275
  Authorization: token,
256
276
  content_type: :json,
257
277
  'X-Audit-Log-Reason': reason
@@ -375,7 +395,7 @@ module Discordrb::API::Server
375
395
  end
376
396
 
377
397
  # Create a server integration
378
- # https://discordapp.com/developers/docs/resources/guild#create-guild-integration
398
+ # https://discord.com/developers/docs/resources/guild#create-guild-integration
379
399
  def create_integration(token, server_id, type, id, reason = nil)
380
400
  Discordrb::API.request(
381
401
  :guilds_sid_integrations,
@@ -403,7 +423,7 @@ module Discordrb::API::Server
403
423
  end
404
424
 
405
425
  # Delete a server integration
406
- # https://discordapp.com/developers/docs/resources/guild#delete-guild-integration
426
+ # https://discord.com/developers/docs/resources/guild#delete-guild-integration
407
427
  def delete_integration(token, server_id, integration_id, reason = nil)
408
428
  Discordrb::API.request(
409
429
  :guilds_sid_integrations_iid,
@@ -428,32 +448,34 @@ module Discordrb::API::Server
428
448
  )
429
449
  end
430
450
 
431
- # Retrieves a server's embed information
432
- # https://discord.com/developers/docs/resources/guild#get-guild-embed
433
- def embed(token, server_id)
451
+ # Retrieves a server's widget information
452
+ # https://discord.com/developers/docs/resources/guild#get-guild-widget
453
+ def widget(token, server_id)
434
454
  Discordrb::API.request(
435
455
  :guilds_sid_embed,
436
456
  server_id,
437
457
  :get,
438
- "#{Discordrb::API.api_base}/guilds/#{server_id}/embed",
458
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/widget",
439
459
  Authorization: token
440
460
  )
441
461
  end
462
+ alias embed widget
442
463
 
443
- # Modify a server's embed settings
444
- # https://discord.com/developers/docs/resources/guild#modify-guild-embed
445
- def modify_embed(token, server_id, enabled, channel_id, reason = nil)
464
+ # Modify a server's widget settings
465
+ # https://discord.com/developers/docs/resources/guild#modify-guild-widget
466
+ def modify_widget(token, server_id, enabled, channel_id, reason = nil)
446
467
  Discordrb::API.request(
447
468
  :guilds_sid_embed,
448
469
  server_id,
449
470
  :patch,
450
- "#{Discordrb::API.api_base}/guilds/#{server_id}/embed",
471
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/widget",
451
472
  { enabled: enabled, channel_id: channel_id }.to_json,
452
473
  Authorization: token,
453
474
  'X-Audit-Log-Reason': reason,
454
475
  content_type: :json
455
476
  )
456
477
  end
478
+ alias modify_embed modify_widget
457
479
 
458
480
  # Adds a custom emoji.
459
481
  # https://discord.com/developers/docs/resources/emoji#create-guild-emoji
@@ -535,4 +557,39 @@ module Discordrb::API::Server
535
557
  Authorization: token
536
558
  )
537
559
  end
560
+
561
+ # Make an member avatar URL from the server, user and avatar IDs
562
+ def avatar_url(server_id, user_id, avatar_id, format = nil)
563
+ format ||= if avatar_id.start_with?('a_')
564
+ 'gif'
565
+ else
566
+ 'webp'
567
+ end
568
+ "#{Discordrb::API.cdn_url}/guilds/#{server_id}/users/#{user_id}/avatars/#{avatar_id}.#{format}"
569
+ end
570
+
571
+ # Make a banner URL from the server, user and banner IDs
572
+ def banner_url(server_id, user_id, banner_id, format = nil)
573
+ format ||= if banner_id.start_with?('a_')
574
+ 'gif'
575
+ else
576
+ 'webp'
577
+ end
578
+ "#{Discordrb::API.cdn_url}/guilds/#{server_id}/users/#{user_id}/banners/#{banner_id}.#{format}"
579
+ end
580
+
581
+ # Ban multiple users in one go
582
+ # https://discord.com/developers/docs/resources/guild#bulk-guild-ban
583
+ def bulk_ban(token, server_id, users, message_seconds, reason = nil)
584
+ Discordrb::API.request(
585
+ :guilds_sid_bulk_bans,
586
+ server_id,
587
+ :post,
588
+ "#{Discordrb::API.api_base}/guilds/#{server_id}/bulk-ban",
589
+ { user_ids: users, delete_message_seconds: message_seconds }.compact.to_json,
590
+ content_type: :json,
591
+ Authorization: token,
592
+ 'X-Audit-Log-Reason': reason
593
+ )
594
+ end
538
595
  end
@@ -28,8 +28,8 @@ module Discordrb::API::User
28
28
  )
29
29
  end
30
30
 
31
- # Change the current bot's nickname on a server
32
- # https://discord.com/developers/docs/resources/user#modify-current-user
31
+ # @deprecated Please use {Discordrb::API::Server.update_current_member} instead.
32
+ # https://discord.com/developers/docs/resources/user#modify-current-user-nick
33
33
  def change_own_nickname(token, server_id, nick, reason = nil)
34
34
  Discordrb::API.request(
35
35
  :guilds_sid_members_me_nick,
@@ -132,9 +132,14 @@ module Discordrb::API::User
132
132
  )
133
133
  end
134
134
 
135
- # Returns one of the "default" discord avatars from the CDN given a discriminator
136
- def default_avatar(discrim = 0)
137
- index = discrim.to_i % 5
135
+ # Returns one of the "default" discord avatars from the CDN given a discriminator or id since new usernames
136
+ # TODO: Maybe change this method again after discriminator removal ?
137
+ def default_avatar(discrim_id = 0, legacy: false)
138
+ index = if legacy
139
+ discrim_id.to_i % 5
140
+ else
141
+ (discrim_id.to_i >> 22) % 5
142
+ end
138
143
  "#{Discordrb::API.cdn_url}/embed/avatars/#{index}.png"
139
144
  end
140
145
 
@@ -147,4 +152,14 @@ module Discordrb::API::User
147
152
  end
148
153
  "#{Discordrb::API.cdn_url}/avatars/#{user_id}/#{avatar_id}.#{format}"
149
154
  end
155
+
156
+ # Make a banner URL from the user and banner IDs
157
+ def banner_url(user_id, banner_id, format = nil)
158
+ format ||= if banner_id.start_with?('a_')
159
+ 'gif'
160
+ else
161
+ 'png'
162
+ end
163
+ "#{Discordrb::API.cdn_url}/banners/#{user_id}/#{banner_id}.#{format}"
164
+ end
150
165
  end
@@ -27,6 +27,32 @@ module Discordrb::API::Webhook
27
27
  )
28
28
  end
29
29
 
30
+ # Execute a webhook via token.
31
+ # https://discord.com/developers/docs/resources/webhook#execute-webhook
32
+ def token_execute_webhook(webhook_token, webhook_id, wait = false, content = nil, username = nil, avatar_url = nil, tts = nil, file = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil)
33
+ body = { content: content, username: username, avatar_url: avatar_url, tts: tts, embeds: embeds&.map(&:to_hash), allowed_mentions: allowed_mentions, flags: flags, components: components }
34
+
35
+ body = if file
36
+ { file: file, payload_json: body.to_json }
37
+ elsif attachments
38
+ files = [*0...attachments.size].zip(attachments).to_h
39
+ { **files, payload_json: body.to_json }
40
+ else
41
+ body.to_json
42
+ end
43
+
44
+ headers = { content_type: :json } unless file || attachments
45
+
46
+ Discordrb::API.request(
47
+ :webhooks_wid,
48
+ webhook_id,
49
+ :post,
50
+ "#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}?wait=#{wait}",
51
+ body,
52
+ headers
53
+ )
54
+ end
55
+
30
56
  # Update a webhook
31
57
  # https://discord.com/developers/docs/resources/webhook#modify-webhook
32
58
  def update_webhook(token, webhook_id, data, reason = nil)
@@ -80,4 +106,50 @@ module Discordrb::API::Webhook
80
106
  'X-Audit-Log-Reason': reason
81
107
  )
82
108
  end
109
+
110
+ # Get a message that was created by the webhook corresponding to the provided token.
111
+ # https://discord.com/developers/docs/resources/webhook#get-webhook-message
112
+ def token_get_message(webhook_token, webhook_id, message_id)
113
+ Discordrb::API.request(
114
+ :webhooks_wid_messages_mid,
115
+ webhook_id,
116
+ :get,
117
+ "#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}"
118
+ )
119
+ end
120
+
121
+ # Edit a webhook message via webhook token
122
+ # https://discord.com/developers/docs/resources/webhook#edit-webhook-message
123
+ def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil)
124
+ body = { content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components }
125
+
126
+ body = if attachments
127
+ files = [*0...attachments.size].zip(attachments).to_h
128
+ { **files, payload_json: body.to_json }
129
+ else
130
+ body.to_json
131
+ end
132
+
133
+ headers = { content_type: :json } unless attachments
134
+
135
+ Discordrb::API.request(
136
+ :webhooks_wid_messages,
137
+ webhook_id,
138
+ :patch,
139
+ "#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}",
140
+ body,
141
+ headers
142
+ )
143
+ end
144
+
145
+ # Delete a webhook message via webhook token.
146
+ # https://discord.com/developers/docs/resources/webhook#delete-webhook-message
147
+ def token_delete_message(webhook_token, webhook_id, message_id)
148
+ Discordrb::API.request(
149
+ :webhooks_wid_messages,
150
+ webhook_id,
151
+ :delete,
152
+ "#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}"
153
+ )
154
+ end
83
155
  end
data/lib/discordrb/api.rb CHANGED
@@ -9,7 +9,7 @@ require 'discordrb/errors'
9
9
  # List of methods representing endpoints in Discord's API
10
10
  module Discordrb::API
11
11
  # The base URL of the Discord REST API.
12
- APIBASE = 'https://discord.com/api/v6'
12
+ APIBASE = 'https://discord.com/api/v9'
13
13
 
14
14
  # The URL of Discord's CDN
15
15
  CDN_URL = 'https://cdn.discordapp.com'
@@ -94,9 +94,6 @@ module Discordrb::API
94
94
  # Add a custom user agent
95
95
  attributes.last[:user_agent] = user_agent if attributes.last.is_a? Hash
96
96
 
97
- # Specify RateLimit precision
98
- attributes.last[:x_ratelimit_precision] = 'millisecond' if attributes.last.is_a?(Hash)
99
-
100
97
  # The most recent Discord rate limit requirements require the support of major parameters, where a particular route
101
98
  # and major parameter combination (*not* the HTTP method) uniquely identifies a RL bucket.
102
99
  key = [key, major_parameter].freeze
@@ -115,6 +112,15 @@ module Discordrb::API
115
112
  response = raw_request(type, attributes)
116
113
  rescue RestClient::Exception => e
117
114
  response = e.response
115
+
116
+ if response.body && !e.is_a?(RestClient::TooManyRequests)
117
+ data = JSON.parse(response.body)
118
+ err_klass = Discordrb::Errors.error_class_for(data['code'] || 0)
119
+ e = err_klass.new(data['message'], data['errors'])
120
+
121
+ Discordrb::LOGGER.error(e.full_message)
122
+ end
123
+
118
124
  raise e
119
125
  rescue Discordrb::Errors::NoPermission => e
120
126
  if e.respond_to?(:_rc_response)
@@ -137,7 +143,7 @@ module Discordrb::API
137
143
 
138
144
  unless mutex.locked?
139
145
  response = JSON.parse(e.response)
140
- wait_seconds = response['retry_after'].to_i / 1000.0
146
+ wait_seconds = response['retry_after'] ? response['retry_after'].to_f : e.response.headers[:retry_after].to_i
141
147
  Discordrb::LOGGER.ratelimit("Locking RL mutex (key: #{key}) for #{wait_seconds} seconds due to Discord rate limiting")
142
148
  trace("429 #{key.join(' ')}")
143
149
 
@@ -197,6 +203,11 @@ module Discordrb::API
197
203
  "#{cdn_url}/splashes/#{server_id}/#{splash_id}.#{format}"
198
204
  end
199
205
 
206
+ # Make a discovery splash URL from server and splash IDs
207
+ def discovery_splash_url(server_id, splash_id, format = 'webp')
208
+ "#{cdn_url}/discovery-splashes/#{server_id}/#{splash_id}.#{format}"
209
+ end
210
+
200
211
  # Make a banner URL from server and banner IDs
201
212
  def banner_url(server_id, banner_id, format = 'webp')
202
213
  "#{cdn_url}/banners/#{server_id}/#{banner_id}.#{format}"
@@ -217,28 +228,27 @@ module Discordrb::API
217
228
  "#{cdn_url}/app-assets/#{application_id}/achievements/#{achievement_id}/icons/#{icon_hash}.#{format}"
218
229
  end
219
230
 
220
- # Login to the server
221
- def login(email, password)
222
- request(
223
- :auth_login,
224
- nil,
225
- :post,
226
- "#{api_base}/auth/login",
227
- email: email,
228
- password: password
229
- )
231
+ # @param role_id [String, Integer]
232
+ # @param icon_hash [String]
233
+ # @param format ['webp', 'png', 'jpeg']
234
+ # @return [String]
235
+ def role_icon_url(role_id, icon_hash, format = 'webp')
236
+ "#{cdn_url}/role-icons/#{role_id}/#{icon_hash}.#{format}"
230
237
  end
231
238
 
232
- # Logout from the server
233
- def logout(token)
234
- request(
235
- :auth_logout,
236
- nil,
237
- :post,
238
- "#{api_base}/auth/logout",
239
- nil,
240
- Authorization: token
241
- )
239
+ # make an avatar decoration URL from an avatar decoration ID.
240
+ def avatar_decoration_url(avatar_decoration_id, format = 'png')
241
+ "#{cdn_url}/avatar-decoration-presets/#{avatar_decoration_id}.#{format}"
242
+ end
243
+
244
+ # make a nameplate URL from the nameplate asset.
245
+ def nameplate_url(nameplate_asset, format = 'webm')
246
+ "#{cdn_url}/assets/collectibles/#{nameplate_asset.delete_suffix('/')}/asset.#{format}"
247
+ end
248
+
249
+ # make a server tag badge URL from a server ID and badge ID.
250
+ def server_tag_badge_url(server_id, badge_id, format = 'webp')
251
+ "#{cdn_url}/guild-tag-badges/#{server_id}/#{badge_id}.#{format}"
242
252
  end
243
253
 
244
254
  # Create an OAuth application