discorb 0.10.2 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/package_register.yml +34 -0
- data/Changelog.md +31 -0
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/discorb.gemspec +0 -2
- data/docs/application_command.md +27 -1
- data/docs/cli/{init.md → new.md} +0 -0
- data/docs/cli/setup.md +1 -1
- data/docs/cli.md +1 -1
- data/docs/events.md +5 -0
- data/docs/extension.md +51 -7
- data/docs/faq.md +27 -5
- data/docs/tutorial.md +3 -1
- data/examples/extension/message_expander.rb +3 -1
- data/lib/discorb/app_command.rb +7 -6
- data/lib/discorb/client.rb +9 -11
- data/lib/discorb/color.rb +1 -0
- data/lib/discorb/common.rb +1 -1
- data/lib/discorb/components.rb +1 -0
- data/lib/discorb/exe/run.rb +2 -2
- data/lib/discorb/extension.rb +9 -8
- data/lib/discorb/gateway.rb +62 -47
- data/lib/discorb/http.rb +26 -41
- data/lib/discorb/integration.rb +2 -2
- data/lib/discorb/interaction.rb +84 -1
- data/lib/discorb/log.rb +3 -2
- data/lib/discorb/member.rb +1 -10
- data/lib/discorb/modules.rb +1 -1
- data/lib/discorb/rate_limit.rb +23 -11
- data/lib/discorb/role.rb +24 -4
- data/lib/discorb/voice_state.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0bee36d996a7e3108f2d02247a0d7516ade1811aeb5a354d1d41f509373381d
|
4
|
+
data.tar.gz: ce6c4f496b8ed5309cd3798b8cf25e271e77e75617631010d77f5ab3347a26aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 514f4b1ce307abe3424fa666a9fab56282e7b3817371411661675507658a42a92c23cda56e6358765fcad25bae69b850e754882576392ddc45da8be08ff3d252
|
7
|
+
data.tar.gz: e11b02e78f5029a0e544a0c7a55d79ee42ee22276160ba0f00dad0bd85c2d5d15109fa28c50dbfccbaf61066e293175e6b38357db396aeaba4b3033e38dbf2c4
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Publish Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- "v*"
|
7
|
+
workflow_dispatch:
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
build:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@master
|
15
|
+
|
16
|
+
- name: Set up Ruby
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: "3.0"
|
20
|
+
|
21
|
+
- name: Setup Release Credentials
|
22
|
+
env:
|
23
|
+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
24
|
+
run: |
|
25
|
+
mkdir -p $HOME/.gem
|
26
|
+
touch $HOME/.gem/credentials
|
27
|
+
chmod 600 $HOME/.gem/credentials
|
28
|
+
echo "---" >$HOME/.gem/credentials
|
29
|
+
echo ":github: Bearer ${GITHUB_TOKEN}" >> $HOME/.gem/credentials
|
30
|
+
- name: Publish Gem to GitHub Packages
|
31
|
+
run: |
|
32
|
+
export OWNER=$( echo ${{ github.repository }} | cut -d "/" -f 1 )
|
33
|
+
gem build *.gemspec
|
34
|
+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
data/Changelog.md
CHANGED
@@ -2,8 +2,39 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
## v0.11
|
6
|
+
|
7
|
+
### v0.11.2
|
8
|
+
|
9
|
+
- Add: Add `setup` event
|
10
|
+
- Fix: Fix gateway resuming
|
11
|
+
- Add: Add GitHub Packages
|
12
|
+
|
13
|
+
### v0.11.1
|
14
|
+
|
15
|
+
- Improve: Improve rate limit handling
|
16
|
+
- Fix: Fix bug in Integration initalization
|
17
|
+
- Change: Change log style
|
18
|
+
- Add: Support OP code 7
|
19
|
+
|
20
|
+
### v0.11.0
|
21
|
+
|
22
|
+
- Add: Improve documents
|
23
|
+
- Add: Implement global rate limits
|
24
|
+
- Add: Add support autocomplete
|
25
|
+
- Add: Add role icon editting
|
26
|
+
- Change: Use `include Discorb::Extension` instead of `< Discorb::Extension`
|
27
|
+
- Fix: Fix role operation
|
28
|
+
|
5
29
|
## v0.10
|
6
30
|
|
31
|
+
### v0.10.3
|
32
|
+
|
33
|
+
- Add: Support role icons
|
34
|
+
- Fix: Fix version order
|
35
|
+
- Change: Use `exec` instead of `system` in `discorb run`
|
36
|
+
- Add: Add `Extension.loaded`
|
37
|
+
|
7
38
|
### v0.10.2
|
8
39
|
|
9
40
|
- Change: `discorb init` is now `discorb new`
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
----
|
10
10
|
|
11
|
-
discorb is a Discord API wrapper
|
11
|
+
discorb is a Discord API wrapper written in Ruby.
|
12
12
|
|
13
13
|
## Installation
|
14
14
|
|
@@ -98,7 +98,7 @@ end
|
|
98
98
|
client.run(ENV["DISCORD_BOT_TOKEN"])
|
99
99
|
```
|
100
100
|
|
101
|
-
Note
|
101
|
+
Note you must run `discorb setup` before using slash commands.
|
102
102
|
|
103
103
|
## Contributing
|
104
104
|
|
data/Rakefile
CHANGED
@@ -156,7 +156,7 @@ namespace :document do
|
|
156
156
|
Rake::Task["document:replace:html"].execute
|
157
157
|
Rake::Task["document:replace:css"].execute
|
158
158
|
Rake::Task["document:replace:eol"].execute
|
159
|
-
tags = `git tag`.force_encoding("utf-8").split("\n")
|
159
|
+
tags = `git tag`.force_encoding("utf-8").split("\n").sort_by { |t| t[1..].split(".").map(&:to_i) }
|
160
160
|
tags.each do |tag|
|
161
161
|
sh "git checkout #{tag} -f"
|
162
162
|
iputs "Building #{tag}"
|
data/discorb.gemspec
CHANGED
@@ -13,8 +13,6 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.license = "MIT"
|
14
14
|
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
|
15
15
|
|
16
|
-
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
17
|
-
|
18
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
19
17
|
spec.metadata["source_code_uri"] = "https://github.com/discorb-lib/discorb"
|
20
18
|
spec.metadata["changelog_uri"] = "https://discorb-lib.github.io/file.Changelog.html"
|
data/docs/application_command.md
CHANGED
@@ -69,6 +69,7 @@ In `options`, hash should be like this:
|
|
69
69
|
| `:choice` | `Hash{String => String, Integer, Float}` | Type of the option. |
|
70
70
|
| `:default` | `Object` | Default value of the option. |
|
71
71
|
| `:channel_types` | `Array<Class<Discorb::Channel>>` | Type of the channel option. |
|
72
|
+
| `:autocomplete` | `Proc` | Autocomplete function. |
|
72
73
|
|
73
74
|
`choices` should be unspecified if you don't want to use it.
|
74
75
|
`choices` is hash like this:
|
@@ -107,7 +108,7 @@ In `type`, You must use one of the following:
|
|
107
108
|
| `:channel` | Channel argument. | None |
|
108
109
|
| `:role` | Role argument. | None |
|
109
110
|
|
110
|
-
|
111
|
+
#### Group Slash Commands
|
111
112
|
|
112
113
|
To register a group of slash commands, use {Discorb::ApplicationCommand::Handler#slash_group}.
|
113
114
|
|
@@ -239,6 +240,31 @@ end
|
|
239
240
|
|
240
241
|
Same as above, you can use block for register commands since v0.5.1.
|
241
242
|
|
243
|
+
#### Use Auto Completing
|
244
|
+
|
245
|
+
Since v0.11.0, you can use auto completion by setting Proc to `:autocomplete` in options.
|
246
|
+
The proc will be called with interaction object and the argument.
|
247
|
+
The proc should return an hash of the autocomplete result.
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
client.slash("hello2", "Greet for you", {
|
251
|
+
"target" => {
|
252
|
+
type: :string,
|
253
|
+
description: "Person to greet",
|
254
|
+
autocomplete: ->(interaction, target) {
|
255
|
+
{
|
256
|
+
"You" => interaction.target.to_s
|
257
|
+
}
|
258
|
+
},
|
259
|
+
},
|
260
|
+
}) do |interaction, target|
|
261
|
+
interaction.post("Hello, #{target}!")
|
262
|
+
end
|
263
|
+
```
|
264
|
+
|
265
|
+
In the above example, `You` will be displayed in the user menu.
|
266
|
+
Due to the limitation of Discord API, the proc must return the result in less than 3 second.
|
267
|
+
|
242
268
|
### Register User Context Menu Command
|
243
269
|
|
244
270
|
```ruby
|
data/docs/cli/{init.md → new.md}
RENAMED
File without changes
|
data/docs/cli/setup.md
CHANGED
data/docs/cli.md
CHANGED
@@ -16,7 +16,7 @@ Currently, discorb has the following commands:
|
|
16
16
|
|
17
17
|
| Command | Description |
|
18
18
|
|---------|-------------|
|
19
|
-
| {file:docs/cli/
|
19
|
+
| {file:docs/cli/new.md `new`} | Create a new project. |
|
20
20
|
| {file:docs/cli/irb.md `irb`} | Start an interactive Ruby shell with connected client. |
|
21
21
|
| {file:docs/cli/run.md `run`} | Run a client. |
|
22
22
|
| {file:docs/cli/setup.md `setup`} | Setup application commands. |
|
data/docs/events.md
CHANGED
@@ -88,6 +88,11 @@ Fires when the client is resumed connection.
|
|
88
88
|
Fires when an error occurs during an event.
|
89
89
|
Defaults to printing the error to stderr, override to handle it yourself.
|
90
90
|
|
91
|
+
#### `setup()`
|
92
|
+
|
93
|
+
Fires when `discorb setup` is run.
|
94
|
+
This is useful for setting up some dependencies, such as the database.
|
95
|
+
|
91
96
|
### Guild events
|
92
97
|
|
93
98
|
#### `guild_join(guild)`
|
data/docs/extension.md
CHANGED
@@ -2,16 +2,18 @@
|
|
2
2
|
|
3
3
|
# Extension
|
4
4
|
|
5
|
-
Extension allows you to seperate
|
5
|
+
Extension allows you to seperate events.
|
6
6
|
|
7
7
|
# @since
|
8
8
|
|
9
9
|
## Make a new extension
|
10
10
|
|
11
|
-
Make a new class that
|
11
|
+
Make a new class that includes Extension.
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
class MyExtension
|
14
|
+
class MyExtension
|
15
|
+
include Discorb::Extension
|
16
|
+
|
15
17
|
# ...
|
16
18
|
end
|
17
19
|
```
|
@@ -21,7 +23,9 @@ end
|
|
21
23
|
Use {Discorb::Extension.event} to register event, or {Discorb::Extension.once_event} to register event only once.
|
22
24
|
|
23
25
|
```ruby
|
24
|
-
class MyExtension
|
26
|
+
class MyExtension
|
27
|
+
include Discorb::Extension
|
28
|
+
|
25
29
|
event :message do |message|
|
26
30
|
# ...
|
27
31
|
end
|
@@ -39,7 +43,9 @@ Note block will be binded to the extension instance.
|
|
39
43
|
Use `Discorb::Extension.command` to register command, see {Discorb::ApplicationCommand::Handler} for more information.
|
40
44
|
|
41
45
|
```ruby
|
42
|
-
class MyExtension
|
46
|
+
class MyExtension
|
47
|
+
include Discorb::Extension
|
48
|
+
|
43
49
|
slash("command", "Command") do |interaction|
|
44
50
|
# ...
|
45
51
|
end
|
@@ -64,7 +70,9 @@ end
|
|
64
70
|
Use {Discorb::Client#load_extension} to load extension.
|
65
71
|
|
66
72
|
```ruby
|
67
|
-
class MyExtension
|
73
|
+
class MyExtension
|
74
|
+
include Discorb::Extension
|
75
|
+
|
68
76
|
event :message do |message|
|
69
77
|
# ...
|
70
78
|
end
|
@@ -78,9 +86,45 @@ client.load_extension(MyExtension)
|
|
78
86
|
You can access {Discorb::Client} from extension with `@client`.
|
79
87
|
|
80
88
|
```ruby
|
81
|
-
class MyExtension
|
89
|
+
class MyExtension
|
90
|
+
include Discorb::Extension
|
91
|
+
|
82
92
|
event :standby do |message|
|
83
93
|
puts "Logged in as #{@client.user}"
|
84
94
|
end
|
85
95
|
end
|
86
96
|
```
|
97
|
+
|
98
|
+
## Receiving Arguments on load
|
99
|
+
|
100
|
+
You can receive arguments by adding some arguments to `#initialize`.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
class MyExtension
|
104
|
+
include Discorb::Extension
|
105
|
+
|
106
|
+
def initialize(client, arg1, arg2)
|
107
|
+
super(client)
|
108
|
+
# @client = client will also work, but it's not recommended.
|
109
|
+
@arg1 = arg1
|
110
|
+
@arg2 = arg2
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
client.load_extension(MyExtension, "arg1", "arg2")
|
115
|
+
|
116
|
+
```
|
117
|
+
|
118
|
+
## Do something on load
|
119
|
+
|
120
|
+
You can do something on load by overriding `.loaded`. Client and arguments will be passed to it.
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
class MyExtension
|
124
|
+
include Discorb::Extension
|
125
|
+
|
126
|
+
def self.loaded(client)
|
127
|
+
puts "This extension is loaded to #{client}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
```
|
data/docs/faq.md
CHANGED
@@ -2,13 +2,25 @@
|
|
2
2
|
|
3
3
|
# Fequently asked questions
|
4
4
|
|
5
|
-
## What is
|
5
|
+
## What is ...?
|
6
|
+
|
7
|
+
### What is `Async::Task`?
|
6
8
|
|
7
9
|
Async::Task is a object for asynchronous tasks.
|
8
10
|
|
9
11
|
https://socketry.github.io/async/ for more information.
|
10
12
|
|
11
|
-
|
13
|
+
### What is `Guild`?
|
14
|
+
|
15
|
+
It means a `server` of Discord.
|
16
|
+
|
17
|
+
### What is difference between `User` and `Member`?
|
18
|
+
|
19
|
+
`User` is a object for account, `Member` is a object for user in guild.
|
20
|
+
|
21
|
+
## How can I ...?
|
22
|
+
|
23
|
+
### How can I do something with sent messages?
|
12
24
|
|
13
25
|
Use `Async::Task#wait` method.
|
14
26
|
|
@@ -22,11 +34,12 @@ message = channel.post("Hello world!").wait # => Message
|
|
22
34
|
message.pin
|
23
35
|
```
|
24
36
|
|
25
|
-
|
37
|
+
|
38
|
+
### How can I send DM to a user?
|
26
39
|
|
27
40
|
Use {Discorb::User#post} method, {Discorb::User} includes {Discorb::Messageable}.
|
28
41
|
|
29
|
-
|
42
|
+
### How can I edit status?
|
30
43
|
|
31
44
|
Use {Discorb::Client#update_presence} method.
|
32
45
|
|
@@ -47,7 +60,7 @@ client.on :ready do
|
|
47
60
|
end
|
48
61
|
```
|
49
62
|
|
50
|
-
|
63
|
+
### How can I send files?
|
51
64
|
|
52
65
|
Use {Discorb::File} class.
|
53
66
|
|
@@ -62,6 +75,15 @@ message.channel.post "File!", files: [Discorb::File.new(File.open("./README.md")
|
|
62
75
|
message.channel.post file: Discorb::File.from_string("Hello world!", "hello.txt")
|
63
76
|
```
|
64
77
|
|
78
|
+
### How can I add reactions?
|
79
|
+
|
80
|
+
Use {Discorb::Message#add_reaction} method.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
message.add_reaction Discorb::UnicodeEmoji["🤔"]
|
84
|
+
message.add_reaction Discorb::UnicodeEmoji["thinking"]
|
85
|
+
```
|
86
|
+
|
65
87
|
# Not fequently asked questions
|
66
88
|
|
67
89
|
## How can I pronounce `discorb`?
|
data/docs/tutorial.md
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
# Tutorial
|
4
4
|
|
5
|
-
Welcome to discorb! This lib allows you to create a discord bot with
|
5
|
+
Welcome to discorb! This lib allows you to create a discord bot with Ruby.
|
6
|
+
Let's get started!
|
6
7
|
|
7
8
|
## Requirements
|
8
9
|
|
@@ -22,6 +23,7 @@ Welcome to discorb! This lib allows you to create a discord bot with ease. So, l
|
|
22
23
|
- [Sublime Text](https://www.sublimetext.com/)
|
23
24
|
- [Brackets](https://brackets.io/)
|
24
25
|
- [Notepad++](https://notepad-plus-plus.org/)
|
26
|
+
- [Vim](https://www.vim.org/)
|
25
27
|
- Git
|
26
28
|
- Bundler
|
27
29
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require "discorb"
|
2
2
|
|
3
|
-
class MessageExpander
|
3
|
+
class MessageExpander
|
4
|
+
include Discorb::Extension
|
5
|
+
|
4
6
|
@@message_regex = Regexp.new(
|
5
7
|
'(?!<)https://(?:ptb\.|canary\.)?discord(?:app)?\.com/channels/' \
|
6
8
|
"(?<guild>[0-9]{18})/(?<channel>[0-9]{18})/(?<message>[0-9]{18})(?!>)"
|
data/lib/discorb/app_command.rb
CHANGED
@@ -26,6 +26,7 @@ module Discorb
|
|
26
26
|
# | `:choice` | `Hash{String => String, Integer, Float}` | Type of the option. |
|
27
27
|
# | `:default` | `Object` | Default value of the option. |
|
28
28
|
# | `:channel_types` | `Array<Class<Discorb::Channel>>` | Type of the channel option. |
|
29
|
+
# | `:autocomplete` | `Proc` | Autocomplete function. |
|
29
30
|
#
|
30
31
|
# @param [Array<#to_s>, false, nil] guild_ids Guild IDs to set the command to. `false` to global command, `nil` to use default.
|
31
32
|
# @param [Proc] block Command block.
|
@@ -236,12 +237,12 @@ module Discorb
|
|
236
237
|
description: value[:description],
|
237
238
|
required: value[:required].nil? ? !value[:optional] : value[:required],
|
238
239
|
}
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
if value[:channel_types]
|
243
|
-
|
244
|
-
|
240
|
+
|
241
|
+
ret[:choices] = value[:choices].map { |t| { name: t[0], value: t[1] } } if value[:choices]
|
242
|
+
|
243
|
+
ret[:channel_types] = value[:channel_types].map(&:channel_type) if value[:channel_types]
|
244
|
+
|
245
|
+
ret[:autocomplete] = !!value[:autocomplete] if value[:autocomplete]
|
245
246
|
ret
|
246
247
|
end
|
247
248
|
{
|
data/lib/discorb/client.rb
CHANGED
@@ -401,6 +401,9 @@ module Discorb
|
|
401
401
|
cmd.define_singleton_method(:extension) { ins.name }
|
402
402
|
@commands << cmd
|
403
403
|
end
|
404
|
+
|
405
|
+
cls = ins.class
|
406
|
+
cls.loaded(self, ...) if cls.respond_to? :loaded
|
404
407
|
@bottom_commands += ins.class.bottom_commands
|
405
408
|
@extensions[ins.class.name] = ins
|
406
409
|
ins
|
@@ -443,16 +446,7 @@ module Discorb
|
|
443
446
|
::File.open(options[:log_file], "a")
|
444
447
|
end
|
445
448
|
@log.level = options[:log_level].to_sym
|
446
|
-
@log.colorize_log =
|
447
|
-
when nil
|
448
|
-
if @log.out == $stdout || @log.out == $stderr
|
449
|
-
true
|
450
|
-
else
|
451
|
-
false
|
452
|
-
end
|
453
|
-
when true, false
|
454
|
-
options[:log_color]
|
455
|
-
end
|
449
|
+
@log.colorize_log = options[:log_color] == nil ? @log.out.isatty : options[:log_color]
|
456
450
|
end
|
457
451
|
end
|
458
452
|
start_client(token)
|
@@ -465,6 +459,10 @@ module Discorb
|
|
465
459
|
guild_ids = false
|
466
460
|
end
|
467
461
|
setup_commands(token, guild_ids: guild_ids).wait
|
462
|
+
@events[:setup]&.each do |event|
|
463
|
+
event.call
|
464
|
+
end
|
465
|
+
self.on_setup if respond_to? :on_setup
|
468
466
|
end
|
469
467
|
end
|
470
468
|
|
@@ -490,7 +488,7 @@ module Discorb
|
|
490
488
|
@close_condition = Async::Condition.new
|
491
489
|
@main_task = Async do
|
492
490
|
@status = :running
|
493
|
-
connect_gateway(
|
491
|
+
connect_gateway(false).wait
|
494
492
|
rescue
|
495
493
|
@status = :stopped
|
496
494
|
@close_condition.signal
|
data/lib/discorb/color.rb
CHANGED
data/lib/discorb/common.rb
CHANGED
@@ -4,7 +4,7 @@ module Discorb
|
|
4
4
|
# @return [String] The API base URL.
|
5
5
|
API_BASE_URL = "https://discord.com/api/v9"
|
6
6
|
# @return [String] The version of discorb.
|
7
|
-
VERSION = "0.
|
7
|
+
VERSION = "0.11.2"
|
8
8
|
# @return [String] The user agent for the bot.
|
9
9
|
USER_AGENT = "DiscordBot (https://discorb-lib.github.io #{VERSION}) Ruby/#{RUBY_VERSION}"
|
10
10
|
|
data/lib/discorb/components.rb
CHANGED
data/lib/discorb/exe/run.rb
CHANGED
@@ -71,9 +71,9 @@ ENV["DISCORB_CLI_TITLE"] = options[:title]
|
|
71
71
|
|
72
72
|
if File.exist? script
|
73
73
|
if options[:bundler]
|
74
|
-
|
74
|
+
exec "bundle exec ruby #{script}"
|
75
75
|
else
|
76
|
-
|
76
|
+
exec "ruby #{script}"
|
77
77
|
end
|
78
78
|
else
|
79
79
|
eputs "Could not load script: \e[31m#{script}\e[91m"
|
data/lib/discorb/extension.rb
CHANGED
@@ -3,15 +3,11 @@
|
|
3
3
|
module Discorb
|
4
4
|
#
|
5
5
|
# Abstract class to make extension.
|
6
|
-
#
|
6
|
+
# Include from this module to make your own extension.
|
7
7
|
# @see file:docs/extension.md
|
8
8
|
# @abstract
|
9
9
|
#
|
10
|
-
|
11
|
-
extend Discorb::ApplicationCommand::Handler
|
12
|
-
|
13
|
-
@events = {}
|
14
|
-
|
10
|
+
module Extension
|
15
11
|
def initialize(client)
|
16
12
|
@client = client
|
17
13
|
end
|
@@ -27,7 +23,12 @@ module Discorb
|
|
27
23
|
@events = ret
|
28
24
|
end
|
29
25
|
|
30
|
-
|
26
|
+
def self.included(base)
|
27
|
+
base.extend(ClassMethods)
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
include Discorb::ApplicationCommand::Handler
|
31
32
|
undef setup_commands
|
32
33
|
|
33
34
|
#
|
@@ -69,7 +70,7 @@ module Discorb
|
|
69
70
|
# @private
|
70
71
|
attr_reader :bottom_commands
|
71
72
|
|
72
|
-
def
|
73
|
+
def self.extended(klass)
|
73
74
|
klass.instance_variable_set(:@commands, [])
|
74
75
|
klass.instance_variable_set(:@bottom_commands, [])
|
75
76
|
klass.instance_variable_set(:@events, {})
|
data/lib/discorb/gateway.rb
CHANGED
@@ -481,11 +481,10 @@ module Discorb
|
|
481
481
|
module Handler
|
482
482
|
private
|
483
483
|
|
484
|
-
def connect_gateway(
|
484
|
+
def connect_gateway(reconnect)
|
485
485
|
@log.info "Connecting to gateway."
|
486
486
|
Async do
|
487
|
-
@http = HTTP.new(self)
|
488
|
-
@first = first
|
487
|
+
@http = HTTP.new(self)
|
489
488
|
_, gateway_response = @http.get("/gateway").wait
|
490
489
|
gateway_url = gateway_response[:url]
|
491
490
|
endpoint = Async::HTTP::Endpoint.parse("#{gateway_url}?v=9&encoding=json&compress=zlib-stream",
|
@@ -495,36 +494,55 @@ module Discorb
|
|
495
494
|
@connection = connection
|
496
495
|
@zlib_stream = Zlib::Inflate.new(Zlib::MAX_WBITS)
|
497
496
|
@buffer = +""
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
497
|
+
begin
|
498
|
+
while (message = @connection.read)
|
499
|
+
@buffer << message
|
500
|
+
if message.end_with?((+"\x00\x00\xff\xff").force_encoding("ASCII-8BIT"))
|
501
|
+
begin
|
502
|
+
data = @zlib_stream.inflate(@buffer)
|
503
|
+
@buffer = +""
|
504
|
+
message = JSON.parse(data, symbolize_names: true)
|
505
|
+
rescue JSON::ParserError
|
506
|
+
@buffer = +""
|
507
|
+
@log.error "Received invalid JSON from gateway."
|
508
|
+
@log.debug "#{data}"
|
509
|
+
else
|
510
|
+
handle_gateway(message, reconnect)
|
511
|
+
end
|
511
512
|
end
|
512
513
|
end
|
514
|
+
rescue EOFError, Async::Wrapper::Cancelled, Async::Wrapper::WaitError
|
515
|
+
# Ignore
|
513
516
|
end
|
514
517
|
end
|
515
518
|
rescue Protocol::WebSocket::ClosedError => e
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
raise ClientError.new("Authentication failed
|
520
|
-
when
|
521
|
-
@log.info "
|
522
|
-
connect_gateway(
|
519
|
+
@tasks.map(&:stop)
|
520
|
+
case e.code
|
521
|
+
when 4004
|
522
|
+
raise ClientError.new("Authentication failed"), cause: nil
|
523
|
+
when 4009
|
524
|
+
@log.info "Session timed out, reconnecting."
|
525
|
+
connect_gateway(true)
|
526
|
+
when 4014
|
527
|
+
raise ClientError.new("Disallowed intents were specified"), cause: nil
|
528
|
+
when 4002, 4003, 4005, 4007
|
529
|
+
raise ClientError.new(<<~EOS), cause: e
|
530
|
+
Disconnected from gateway, probably due to library issues.
|
531
|
+
#{e.message}
|
532
|
+
|
533
|
+
Please report this to the library issue tracker.
|
534
|
+
https://github.com/discorb-lib/discorb/issues
|
535
|
+
EOS
|
536
|
+
when 1001
|
537
|
+
@log.info "Gateway closed with code 1001, reconnecting."
|
538
|
+
connect_gateway(true)
|
523
539
|
else
|
524
|
-
@log.error "Discord WebSocket closed
|
540
|
+
@log.error "Discord WebSocket closed with code #{e.code}."
|
541
|
+
@log.debug "#{e.message}"
|
525
542
|
connect_gateway(false)
|
526
543
|
end
|
527
|
-
rescue
|
544
|
+
rescue => e
|
545
|
+
@log.error "Discord WebSocket error: #{e.message}"
|
528
546
|
connect_gateway(false)
|
529
547
|
end
|
530
548
|
end
|
@@ -533,18 +551,26 @@ module Discorb
|
|
533
551
|
def send_gateway(opcode, **value)
|
534
552
|
@connection.write({ op: opcode, d: value }.to_json)
|
535
553
|
@connection.flush
|
536
|
-
@log.debug "Sent message
|
554
|
+
@log.debug "Sent message #{{ op: opcode, d: value }.to_json.gsub(@token, "[Token]")}"
|
537
555
|
end
|
538
556
|
|
539
|
-
def handle_gateway(payload)
|
557
|
+
def handle_gateway(payload, reconnect)
|
540
558
|
Async do |task|
|
541
559
|
data = payload[:d]
|
542
560
|
@last_s = payload[:s] if payload[:s]
|
543
|
-
@log.debug "Received message with opcode #{payload[:op]} from gateway:
|
561
|
+
@log.debug "Received message with opcode #{payload[:op]} from gateway:"
|
562
|
+
@log.debug "#{payload.to_json.gsub(@token, "[Token]")}"
|
544
563
|
case payload[:op]
|
545
564
|
when 10
|
546
565
|
@heartbeat_interval = data[:heartbeat_interval]
|
547
|
-
if
|
566
|
+
if reconnect
|
567
|
+
payload = {
|
568
|
+
token: @token,
|
569
|
+
session_id: @session_id,
|
570
|
+
seq: @last_s,
|
571
|
+
}
|
572
|
+
send_gateway(6, **payload)
|
573
|
+
else
|
548
574
|
payload = {
|
549
575
|
token: @token,
|
550
576
|
intents: @intents.value,
|
@@ -553,33 +579,22 @@ module Discorb
|
|
553
579
|
}
|
554
580
|
payload[:presence] = @identify_presence if @identify_presence
|
555
581
|
send_gateway(2, **payload)
|
556
|
-
Async do
|
557
|
-
sleep 2
|
558
|
-
next unless @uncached_guilds.nil?
|
559
|
-
|
560
|
-
raise ClientError, "Failed to connect to gateway.\nHint: This usually means that your intents are invalid."
|
561
|
-
exit 1
|
562
|
-
end
|
563
|
-
else
|
564
|
-
payload = {
|
565
|
-
token: @token,
|
566
|
-
session_id: @session_id,
|
567
|
-
seq: @last_s,
|
568
|
-
}
|
569
|
-
send_gateway(6, **payload)
|
570
582
|
end
|
583
|
+
when 7
|
584
|
+
@log.info "Received opcode 7, reconnecting"
|
585
|
+
@tasks.map(&:stop)
|
571
586
|
when 9
|
572
587
|
@log.warn "Received opcode 9, closed connection"
|
573
588
|
@tasks.map(&:stop)
|
574
589
|
if data
|
575
590
|
@log.info "Connection is resumable, reconnecting"
|
576
591
|
@connection.close
|
577
|
-
connect_gateway(
|
592
|
+
connect_gateway(true)
|
578
593
|
else
|
579
594
|
@log.info "Connection is not resumable, reconnecting with opcode 2"
|
580
|
-
sleep(2)
|
581
595
|
@connection.close
|
582
|
-
|
596
|
+
sleep(2)
|
597
|
+
connect_gateway(false)
|
583
598
|
end
|
584
599
|
when 11
|
585
600
|
@log.debug "Received opcode 11"
|
@@ -1024,7 +1039,7 @@ module Discorb
|
|
1024
1039
|
if respond_to?("event_" + event_name.downcase)
|
1025
1040
|
__send__("event_" + event_name.downcase, data)
|
1026
1041
|
else
|
1027
|
-
@log.debug "
|
1042
|
+
@log.debug "#{event_name}\n#{data.inspect}"
|
1028
1043
|
end
|
1029
1044
|
end
|
1030
1045
|
end
|
data/lib/discorb/http.rb
CHANGED
@@ -36,13 +36,7 @@ module Discorb
|
|
36
36
|
resp = http.get(get_path(path), get_headers(headers, "", audit_log_reason), **kwargs)
|
37
37
|
data = get_response_data(resp)
|
38
38
|
@ratelimit_handler.save("GET", path, resp)
|
39
|
-
|
40
|
-
@client.log.warn "Ratelimit exceeded for #{path}, trying again in #{data[:retry_after]} seconds."
|
41
|
-
task.sleep(data[:retry_after])
|
42
|
-
get(path, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
43
|
-
else
|
44
|
-
[resp, data]
|
45
|
-
end)
|
39
|
+
handle_response(:patch, resp, data, path, nil, headers, audit_log_reason, kwargs)
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
@@ -67,12 +61,7 @@ module Discorb
|
|
67
61
|
resp = http.post(get_path(path), get_body(body), get_headers(headers, body, audit_log_reason), **kwargs)
|
68
62
|
data = get_response_data(resp)
|
69
63
|
@ratelimit_handler.save("POST", path, resp)
|
70
|
-
|
71
|
-
task.sleep(data[:retry_after])
|
72
|
-
post(path, body, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
73
|
-
else
|
74
|
-
[resp, data]
|
75
|
-
end)
|
64
|
+
handle_response(:post, resp, data, path, body, headers, audit_log_reason, kwargs)
|
76
65
|
end
|
77
66
|
end
|
78
67
|
|
@@ -97,12 +86,7 @@ module Discorb
|
|
97
86
|
resp = http.patch(get_path(path), get_body(body), get_headers(headers, body, audit_log_reason), **kwargs)
|
98
87
|
data = get_response_data(resp)
|
99
88
|
@ratelimit_handler.save("PATCH", path, resp)
|
100
|
-
|
101
|
-
task.sleep(data[:retry_after])
|
102
|
-
patch(path, body, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
103
|
-
else
|
104
|
-
[resp, data]
|
105
|
-
end)
|
89
|
+
handle_response(:patch, resp, data, path, body, headers, audit_log_reason, kwargs)
|
106
90
|
end
|
107
91
|
end
|
108
92
|
|
@@ -127,12 +111,7 @@ module Discorb
|
|
127
111
|
resp = http.put(get_path(path), get_body(body), get_headers(headers, body, audit_log_reason), **kwargs)
|
128
112
|
data = get_response_data(resp)
|
129
113
|
@ratelimit_handler.save("PUT", path, resp)
|
130
|
-
|
131
|
-
task.sleep(data[:retry_after])
|
132
|
-
put(path, body, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
133
|
-
else
|
134
|
-
[resp, data]
|
135
|
-
end)
|
114
|
+
handle_response(:put, resp, data, path, body, headers, audit_log_reason, kwargs)
|
136
115
|
end
|
137
116
|
end
|
138
117
|
|
@@ -151,17 +130,12 @@ module Discorb
|
|
151
130
|
# @raise [Discorb::HTTPError] The request was failed.
|
152
131
|
#
|
153
132
|
def delete(path, headers: nil, audit_log_reason: nil, **kwargs)
|
154
|
-
Async do
|
133
|
+
Async do
|
155
134
|
@ratelimit_handler.wait("DELETE", path)
|
156
135
|
resp = http.delete(get_path(path), get_headers(headers, "", audit_log_reason))
|
157
136
|
data = get_response_data(resp)
|
158
137
|
@ratelimit_handler.save("DELETE", path, resp)
|
159
|
-
|
160
|
-
task.sleep(data[:retry_after])
|
161
|
-
delete(path, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
162
|
-
else
|
163
|
-
[resp, data]
|
164
|
-
end)
|
138
|
+
handle_response(:delete, resp, data, path, nil, headers, audit_log_reason, kwargs)
|
165
139
|
end
|
166
140
|
end
|
167
141
|
|
@@ -198,9 +172,16 @@ module Discorb
|
|
198
172
|
|
199
173
|
private
|
200
174
|
|
201
|
-
def
|
202
|
-
resp, data = *ary
|
175
|
+
def handle_response(method, resp, data, path, body, headers, audit_log_reason, kwargs)
|
203
176
|
case resp.code
|
177
|
+
when "429"
|
178
|
+
@client.log.info("Rate limit exceeded for #{method} #{path}, waiting #{data[:retry_after]} seconds")
|
179
|
+
sleep(data[:retry_after])
|
180
|
+
if body
|
181
|
+
__send__(method, path, body, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
182
|
+
else
|
183
|
+
__send__(method, path, headers: headers, audit_log_reason: audit_log_reason, **kwargs).wait
|
184
|
+
end
|
204
185
|
when "400"
|
205
186
|
raise BadRequestError.new(resp, data)
|
206
187
|
when "401"
|
@@ -247,15 +228,19 @@ module Discorb
|
|
247
228
|
end
|
248
229
|
|
249
230
|
def get_response_data(resp)
|
250
|
-
|
251
|
-
|
231
|
+
begin
|
232
|
+
data = JSON.parse(resp.body, symbolize_names: true)
|
233
|
+
rescue JSON::ParserError, TypeError
|
234
|
+
if resp.body.nil? || resp.body.empty?
|
235
|
+
data = nil
|
236
|
+
else
|
237
|
+
data = resp.body
|
238
|
+
end
|
252
239
|
end
|
253
|
-
|
254
|
-
|
255
|
-
nil
|
256
|
-
else
|
257
|
-
JSON.parse(rd, symbolize_names: true)
|
240
|
+
if resp["Via"].nil? && resp.code == "429" && data.is_a?(String)
|
241
|
+
raise CloudFlareBanError.new(resp, @client)
|
258
242
|
end
|
243
|
+
data
|
259
244
|
end
|
260
245
|
|
261
246
|
def http
|
data/lib/discorb/integration.rb
CHANGED
@@ -63,7 +63,7 @@ module Discorb
|
|
63
63
|
#
|
64
64
|
def delete!(reason: nil)
|
65
65
|
Async do
|
66
|
-
@client.http.delete("/guilds/#{@guild}/integrations/#{@id}",
|
66
|
+
@client.http.delete("/guilds/#{@guild}/integrations/#{@id}", audit_log_reason: reason).wait
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -80,7 +80,7 @@ module Discorb
|
|
80
80
|
@enable_emoticons = data[:enable_emoticons]
|
81
81
|
@expire_behavior = self.class.expire_behavior[data[:expire_behavior]]
|
82
82
|
@expire_grace_period = data[:expire_grace_period]
|
83
|
-
@user = @client.users[data[:user].
|
83
|
+
@user = @client.users[data[:user][:id]] or Discorb::User.new(@client, data[:user])
|
84
84
|
@account = Account.new(data[:account])
|
85
85
|
@subscriber_count = data[:subscriber_count]
|
86
86
|
@revoked = data[:revoked]
|
data/lib/discorb/interaction.rb
CHANGED
@@ -364,7 +364,7 @@ module Discorb
|
|
364
364
|
end
|
365
365
|
|
366
366
|
unless (command = @client.bottom_commands.find { |c| c.to_s == name && c.type_raw == 1 })
|
367
|
-
@client.log.warn "Unknown command name #{name},
|
367
|
+
@client.log.warn "Unknown command name #{name}, ignoring"
|
368
368
|
next
|
369
369
|
end
|
370
370
|
|
@@ -451,6 +451,89 @@ module Discorb
|
|
451
451
|
end
|
452
452
|
end
|
453
453
|
|
454
|
+
#
|
455
|
+
# Represents auto complete interaction.
|
456
|
+
#
|
457
|
+
class AutoComplete < Interaction
|
458
|
+
@interaction_type = 4
|
459
|
+
@interaction_name = :auto_complete
|
460
|
+
|
461
|
+
# @private
|
462
|
+
def _set_data(data)
|
463
|
+
super
|
464
|
+
Sync do
|
465
|
+
name = data[:name]
|
466
|
+
options = nil
|
467
|
+
if (option = data[:options]&.first)
|
468
|
+
case option[:type]
|
469
|
+
when 1
|
470
|
+
name += " #{option[:name]}"
|
471
|
+
options = option[:options]
|
472
|
+
when 2
|
473
|
+
name += " #{option[:name]}"
|
474
|
+
if (option_sub = option[:options]&.first)
|
475
|
+
if option_sub[:type] == 1
|
476
|
+
name += " #{option_sub[:name]}"
|
477
|
+
options = option_sub[:options]
|
478
|
+
else
|
479
|
+
options = option[:options]
|
480
|
+
end
|
481
|
+
end
|
482
|
+
else
|
483
|
+
options = data[:options]
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
unless (command = @client.bottom_commands.find { |c| c.to_s == name && c.type_raw == 1 })
|
488
|
+
@client.log.warn "Unknown command name #{name}, ignoring"
|
489
|
+
next
|
490
|
+
end
|
491
|
+
|
492
|
+
option_map = command.options.map { |k, v| [k.to_s, v[:default]] }.to_h
|
493
|
+
options ||= []
|
494
|
+
options.each_with_index do |option|
|
495
|
+
val = case option[:type]
|
496
|
+
when 3, 4, 5, 10
|
497
|
+
option[:value]
|
498
|
+
when 6
|
499
|
+
guild.members[option[:value]] || guild.fetch_member(option[:value]).wait
|
500
|
+
when 7
|
501
|
+
guild.channels[option[:value]] || guild.fetch_channels.wait.find { |channel| channel.id == option[:value] }
|
502
|
+
when 8
|
503
|
+
guild.roles[option[:value]] || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
|
504
|
+
when 9
|
505
|
+
guild.members[option[:value]] || guild.roles[option[:value]] || guild.fetch_member(option[:value]).wait || guild.fetch_roles.wait.find { |role| role.id == option[:value] }
|
506
|
+
end
|
507
|
+
option_map[option[:name]] = val
|
508
|
+
end
|
509
|
+
focused_index = options.find_index { |o| o[:focused] }
|
510
|
+
val = command.options.values[focused_index][:autocomplete]&.call(self, *command.options.map { |k, v| option_map[k.to_s] })
|
511
|
+
send_complete_result(val)
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
# @private
|
516
|
+
def send_complete_result(val)
|
517
|
+
@client.http.post("/interactions/#{@id}/#{@token}/callback", {
|
518
|
+
type: 8,
|
519
|
+
data: {
|
520
|
+
choices: val.map do |vk, vv|
|
521
|
+
{
|
522
|
+
name: vk,
|
523
|
+
value: vv,
|
524
|
+
}
|
525
|
+
end,
|
526
|
+
},
|
527
|
+
}).wait
|
528
|
+
rescue Discorb::NotFoundError
|
529
|
+
@client.log.warn "Failed to send auto complete result, This may be caused by the suggestion is taking too long (over 3 seconds) to respond", fallback: $stderr
|
530
|
+
end
|
531
|
+
|
532
|
+
class << self
|
533
|
+
alias make_interaction new
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
454
537
|
#
|
455
538
|
# Represents a message component interaction.
|
456
539
|
# @abstract
|
data/lib/discorb/log.rb
CHANGED
@@ -65,10 +65,11 @@ module Discorb
|
|
65
65
|
return
|
66
66
|
end
|
67
67
|
|
68
|
+
time = Time.now.iso8601
|
68
69
|
if @colorize_log
|
69
|
-
@out.puts("\e[
|
70
|
+
@out.puts("\e[90m#{time}\e[0m #{color}#{name.ljust(5)}\e[0m #{message}")
|
70
71
|
else
|
71
|
-
@out.puts("
|
72
|
+
@out.puts("#{time} #{name.ljust(5)} #{message}")
|
72
73
|
end
|
73
74
|
end
|
74
75
|
end
|
data/lib/discorb/member.rb
CHANGED
@@ -71,21 +71,12 @@ module Discorb
|
|
71
71
|
_set_data(user_data, member_data)
|
72
72
|
end
|
73
73
|
|
74
|
-
#
|
75
|
-
# Format the member to `@name` style.
|
76
|
-
#
|
77
|
-
# @return [String] The formatted member.
|
78
|
-
#
|
79
|
-
def to_s
|
80
|
-
"@#{name}"
|
81
|
-
end
|
82
|
-
|
83
74
|
#
|
84
75
|
# Format the member to `Username#Discriminator` style.
|
85
76
|
#
|
86
77
|
# @return [String] The formatted member.
|
87
78
|
#
|
88
|
-
def
|
79
|
+
def to_s
|
89
80
|
"#{username}##{discriminator}"
|
90
81
|
end
|
91
82
|
|
data/lib/discorb/modules.rb
CHANGED
@@ -94,7 +94,7 @@ module Discorb
|
|
94
94
|
#
|
95
95
|
def delete_message!(message_id, reason: nil)
|
96
96
|
Async do
|
97
|
-
@client.http.delete("/channels/#{channel_id.wait}/messages/#{message_id}",
|
97
|
+
@client.http.delete("/channels/#{channel_id.wait}/messages/#{message_id}", audit_log_reason: reason).wait
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
data/lib/discorb/rate_limit.rb
CHANGED
@@ -9,8 +9,9 @@ module Discorb
|
|
9
9
|
# @private
|
10
10
|
def initialize(client)
|
11
11
|
@client = client
|
12
|
-
@
|
13
|
-
@
|
12
|
+
@current_ratelimits = {}
|
13
|
+
@path_ratelimit_bucket = {}
|
14
|
+
@global = false
|
14
15
|
end
|
15
16
|
|
16
17
|
#
|
@@ -22,18 +23,26 @@ module Discorb
|
|
22
23
|
def wait(method, path)
|
23
24
|
return if path.start_with?("https://")
|
24
25
|
|
25
|
-
|
26
|
+
if @global
|
27
|
+
time = b[:reset_at] - Time.now.to_f
|
28
|
+
@client.log.info("global rate limit reached, waiting #{time} seconds")
|
29
|
+
sleep(time)
|
30
|
+
@global = false
|
31
|
+
end
|
32
|
+
|
33
|
+
return unless hash = @path_ratelimit_bucket[method + path]
|
26
34
|
|
27
|
-
return unless b = @
|
35
|
+
return unless b = @current_ratelimits[hash]
|
28
36
|
|
29
|
-
if b[:reset_at] < Time.now.
|
30
|
-
@
|
37
|
+
if b[:reset_at] < Time.now.to_f
|
38
|
+
@current_ratelimits.delete(hash)
|
31
39
|
return
|
32
40
|
end
|
33
41
|
return if b[:remaining] > 0
|
34
42
|
|
35
|
-
|
36
|
-
|
43
|
+
time = b[:reset_at] - Time.now.to_f
|
44
|
+
@client.log.info("rate limit for #{method} #{path} reached, waiting #{time} seconds")
|
45
|
+
sleep(time)
|
37
46
|
end
|
38
47
|
|
39
48
|
#
|
@@ -44,12 +53,15 @@ module Discorb
|
|
44
53
|
# @param [Net::HTTPResponse] resp The response.
|
45
54
|
#
|
46
55
|
def save(method, path, resp)
|
56
|
+
if resp["X-Ratelimit-Global"] == "true"
|
57
|
+
@global = Time.now.to_f + JSON.parse(resp.body, symbolize_names: true)[:retry_after]
|
58
|
+
end
|
47
59
|
return unless resp["X-RateLimit-Remaining"]
|
48
60
|
|
49
|
-
@
|
50
|
-
@
|
61
|
+
@path_ratelimit_bucket[method + path] = resp["X-RateLimit-Bucket"]
|
62
|
+
@current_ratelimits[resp["X-RateLimit-Bucket"]] = {
|
51
63
|
remaining: resp["X-RateLimit-Remaining"].to_i,
|
52
|
-
reset_at: resp["X-RateLimit-Reset"].
|
64
|
+
reset_at: Time.now.to_f + resp["X-RateLimit-Reset-After"].to_f,
|
53
65
|
}
|
54
66
|
end
|
55
67
|
end
|
data/lib/discorb/role.rb
CHANGED
@@ -26,6 +26,10 @@ module Discorb
|
|
26
26
|
# @return [Boolean] Whether the role is a default role.
|
27
27
|
attr_reader :mentionable
|
28
28
|
alias mentionable? mentionable
|
29
|
+
# @return [Discorb::Asset, nil] The icon of the role.
|
30
|
+
attr_reader :custom_icon
|
31
|
+
# @return [Discorb::Emoji, nil] The emoji of the role.
|
32
|
+
attr_reader :emoji
|
29
33
|
|
30
34
|
# @!attribute [r] mention
|
31
35
|
# @return [String] The mention of the role.
|
@@ -33,6 +37,8 @@ module Discorb
|
|
33
37
|
# @return [Boolean] Whether the role has a color.
|
34
38
|
# @!attribute [r] tag
|
35
39
|
# @return [Discorb::Role::Tag] The tag of the role.
|
40
|
+
# @!attribute [r] icon
|
41
|
+
# @return [Discorb::Asset, Discorb::Emoji] The icon of the role.
|
36
42
|
|
37
43
|
include Comparable
|
38
44
|
|
@@ -44,6 +50,10 @@ module Discorb
|
|
44
50
|
_set_data(data)
|
45
51
|
end
|
46
52
|
|
53
|
+
def icon
|
54
|
+
@custom_icon || @emoji
|
55
|
+
end
|
56
|
+
|
47
57
|
#
|
48
58
|
# Compares two roles by their position.
|
49
59
|
#
|
@@ -88,7 +98,7 @@ module Discorb
|
|
88
98
|
#
|
89
99
|
def move(position, reason: nil)
|
90
100
|
Async do
|
91
|
-
@client.http.patch("/guilds/#{@
|
101
|
+
@client.http.patch("/guilds/#{@guild.id}/roles", { id: @id, position: position }, audit_log_reason: reason).wait
|
92
102
|
end
|
93
103
|
end
|
94
104
|
|
@@ -103,9 +113,10 @@ module Discorb
|
|
103
113
|
# @param [Discorb::Color] color The new color of the role.
|
104
114
|
# @param [Boolean] hoist Whether the role should be hoisted.
|
105
115
|
# @param [Boolean] mentionable Whether the role should be mentionable.
|
116
|
+
# @param [Discorb::Image, Discorb::UnicodeEmoji] icon The new icon or emoji of the role.
|
106
117
|
# @param [String] reason The reason for editing the role.
|
107
118
|
#
|
108
|
-
def edit(name: :unset, position: :unset, color: :unset, hoist: :unset, mentionable: :unset, reason: nil)
|
119
|
+
def edit(name: :unset, position: :unset, color: :unset, hoist: :unset, mentionable: :unset, icon: :unset, reason: nil)
|
109
120
|
Async do
|
110
121
|
payload = {}
|
111
122
|
payload[:name] = name if name != :unset
|
@@ -113,7 +124,14 @@ module Discorb
|
|
113
124
|
payload[:color] = color.to_i if color != :unset
|
114
125
|
payload[:hoist] = hoist if hoist != :unset
|
115
126
|
payload[:mentionable] = mentionable if mentionable != :unset
|
116
|
-
|
127
|
+
if icon != :unset
|
128
|
+
if icon.is_a?(Discorb::Image)
|
129
|
+
payload[:icon] = icon.to_s
|
130
|
+
else
|
131
|
+
payload[:unicode_emoji] = icon.to_s
|
132
|
+
end
|
133
|
+
end
|
134
|
+
@client.http.patch("/guilds/#{@guild.id}/roles/#{@id}", payload, audit_log_reason: reason).wait
|
117
135
|
end
|
118
136
|
end
|
119
137
|
|
@@ -126,7 +144,7 @@ module Discorb
|
|
126
144
|
#
|
127
145
|
def delete!(reason: nil)
|
128
146
|
Async do
|
129
|
-
@client.http.delete("/guilds/#{@
|
147
|
+
@client.http.delete("/guilds/#{@guild.id}/roles/#{@id}", audit_log_reason: reason).wait
|
130
148
|
end
|
131
149
|
end
|
132
150
|
|
@@ -182,6 +200,8 @@ module Discorb
|
|
182
200
|
@managed = data[:managed]
|
183
201
|
@mentionable = data[:mentionable]
|
184
202
|
@tags = data[:tags] || {}
|
203
|
+
@custom_icon = data[:icon] ? Asset.new(self, data[:icon], path: "role-icons/#{@id}") : nil
|
204
|
+
@emoji = data[:unicode_emoji] ? UnicodeEmoji.new(data[:unicode_emoji]) : nil
|
185
205
|
@guild.roles[@id] = self unless data[:no_cache]
|
186
206
|
@data.update(data)
|
187
207
|
end
|
data/lib/discorb/voice_state.rb
CHANGED
@@ -193,7 +193,7 @@ module Discorb
|
|
193
193
|
#
|
194
194
|
def delete!(reason: nil)
|
195
195
|
Async do
|
196
|
-
@client.http.delete("/stage-instances/#{@channel_id}",
|
196
|
+
@client.http.delete("/stage-instances/#{@channel_id}", audit_log_reason: reason).wait
|
197
197
|
self
|
198
198
|
end
|
199
199
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discorb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sevenc-nanashi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -79,6 +79,7 @@ files:
|
|
79
79
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
80
80
|
- ".github/workflows/build_main.yml"
|
81
81
|
- ".github/workflows/build_version.yml"
|
82
|
+
- ".github/workflows/package_register.yml"
|
82
83
|
- ".gitignore"
|
83
84
|
- ".yardopts"
|
84
85
|
- Changelog.md
|
@@ -103,8 +104,8 @@ files:
|
|
103
104
|
- docs/assets/08_hello_once.png
|
104
105
|
- docs/assets/unused_ping_pong.png
|
105
106
|
- docs/cli.md
|
106
|
-
- docs/cli/init.md
|
107
107
|
- docs/cli/irb.md
|
108
|
+
- docs/cli/new.md
|
108
109
|
- docs/cli/run.md
|
109
110
|
- docs/cli/setup.md
|
110
111
|
- docs/events.md
|
@@ -191,7 +192,6 @@ homepage: https://github.com/discorb-lib/discorb
|
|
191
192
|
licenses:
|
192
193
|
- MIT
|
193
194
|
metadata:
|
194
|
-
allowed_push_host: https://rubygems.org
|
195
195
|
homepage_uri: https://github.com/discorb-lib/discorb
|
196
196
|
source_code_uri: https://github.com/discorb-lib/discorb
|
197
197
|
changelog_uri: https://discorb-lib.github.io/file.Changelog.html
|