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.

Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +126 -0
  3. data/.codeclimate.yml +16 -0
  4. data/.github/CONTRIBUTING.md +13 -0
  5. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  6. data/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  7. data/.github/pull_request_template.md +37 -0
  8. data/.gitignore +5 -0
  9. data/.rubocop.yml +39 -33
  10. data/.travis.yml +27 -2
  11. data/.yardopts +1 -1
  12. data/CHANGELOG.md +808 -208
  13. data/Gemfile +4 -1
  14. data/LICENSE.txt +1 -1
  15. data/README.md +108 -53
  16. data/Rakefile +14 -1
  17. data/bin/console +1 -0
  18. data/bin/travis_build_docs.sh +17 -0
  19. data/discordrb-webhooks.gemspec +26 -0
  20. data/discordrb.gemspec +24 -15
  21. data/lib/discordrb.rb +75 -2
  22. data/lib/discordrb/allowed_mentions.rb +36 -0
  23. data/lib/discordrb/api.rb +126 -27
  24. data/lib/discordrb/api/channel.rb +165 -43
  25. data/lib/discordrb/api/invite.rb +10 -7
  26. data/lib/discordrb/api/server.rb +240 -61
  27. data/lib/discordrb/api/user.rb +26 -24
  28. data/lib/discordrb/api/webhook.rb +83 -0
  29. data/lib/discordrb/await.rb +1 -2
  30. data/lib/discordrb/bot.rb +417 -149
  31. data/lib/discordrb/cache.rb +42 -10
  32. data/lib/discordrb/colour_rgb.rb +43 -0
  33. data/lib/discordrb/commands/command_bot.rb +186 -31
  34. data/lib/discordrb/commands/container.rb +30 -16
  35. data/lib/discordrb/commands/parser.rb +102 -47
  36. data/lib/discordrb/commands/rate_limiter.rb +18 -17
  37. data/lib/discordrb/container.rb +245 -41
  38. data/lib/discordrb/data.rb +27 -2511
  39. data/lib/discordrb/data/activity.rb +264 -0
  40. data/lib/discordrb/data/application.rb +50 -0
  41. data/lib/discordrb/data/attachment.rb +56 -0
  42. data/lib/discordrb/data/audit_logs.rb +345 -0
  43. data/lib/discordrb/data/channel.rb +849 -0
  44. data/lib/discordrb/data/embed.rb +251 -0
  45. data/lib/discordrb/data/emoji.rb +82 -0
  46. data/lib/discordrb/data/integration.rb +83 -0
  47. data/lib/discordrb/data/invite.rb +137 -0
  48. data/lib/discordrb/data/member.rb +297 -0
  49. data/lib/discordrb/data/message.rb +334 -0
  50. data/lib/discordrb/data/overwrite.rb +102 -0
  51. data/lib/discordrb/data/profile.rb +91 -0
  52. data/lib/discordrb/data/reaction.rb +33 -0
  53. data/lib/discordrb/data/recipient.rb +34 -0
  54. data/lib/discordrb/data/role.rb +191 -0
  55. data/lib/discordrb/data/server.rb +1002 -0
  56. data/lib/discordrb/data/user.rb +204 -0
  57. data/lib/discordrb/data/voice_region.rb +45 -0
  58. data/lib/discordrb/data/voice_state.rb +41 -0
  59. data/lib/discordrb/data/webhook.rb +145 -0
  60. data/lib/discordrb/errors.rb +36 -2
  61. data/lib/discordrb/events/bans.rb +7 -5
  62. data/lib/discordrb/events/channels.rb +2 -0
  63. data/lib/discordrb/events/generic.rb +19 -3
  64. data/lib/discordrb/events/guilds.rb +129 -6
  65. data/lib/discordrb/events/invites.rb +125 -0
  66. data/lib/discordrb/events/members.rb +6 -2
  67. data/lib/discordrb/events/message.rb +86 -36
  68. data/lib/discordrb/events/presence.rb +23 -16
  69. data/lib/discordrb/events/raw.rb +47 -0
  70. data/lib/discordrb/events/reactions.rb +159 -0
  71. data/lib/discordrb/events/roles.rb +7 -6
  72. data/lib/discordrb/events/typing.rb +9 -5
  73. data/lib/discordrb/events/voice_server_update.rb +47 -0
  74. data/lib/discordrb/events/voice_state_update.rb +29 -9
  75. data/lib/discordrb/events/webhooks.rb +64 -0
  76. data/lib/discordrb/gateway.rb +219 -88
  77. data/lib/discordrb/id_object.rb +39 -0
  78. data/lib/discordrb/light.rb +1 -1
  79. data/lib/discordrb/light/integrations.rb +1 -1
  80. data/lib/discordrb/light/light_bot.rb +1 -1
  81. data/lib/discordrb/logger.rb +12 -11
  82. data/lib/discordrb/paginator.rb +57 -0
  83. data/lib/discordrb/permissions.rb +148 -14
  84. data/lib/discordrb/version.rb +1 -1
  85. data/lib/discordrb/voice/encoder.rb +14 -15
  86. data/lib/discordrb/voice/network.rb +86 -45
  87. data/lib/discordrb/voice/sodium.rb +96 -0
  88. data/lib/discordrb/voice/voice_bot.rb +52 -40
  89. data/lib/discordrb/webhooks.rb +12 -0
  90. data/lib/discordrb/websocket.rb +2 -2
  91. 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
@@ -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://discordapp.com/api/v6'.freeze
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 bot name, previously specified using #bot_name=.
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/meew0/discordrb, v#{Discordrb::VERSION})"
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} #{required} #{@bot_name}"
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
- raise Discordrb::Errors::NoPermission, "The bot doesn't have the required permission to do this!"
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. e. wait for the mutex to unlock and don't do anything with it afterwards
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 = raw_request(type, attributes)
93
-
94
- if response.headers[:x_ratelimit_remaining] == '0' && !mutex.locked?
95
- Discordrb::LOGGER.debug "RL bucket depletion detected! Date: #{response.headers[:date]} Reset: #{response.headers[:x_ratelimit_reset]}"
96
-
97
- now = Time.rfc2822(response.headers[:date])
98
- reset = Time.at(response.headers[:x_ratelimit_reset].to_i)
99
-
100
- delta = reset - now
101
-
102
- Discordrb::LOGGER.warn("Locking RL mutex (key: #{key}) for #{delta} seconds preemptively")
103
- sync_wait(delta, mutex)
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.warn("Locking RL mutex (key: #{key}) for #{wait_seconds} seconds due to Discord rate limiting")
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
- "#{api_base}/guilds/#{server_id}/icons/#{icon_id}.jpg"
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
- "https://cdn.discordapp.com/app-icons/#{app_id}/#{icon_id}.jpg"
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
- "https://cdn.discordapp.com/emojis/#{emoji_id}.png"
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://discordapp.com/developers/docs/resources/channel#get-channel
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://discordapp.com/developers/docs/resources/channel#modify-channel
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
- { name: name, position: position, topic: topic, bitrate: bitrate, user_limit: user_limit }.to_json,
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://discordapp.com/developers/docs/resources/channel#deleteclose-channel
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://discordapp.com/developers/docs/resources/channel#get-channel-messages
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://discordapp.com/developers/docs/resources/channel#get-channel-message
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
- def create_message(token, channel_id, message, mentions = [], tts = false, _server_id = nil) # send message
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
- { content: message, mentions: mentions, tts: tts }.to_json,
76
- Authorization: token,
77
- content_type: :json
94
+ body,
95
+ **headers
78
96
  )
79
- rescue RestClient::InternalServerError
80
- raise Discordrb::Errors::MessageTooLong, "Message over the character limit (#{message.length} > 2000)"
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://discordapp.com/developers/docs/resources/channel#upload-file
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://discordapp.com/developers/docs/resources/channel#edit-message
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/bulk_delete",
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://discordapp.com/developers/docs/resources/channel#edit-channel-permissions
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://discordapp.com/developers/docs/resources/channel#get-channel-invites
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://discordapp.com/developers/docs/resources/channel#create-channel-invite
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://discordapp.com/developers/docs/resources/channel#delete-channel-permission
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://discordapp.com/developers/docs/resources/channel#trigger-typing-indicator
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://discordapp.com/developers/docs/resources/channel#get-pinned-messages
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