rubycord 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|