rubycord 1.0.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 +7 -0
- data/lib/rubycord/allowed_mentions.rb +34 -0
- data/lib/rubycord/api/application.rb +200 -0
- data/lib/rubycord/api/channel.rb +597 -0
- data/lib/rubycord/api/interaction.rb +52 -0
- data/lib/rubycord/api/invite.rb +42 -0
- data/lib/rubycord/api/server.rb +557 -0
- data/lib/rubycord/api/user.rb +153 -0
- data/lib/rubycord/api/webhook.rb +138 -0
- data/lib/rubycord/api.rb +356 -0
- data/lib/rubycord/await.rb +49 -0
- data/lib/rubycord/bot.rb +1757 -0
- data/lib/rubycord/cache.rb +259 -0
- data/lib/rubycord/colour_rgb.rb +41 -0
- data/lib/rubycord/commands/command_bot.rb +519 -0
- data/lib/rubycord/commands/container.rb +110 -0
- data/lib/rubycord/commands/events.rb +9 -0
- data/lib/rubycord/commands/parser.rb +325 -0
- data/lib/rubycord/commands/rate_limiter.rb +142 -0
- data/lib/rubycord/container.rb +753 -0
- data/lib/rubycord/data/activity.rb +269 -0
- data/lib/rubycord/data/application.rb +48 -0
- data/lib/rubycord/data/attachment.rb +109 -0
- data/lib/rubycord/data/audit_logs.rb +343 -0
- data/lib/rubycord/data/channel.rb +996 -0
- data/lib/rubycord/data/component.rb +227 -0
- data/lib/rubycord/data/embed.rb +249 -0
- data/lib/rubycord/data/emoji.rb +80 -0
- data/lib/rubycord/data/integration.rb +120 -0
- data/lib/rubycord/data/interaction.rb +798 -0
- data/lib/rubycord/data/invite.rb +135 -0
- data/lib/rubycord/data/member.rb +370 -0
- data/lib/rubycord/data/message.rb +412 -0
- data/lib/rubycord/data/overwrite.rb +106 -0
- data/lib/rubycord/data/profile.rb +89 -0
- data/lib/rubycord/data/reaction.rb +31 -0
- data/lib/rubycord/data/recipient.rb +32 -0
- data/lib/rubycord/data/role.rb +246 -0
- data/lib/rubycord/data/server.rb +1002 -0
- data/lib/rubycord/data/user.rb +261 -0
- data/lib/rubycord/data/voice_region.rb +43 -0
- data/lib/rubycord/data/voice_state.rb +39 -0
- data/lib/rubycord/data/webhook.rb +232 -0
- data/lib/rubycord/data.rb +40 -0
- data/lib/rubycord/errors.rb +737 -0
- data/lib/rubycord/events/await.rb +46 -0
- data/lib/rubycord/events/bans.rb +58 -0
- data/lib/rubycord/events/channels.rb +186 -0
- data/lib/rubycord/events/generic.rb +126 -0
- data/lib/rubycord/events/guilds.rb +191 -0
- data/lib/rubycord/events/interactions.rb +480 -0
- data/lib/rubycord/events/invites.rb +123 -0
- data/lib/rubycord/events/lifetime.rb +29 -0
- data/lib/rubycord/events/members.rb +91 -0
- data/lib/rubycord/events/message.rb +337 -0
- data/lib/rubycord/events/presence.rb +127 -0
- data/lib/rubycord/events/raw.rb +45 -0
- data/lib/rubycord/events/reactions.rb +156 -0
- data/lib/rubycord/events/roles.rb +86 -0
- data/lib/rubycord/events/threads.rb +94 -0
- data/lib/rubycord/events/typing.rb +70 -0
- data/lib/rubycord/events/voice_server_update.rb +45 -0
- data/lib/rubycord/events/voice_state_update.rb +103 -0
- data/lib/rubycord/events/webhooks.rb +62 -0
- data/lib/rubycord/gateway.rb +867 -0
- data/lib/rubycord/id_object.rb +37 -0
- data/lib/rubycord/light/data.rb +60 -0
- data/lib/rubycord/light/integrations.rb +71 -0
- data/lib/rubycord/light/light_bot.rb +56 -0
- data/lib/rubycord/light.rb +6 -0
- data/lib/rubycord/logger.rb +118 -0
- data/lib/rubycord/paginator.rb +55 -0
- data/lib/rubycord/permissions.rb +251 -0
- data/lib/rubycord/version.rb +5 -0
- data/lib/rubycord/voice/encoder.rb +113 -0
- data/lib/rubycord/voice/network.rb +366 -0
- data/lib/rubycord/voice/sodium.rb +96 -0
- data/lib/rubycord/voice/voice_bot.rb +408 -0
- data/lib/rubycord/webhooks/builder.rb +100 -0
- data/lib/rubycord/webhooks/client.rb +132 -0
- data/lib/rubycord/webhooks/embeds.rb +248 -0
- data/lib/rubycord/webhooks/modal.rb +78 -0
- data/lib/rubycord/webhooks/version.rb +7 -0
- data/lib/rubycord/webhooks/view.rb +192 -0
- data/lib/rubycord/webhooks.rb +12 -0
- data/lib/rubycord/websocket.rb +70 -0
- data/lib/rubycord.rb +140 -0
- metadata +231 -0
@@ -0,0 +1,138 @@
|
|
1
|
+
# API calls for Webhook object
|
2
|
+
module Rubycord::API::Webhook
|
3
|
+
module_function
|
4
|
+
|
5
|
+
# Get a webhook
|
6
|
+
# https://discord.com/developers/docs/resources/webhook#get-webhook
|
7
|
+
def webhook(token, webhook_id)
|
8
|
+
Rubycord::API.request(
|
9
|
+
:webhooks_wid,
|
10
|
+
nil,
|
11
|
+
:get,
|
12
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}",
|
13
|
+
Authorization: token
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get a webhook via webhook token
|
18
|
+
# https://discord.com/developers/docs/resources/webhook#get-webhook-with-token
|
19
|
+
def token_webhook(webhook_token, webhook_id)
|
20
|
+
Rubycord::API.request(
|
21
|
+
:webhooks_wid,
|
22
|
+
nil,
|
23
|
+
:get,
|
24
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}"
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Execute a webhook via token.
|
29
|
+
# https://discord.com/developers/docs/resources/webhook#execute-webhook
|
30
|
+
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)
|
31
|
+
body = {content: content, username: username, avatar_url: avatar_url, tts: tts, embeds: embeds&.map(&:to_hash), allowed_mentions: allowed_mentions, flags: flags, components: components}
|
32
|
+
body = if file
|
33
|
+
{file: file, payload_json: body.to_json}
|
34
|
+
else
|
35
|
+
body.to_json
|
36
|
+
end
|
37
|
+
|
38
|
+
headers = {content_type: :json} unless file
|
39
|
+
|
40
|
+
Rubycord::API.request(
|
41
|
+
:webhooks_wid,
|
42
|
+
webhook_id,
|
43
|
+
:post,
|
44
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}?wait=#{wait}",
|
45
|
+
body,
|
46
|
+
headers
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Update a webhook
|
51
|
+
# https://discord.com/developers/docs/resources/webhook#modify-webhook
|
52
|
+
def update_webhook(token, webhook_id, data, reason = nil)
|
53
|
+
Rubycord::API.request(
|
54
|
+
:webhooks_wid,
|
55
|
+
webhook_id,
|
56
|
+
:patch,
|
57
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}",
|
58
|
+
data.to_json,
|
59
|
+
Authorization: token,
|
60
|
+
content_type: :json,
|
61
|
+
"X-Audit-Log-Reason": reason
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Update a webhook via webhook token
|
66
|
+
# https://discord.com/developers/docs/resources/webhook#modify-webhook-with-token
|
67
|
+
def token_update_webhook(webhook_token, webhook_id, data, reason = nil)
|
68
|
+
Rubycord::API.request(
|
69
|
+
:webhooks_wid,
|
70
|
+
webhook_id,
|
71
|
+
:patch,
|
72
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}",
|
73
|
+
data.to_json,
|
74
|
+
content_type: :json,
|
75
|
+
"X-Audit-Log-Reason": reason
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Deletes a webhook
|
80
|
+
# https://discord.com/developers/docs/resources/webhook#delete-webhook
|
81
|
+
def delete_webhook(token, webhook_id, reason = nil)
|
82
|
+
Rubycord::API.request(
|
83
|
+
:webhooks_wid,
|
84
|
+
webhook_id,
|
85
|
+
:delete,
|
86
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}",
|
87
|
+
Authorization: token,
|
88
|
+
"X-Audit-Log-Reason": reason
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Deletes a webhook via webhook token
|
93
|
+
# https://discord.com/developers/docs/resources/webhook#delete-webhook-with-token
|
94
|
+
def token_delete_webhook(webhook_token, webhook_id, reason = nil)
|
95
|
+
Rubycord::API.request(
|
96
|
+
:webhooks_wid,
|
97
|
+
webhook_id,
|
98
|
+
:delete,
|
99
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}",
|
100
|
+
"X-Audit-Log-Reason": reason
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Get a message that was created by the webhook corresponding to the provided token.
|
105
|
+
# https://discord.com/developers/docs/resources/webhook#get-webhook-message
|
106
|
+
def token_get_message(webhook_token, webhook_id, message_id)
|
107
|
+
Rubycord::API.request(
|
108
|
+
:webhooks_wid_messages_mid,
|
109
|
+
webhook_id,
|
110
|
+
:get,
|
111
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}"
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Edit a webhook message via webhook token
|
116
|
+
# https://discord.com/developers/docs/resources/webhook#edit-webhook-message
|
117
|
+
def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil)
|
118
|
+
Rubycord::API.request(
|
119
|
+
:webhooks_wid_messages,
|
120
|
+
webhook_id,
|
121
|
+
:patch,
|
122
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}",
|
123
|
+
{content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components}.to_json,
|
124
|
+
content_type: :json
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Delete a webhook message via webhook token.
|
129
|
+
# https://discord.com/developers/docs/resources/webhook#delete-webhook-message
|
130
|
+
def token_delete_message(webhook_token, webhook_id, message_id)
|
131
|
+
Rubycord::API.request(
|
132
|
+
:webhooks_wid_messages,
|
133
|
+
webhook_id,
|
134
|
+
:delete,
|
135
|
+
"#{Rubycord::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}"
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
data/lib/rubycord/api.rb
ADDED
@@ -0,0 +1,356 @@
|
|
1
|
+
require "rest-client"
|
2
|
+
require "json"
|
3
|
+
require "time"
|
4
|
+
|
5
|
+
require "rubycord/errors"
|
6
|
+
|
7
|
+
# List of methods representing endpoints in Discord's API
|
8
|
+
module Rubycord::API
|
9
|
+
# The base URL of the Discord REST API.
|
10
|
+
APIBASE = "https://discord.com/api/v9"
|
11
|
+
|
12
|
+
# The URL of Discord's CDN
|
13
|
+
CDN_URL = "https://cdn.discordapp.com"
|
14
|
+
|
15
|
+
module_function
|
16
|
+
|
17
|
+
# @return [String] the currently used API base URL.
|
18
|
+
def api_base
|
19
|
+
@api_base || APIBASE
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets the API base URL to something.
|
23
|
+
def api_base=(value)
|
24
|
+
@api_base = value
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [String] the currently used CDN url
|
28
|
+
def cdn_url
|
29
|
+
@cdn_url || CDN_URL
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [String] the bot name, previously specified using {.bot_name=}.
|
33
|
+
def bot_name
|
34
|
+
@bot_name
|
35
|
+
end
|
36
|
+
|
37
|
+
# Sets the bot name to something. Used in {.user_agent}. For the bot's username, see {Profile#username=}.
|
38
|
+
def bot_name=(value)
|
39
|
+
@bot_name = value
|
40
|
+
end
|
41
|
+
|
42
|
+
# Changes the rate limit tracing behaviour. If rate limit tracing is on, a full backtrace will be logged on every RL
|
43
|
+
# hit.
|
44
|
+
# @param value [true, false] whether or not to enable rate limit tracing
|
45
|
+
def trace=(value)
|
46
|
+
@trace = value
|
47
|
+
end
|
48
|
+
|
49
|
+
# Generate a user agent identifying this requester as rubycord.
|
50
|
+
def user_agent
|
51
|
+
# This particular string is required by the Discord devs.
|
52
|
+
required = "DiscordBot (https://github.com/dakurei-gems/rubycord, v#{Rubycord::VERSION})"
|
53
|
+
@bot_name ||= ""
|
54
|
+
|
55
|
+
"#{required} rest-client/#{RestClient::VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} rubycord/#{Rubycord::VERSION} #{@bot_name}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Resets all rate limit mutexes
|
59
|
+
def reset_mutexes
|
60
|
+
@mutexes = {}
|
61
|
+
@global_mutex = Mutex.new
|
62
|
+
end
|
63
|
+
|
64
|
+
# Wait a specified amount of time synchronised with the specified mutex.
|
65
|
+
def sync_wait(time, mutex)
|
66
|
+
mutex.synchronize { sleep time }
|
67
|
+
end
|
68
|
+
|
69
|
+
# Wait for a specified mutex to unlock and do nothing with it afterwards.
|
70
|
+
def mutex_wait(mutex)
|
71
|
+
mutex.lock
|
72
|
+
mutex.unlock
|
73
|
+
end
|
74
|
+
|
75
|
+
# Performs a RestClient request.
|
76
|
+
# @param type [Symbol] The type of HTTP request to use.
|
77
|
+
# @param attributes [Array] The attributes for the request.
|
78
|
+
def raw_request(type, attributes)
|
79
|
+
RestClient.send(type, *attributes)
|
80
|
+
rescue RestClient::Forbidden => e
|
81
|
+
# HACK: for #request, dynamically inject restclient's response into NoPermission - this allows us to rate limit
|
82
|
+
noprm = Rubycord::Errors::NoPermission.new
|
83
|
+
noprm.define_singleton_method(:_rc_response) { e.response }
|
84
|
+
raise noprm, "The bot doesn't have the required permission to do this!"
|
85
|
+
rescue RestClient::BadGateway
|
86
|
+
Rubycord::LOGGER.warn("Got a 502 while sending a request! Not a big deal, retrying the request")
|
87
|
+
retry
|
88
|
+
end
|
89
|
+
|
90
|
+
# Make an API request, including rate limit handling.
|
91
|
+
def request(key, major_parameter, type, *attributes)
|
92
|
+
# Add a custom user agent
|
93
|
+
attributes.last[:user_agent] = user_agent if attributes.last.is_a? Hash
|
94
|
+
|
95
|
+
# The most recent Discord rate limit requirements require the support of major parameters, where a particular route
|
96
|
+
# and major parameter combination (*not* the HTTP method) uniquely identifies a RL bucket.
|
97
|
+
key = [key, major_parameter].freeze
|
98
|
+
|
99
|
+
begin
|
100
|
+
mutex = @mutexes[key] ||= Mutex.new
|
101
|
+
|
102
|
+
# Lock and unlock, i.e. wait for the mutex to unlock and don't do anything with it afterwards
|
103
|
+
mutex_wait(mutex)
|
104
|
+
|
105
|
+
# If the global mutex happens to be locked right now, wait for that as well.
|
106
|
+
mutex_wait(@global_mutex) if @global_mutex.locked?
|
107
|
+
|
108
|
+
response = nil
|
109
|
+
begin
|
110
|
+
response = raw_request(type, attributes)
|
111
|
+
rescue RestClient::Exception => e
|
112
|
+
response = e.response
|
113
|
+
|
114
|
+
if response.body && !e.is_a?(RestClient::TooManyRequests)
|
115
|
+
data = JSON.parse(response.body)
|
116
|
+
err_klass = Rubycord::Errors.error_class_for(data["code"] || 0)
|
117
|
+
e = err_klass.new(data["message"], data["errors"])
|
118
|
+
|
119
|
+
Rubycord::LOGGER.error(e.full_message)
|
120
|
+
end
|
121
|
+
|
122
|
+
raise e
|
123
|
+
rescue Rubycord::Errors::NoPermission => e
|
124
|
+
if e.respond_to?(:_rc_response)
|
125
|
+
response = e._rc_response
|
126
|
+
else
|
127
|
+
Rubycord::LOGGER.warn("NoPermission doesn't respond_to? _rc_response!")
|
128
|
+
end
|
129
|
+
|
130
|
+
raise e
|
131
|
+
ensure
|
132
|
+
if response
|
133
|
+
handle_preemptive_rl(response.headers, mutex, key) if response.headers[:x_ratelimit_remaining] == "0" && !mutex.locked?
|
134
|
+
else
|
135
|
+
Rubycord::LOGGER.ratelimit("Response was nil before trying to preemptively rate limit!")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
rescue RestClient::TooManyRequests => e
|
139
|
+
# If the 429 is from the global RL, then we have to use the global mutex instead.
|
140
|
+
mutex = @global_mutex if e.response.headers[:x_ratelimit_global] == "true"
|
141
|
+
|
142
|
+
unless mutex.locked?
|
143
|
+
response = JSON.parse(e.response)
|
144
|
+
wait_seconds = response["retry_after"] ? response["retry_after"].to_f : e.response.headers[:retry_after].to_i
|
145
|
+
Rubycord::LOGGER.ratelimit("Locking RL mutex (key: #{key}) for #{wait_seconds} seconds due to Discord rate limiting")
|
146
|
+
trace("429 #{key.join(" ")}")
|
147
|
+
|
148
|
+
# Wait the required time synchronized by the mutex (so other incoming requests have to wait) but only do it if
|
149
|
+
# the mutex isn't locked already so it will only ever wait once
|
150
|
+
sync_wait(wait_seconds, mutex)
|
151
|
+
end
|
152
|
+
|
153
|
+
retry
|
154
|
+
end
|
155
|
+
|
156
|
+
response
|
157
|
+
end
|
158
|
+
|
159
|
+
# Handles pre-emptive rate limiting by waiting the given mutex by the difference of the Date header to the
|
160
|
+
# X-Ratelimit-Reset header, thus making sure we don't get 429'd in any subsequent requests.
|
161
|
+
def handle_preemptive_rl(headers, mutex, key)
|
162
|
+
Rubycord::LOGGER.ratelimit "RL bucket depletion detected! Date: #{headers[:date]} Reset: #{headers[:x_ratelimit_reset]}"
|
163
|
+
delta = headers[:x_ratelimit_reset_after].to_f
|
164
|
+
Rubycord::LOGGER.warn("Locking RL mutex (key: #{key}) for #{delta} seconds pre-emptively")
|
165
|
+
sync_wait(delta, mutex)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Perform rate limit tracing. All this method does is log the current backtrace to the console with the `:ratelimit`
|
169
|
+
# level.
|
170
|
+
# @param reason [String] the reason to include with the backtrace.
|
171
|
+
def trace(reason)
|
172
|
+
unless @trace
|
173
|
+
Rubycord::LOGGER.debug("trace was called with reason #{reason}, but tracing is not enabled")
|
174
|
+
return
|
175
|
+
end
|
176
|
+
|
177
|
+
Rubycord::LOGGER.ratelimit("Trace (#{reason}):")
|
178
|
+
|
179
|
+
caller.each do |str|
|
180
|
+
Rubycord::LOGGER.ratelimit(" #{str}")
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Make an icon URL from server and icon IDs
|
185
|
+
def icon_url(server_id, icon_id, format = "webp")
|
186
|
+
"#{cdn_url}/icons/#{server_id}/#{icon_id}.#{format}"
|
187
|
+
end
|
188
|
+
|
189
|
+
# Make an icon URL from application and icon IDs
|
190
|
+
def app_icon_url(app_id, icon_id, format = "webp")
|
191
|
+
"#{cdn_url}/app-icons/#{app_id}/#{icon_id}.#{format}"
|
192
|
+
end
|
193
|
+
|
194
|
+
# Make a widget picture URL from server ID
|
195
|
+
def widget_url(server_id, style = "shield")
|
196
|
+
"#{api_base}/guilds/#{server_id}/widget.png?style=#{style}"
|
197
|
+
end
|
198
|
+
|
199
|
+
# Make a splash URL from server and splash IDs
|
200
|
+
def splash_url(server_id, splash_id, format = "webp")
|
201
|
+
"#{cdn_url}/splashes/#{server_id}/#{splash_id}.#{format}"
|
202
|
+
end
|
203
|
+
|
204
|
+
# Make a banner URL from server and banner IDs
|
205
|
+
def banner_url(server_id, banner_id, format = "webp")
|
206
|
+
"#{cdn_url}/banners/#{server_id}/#{banner_id}.#{format}"
|
207
|
+
end
|
208
|
+
|
209
|
+
# Make an emoji icon URL from emoji ID
|
210
|
+
def emoji_icon_url(emoji_id, format = "webp")
|
211
|
+
"#{cdn_url}/emojis/#{emoji_id}.#{format}"
|
212
|
+
end
|
213
|
+
|
214
|
+
# Make an asset URL from application and asset IDs
|
215
|
+
def asset_url(application_id, asset_id, format = "webp")
|
216
|
+
"#{cdn_url}/app-assets/#{application_id}/#{asset_id}.#{format}"
|
217
|
+
end
|
218
|
+
|
219
|
+
# Make an achievement icon URL from application ID, achievement ID, and icon hash
|
220
|
+
def achievement_icon_url(application_id, achievement_id, icon_hash, format = "webp")
|
221
|
+
"#{cdn_url}/app-assets/#{application_id}/achievements/#{achievement_id}/icons/#{icon_hash}.#{format}"
|
222
|
+
end
|
223
|
+
|
224
|
+
# @param role_id [String, Integer]
|
225
|
+
# @param icon_hash [String]
|
226
|
+
# @param format ['webp', 'png', 'jpeg']
|
227
|
+
# @return [String]
|
228
|
+
def role_icon_url(role_id, icon_hash, format = "webp")
|
229
|
+
"#{cdn_url}/role-icons/#{role_id}/#{icon_hash}.#{format}"
|
230
|
+
end
|
231
|
+
|
232
|
+
# Login to the server
|
233
|
+
def login(email, password)
|
234
|
+
request(
|
235
|
+
:auth_login,
|
236
|
+
nil,
|
237
|
+
:post,
|
238
|
+
"#{api_base}/auth/login",
|
239
|
+
email: email,
|
240
|
+
password: password
|
241
|
+
)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Logout from the server
|
245
|
+
def logout(token)
|
246
|
+
request(
|
247
|
+
:auth_logout,
|
248
|
+
nil,
|
249
|
+
:post,
|
250
|
+
"#{api_base}/auth/logout",
|
251
|
+
nil,
|
252
|
+
Authorization: token
|
253
|
+
)
|
254
|
+
end
|
255
|
+
|
256
|
+
# Create an OAuth application
|
257
|
+
def create_oauth_application(token, name, redirect_uris)
|
258
|
+
request(
|
259
|
+
:oauth2_applications,
|
260
|
+
nil,
|
261
|
+
:post,
|
262
|
+
"#{api_base}/oauth2/applications",
|
263
|
+
{name: name, redirect_uris: redirect_uris}.to_json,
|
264
|
+
Authorization: token,
|
265
|
+
content_type: :json
|
266
|
+
)
|
267
|
+
end
|
268
|
+
|
269
|
+
# Change an OAuth application's properties
|
270
|
+
def update_oauth_application(token, name, redirect_uris, description = "", icon = nil)
|
271
|
+
request(
|
272
|
+
:oauth2_applications,
|
273
|
+
nil,
|
274
|
+
:put,
|
275
|
+
"#{api_base}/oauth2/applications",
|
276
|
+
{name: name, redirect_uris: redirect_uris, description: description, icon: icon}.to_json,
|
277
|
+
Authorization: token,
|
278
|
+
content_type: :json
|
279
|
+
)
|
280
|
+
end
|
281
|
+
|
282
|
+
# Get the bot's OAuth application's information
|
283
|
+
def oauth_application(token)
|
284
|
+
request(
|
285
|
+
:oauth2_applications_me,
|
286
|
+
nil,
|
287
|
+
:get,
|
288
|
+
"#{api_base}/oauth2/applications/@me",
|
289
|
+
Authorization: token
|
290
|
+
)
|
291
|
+
end
|
292
|
+
|
293
|
+
# Acknowledge that a message has been received
|
294
|
+
# The last acknowledged message will be sent in the ready packet,
|
295
|
+
# so this is an easy way to catch up on messages
|
296
|
+
def acknowledge_message(token, channel_id, message_id)
|
297
|
+
request(
|
298
|
+
:channels_cid_messages_mid_ack,
|
299
|
+
nil, # This endpoint is unavailable for bot accounts and thus isn't subject to its rate limit requirements.
|
300
|
+
:post,
|
301
|
+
"#{api_base}/channels/#{channel_id}/messages/#{message_id}/ack",
|
302
|
+
nil,
|
303
|
+
Authorization: token
|
304
|
+
)
|
305
|
+
end
|
306
|
+
|
307
|
+
# Get the gateway to be used
|
308
|
+
def gateway(token)
|
309
|
+
request(
|
310
|
+
:gateway,
|
311
|
+
nil,
|
312
|
+
:get,
|
313
|
+
"#{api_base}/gateway",
|
314
|
+
Authorization: token
|
315
|
+
)
|
316
|
+
end
|
317
|
+
|
318
|
+
# Get the gateway to be used, with additional information for sharding and
|
319
|
+
# session start limits
|
320
|
+
def gateway_bot(token)
|
321
|
+
request(
|
322
|
+
:gateway_bot,
|
323
|
+
nil,
|
324
|
+
:get,
|
325
|
+
"#{api_base}/gateway/bot",
|
326
|
+
Authorization: token
|
327
|
+
)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Validate a token (this request will fail if the token is invalid)
|
331
|
+
def validate_token(token)
|
332
|
+
request(
|
333
|
+
:auth_login,
|
334
|
+
nil,
|
335
|
+
:post,
|
336
|
+
"#{api_base}/auth/login",
|
337
|
+
{}.to_json,
|
338
|
+
Authorization: token,
|
339
|
+
content_type: :json
|
340
|
+
)
|
341
|
+
end
|
342
|
+
|
343
|
+
# Get a list of available voice regions
|
344
|
+
def voice_regions(token)
|
345
|
+
request(
|
346
|
+
:voice_regions,
|
347
|
+
nil,
|
348
|
+
:get,
|
349
|
+
"#{api_base}/voice/regions",
|
350
|
+
Authorization: token,
|
351
|
+
content_type: :json
|
352
|
+
)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
Rubycord::API.reset_mutexes
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rubycord
|
2
|
+
# Awaits are a way to register new, temporary event handlers on the fly. Awaits can be
|
3
|
+
# registered using {Bot#add_await}, {User#await}, {Message#await} and {Channel#await}.
|
4
|
+
#
|
5
|
+
# Awaits contain a block that will be called before the await event will be triggered.
|
6
|
+
# If this block returns anything that is not `false` exactly, the await will be deleted.
|
7
|
+
# If no block is present, the await will also be deleted. This is an easy way to make
|
8
|
+
# temporary events that are only temporary under certain conditions.
|
9
|
+
#
|
10
|
+
# Besides the given block, an {Rubycord::Events::AwaitEvent} will also be executed with the key and
|
11
|
+
# the type of the await that was triggered. It's possible to register multiple events
|
12
|
+
# that trigger on the same await.
|
13
|
+
class Await
|
14
|
+
# The key that uniquely identifies this await.
|
15
|
+
# @return [Symbol] The unique key.
|
16
|
+
attr_reader :key
|
17
|
+
|
18
|
+
# The class of the event that this await listens for.
|
19
|
+
# @return [Class] The event class.
|
20
|
+
attr_reader :type
|
21
|
+
|
22
|
+
# The attributes of the event that will be listened for.
|
23
|
+
# @return [Hash] A hash of attributes.
|
24
|
+
attr_reader :attributes
|
25
|
+
|
26
|
+
# Makes a new await. For internal use only.
|
27
|
+
# @!visibility private
|
28
|
+
def initialize(bot, key, type, attributes, block = nil)
|
29
|
+
@bot = bot
|
30
|
+
@key = key
|
31
|
+
@type = type
|
32
|
+
@attributes = attributes
|
33
|
+
@block = block
|
34
|
+
end
|
35
|
+
|
36
|
+
# Checks whether the await can be triggered by the given event, and if it can, execute the block
|
37
|
+
# and return its result along with this await's key.
|
38
|
+
# @param event [Event] An event to check for.
|
39
|
+
# @return [Array] This await's key and whether or not it should be deleted. If there was no match, both are nil.
|
40
|
+
def match(event)
|
41
|
+
dummy_handler = EventContainer.handler_class(@type).new(@attributes, @bot)
|
42
|
+
return [nil, nil] unless event.instance_of?(@type) && dummy_handler.matches?(event)
|
43
|
+
|
44
|
+
should_delete = true if (@block && @block.call(event) != false) || !@block
|
45
|
+
|
46
|
+
[@key, should_delete]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|