discordrb 3.3.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +152 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/pull_request_template.md +37 -0
- data/.github/workflows/codeql.yml +65 -0
- data/.markdownlint.json +4 -0
- data/.rubocop.yml +39 -36
- data/CHANGELOG.md +874 -552
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +80 -86
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/discordrb-webhooks.gemspec +9 -6
- data/discordrb.gemspec +21 -18
- data/lib/discordrb/allowed_mentions.rb +36 -0
- data/lib/discordrb/api/application.rb +202 -0
- data/lib/discordrb/api/channel.rb +236 -47
- data/lib/discordrb/api/interaction.rb +54 -0
- data/lib/discordrb/api/invite.rb +5 -5
- data/lib/discordrb/api/server.rb +94 -66
- data/lib/discordrb/api/user.rb +17 -11
- data/lib/discordrb/api/webhook.rb +63 -6
- data/lib/discordrb/api.rb +55 -16
- data/lib/discordrb/await.rb +0 -1
- data/lib/discordrb/bot.rb +480 -93
- data/lib/discordrb/cache.rb +31 -24
- data/lib/discordrb/colour_rgb.rb +43 -0
- data/lib/discordrb/commands/command_bot.rb +35 -12
- data/lib/discordrb/commands/container.rb +21 -24
- data/lib/discordrb/commands/parser.rb +20 -20
- data/lib/discordrb/commands/rate_limiter.rb +4 -3
- data/lib/discordrb/container.rb +209 -20
- data/lib/discordrb/data/activity.rb +271 -0
- data/lib/discordrb/data/application.rb +50 -0
- data/lib/discordrb/data/attachment.rb +71 -0
- data/lib/discordrb/data/audit_logs.rb +345 -0
- data/lib/discordrb/data/channel.rb +993 -0
- data/lib/discordrb/data/component.rb +229 -0
- data/lib/discordrb/data/embed.rb +251 -0
- data/lib/discordrb/data/emoji.rb +82 -0
- data/lib/discordrb/data/integration.rb +122 -0
- data/lib/discordrb/data/interaction.rb +800 -0
- data/lib/discordrb/data/invite.rb +137 -0
- data/lib/discordrb/data/member.rb +372 -0
- data/lib/discordrb/data/message.rb +414 -0
- data/lib/discordrb/data/overwrite.rb +108 -0
- data/lib/discordrb/data/profile.rb +91 -0
- data/lib/discordrb/data/reaction.rb +33 -0
- data/lib/discordrb/data/recipient.rb +34 -0
- data/lib/discordrb/data/role.rb +248 -0
- data/lib/discordrb/data/server.rb +1004 -0
- data/lib/discordrb/data/user.rb +264 -0
- data/lib/discordrb/data/voice_region.rb +45 -0
- data/lib/discordrb/data/voice_state.rb +41 -0
- data/lib/discordrb/data/webhook.rb +238 -0
- data/lib/discordrb/data.rb +28 -4180
- data/lib/discordrb/errors.rb +46 -4
- data/lib/discordrb/events/bans.rb +7 -5
- data/lib/discordrb/events/channels.rb +3 -1
- data/lib/discordrb/events/guilds.rb +16 -9
- data/lib/discordrb/events/interactions.rb +482 -0
- data/lib/discordrb/events/invites.rb +125 -0
- data/lib/discordrb/events/members.rb +6 -2
- data/lib/discordrb/events/message.rb +72 -27
- data/lib/discordrb/events/presence.rb +35 -18
- data/lib/discordrb/events/raw.rb +1 -3
- data/lib/discordrb/events/reactions.rb +49 -4
- data/lib/discordrb/events/threads.rb +96 -0
- data/lib/discordrb/events/typing.rb +6 -4
- data/lib/discordrb/events/voice_server_update.rb +47 -0
- data/lib/discordrb/events/voice_state_update.rb +15 -10
- data/lib/discordrb/events/webhooks.rb +9 -6
- data/lib/discordrb/gateway.rb +99 -71
- data/lib/discordrb/id_object.rb +39 -0
- data/lib/discordrb/light/integrations.rb +1 -1
- data/lib/discordrb/light/light_bot.rb +1 -1
- data/lib/discordrb/logger.rb +4 -4
- data/lib/discordrb/paginator.rb +57 -0
- data/lib/discordrb/permissions.rb +159 -39
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +16 -7
- data/lib/discordrb/voice/network.rb +99 -47
- data/lib/discordrb/voice/sodium.rb +98 -0
- data/lib/discordrb/voice/voice_bot.rb +33 -25
- data/lib/discordrb/webhooks.rb +2 -0
- data/lib/discordrb.rb +107 -1
- metadata +126 -54
- data/.codeclimate.yml +0 -16
- data/.travis.yml +0 -33
- data/bin/travis_build_docs.sh +0 -17
- /data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
@@ -5,7 +5,7 @@ module Discordrb::API::Webhook
|
|
5
5
|
module_function
|
6
6
|
|
7
7
|
# Get a webhook
|
8
|
-
# https://
|
8
|
+
# https://discord.com/developers/docs/resources/webhook#get-webhook
|
9
9
|
def webhook(token, webhook_id)
|
10
10
|
Discordrb::API.request(
|
11
11
|
:webhooks_wid,
|
@@ -17,7 +17,7 @@ module Discordrb::API::Webhook
|
|
17
17
|
end
|
18
18
|
|
19
19
|
# Get a webhook via webhook token
|
20
|
-
# https://
|
20
|
+
# https://discord.com/developers/docs/resources/webhook#get-webhook-with-token
|
21
21
|
def token_webhook(webhook_token, webhook_id)
|
22
22
|
Discordrb::API.request(
|
23
23
|
:webhooks_wid,
|
@@ -27,8 +27,30 @@ 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)
|
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
|
+
body = if file
|
35
|
+
{ file: file, payload_json: body.to_json }
|
36
|
+
else
|
37
|
+
body.to_json
|
38
|
+
end
|
39
|
+
|
40
|
+
headers = { content_type: :json } unless file
|
41
|
+
|
42
|
+
Discordrb::API.request(
|
43
|
+
:webhooks_wid,
|
44
|
+
webhook_id,
|
45
|
+
:post,
|
46
|
+
"#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}?wait=#{wait}",
|
47
|
+
body,
|
48
|
+
headers
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
30
52
|
# Update a webhook
|
31
|
-
# https://
|
53
|
+
# https://discord.com/developers/docs/resources/webhook#modify-webhook
|
32
54
|
def update_webhook(token, webhook_id, data, reason = nil)
|
33
55
|
Discordrb::API.request(
|
34
56
|
:webhooks_wid,
|
@@ -43,7 +65,7 @@ module Discordrb::API::Webhook
|
|
43
65
|
end
|
44
66
|
|
45
67
|
# Update a webhook via webhook token
|
46
|
-
# https://
|
68
|
+
# https://discord.com/developers/docs/resources/webhook#modify-webhook-with-token
|
47
69
|
def token_update_webhook(webhook_token, webhook_id, data, reason = nil)
|
48
70
|
Discordrb::API.request(
|
49
71
|
:webhooks_wid,
|
@@ -57,7 +79,7 @@ module Discordrb::API::Webhook
|
|
57
79
|
end
|
58
80
|
|
59
81
|
# Deletes a webhook
|
60
|
-
# https://
|
82
|
+
# https://discord.com/developers/docs/resources/webhook#delete-webhook
|
61
83
|
def delete_webhook(token, webhook_id, reason = nil)
|
62
84
|
Discordrb::API.request(
|
63
85
|
:webhooks_wid,
|
@@ -70,7 +92,7 @@ module Discordrb::API::Webhook
|
|
70
92
|
end
|
71
93
|
|
72
94
|
# Deletes a webhook via webhook token
|
73
|
-
# https://
|
95
|
+
# https://discord.com/developers/docs/resources/webhook#delete-webhook-with-token
|
74
96
|
def token_delete_webhook(webhook_token, webhook_id, reason = nil)
|
75
97
|
Discordrb::API.request(
|
76
98
|
:webhooks_wid,
|
@@ -80,4 +102,39 @@ module Discordrb::API::Webhook
|
|
80
102
|
'X-Audit-Log-Reason': reason
|
81
103
|
)
|
82
104
|
end
|
105
|
+
|
106
|
+
# Get a message that was created by the webhook corresponding to the provided token.
|
107
|
+
# https://discord.com/developers/docs/resources/webhook#get-webhook-message
|
108
|
+
def token_get_message(webhook_token, webhook_id, message_id)
|
109
|
+
Discordrb::API.request(
|
110
|
+
:webhooks_wid_messages_mid,
|
111
|
+
webhook_id,
|
112
|
+
:get,
|
113
|
+
"#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}"
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Edit a webhook message via webhook token
|
118
|
+
# https://discord.com/developers/docs/resources/webhook#edit-webhook-message
|
119
|
+
def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil)
|
120
|
+
Discordrb::API.request(
|
121
|
+
:webhooks_wid_messages,
|
122
|
+
webhook_id,
|
123
|
+
:patch,
|
124
|
+
"#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}",
|
125
|
+
{ content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components }.to_json,
|
126
|
+
content_type: :json
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Delete a webhook message via webhook token.
|
131
|
+
# https://discord.com/developers/docs/resources/webhook#delete-webhook-message
|
132
|
+
def token_delete_message(webhook_token, webhook_id, message_id)
|
133
|
+
Discordrb::API.request(
|
134
|
+
:webhooks_wid_messages,
|
135
|
+
webhook_id,
|
136
|
+
:delete,
|
137
|
+
"#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}"
|
138
|
+
)
|
139
|
+
end
|
83
140
|
end
|
data/lib/discordrb/api.rb
CHANGED
@@ -9,10 +9,10 @@ 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://
|
12
|
+
APIBASE = 'https://discord.com/api/v9'
|
13
13
|
|
14
14
|
# The URL of Discord's CDN
|
15
|
-
CDN_URL = 'https://cdn.discordapp.com'
|
15
|
+
CDN_URL = 'https://cdn.discordapp.com'
|
16
16
|
|
17
17
|
module_function
|
18
18
|
|
@@ -31,12 +31,12 @@ module Discordrb::API
|
|
31
31
|
@cdn_url || CDN_URL
|
32
32
|
end
|
33
33
|
|
34
|
-
# @return [String] the bot name, previously specified using
|
34
|
+
# @return [String] the bot name, previously specified using {.bot_name=}.
|
35
35
|
def bot_name
|
36
36
|
@bot_name
|
37
37
|
end
|
38
38
|
|
39
|
-
# Sets the bot name to something.
|
39
|
+
# Sets the bot name to something. Used in {.user_agent}. For the bot's username, see {Profile#username=}.
|
40
40
|
def bot_name=(value)
|
41
41
|
@bot_name = value
|
42
42
|
end
|
@@ -51,7 +51,7 @@ module Discordrb::API
|
|
51
51
|
# Generate a user agent identifying this requester as discordrb.
|
52
52
|
def user_agent
|
53
53
|
# This particular string is required by the Discord devs.
|
54
|
-
required = "DiscordBot (https://github.com/
|
54
|
+
required = "DiscordBot (https://github.com/shardlab/discordrb, v#{Discordrb::VERSION})"
|
55
55
|
@bot_name ||= ''
|
56
56
|
|
57
57
|
"#{required} rest-client/#{RestClient::VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} discordrb/#{Discordrb::VERSION} #{@bot_name}"
|
@@ -80,7 +80,7 @@ module Discordrb::API
|
|
80
80
|
def raw_request(type, attributes)
|
81
81
|
RestClient.send(type, *attributes)
|
82
82
|
rescue RestClient::Forbidden => e
|
83
|
-
# HACK: for #request, dynamically inject restclient's response into NoPermission - this allows us to
|
83
|
+
# HACK: for #request, dynamically inject restclient's response into NoPermission - this allows us to rate limit
|
84
84
|
noprm = Discordrb::Errors::NoPermission.new
|
85
85
|
noprm.define_singleton_method(:_rc_response) { e.response }
|
86
86
|
raise noprm, "The bot doesn't have the required permission to do this!"
|
@@ -112,6 +112,15 @@ module Discordrb::API
|
|
112
112
|
response = raw_request(type, attributes)
|
113
113
|
rescue RestClient::Exception => e
|
114
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
|
+
|
115
124
|
raise e
|
116
125
|
rescue Discordrb::Errors::NoPermission => e
|
117
126
|
if e.respond_to?(:_rc_response)
|
@@ -134,7 +143,7 @@ module Discordrb::API
|
|
134
143
|
|
135
144
|
unless mutex.locked?
|
136
145
|
response = JSON.parse(e.response)
|
137
|
-
wait_seconds = response['retry_after'].
|
146
|
+
wait_seconds = response['retry_after'] ? response['retry_after'].to_f : e.response.headers[:retry_after].to_i
|
138
147
|
Discordrb::LOGGER.ratelimit("Locking RL mutex (key: #{key}) for #{wait_seconds} seconds due to Discord rate limiting")
|
139
148
|
trace("429 #{key.join(' ')}")
|
140
149
|
|
@@ -149,17 +158,12 @@ module Discordrb::API
|
|
149
158
|
response
|
150
159
|
end
|
151
160
|
|
152
|
-
# Handles
|
161
|
+
# Handles pre-emptive rate limiting by waiting the given mutex by the difference of the Date header to the
|
153
162
|
# X-Ratelimit-Reset header, thus making sure we don't get 429'd in any subsequent requests.
|
154
163
|
def handle_preemptive_rl(headers, mutex, key)
|
155
164
|
Discordrb::LOGGER.ratelimit "RL bucket depletion detected! Date: #{headers[:date]} Reset: #{headers[:x_ratelimit_reset]}"
|
156
|
-
|
157
|
-
|
158
|
-
reset = Time.at(headers[:x_ratelimit_reset].to_i)
|
159
|
-
|
160
|
-
delta = reset - now
|
161
|
-
|
162
|
-
Discordrb::LOGGER.warn("Locking RL mutex (key: #{key}) for #{delta} seconds preemptively")
|
165
|
+
delta = headers[:x_ratelimit_reset_after].to_f
|
166
|
+
Discordrb::LOGGER.warn("Locking RL mutex (key: #{key}) for #{delta} seconds pre-emptively")
|
163
167
|
sync_wait(delta, mutex)
|
164
168
|
end
|
165
169
|
|
@@ -175,7 +179,7 @@ module Discordrb::API
|
|
175
179
|
Discordrb::LOGGER.ratelimit("Trace (#{reason}):")
|
176
180
|
|
177
181
|
caller.each do |str|
|
178
|
-
Discordrb::LOGGER.ratelimit(
|
182
|
+
Discordrb::LOGGER.ratelimit(" #{str}")
|
179
183
|
end
|
180
184
|
end
|
181
185
|
|
@@ -199,11 +203,34 @@ module Discordrb::API
|
|
199
203
|
"#{cdn_url}/splashes/#{server_id}/#{splash_id}.#{format}"
|
200
204
|
end
|
201
205
|
|
206
|
+
# Make a banner URL from server and banner IDs
|
207
|
+
def banner_url(server_id, banner_id, format = 'webp')
|
208
|
+
"#{cdn_url}/banners/#{server_id}/#{banner_id}.#{format}"
|
209
|
+
end
|
210
|
+
|
202
211
|
# Make an emoji icon URL from emoji ID
|
203
212
|
def emoji_icon_url(emoji_id, format = 'webp')
|
204
213
|
"#{cdn_url}/emojis/#{emoji_id}.#{format}"
|
205
214
|
end
|
206
215
|
|
216
|
+
# Make an asset URL from application and asset IDs
|
217
|
+
def asset_url(application_id, asset_id, format = 'webp')
|
218
|
+
"#{cdn_url}/app-assets/#{application_id}/#{asset_id}.#{format}"
|
219
|
+
end
|
220
|
+
|
221
|
+
# Make an achievement icon URL from application ID, achievement ID, and icon hash
|
222
|
+
def achievement_icon_url(application_id, achievement_id, icon_hash, format = 'webp')
|
223
|
+
"#{cdn_url}/app-assets/#{application_id}/achievements/#{achievement_id}/icons/#{icon_hash}.#{format}"
|
224
|
+
end
|
225
|
+
|
226
|
+
# @param role_id [String, Integer]
|
227
|
+
# @param icon_hash [String]
|
228
|
+
# @param format ['webp', 'png', 'jpeg']
|
229
|
+
# @return [String]
|
230
|
+
def role_icon_url(role_id, icon_hash, format = 'webp')
|
231
|
+
"#{cdn_url}/role-icons/#{role_id}/#{icon_hash}.#{format}"
|
232
|
+
end
|
233
|
+
|
207
234
|
# Login to the server
|
208
235
|
def login(email, password)
|
209
236
|
request(
|
@@ -290,6 +317,18 @@ module Discordrb::API
|
|
290
317
|
)
|
291
318
|
end
|
292
319
|
|
320
|
+
# Get the gateway to be used, with additional information for sharding and
|
321
|
+
# session start limits
|
322
|
+
def gateway_bot(token)
|
323
|
+
request(
|
324
|
+
:gateway_bot,
|
325
|
+
nil,
|
326
|
+
:get,
|
327
|
+
"#{api_base}/gateway/bot",
|
328
|
+
Authorization: token
|
329
|
+
)
|
330
|
+
end
|
331
|
+
|
293
332
|
# Validate a token (this request will fail if the token is invalid)
|
294
333
|
def validate_token(token)
|
295
334
|
request(
|
data/lib/discordrb/await.rb
CHANGED
@@ -43,7 +43,6 @@ module Discordrb
|
|
43
43
|
dummy_handler = EventContainer.handler_class(@type).new(@attributes, @bot)
|
44
44
|
return [nil, nil] unless event.instance_of?(@type) && dummy_handler.matches?(event)
|
45
45
|
|
46
|
-
should_delete = nil
|
47
46
|
should_delete = true if (@block && @block.call(event) != false) || !@block
|
48
47
|
|
49
48
|
[@key, should_delete]
|