discordrb 3.3.0 → 3.5.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.
- 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]
|