discordrb 3.1.1 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of discordrb might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.circleci/config.yml +126 -0
- data/.codeclimate.yml +16 -0
- data/.github/CONTRIBUTING.md +13 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
- data/.github/pull_request_template.md +37 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +39 -33
- data/.travis.yml +27 -2
- data/.yardopts +1 -1
- data/CHANGELOG.md +808 -208
- data/Gemfile +4 -1
- data/LICENSE.txt +1 -1
- data/README.md +108 -53
- data/Rakefile +14 -1
- data/bin/console +1 -0
- data/bin/travis_build_docs.sh +17 -0
- data/discordrb-webhooks.gemspec +26 -0
- data/discordrb.gemspec +24 -15
- data/lib/discordrb.rb +75 -2
- data/lib/discordrb/allowed_mentions.rb +36 -0
- data/lib/discordrb/api.rb +126 -27
- data/lib/discordrb/api/channel.rb +165 -43
- data/lib/discordrb/api/invite.rb +10 -7
- data/lib/discordrb/api/server.rb +240 -61
- data/lib/discordrb/api/user.rb +26 -24
- data/lib/discordrb/api/webhook.rb +83 -0
- data/lib/discordrb/await.rb +1 -2
- data/lib/discordrb/bot.rb +417 -149
- data/lib/discordrb/cache.rb +42 -10
- data/lib/discordrb/colour_rgb.rb +43 -0
- data/lib/discordrb/commands/command_bot.rb +186 -31
- data/lib/discordrb/commands/container.rb +30 -16
- data/lib/discordrb/commands/parser.rb +102 -47
- data/lib/discordrb/commands/rate_limiter.rb +18 -17
- data/lib/discordrb/container.rb +245 -41
- data/lib/discordrb/data.rb +27 -2511
- data/lib/discordrb/data/activity.rb +264 -0
- data/lib/discordrb/data/application.rb +50 -0
- data/lib/discordrb/data/attachment.rb +56 -0
- data/lib/discordrb/data/audit_logs.rb +345 -0
- data/lib/discordrb/data/channel.rb +849 -0
- data/lib/discordrb/data/embed.rb +251 -0
- data/lib/discordrb/data/emoji.rb +82 -0
- data/lib/discordrb/data/integration.rb +83 -0
- data/lib/discordrb/data/invite.rb +137 -0
- data/lib/discordrb/data/member.rb +297 -0
- data/lib/discordrb/data/message.rb +334 -0
- data/lib/discordrb/data/overwrite.rb +102 -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 +191 -0
- data/lib/discordrb/data/server.rb +1002 -0
- data/lib/discordrb/data/user.rb +204 -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 +145 -0
- data/lib/discordrb/errors.rb +36 -2
- data/lib/discordrb/events/bans.rb +7 -5
- data/lib/discordrb/events/channels.rb +2 -0
- data/lib/discordrb/events/generic.rb +19 -3
- data/lib/discordrb/events/guilds.rb +129 -6
- data/lib/discordrb/events/invites.rb +125 -0
- data/lib/discordrb/events/members.rb +6 -2
- data/lib/discordrb/events/message.rb +86 -36
- data/lib/discordrb/events/presence.rb +23 -16
- data/lib/discordrb/events/raw.rb +47 -0
- data/lib/discordrb/events/reactions.rb +159 -0
- data/lib/discordrb/events/roles.rb +7 -6
- data/lib/discordrb/events/typing.rb +9 -5
- data/lib/discordrb/events/voice_server_update.rb +47 -0
- data/lib/discordrb/events/voice_state_update.rb +29 -9
- data/lib/discordrb/events/webhooks.rb +64 -0
- data/lib/discordrb/gateway.rb +219 -88
- data/lib/discordrb/id_object.rb +39 -0
- data/lib/discordrb/light.rb +1 -1
- data/lib/discordrb/light/integrations.rb +1 -1
- data/lib/discordrb/light/light_bot.rb +1 -1
- data/lib/discordrb/logger.rb +12 -11
- data/lib/discordrb/paginator.rb +57 -0
- data/lib/discordrb/permissions.rb +148 -14
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +14 -15
- data/lib/discordrb/voice/network.rb +86 -45
- data/lib/discordrb/voice/sodium.rb +96 -0
- data/lib/discordrb/voice/voice_bot.rb +52 -40
- data/lib/discordrb/webhooks.rb +12 -0
- data/lib/discordrb/websocket.rb +2 -2
- metadata +137 -34
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'discordrb/id_object'
|
4
|
+
|
5
|
+
module Discordrb
|
6
|
+
# Builder class for `allowed_mentions` when sending messages.
|
7
|
+
class AllowedMentions
|
8
|
+
# @return [Array<"users", "roles", "everyone">, nil]
|
9
|
+
attr_accessor :parse
|
10
|
+
|
11
|
+
# @return [Array<String, Integer>, nil]
|
12
|
+
attr_accessor :users
|
13
|
+
|
14
|
+
# @return [Array<String, Integer>, nil]
|
15
|
+
attr_accessor :roles
|
16
|
+
|
17
|
+
# @param parse [Array<"users", "roles", "everyone">] Mention types that can be inferred from the message.
|
18
|
+
# `users` and `roles` allow for all mentions of the respective type to ping. `everyone` allows usage of `@everyone` and `@here`
|
19
|
+
# @param users [Array<User, String, Integer>] Users or user IDs that can be pinged. Cannot be used in conjunction with `"users"` in `parse`
|
20
|
+
# @param roles [Array<Role, String, Integer>] Roles or role IDs that can be pinged. Cannot be used in conjunction with `"roles"` in `parse`
|
21
|
+
def initialize(parse: nil, users: nil, roles: nil)
|
22
|
+
@parse = parse
|
23
|
+
@users = users
|
24
|
+
@roles = roles
|
25
|
+
end
|
26
|
+
|
27
|
+
# @!visibility private
|
28
|
+
def to_hash
|
29
|
+
{
|
30
|
+
parse: @parse,
|
31
|
+
users: @users&.map { |user| user.is_a?(IDObject) ? user.id : user },
|
32
|
+
roles: @roles&.map { |role| role.is_a?(IDObject) ? role.id : role }
|
33
|
+
}.compact
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/discordrb/api.rb
CHANGED
@@ -9,7 +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/v6'
|
13
|
+
|
14
|
+
# The URL of Discord's CDN
|
15
|
+
CDN_URL = 'https://cdn.discordapp.com'
|
13
16
|
|
14
17
|
module_function
|
15
18
|
|
@@ -23,23 +26,35 @@ module Discordrb::API
|
|
23
26
|
@api_base = value
|
24
27
|
end
|
25
28
|
|
26
|
-
# @return [String] the
|
29
|
+
# @return [String] the currently used CDN url
|
30
|
+
def cdn_url
|
31
|
+
@cdn_url || CDN_URL
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [String] the bot name, previously specified using {.bot_name=}.
|
27
35
|
def bot_name
|
28
36
|
@bot_name
|
29
37
|
end
|
30
38
|
|
31
|
-
# 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=}.
|
32
40
|
def bot_name=(value)
|
33
41
|
@bot_name = value
|
34
42
|
end
|
35
43
|
|
44
|
+
# Changes the rate limit tracing behaviour. If rate limit tracing is on, a full backtrace will be logged on every RL
|
45
|
+
# hit.
|
46
|
+
# @param value [true, false] whether or not to enable rate limit tracing
|
47
|
+
def trace=(value)
|
48
|
+
@trace = value
|
49
|
+
end
|
50
|
+
|
36
51
|
# Generate a user agent identifying this requester as discordrb.
|
37
52
|
def user_agent
|
38
53
|
# This particular string is required by the Discord devs.
|
39
|
-
required = "DiscordBot (https://github.com/
|
54
|
+
required = "DiscordBot (https://github.com/shardlab/discordrb, v#{Discordrb::VERSION})"
|
40
55
|
@bot_name ||= ''
|
41
56
|
|
42
|
-
"rest-client/#{RestClient::VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} discordrb/#{Discordrb::VERSION} #{
|
57
|
+
"#{required} rest-client/#{RestClient::VERSION} #{RUBY_ENGINE}/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} discordrb/#{Discordrb::VERSION} #{@bot_name}"
|
43
58
|
end
|
44
59
|
|
45
60
|
# Resets all rate limit mutexes
|
@@ -64,8 +79,11 @@ module Discordrb::API
|
|
64
79
|
# @param attributes [Array] The attributes for the request.
|
65
80
|
def raw_request(type, attributes)
|
66
81
|
RestClient.send(type, *attributes)
|
67
|
-
rescue RestClient::Forbidden
|
68
|
-
|
82
|
+
rescue RestClient::Forbidden => e
|
83
|
+
# HACK: for #request, dynamically inject restclient's response into NoPermission - this allows us to rate limit
|
84
|
+
noprm = Discordrb::Errors::NoPermission.new
|
85
|
+
noprm.define_singleton_method(:_rc_response) { e.response }
|
86
|
+
raise noprm, "The bot doesn't have the required permission to do this!"
|
69
87
|
rescue RestClient::BadGateway
|
70
88
|
Discordrb::LOGGER.warn('Got a 502 while sending a request! Not a big deal, retrying the request')
|
71
89
|
retry
|
@@ -76,6 +94,9 @@ module Discordrb::API
|
|
76
94
|
# Add a custom user agent
|
77
95
|
attributes.last[:user_agent] = user_agent if attributes.last.is_a? Hash
|
78
96
|
|
97
|
+
# Specify RateLimit precision
|
98
|
+
attributes.last[:x_ratelimit_precision] = 'millisecond'
|
99
|
+
|
79
100
|
# The most recent Discord rate limit requirements require the support of major parameters, where a particular route
|
80
101
|
# and major parameter combination (*not* the HTTP method) uniquely identifies a RL bucket.
|
81
102
|
key = [key, major_parameter].freeze
|
@@ -83,24 +104,32 @@ module Discordrb::API
|
|
83
104
|
begin
|
84
105
|
mutex = @mutexes[key] ||= Mutex.new
|
85
106
|
|
86
|
-
# Lock and unlock, i.
|
107
|
+
# Lock and unlock, i.e. wait for the mutex to unlock and don't do anything with it afterwards
|
87
108
|
mutex_wait(mutex)
|
88
109
|
|
89
110
|
# If the global mutex happens to be locked right now, wait for that as well.
|
90
111
|
mutex_wait(@global_mutex) if @global_mutex.locked?
|
91
112
|
|
92
|
-
response =
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
113
|
+
response = nil
|
114
|
+
begin
|
115
|
+
response = raw_request(type, attributes)
|
116
|
+
rescue RestClient::Exception => e
|
117
|
+
response = e.response
|
118
|
+
raise e
|
119
|
+
rescue Discordrb::Errors::NoPermission => e
|
120
|
+
if e.respond_to?(:_rc_response)
|
121
|
+
response = e._rc_response
|
122
|
+
else
|
123
|
+
Discordrb::LOGGER.warn("NoPermission doesn't respond_to? _rc_response!")
|
124
|
+
end
|
125
|
+
|
126
|
+
raise e
|
127
|
+
ensure
|
128
|
+
if response
|
129
|
+
handle_preemptive_rl(response.headers, mutex, key) if response.headers[:x_ratelimit_remaining] == '0' && !mutex.locked?
|
130
|
+
else
|
131
|
+
Discordrb::LOGGER.ratelimit('Response was nil before trying to preemptively rate limit!')
|
132
|
+
end
|
104
133
|
end
|
105
134
|
rescue RestClient::TooManyRequests => e
|
106
135
|
# If the 429 is from the global RL, then we have to use the global mutex instead.
|
@@ -109,7 +138,8 @@ module Discordrb::API
|
|
109
138
|
unless mutex.locked?
|
110
139
|
response = JSON.parse(e.response)
|
111
140
|
wait_seconds = response['retry_after'].to_i / 1000.0
|
112
|
-
Discordrb::LOGGER.
|
141
|
+
Discordrb::LOGGER.ratelimit("Locking RL mutex (key: #{key}) for #{wait_seconds} seconds due to Discord rate limiting")
|
142
|
+
trace("429 #{key.join(' ')}")
|
113
143
|
|
114
144
|
# Wait the required time synchronized by the mutex (so other incoming requests have to wait) but only do it if
|
115
145
|
# the mutex isn't locked already so it will only ever wait once
|
@@ -122,14 +152,39 @@ module Discordrb::API
|
|
122
152
|
response
|
123
153
|
end
|
124
154
|
|
155
|
+
# Handles pre-emptive rate limiting by waiting the given mutex by the difference of the Date header to the
|
156
|
+
# X-Ratelimit-Reset header, thus making sure we don't get 429'd in any subsequent requests.
|
157
|
+
def handle_preemptive_rl(headers, mutex, key)
|
158
|
+
Discordrb::LOGGER.ratelimit "RL bucket depletion detected! Date: #{headers[:date]} Reset: #{headers[:x_ratelimit_reset]}"
|
159
|
+
delta = headers[:x_ratelimit_reset_after].to_f
|
160
|
+
Discordrb::LOGGER.warn("Locking RL mutex (key: #{key}) for #{delta} seconds pre-emptively")
|
161
|
+
sync_wait(delta, mutex)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Perform rate limit tracing. All this method does is log the current backtrace to the console with the `:ratelimit`
|
165
|
+
# level.
|
166
|
+
# @param reason [String] the reason to include with the backtrace.
|
167
|
+
def trace(reason)
|
168
|
+
unless @trace
|
169
|
+
Discordrb::LOGGER.debug("trace was called with reason #{reason}, but tracing is not enabled")
|
170
|
+
return
|
171
|
+
end
|
172
|
+
|
173
|
+
Discordrb::LOGGER.ratelimit("Trace (#{reason}):")
|
174
|
+
|
175
|
+
caller.each do |str|
|
176
|
+
Discordrb::LOGGER.ratelimit(" #{str}")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
125
180
|
# Make an icon URL from server and icon IDs
|
126
|
-
def icon_url(server_id, icon_id)
|
127
|
-
"#{
|
181
|
+
def icon_url(server_id, icon_id, format = 'webp')
|
182
|
+
"#{cdn_url}/icons/#{server_id}/#{icon_id}.#{format}"
|
128
183
|
end
|
129
184
|
|
130
185
|
# Make an icon URL from application and icon IDs
|
131
|
-
def app_icon_url(app_id, icon_id)
|
132
|
-
"
|
186
|
+
def app_icon_url(app_id, icon_id, format = 'webp')
|
187
|
+
"#{cdn_url}/app-icons/#{app_id}/#{icon_id}.#{format}"
|
133
188
|
end
|
134
189
|
|
135
190
|
# Make a widget picture URL from server ID
|
@@ -137,9 +192,29 @@ module Discordrb::API
|
|
137
192
|
"#{api_base}/guilds/#{server_id}/widget.png?style=#{style}"
|
138
193
|
end
|
139
194
|
|
195
|
+
# Make a splash URL from server and splash IDs
|
196
|
+
def splash_url(server_id, splash_id, format = 'webp')
|
197
|
+
"#{cdn_url}/splashes/#{server_id}/#{splash_id}.#{format}"
|
198
|
+
end
|
199
|
+
|
200
|
+
# Make a banner URL from server and banner IDs
|
201
|
+
def banner_url(server_id, banner_id, format = 'webp')
|
202
|
+
"#{cdn_url}/banners/#{server_id}/#{banner_id}.#{format}"
|
203
|
+
end
|
204
|
+
|
140
205
|
# Make an emoji icon URL from emoji ID
|
141
|
-
def emoji_icon_url(emoji_id)
|
142
|
-
"
|
206
|
+
def emoji_icon_url(emoji_id, format = 'webp')
|
207
|
+
"#{cdn_url}/emojis/#{emoji_id}.#{format}"
|
208
|
+
end
|
209
|
+
|
210
|
+
# Make an asset URL from application and asset IDs
|
211
|
+
def asset_url(application_id, asset_id, format = 'webp')
|
212
|
+
"#{cdn_url}/app-assets/#{application_id}/#{asset_id}.#{format}"
|
213
|
+
end
|
214
|
+
|
215
|
+
# Make an achievement icon URL from application ID, achievement ID, and icon hash
|
216
|
+
def achievement_icon_url(application_id, achievement_id, icon_hash, format = 'webp')
|
217
|
+
"#{cdn_url}/app-assets/#{application_id}/achievements/#{achievement_id}/icons/#{icon_hash}.#{format}"
|
143
218
|
end
|
144
219
|
|
145
220
|
# Login to the server
|
@@ -228,6 +303,18 @@ module Discordrb::API
|
|
228
303
|
)
|
229
304
|
end
|
230
305
|
|
306
|
+
# Get the gateway to be used, with additional information for sharding and
|
307
|
+
# session start limits
|
308
|
+
def gateway_bot(token)
|
309
|
+
request(
|
310
|
+
:gateway_bot,
|
311
|
+
nil,
|
312
|
+
:get,
|
313
|
+
"#{api_base}/gateway/bot",
|
314
|
+
Authorization: token
|
315
|
+
)
|
316
|
+
end
|
317
|
+
|
231
318
|
# Validate a token (this request will fail if the token is invalid)
|
232
319
|
def validate_token(token)
|
233
320
|
request(
|
@@ -240,6 +327,18 @@ module Discordrb::API
|
|
240
327
|
content_type: :json
|
241
328
|
)
|
242
329
|
end
|
330
|
+
|
331
|
+
# Get a list of available voice regions
|
332
|
+
def voice_regions(token)
|
333
|
+
request(
|
334
|
+
:voice_regions,
|
335
|
+
nil,
|
336
|
+
:get,
|
337
|
+
"#{api_base}/voice/regions",
|
338
|
+
Authorization: token,
|
339
|
+
content_type: :json
|
340
|
+
)
|
341
|
+
end
|
243
342
|
end
|
244
343
|
|
245
344
|
Discordrb::API.reset_mutexes
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# API calls for Channel
|
2
4
|
module Discordrb::API::Channel
|
3
5
|
module_function
|
4
6
|
|
5
7
|
# Get a channel's data
|
6
|
-
# https://
|
8
|
+
# https://discord.com/developers/docs/resources/channel#get-channel
|
7
9
|
def resolve(token, channel_id)
|
8
10
|
Discordrb::API.request(
|
9
11
|
:channels_cid,
|
@@ -15,45 +17,49 @@ module Discordrb::API::Channel
|
|
15
17
|
end
|
16
18
|
|
17
19
|
# Update a channel's data
|
18
|
-
# https://
|
19
|
-
def update(token, channel_id, name, topic, position, bitrate, user_limit)
|
20
|
+
# https://discord.com/developers/docs/resources/channel#modify-channel
|
21
|
+
def update(token, channel_id, name, topic, position, bitrate, user_limit, nsfw, permission_overwrites = nil, parent_id = nil, rate_limit_per_user = nil, reason = nil)
|
22
|
+
data = { name: name, position: position, topic: topic, bitrate: bitrate, user_limit: user_limit, nsfw: nsfw, parent_id: parent_id, rate_limit_per_user: rate_limit_per_user }
|
23
|
+
data[:permission_overwrites] = permission_overwrites unless permission_overwrites.nil?
|
20
24
|
Discordrb::API.request(
|
21
25
|
:channels_cid,
|
22
26
|
channel_id,
|
23
27
|
:patch,
|
24
28
|
"#{Discordrb::API.api_base}/channels/#{channel_id}",
|
25
|
-
|
29
|
+
data.to_json,
|
26
30
|
Authorization: token,
|
27
|
-
content_type: :json
|
31
|
+
content_type: :json,
|
32
|
+
'X-Audit-Log-Reason': reason
|
28
33
|
)
|
29
34
|
end
|
30
35
|
|
31
36
|
# Delete a channel
|
32
|
-
# https://
|
33
|
-
def delete(token, channel_id)
|
37
|
+
# https://discord.com/developers/docs/resources/channel#deleteclose-channel
|
38
|
+
def delete(token, channel_id, reason = nil)
|
34
39
|
Discordrb::API.request(
|
35
40
|
:channels_cid,
|
36
41
|
channel_id,
|
37
42
|
:delete,
|
38
43
|
"#{Discordrb::API.api_base}/channels/#{channel_id}",
|
39
|
-
Authorization: token
|
44
|
+
Authorization: token,
|
45
|
+
'X-Audit-Log-Reason': reason
|
40
46
|
)
|
41
47
|
end
|
42
48
|
|
43
49
|
# Get a list of messages from a channel's history
|
44
|
-
# https://
|
45
|
-
def messages(token, channel_id, amount, before = nil, after = nil)
|
50
|
+
# https://discord.com/developers/docs/resources/channel#get-channel-messages
|
51
|
+
def messages(token, channel_id, amount, before = nil, after = nil, around = nil)
|
46
52
|
Discordrb::API.request(
|
47
53
|
:channels_cid_messages,
|
48
54
|
channel_id,
|
49
55
|
:get,
|
50
|
-
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages?limit=#{amount}#{"&before=#{before}" if before}#{"&after=#{after}" if after}",
|
56
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages?limit=#{amount}#{"&before=#{before}" if before}#{"&after=#{after}" if after}#{"&around=#{around}" if around}",
|
51
57
|
Authorization: token
|
52
58
|
)
|
53
59
|
end
|
54
60
|
|
55
61
|
# Get a single message from a channel's history by id
|
56
|
-
# https://
|
62
|
+
# https://discord.com/developers/docs/resources/channel#get-channel-message
|
57
63
|
def message(token, channel_id, message_id)
|
58
64
|
Discordrb::API.request(
|
59
65
|
:channels_cid_messages_mid,
|
@@ -66,22 +72,37 @@ module Discordrb::API::Channel
|
|
66
72
|
|
67
73
|
# Send a message to a channel
|
68
74
|
# https://discordapp.com/developers/docs/resources/channel#create-message
|
69
|
-
|
75
|
+
# @param attachments [Array<File>, nil] Attachments to use with `attachment://` in embeds. See
|
76
|
+
# https://discord.com/developers/docs/resources/channel#create-message-using-attachments-within-embeds
|
77
|
+
def create_message(token, channel_id, message, tts = false, embed = nil, nonce = nil, attachments = nil, allowed_mentions = nil, message_reference = nil)
|
78
|
+
body = { content: message, tts: tts, embed: embed, nonce: nonce, allowed_mentions: allowed_mentions, message_reference: message_reference }
|
79
|
+
body = if attachments
|
80
|
+
files = [*0...attachments.size].zip(attachments).to_h
|
81
|
+
{ **files, payload_json: body.to_json }
|
82
|
+
else
|
83
|
+
body.to_json
|
84
|
+
end
|
85
|
+
|
86
|
+
headers = { Authorization: token }
|
87
|
+
headers[:content_type] = :json unless attachments
|
88
|
+
|
70
89
|
Discordrb::API.request(
|
71
90
|
:channels_cid_messages_mid,
|
72
91
|
channel_id,
|
73
92
|
:post,
|
74
93
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages",
|
75
|
-
|
76
|
-
|
77
|
-
content_type: :json
|
94
|
+
body,
|
95
|
+
**headers
|
78
96
|
)
|
79
|
-
rescue RestClient::
|
80
|
-
|
97
|
+
rescue RestClient::BadRequest => e
|
98
|
+
parsed = JSON.parse(e.response.body)
|
99
|
+
raise Discordrb::Errors::MessageTooLong, "Message over the character limit (#{message.length} > 2000)" if parsed['content'].is_a?(Array) && parsed['content'].first == 'Must be 2000 or fewer in length.'
|
100
|
+
|
101
|
+
raise
|
81
102
|
end
|
82
103
|
|
83
104
|
# Send a file as a message to a channel
|
84
|
-
# https://
|
105
|
+
# https://discord.com/developers/docs/resources/channel#upload-file
|
85
106
|
def upload_file(token, channel_id, file, caption: nil, tts: false)
|
86
107
|
Discordrb::API.request(
|
87
108
|
:channels_cid_messages_mid,
|
@@ -94,14 +115,14 @@ module Discordrb::API::Channel
|
|
94
115
|
end
|
95
116
|
|
96
117
|
# Edit a message
|
97
|
-
# https://
|
98
|
-
def edit_message(token, channel_id, message_id, message, mentions = [])
|
118
|
+
# https://discord.com/developers/docs/resources/channel#edit-message
|
119
|
+
def edit_message(token, channel_id, message_id, message, mentions = [], embed = nil)
|
99
120
|
Discordrb::API.request(
|
100
121
|
:channels_cid_messages_mid,
|
101
122
|
channel_id,
|
102
123
|
:patch,
|
103
124
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}",
|
104
|
-
{ content: message, mentions: mentions }.to_json,
|
125
|
+
{ content: message, mentions: mentions, embed: embed }.to_json,
|
105
126
|
Authorization: token,
|
106
127
|
content_type: :json
|
107
128
|
)
|
@@ -109,33 +130,102 @@ module Discordrb::API::Channel
|
|
109
130
|
|
110
131
|
# Delete a message
|
111
132
|
# https://discordapp.com/developers/docs/resources/channel#delete-message
|
112
|
-
def delete_message(token, channel_id, message_id)
|
133
|
+
def delete_message(token, channel_id, message_id, reason = nil)
|
113
134
|
Discordrb::API.request(
|
114
135
|
:channels_cid_messages_mid,
|
115
136
|
channel_id,
|
116
137
|
:delete,
|
117
138
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}",
|
118
|
-
Authorization: token
|
139
|
+
Authorization: token,
|
140
|
+
'X-Audit-Log-Reason': reason
|
119
141
|
)
|
120
142
|
end
|
121
143
|
|
122
144
|
# Delete messages in bulk
|
123
145
|
# https://discordapp.com/developers/docs/resources/channel#bulk-delete-messages
|
124
|
-
def bulk_delete_messages(token, channel_id, messages = [])
|
146
|
+
def bulk_delete_messages(token, channel_id, messages = [], reason = nil)
|
125
147
|
Discordrb::API.request(
|
126
148
|
:channels_cid_messages_bulk_delete,
|
127
149
|
channel_id,
|
128
150
|
:post,
|
129
|
-
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/
|
151
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/bulk-delete",
|
130
152
|
{ messages: messages }.to_json,
|
131
153
|
Authorization: token,
|
154
|
+
content_type: :json,
|
155
|
+
'X-Audit-Log-Reason': reason
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Create a reaction on a message using this client
|
160
|
+
# https://discord.com/developers/docs/resources/channel#create-reaction
|
161
|
+
def create_reaction(token, channel_id, message_id, emoji)
|
162
|
+
emoji = URI.encode_www_form_component(emoji) unless emoji.ascii_only?
|
163
|
+
Discordrb::API.request(
|
164
|
+
:channels_cid_messages_mid_reactions_emoji_me,
|
165
|
+
channel_id,
|
166
|
+
:put,
|
167
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}/@me",
|
168
|
+
nil,
|
169
|
+
Authorization: token,
|
132
170
|
content_type: :json
|
133
171
|
)
|
134
172
|
end
|
135
173
|
|
174
|
+
# Delete this client's own reaction on a message
|
175
|
+
# https://discord.com/developers/docs/resources/channel#delete-own-reaction
|
176
|
+
def delete_own_reaction(token, channel_id, message_id, emoji)
|
177
|
+
emoji = URI.encode_www_form_component(emoji) unless emoji.ascii_only?
|
178
|
+
Discordrb::API.request(
|
179
|
+
:channels_cid_messages_mid_reactions_emoji_me,
|
180
|
+
channel_id,
|
181
|
+
:delete,
|
182
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}/@me",
|
183
|
+
Authorization: token
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Delete another client's reaction on a message
|
188
|
+
# https://discord.com/developers/docs/resources/channel#delete-user-reaction
|
189
|
+
def delete_user_reaction(token, channel_id, message_id, emoji, user_id)
|
190
|
+
emoji = URI.encode_www_form_component(emoji) unless emoji.ascii_only?
|
191
|
+
Discordrb::API.request(
|
192
|
+
:channels_cid_messages_mid_reactions_emoji_uid,
|
193
|
+
channel_id,
|
194
|
+
:delete,
|
195
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}/#{user_id}",
|
196
|
+
Authorization: token
|
197
|
+
)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Get a list of clients who reacted with a specific reaction on a message
|
201
|
+
# https://discord.com/developers/docs/resources/channel#get-reactions
|
202
|
+
def get_reactions(token, channel_id, message_id, emoji, before_id, after_id, limit = 100)
|
203
|
+
emoji = URI.encode_www_form_component(emoji) unless emoji.ascii_only?
|
204
|
+
query_string = "limit=#{limit}#{"&before=#{before_id}" if before_id}#{"&after=#{after_id}" if after_id}"
|
205
|
+
Discordrb::API.request(
|
206
|
+
:channels_cid_messages_mid_reactions_emoji,
|
207
|
+
channel_id,
|
208
|
+
:get,
|
209
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}?#{query_string}",
|
210
|
+
Authorization: token
|
211
|
+
)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Deletes all reactions on a message from all clients
|
215
|
+
# https://discord.com/developers/docs/resources/channel#delete-all-reactions
|
216
|
+
def delete_all_reactions(token, channel_id, message_id)
|
217
|
+
Discordrb::API.request(
|
218
|
+
:channels_cid_messages_mid_reactions,
|
219
|
+
channel_id,
|
220
|
+
:delete,
|
221
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions",
|
222
|
+
Authorization: token
|
223
|
+
)
|
224
|
+
end
|
225
|
+
|
136
226
|
# Update a channels permission for a role or member
|
137
|
-
# https://
|
138
|
-
def update_permission(token, channel_id, overwrite_id, allow, deny, type)
|
227
|
+
# https://discord.com/developers/docs/resources/channel#edit-channel-permissions
|
228
|
+
def update_permission(token, channel_id, overwrite_id, allow, deny, type, reason = nil)
|
139
229
|
Discordrb::API.request(
|
140
230
|
:channels_cid_permissions_oid,
|
141
231
|
channel_id,
|
@@ -143,12 +233,13 @@ module Discordrb::API::Channel
|
|
143
233
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/permissions/#{overwrite_id}",
|
144
234
|
{ type: type, id: overwrite_id, allow: allow, deny: deny }.to_json,
|
145
235
|
Authorization: token,
|
146
|
-
content_type: :json
|
236
|
+
content_type: :json,
|
237
|
+
'X-Audit-Log-Reason': reason
|
147
238
|
)
|
148
239
|
end
|
149
240
|
|
150
241
|
# Get a channel's invite list
|
151
|
-
# https://
|
242
|
+
# https://discord.com/developers/docs/resources/channel#get-channel-invites
|
152
243
|
def invites(token, channel_id)
|
153
244
|
Discordrb::API.request(
|
154
245
|
:channels_cid_invites,
|
@@ -160,33 +251,35 @@ module Discordrb::API::Channel
|
|
160
251
|
end
|
161
252
|
|
162
253
|
# Create an instant invite from a server or a channel id
|
163
|
-
# https://
|
164
|
-
def create_invite(token, channel_id, max_age = 0, max_uses = 0, temporary = false)
|
254
|
+
# https://discord.com/developers/docs/resources/channel#create-channel-invite
|
255
|
+
def create_invite(token, channel_id, max_age = 0, max_uses = 0, temporary = false, unique = false, reason = nil)
|
165
256
|
Discordrb::API.request(
|
166
257
|
:channels_cid_invites,
|
167
258
|
channel_id,
|
168
259
|
:post,
|
169
260
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/invites",
|
170
|
-
{ max_age: max_age, max_uses: max_uses, temporary: temporary }.to_json,
|
261
|
+
{ max_age: max_age, max_uses: max_uses, temporary: temporary, unique: unique }.to_json,
|
171
262
|
Authorization: token,
|
172
|
-
content_type: :json
|
263
|
+
content_type: :json,
|
264
|
+
'X-Audit-Log-Reason': reason
|
173
265
|
)
|
174
266
|
end
|
175
267
|
|
176
268
|
# Delete channel permission
|
177
|
-
# https://
|
178
|
-
def delete_permission(token, channel_id, overwrite_id)
|
269
|
+
# https://discord.com/developers/docs/resources/channel#delete-channel-permission
|
270
|
+
def delete_permission(token, channel_id, overwrite_id, reason = nil)
|
179
271
|
Discordrb::API.request(
|
180
272
|
:channels_cid_permissions_oid,
|
181
273
|
channel_id,
|
182
274
|
:delete,
|
183
275
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/permissions/#{overwrite_id}",
|
184
|
-
Authorization: token
|
276
|
+
Authorization: token,
|
277
|
+
'X-Audit-Log-Reason': reason
|
185
278
|
)
|
186
279
|
end
|
187
280
|
|
188
281
|
# Start typing (needs to be resent every 5 seconds to keep up the typing)
|
189
|
-
# https://
|
282
|
+
# https://discord.com/developers/docs/resources/channel#trigger-typing-indicator
|
190
283
|
def start_typing(token, channel_id)
|
191
284
|
Discordrb::API.request(
|
192
285
|
:channels_cid_typing,
|
@@ -199,7 +292,7 @@ module Discordrb::API::Channel
|
|
199
292
|
end
|
200
293
|
|
201
294
|
# Get a list of pinned messages in a channel
|
202
|
-
# https://
|
295
|
+
# https://discord.com/developers/docs/resources/channel#get-pinned-messages
|
203
296
|
def pinned_messages(token, channel_id)
|
204
297
|
Discordrb::API.request(
|
205
298
|
:channels_cid_pins,
|
@@ -212,26 +305,28 @@ module Discordrb::API::Channel
|
|
212
305
|
|
213
306
|
# Pin a message
|
214
307
|
# https://discordapp.com/developers/docs/resources/channel#add-pinned-channel-message
|
215
|
-
def pin_message(token, channel_id, message_id)
|
308
|
+
def pin_message(token, channel_id, message_id, reason = nil)
|
216
309
|
Discordrb::API.request(
|
217
310
|
:channels_cid_pins_mid,
|
218
311
|
channel_id,
|
219
312
|
:put,
|
220
313
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/pins/#{message_id}",
|
221
314
|
nil,
|
222
|
-
Authorization: token
|
315
|
+
Authorization: token,
|
316
|
+
'X-Audit-Log-Reason': reason
|
223
317
|
)
|
224
318
|
end
|
225
319
|
|
226
320
|
# Unpin a message
|
227
321
|
# https://discordapp.com/developers/docs/resources/channel#delete-pinned-channel-message
|
228
|
-
def unpin_message(token, channel_id, message_id)
|
322
|
+
def unpin_message(token, channel_id, message_id, reason = nil)
|
229
323
|
Discordrb::API.request(
|
230
324
|
:channels_cid_pins_mid,
|
231
325
|
channel_id,
|
232
326
|
:delete,
|
233
327
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/pins/#{message_id}",
|
234
|
-
Authorization: token
|
328
|
+
Authorization: token,
|
329
|
+
'X-Audit-Log-Reason': reason
|
235
330
|
)
|
236
331
|
end
|
237
332
|
|
@@ -303,4 +398,31 @@ module Discordrb::API::Channel
|
|
303
398
|
content_type: :json
|
304
399
|
)
|
305
400
|
end
|
401
|
+
|
402
|
+
# Create a webhook
|
403
|
+
# https://discord.com/developers/docs/resources/webhook#create-webhook
|
404
|
+
def create_webhook(token, channel_id, name, avatar = nil, reason = nil)
|
405
|
+
Discordrb::API.request(
|
406
|
+
:channels_cid_webhooks,
|
407
|
+
channel_id,
|
408
|
+
:post,
|
409
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/webhooks",
|
410
|
+
{ name: name, avatar: avatar }.to_json,
|
411
|
+
Authorization: token,
|
412
|
+
content_type: :json,
|
413
|
+
'X-Audit-Log-Reason': reason
|
414
|
+
)
|
415
|
+
end
|
416
|
+
|
417
|
+
# Get channel webhooks
|
418
|
+
# https://discord.com/developers/docs/resources/webhook#get-channel-webhooks
|
419
|
+
def webhooks(token, channel_id)
|
420
|
+
Discordrb::API.request(
|
421
|
+
:channels_cid_webhooks,
|
422
|
+
channel_id,
|
423
|
+
:get,
|
424
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/webhooks",
|
425
|
+
Authorization: token
|
426
|
+
)
|
427
|
+
end
|
306
428
|
end
|