discordrb 3.2.1 → 3.3.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/.gitignore +4 -0
- data/.rubocop.yml +3 -3
- data/.travis.yml +28 -3
- data/.yardopts +1 -1
- data/CHANGELOG.md +555 -144
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +0 -4
- data/README.md +86 -15
- data/Rakefile +2 -2
- data/bin/travis_build_docs.sh +17 -0
- data/discordrb-webhooks.gemspec +2 -1
- data/discordrb.gemspec +12 -5
- data/lib/discordrb.rb +2 -2
- data/lib/discordrb/api.rb +94 -25
- data/lib/discordrb/api/channel.rb +53 -17
- data/lib/discordrb/api/invite.rb +7 -4
- data/lib/discordrb/api/server.rb +173 -36
- data/lib/discordrb/api/user.rb +18 -4
- data/lib/discordrb/api/webhook.rb +83 -0
- data/lib/discordrb/await.rb +1 -1
- data/lib/discordrb/bot.rb +191 -102
- data/lib/discordrb/cache.rb +39 -9
- data/lib/discordrb/commands/command_bot.rb +79 -24
- data/lib/discordrb/commands/container.rb +16 -2
- data/lib/discordrb/commands/parser.rb +46 -7
- data/lib/discordrb/commands/rate_limiter.rb +8 -6
- data/lib/discordrb/container.rb +51 -7
- data/lib/discordrb/data.rb +1729 -286
- data/lib/discordrb/errors.rb +34 -1
- data/lib/discordrb/events/generic.rb +1 -1
- data/lib/discordrb/events/guilds.rb +1 -0
- data/lib/discordrb/events/message.rb +18 -12
- data/lib/discordrb/events/presence.rb +7 -2
- data/lib/discordrb/events/reactions.rb +13 -4
- data/lib/discordrb/events/roles.rb +7 -6
- data/lib/discordrb/events/typing.rb +1 -1
- data/lib/discordrb/events/webhooks.rb +61 -0
- data/lib/discordrb/gateway.rb +85 -32
- data/lib/discordrb/light.rb +1 -1
- data/lib/discordrb/logger.rb +8 -7
- data/lib/discordrb/permissions.rb +41 -4
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +10 -8
- data/lib/discordrb/voice/voice_bot.rb +4 -4
- data/lib/discordrb/websocket.rb +2 -2
- metadata +59 -14
data/CONTRIBUTING.md
CHANGED
@@ -10,4 +10,4 @@ For PRs, please make sure that you tested your code before every push; it's a li
|
|
10
10
|
to a PR because of small avoidable oversights. (Huge bonus points if you're adding specs for your code! This project
|
11
11
|
has very few specs in places where it should have more so every added spec is very much appreciated.)
|
12
12
|
|
13
|
-
If you have any questions at all, don't be afraid to ask in the [discordrb channel on Discord](https://discord.gg/
|
13
|
+
If you have any questions at all, don't be afraid to ask in the [discordrb channel on Discord](https://discord.gg/cyK3Hjm).
|
data/Gemfile
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Test coverage reporting for CodeClimate
|
4
|
-
gem 'codeclimate-test-reporter', group: :test, require: nil
|
5
|
-
gem 'simplecov', group: :test
|
6
|
-
|
7
3
|
# Specify your gem's dependencies in discordrb.gemspec
|
8
4
|
gemspec name: 'discordrb'
|
9
5
|
gemspec name: 'discordrb-webhooks', development_group: 'webhooks'
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
[![Gem](https://img.shields.io/gem/v/discordrb.svg)](https://rubygems.org/gems/discordrb)
|
2
2
|
[![Gem](https://img.shields.io/gem/dt/discordrb.svg)](https://rubygems.org/gems/discordrb)
|
3
3
|
[![Build Status](https://travis-ci.org/meew0/discordrb.svg?branch=master)](https://travis-ci.org/meew0/discordrb)
|
4
|
-
[![Inline docs](
|
4
|
+
[![Inline docs](https://inch-ci.org/github/meew0/discordrb.svg?branch=master&style=shields)](https://inch-ci.org/github/meew0/discordrb)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/meew0/discordrb/badges/gpa.svg)](https://codeclimate.com/github/meew0/discordrb)
|
6
6
|
[![Test Coverage](https://codeclimate.com/github/meew0/discordrb/badges/coverage.svg)](https://codeclimate.com/github/meew0/discordrb/coverage)
|
7
|
-
[![Join Discord](https://img.shields.io/badge/discord-join-7289DA.svg)](https://discord.gg/
|
7
|
+
[![Join Discord](https://img.shields.io/badge/discord-join-7289DA.svg)](https://discord.gg/cyK3Hjm)
|
8
8
|
# discordrb
|
9
9
|
|
10
10
|
An implementation of the [Discord](https://discordapp.com/) API using Ruby.
|
@@ -14,16 +14,19 @@ An implementation of the [Discord](https://discordapp.com/) API using Ruby.
|
|
14
14
|
* [Dependencies](https://github.com/meew0/discordrb#dependencies)
|
15
15
|
* [Installation](https://github.com/meew0/discordrb#installation)
|
16
16
|
* [Usage](https://github.com/meew0/discordrb#usage)
|
17
|
+
* [Webhooks Client](https://github.com/meew0/discordrb#webhooks-client)
|
17
18
|
* [Support](https://github.com/meew0/discordrb#support)
|
18
19
|
* [Development](https://github.com/meew0/discordrb#development), [Contributing](https://github.com/meew0/discordrb#contributing)
|
19
20
|
* [License](https://github.com/meew0/discordrb#license)
|
20
21
|
|
21
|
-
See also: [Documentation](
|
22
|
+
See also: [Documentation](https://www.rubydoc.info/gems/discordrb), [Tutorials](https://github.com/meew0/discordrb/wiki)
|
22
23
|
|
23
24
|
## Dependencies
|
24
25
|
|
25
|
-
* Ruby 2.
|
26
|
-
* An installed build system for native extensions (on Windows, try the [DevKit](
|
26
|
+
* Ruby 2.2+
|
27
|
+
* An installed build system for native extensions (on Windows for Ruby < 2.4, try the [DevKit](https://rubyinstaller.org/downloads/); installation instructions [here](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit#quick-start) - you only need to do the quick start)
|
28
|
+
|
29
|
+
> **Note:** RubyInstaller for Ruby versions 2.4+ will install the DevKit as the last step of the installation.
|
27
30
|
|
28
31
|
### Voice dependencies
|
29
32
|
|
@@ -36,19 +39,35 @@ In addition to this, if you're on Windows and want to use voice functionality, y
|
|
36
39
|
|
37
40
|
## Installation
|
38
41
|
|
39
|
-
###
|
42
|
+
### With Bundler
|
43
|
+
|
44
|
+
Using [Bundler](https://bundler.io/#getting-started), you can add discordrb to your Gemfile:
|
45
|
+
|
46
|
+
gem 'discordrb'
|
47
|
+
|
48
|
+
And then install via `bundle install`.
|
49
|
+
|
50
|
+
Run the [ping example](https://github.com/meew0/discordrb/blob/master/examples/ping.rb) to verify that the installation works (make sure to replace the token and client ID in there with your bots'!):
|
51
|
+
|
52
|
+
To run the bot while using bundler:
|
53
|
+
|
54
|
+
bundle exec ruby ping.rb
|
55
|
+
|
56
|
+
### With Gem
|
40
57
|
|
41
|
-
|
58
|
+
Alternatively, while Bundler is the recommended option, you can also install discordrb without it.
|
59
|
+
|
60
|
+
#### Linux / macOS
|
42
61
|
|
43
62
|
gem install discordrb
|
44
63
|
|
45
|
-
|
64
|
+
#### Windows
|
46
65
|
|
47
|
-
|
66
|
+
> **Make sure you have the DevKit installed! See the [Dependencies](https://github.com/meew0/discordrb#dependencies) section)**
|
48
67
|
|
49
68
|
gem install discordrb --platform=ruby
|
50
69
|
|
51
|
-
|
70
|
+
To run the bot:
|
52
71
|
|
53
72
|
ruby ping.rb
|
54
73
|
|
@@ -59,7 +78,23 @@ Run the [ping example](https://github.com/meew0/discordrb/blob/master/examples/p
|
|
59
78
|
ERROR: Error installing discordrb:
|
60
79
|
The 'websocket-driver' native gem requires installed build tools.
|
61
80
|
|
62
|
-
You're missing the development kit required to build native extensions.
|
81
|
+
You're missing the development kit required to build native extensions.
|
82
|
+
|
83
|
+
##### RubyInstaller for ruby 2.4.3-2 and above
|
84
|
+
|
85
|
+
RubyInstaller after version 2.3.3 now includes the development kit in the installer. If you do not have the development kit and have installed ruby using RubyInstaller, open a command prompt with administrator privileges and run:
|
86
|
+
|
87
|
+
ridk install
|
88
|
+
|
89
|
+
Select option 3, and then run
|
90
|
+
|
91
|
+
ridk enable
|
92
|
+
|
93
|
+
To enable the changes
|
94
|
+
|
95
|
+
##### RubyInstaller for ruby 2.3.3 and below
|
96
|
+
|
97
|
+
Download the development kit [here](https://rubyinstaller.org/downloads/) (scroll down to "Development Kit", then choose the one for Ruby 2.0 and your system architecture) and extract it somewhere. Open a command prompt in that folder and run:
|
63
98
|
|
64
99
|
ruby dk.rb init
|
65
100
|
ruby dk.rb install
|
@@ -67,6 +102,9 @@ You're missing the development kit required to build native extensions. Download
|
|
67
102
|
Then reinstall discordrb:
|
68
103
|
|
69
104
|
gem uninstall discordrb
|
105
|
+
bundle install
|
106
|
+
|
107
|
+
# Or, if you didn't use bundler:
|
70
108
|
gem install discordrb
|
71
109
|
|
72
110
|
**If Ruby complains about `ffi_c` not being able to be found:**
|
@@ -88,7 +126,7 @@ You can make a simple bot like this:
|
|
88
126
|
```ruby
|
89
127
|
require 'discordrb'
|
90
128
|
|
91
|
-
bot = Discordrb::Bot.new token: '<token here>'
|
129
|
+
bot = Discordrb::Bot.new token: '<token here>'
|
92
130
|
|
93
131
|
bot.message(with_text: 'Ping!') do |event|
|
94
132
|
event.respond 'Pong!'
|
@@ -99,9 +137,43 @@ bot.run
|
|
99
137
|
|
100
138
|
This bot responds to every "Ping!" with a "Pong!".
|
101
139
|
|
140
|
+
See [additional examples here](https://github.com/meew0/discordrb/tree/master/examples).
|
141
|
+
|
142
|
+
You can find examples of projects that use discordrb by [searching for the discordrb topic on GitHub](https://github.com/topics/discordrb).
|
143
|
+
|
144
|
+
If you've made an open source project on GitHub that uses discordrb, consider adding the `discordrb` topic to your repo!
|
145
|
+
|
146
|
+
## Webhooks Client
|
147
|
+
|
148
|
+
Also included is a webhooks client, which can be used as a separate gem `discordrb-webhooks`. This special client can be used to form requests to Discord webhook URLs in a high-level manner.
|
149
|
+
|
150
|
+
- [`discordrb-webhooks` documentation](https://www.rubydoc.info/gems/discordrb-webhooks)
|
151
|
+
- [More information about webhooks](https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks)
|
152
|
+
- [Embed visualizer tool](https://leovoel.github.io/embed-visualizer/) - Includes a discordrb code generator for forming embeds
|
153
|
+
|
154
|
+
### Usage
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
require 'discordrb/webhooks'
|
158
|
+
|
159
|
+
WEBHOOK_URL = 'https://discordapp.com/api/webhooks/424070213278105610/yByxDncRvHi02mhKQheviQI2erKkfRRwFcEp0MMBfib1ds6ZHN13xhPZNS2-fJo_ApSw'.freeze
|
160
|
+
|
161
|
+
client = Discordrb::Webhooks::Client.new(url: WEBHOOK_URL)
|
162
|
+
client.execute do |builder|
|
163
|
+
builder.content = 'Hello world!'
|
164
|
+
builder.add_embed do |embed|
|
165
|
+
embed.title = 'Embed title'
|
166
|
+
embed.description = 'Embed description'
|
167
|
+
embed.timestamp = Time.now
|
168
|
+
end
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
**Note:** The `discordrb` gem relies on `discordrb-webhooks`. If you already have `discordrb` installed, `require 'discordrb/webhooks'` will include all of the `Webhooks` features as well.
|
173
|
+
|
102
174
|
## Support
|
103
175
|
|
104
|
-
You can find me (@meew0, ID 66237334693085184) on the unofficial Discord API server - if you have a question, just ask there, I or somebody else will probably answer you: https://discord.gg/
|
176
|
+
You can find me (@meew0, ID 66237334693085184) on the unofficial Discord API server - if you have a question, just ask there, I or somebody else will probably answer you: https://discord.gg/3Trm6FW
|
105
177
|
|
106
178
|
## Development
|
107
179
|
|
@@ -115,7 +187,6 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
115
187
|
|
116
188
|
Bug reports and pull requests are welcome on GitHub at https://github.com/meew0/discordrb.
|
117
189
|
|
118
|
-
|
119
190
|
## License
|
120
191
|
|
121
|
-
The gem is available as open source under the terms of the [MIT License](
|
192
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -8,8 +8,8 @@ namespace :webhooks do
|
|
8
8
|
Bundler::GemHelper.install_tasks(name: 'discordrb-webhooks')
|
9
9
|
end
|
10
10
|
|
11
|
-
task build: [
|
12
|
-
task release: [
|
11
|
+
task build: %i[main:build webhooks:build]
|
12
|
+
task release: %i[main:release webhooks:release]
|
13
13
|
|
14
14
|
# Make "build" the default task
|
15
15
|
task default: :build
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# Script to build docs for travis usage
|
3
|
+
|
4
|
+
set -e
|
5
|
+
|
6
|
+
SOURCE_BRANCH=$TRAVIS_BRANCH
|
7
|
+
|
8
|
+
if [ -n "$TRAVIS_TAG" ]; then
|
9
|
+
SOURCE_BRANCH=$TRAVIS_TAG
|
10
|
+
fi
|
11
|
+
|
12
|
+
# Use YARD to build docs
|
13
|
+
bundle exec yard
|
14
|
+
|
15
|
+
# Move to correct folder
|
16
|
+
mkdir -p docs/$SOURCE_BRANCH
|
17
|
+
mv doc/* docs/$SOURCE_BRANCH/
|
data/discordrb-webhooks.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'discordrb/webhooks/version'
|
@@ -19,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
19
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
21
|
spec.require_paths = ['lib']
|
21
22
|
|
22
|
-
spec.add_dependency 'rest-client'
|
23
|
+
spec.add_dependency 'rest-client', '>= 2.1.0.rc1'
|
23
24
|
|
24
25
|
spec.required_ruby_version = '>= 2.1.0'
|
25
26
|
end
|
data/discordrb.gemspec
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'discordrb/version'
|
@@ -17,21 +18,27 @@ Gem::Specification.new do |spec|
|
|
17
18
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples|lib/discordrb/webhooks)/}) }
|
18
19
|
spec.bindir = 'exe'
|
19
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.metadata = {
|
22
|
+
'changelog_uri' => 'https://github.com/meew0/discordrb/blob/master/CHANGELOG.md'
|
23
|
+
}
|
20
24
|
spec.require_paths = ['lib']
|
21
25
|
|
22
|
-
spec.add_dependency 'rest-client'
|
26
|
+
spec.add_dependency 'rest-client', '>= 2.1.0.rc1'
|
23
27
|
spec.add_dependency 'opus-ruby'
|
24
28
|
spec.add_dependency 'websocket-client-simple', '>= 0.3.0'
|
25
29
|
spec.add_dependency 'rbnacl', '~> 3.4.0' # 24: update
|
30
|
+
spec.add_dependency 'ffi', '>= 1.9.24'
|
26
31
|
|
27
|
-
spec.add_dependency 'discordrb-webhooks', '~> 3.
|
32
|
+
spec.add_dependency 'discordrb-webhooks', '~> 3.3.0'
|
28
33
|
|
29
|
-
spec.required_ruby_version = '>= 2.
|
34
|
+
spec.required_ruby_version = '>= 2.2.4'
|
30
35
|
|
31
36
|
spec.add_development_dependency 'bundler', '~> 1.10'
|
32
37
|
spec.add_development_dependency 'rake', '~> 10.0'
|
33
|
-
spec.add_development_dependency 'yard', '~> 0.
|
38
|
+
spec.add_development_dependency 'yard', '~> 0.9.9'
|
39
|
+
spec.add_development_dependency 'redcarpet', '~> 3.4.0' # YARD markdown formatting
|
34
40
|
spec.add_development_dependency 'rspec', '~> 3.4.0'
|
35
41
|
spec.add_development_dependency 'rspec-prof', '~> 0.0.7'
|
36
|
-
spec.add_development_dependency 'rubocop', '0.
|
42
|
+
spec.add_development_dependency 'rubocop', '0.49.1'
|
43
|
+
spec.add_development_dependency 'simplecov', '~> 0.16.0'
|
37
44
|
end
|
data/lib/discordrb.rb
CHANGED
@@ -15,7 +15,7 @@ end
|
|
15
15
|
|
16
16
|
# In discordrb, Integer and {String} are monkey-patched to allow for easy resolution of IDs
|
17
17
|
class Integer
|
18
|
-
# @return [Integer] The Discord ID represented by this integer, i.
|
18
|
+
# @return [Integer] The Discord ID represented by this integer, i.e. the integer itself
|
19
19
|
def resolve_id
|
20
20
|
self
|
21
21
|
end
|
@@ -23,7 +23,7 @@ end
|
|
23
23
|
|
24
24
|
# In discordrb, {Integer} and String are monkey-patched to allow for easy resolution of IDs
|
25
25
|
class String
|
26
|
-
# @return [Integer] The Discord ID represented by this string, i.
|
26
|
+
# @return [Integer] The Discord ID represented by this string, i.e. the string converted to an integer
|
27
27
|
def resolve_id
|
28
28
|
to_i
|
29
29
|
end
|
data/lib/discordrb/api.rb
CHANGED
@@ -11,6 +11,9 @@ module Discordrb::API
|
|
11
11
|
# The base URL of the Discord REST API.
|
12
12
|
APIBASE = 'https://discordapp.com/api/v6'.freeze
|
13
13
|
|
14
|
+
# The URL of Discord's CDN
|
15
|
+
CDN_URL = 'https://cdn.discordapp.com'.freeze
|
16
|
+
|
14
17
|
module_function
|
15
18
|
|
16
19
|
# @return [String] the currently used API base URL.
|
@@ -23,6 +26,11 @@ module Discordrb::API
|
|
23
26
|
@api_base = value
|
24
27
|
end
|
25
28
|
|
29
|
+
# @return [String] the currently used CDN url
|
30
|
+
def cdn_url
|
31
|
+
@cdn_url || CDN_URL
|
32
|
+
end
|
33
|
+
|
26
34
|
# @return [String] the bot name, previously specified using #bot_name=.
|
27
35
|
def bot_name
|
28
36
|
@bot_name
|
@@ -33,13 +41,20 @@ module Discordrb::API
|
|
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
54
|
required = "DiscordBot (https://github.com/meew0/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 ratelimit
|
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
|
@@ -83,24 +101,32 @@ module Discordrb::API
|
|
83
101
|
begin
|
84
102
|
mutex = @mutexes[key] ||= Mutex.new
|
85
103
|
|
86
|
-
# Lock and unlock, i.
|
104
|
+
# Lock and unlock, i.e. wait for the mutex to unlock and don't do anything with it afterwards
|
87
105
|
mutex_wait(mutex)
|
88
106
|
|
89
107
|
# If the global mutex happens to be locked right now, wait for that as well.
|
90
108
|
mutex_wait(@global_mutex) if @global_mutex.locked?
|
91
109
|
|
92
|
-
response =
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
110
|
+
response = nil
|
111
|
+
begin
|
112
|
+
response = raw_request(type, attributes)
|
113
|
+
rescue RestClient::Exception => e
|
114
|
+
response = e.response
|
115
|
+
raise e
|
116
|
+
rescue Discordrb::Errors::NoPermission => e
|
117
|
+
if e.respond_to?(:_rc_response)
|
118
|
+
response = e._rc_response
|
119
|
+
else
|
120
|
+
Discordrb::LOGGER.warn("NoPermission doesn't respond_to? _rc_response!")
|
121
|
+
end
|
122
|
+
|
123
|
+
raise e
|
124
|
+
ensure
|
125
|
+
if response
|
126
|
+
handle_preemptive_rl(response.headers, mutex, key) if response.headers[:x_ratelimit_remaining] == '0' && !mutex.locked?
|
127
|
+
else
|
128
|
+
Discordrb::LOGGER.ratelimit('Response was nil before trying to preemptively rate limit!')
|
129
|
+
end
|
104
130
|
end
|
105
131
|
rescue RestClient::TooManyRequests => e
|
106
132
|
# If the 429 is from the global RL, then we have to use the global mutex instead.
|
@@ -109,7 +135,8 @@ module Discordrb::API
|
|
109
135
|
unless mutex.locked?
|
110
136
|
response = JSON.parse(e.response)
|
111
137
|
wait_seconds = response['retry_after'].to_i / 1000.0
|
112
|
-
Discordrb::LOGGER.
|
138
|
+
Discordrb::LOGGER.ratelimit("Locking RL mutex (key: #{key}) for #{wait_seconds} seconds due to Discord rate limiting")
|
139
|
+
trace("429 #{key.join(' ')}")
|
113
140
|
|
114
141
|
# Wait the required time synchronized by the mutex (so other incoming requests have to wait) but only do it if
|
115
142
|
# the mutex isn't locked already so it will only ever wait once
|
@@ -122,14 +149,44 @@ module Discordrb::API
|
|
122
149
|
response
|
123
150
|
end
|
124
151
|
|
152
|
+
# Handles premeptive ratelimiting by waiting the given mutex by the difference of the Date header to the
|
153
|
+
# X-Ratelimit-Reset header, thus making sure we don't get 429'd in any subsequent requests.
|
154
|
+
def handle_preemptive_rl(headers, mutex, key)
|
155
|
+
Discordrb::LOGGER.ratelimit "RL bucket depletion detected! Date: #{headers[:date]} Reset: #{headers[:x_ratelimit_reset]}"
|
156
|
+
|
157
|
+
now = Time.rfc2822(headers[:date])
|
158
|
+
reset = Time.at(headers[:x_ratelimit_reset].to_i)
|
159
|
+
|
160
|
+
delta = reset - now
|
161
|
+
|
162
|
+
Discordrb::LOGGER.warn("Locking RL mutex (key: #{key}) for #{delta} seconds preemptively")
|
163
|
+
sync_wait(delta, mutex)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Perform rate limit tracing. All this method does is log the current backtrace to the console with the `:ratelimit`
|
167
|
+
# level.
|
168
|
+
# @param reason [String] the reason to include with the backtrace.
|
169
|
+
def trace(reason)
|
170
|
+
unless @trace
|
171
|
+
Discordrb::LOGGER.debug("trace was called with reason #{reason}, but tracing is not enabled")
|
172
|
+
return
|
173
|
+
end
|
174
|
+
|
175
|
+
Discordrb::LOGGER.ratelimit("Trace (#{reason}):")
|
176
|
+
|
177
|
+
caller.each do |str|
|
178
|
+
Discordrb::LOGGER.ratelimit(' ' + str)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
125
182
|
# Make an icon URL from server and icon IDs
|
126
|
-
def icon_url(server_id, icon_id)
|
127
|
-
"#{
|
183
|
+
def icon_url(server_id, icon_id, format = 'webp')
|
184
|
+
"#{cdn_url}/icons/#{server_id}/#{icon_id}.#{format}"
|
128
185
|
end
|
129
186
|
|
130
187
|
# Make an icon URL from application and icon IDs
|
131
|
-
def app_icon_url(app_id, icon_id)
|
132
|
-
"
|
188
|
+
def app_icon_url(app_id, icon_id, format = 'webp')
|
189
|
+
"#{cdn_url}/app-icons/#{app_id}/#{icon_id}.#{format}"
|
133
190
|
end
|
134
191
|
|
135
192
|
# Make a widget picture URL from server ID
|
@@ -138,13 +195,13 @@ module Discordrb::API
|
|
138
195
|
end
|
139
196
|
|
140
197
|
# Make a splash URL from server and splash IDs
|
141
|
-
def splash_url(server_id, splash_id)
|
142
|
-
"
|
198
|
+
def splash_url(server_id, splash_id, format = 'webp')
|
199
|
+
"#{cdn_url}/splashes/#{server_id}/#{splash_id}.#{format}"
|
143
200
|
end
|
144
201
|
|
145
202
|
# Make an emoji icon URL from emoji ID
|
146
|
-
def emoji_icon_url(emoji_id)
|
147
|
-
"
|
203
|
+
def emoji_icon_url(emoji_id, format = 'webp')
|
204
|
+
"#{cdn_url}/emojis/#{emoji_id}.#{format}"
|
148
205
|
end
|
149
206
|
|
150
207
|
# Login to the server
|
@@ -245,6 +302,18 @@ module Discordrb::API
|
|
245
302
|
content_type: :json
|
246
303
|
)
|
247
304
|
end
|
305
|
+
|
306
|
+
# Get a list of available voice regions
|
307
|
+
def voice_regions(token)
|
308
|
+
request(
|
309
|
+
:voice_regions,
|
310
|
+
nil,
|
311
|
+
:get,
|
312
|
+
"#{api_base}/voice/regions",
|
313
|
+
Authorization: token,
|
314
|
+
content_type: :json
|
315
|
+
)
|
316
|
+
end
|
248
317
|
end
|
249
318
|
|
250
319
|
Discordrb::API.reset_mutexes
|