onyxcord 2.0.5 → 2.0.6
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/CHANGELOG.md +8 -0
- data/lib/onyxcord/application_commands/command.rb +102 -0
- data/lib/onyxcord/application_commands/context.rb +99 -0
- data/lib/onyxcord/application_commands/option.rb +80 -0
- data/lib/onyxcord/application_commands/registry.rb +50 -0
- data/lib/onyxcord/application_commands.rb +11 -0
- data/lib/onyxcord/async/runtime.rb +30 -0
- data/lib/onyxcord/rate_limiter/async_rest.rb +149 -0
- data/lib/onyxcord/version.rb +1 -1
- data/lib/onyxcord/webhooks/version.rb +1 -1
- metadata +8 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c794e2e7f5ad51dea52e27c049fb7d08fb7b54c84b452243fe549cd54f46dd5d
|
|
4
|
+
data.tar.gz: 2f7e1a9df9cf56085e31dd7bc13e843f8c5bee2e9083817305e6936117c92dd4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dce8555d60a8bf6662bfc357c64918e75ff803ab30c43c93dab390756ee52e0057f20914367ec4cce89e5a6906c0745f99b89f42953bb9b91648caa3fe296378
|
|
7
|
+
data.tar.gz: 7b25cd2d344182abbdce7fb5f74f8cffb7dea3ad478d6a03e9018ea138635fac13e9203184f656f677c39b85b26f1a8287f24ac6a855b5b9ae64ec12165e8c72
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.6 - 2026-06-28
|
|
4
|
+
|
|
5
|
+
### Correcoes de empacotamento
|
|
6
|
+
|
|
7
|
+
- Incluidos na gem os arquivos da infraestrutura async que ficaram fora do pacote `2.0.5`: `onyxcord/async/runtime` e `onyxcord/rate_limiter/async_rest`.
|
|
8
|
+
- Incluidos na gem os arquivos da DSL moderna de application commands: `onyxcord/application_commands` e seus componentes internos.
|
|
9
|
+
- Corrige `LoadError: cannot load such file -- onyxcord/async/runtime` ao usar a gem publicada.
|
|
10
|
+
|
|
3
11
|
## 2.0.5 - 2026-06-28
|
|
4
12
|
|
|
5
13
|
### Async Runtime (Infraestrutura nao-bloqueante)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
module ApplicationCommands
|
|
5
|
+
class Command
|
|
6
|
+
attr_reader :name, :description, :type, :attributes, :options, :block
|
|
7
|
+
|
|
8
|
+
TYPES = {
|
|
9
|
+
chat_input: 1,
|
|
10
|
+
user: 2,
|
|
11
|
+
message: 3
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
def self.chat_input(name, description:, **attributes, &block)
|
|
15
|
+
new(name, description: description, type: :chat_input, **attributes, &block)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.user(name, **attributes, &block)
|
|
19
|
+
new(name, description: '', type: :user, **attributes, &block)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.message(name, **attributes, &block)
|
|
23
|
+
new(name, description: '', type: :message, **attributes, &block)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(name, description: '', type: :chat_input, **attributes, &block)
|
|
27
|
+
@name = name.to_s
|
|
28
|
+
@description = description
|
|
29
|
+
@type = type
|
|
30
|
+
@attributes = attributes
|
|
31
|
+
@options = []
|
|
32
|
+
@block = block
|
|
33
|
+
@executor = nil
|
|
34
|
+
@default_member_permissions = attributes[:default_member_permissions]
|
|
35
|
+
@nsfw = attributes[:nsfw]
|
|
36
|
+
@contexts = attributes[:contexts]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def parse(&block)
|
|
40
|
+
instance_eval(&block) if block
|
|
41
|
+
self
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def execute(&block)
|
|
45
|
+
@executor = block
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def call(context)
|
|
49
|
+
return unless @executor
|
|
50
|
+
|
|
51
|
+
@executor.call(context)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_h
|
|
55
|
+
data = {
|
|
56
|
+
name: @name,
|
|
57
|
+
type: TYPES[@type] || @type
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
data[:description] = @description if @type == :chat_input
|
|
61
|
+
data[:options] = @options.map(&:to_h) unless @options.empty?
|
|
62
|
+
data[:default_member_permissions] = @default_member_permissions if @default_member_permissions
|
|
63
|
+
data[:nsfw] = @nsfw if @nsfw
|
|
64
|
+
data[:contexts] = @contexts if @contexts
|
|
65
|
+
|
|
66
|
+
data
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
Option::OPTION_METHODS.each do |method_name, option_type|
|
|
70
|
+
define_method(method_name) do |name, description = '', **attrs, &blk|
|
|
71
|
+
opt = Option.new(name, description, option_type, **attrs, &blk)
|
|
72
|
+
@options << opt
|
|
73
|
+
opt
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def subcommand(name, description, &block)
|
|
78
|
+
sub = Option.new(name, description, :subcommand, &block)
|
|
79
|
+
@options << sub
|
|
80
|
+
sub
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def subcommand_group(name, description, &block)
|
|
84
|
+
group = Option.new(name, description, :subcommand_group, &block)
|
|
85
|
+
@options << group
|
|
86
|
+
group
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def method_missing(method_name, *args, **kwargs, &block)
|
|
90
|
+
if @block && @block.arity.positive?
|
|
91
|
+
@block.call(Context::Proxy.new(self, method_name, args, kwargs, block))
|
|
92
|
+
else
|
|
93
|
+
super
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
98
|
+
true
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
module ApplicationCommands
|
|
5
|
+
class Context
|
|
6
|
+
attr_reader :event, :command
|
|
7
|
+
|
|
8
|
+
def initialize(event, command)
|
|
9
|
+
@event = event
|
|
10
|
+
@command = command
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def bot
|
|
14
|
+
event.bot
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def user
|
|
18
|
+
event.user
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def member
|
|
22
|
+
event.user
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def guild
|
|
26
|
+
event.server
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def guild_id
|
|
30
|
+
event.server_id
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def channel
|
|
34
|
+
event.channel
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def channel_id
|
|
38
|
+
event.channel_id
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def server
|
|
42
|
+
event.server
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def server_id
|
|
46
|
+
event.server_id
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def options
|
|
50
|
+
return {} unless event.data
|
|
51
|
+
|
|
52
|
+
if event.data['options']
|
|
53
|
+
result = {}
|
|
54
|
+
event.data['options'].each do |opt|
|
|
55
|
+
key = opt['name'].to_sym
|
|
56
|
+
result[key] = opt['value']
|
|
57
|
+
end
|
|
58
|
+
result
|
|
59
|
+
else
|
|
60
|
+
{}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def respond(...)
|
|
65
|
+
event.respond(...)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def defer(...)
|
|
69
|
+
event.defer(...)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def edit_original(...)
|
|
73
|
+
event.edit_response(...)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def delete_original
|
|
77
|
+
event.delete_response
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def followup(...)
|
|
81
|
+
event.send_message(...)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class Proxy
|
|
85
|
+
def initialize(command, method_name, args, kwargs, block)
|
|
86
|
+
@command = command
|
|
87
|
+
@method_name = method_name
|
|
88
|
+
@args = args
|
|
89
|
+
@kwargs = kwargs
|
|
90
|
+
@block = block
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def to_h
|
|
94
|
+
{}
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
module ApplicationCommands
|
|
5
|
+
class Option
|
|
6
|
+
attr_reader :name, :description, :type, :attributes, :options
|
|
7
|
+
|
|
8
|
+
OPTION_TYPES = {
|
|
9
|
+
subcommand: 1,
|
|
10
|
+
subcommand_group: 2,
|
|
11
|
+
string: 3,
|
|
12
|
+
integer: 4,
|
|
13
|
+
boolean: 5,
|
|
14
|
+
user: 6,
|
|
15
|
+
channel: 7,
|
|
16
|
+
role: 8,
|
|
17
|
+
mentionable: 9,
|
|
18
|
+
number: 10,
|
|
19
|
+
attachment: 11
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
OPTION_METHODS = OPTION_TYPES.each_with_object({}) do |(name, value), hash|
|
|
23
|
+
next if %i[subcommand subcommand_group].include?(name)
|
|
24
|
+
|
|
25
|
+
hash[name] = value
|
|
26
|
+
end.freeze
|
|
27
|
+
|
|
28
|
+
def initialize(name, description, type, **attributes, &block)
|
|
29
|
+
@name = name.to_s
|
|
30
|
+
@description = description
|
|
31
|
+
@type = type
|
|
32
|
+
@attributes = attributes
|
|
33
|
+
@options = []
|
|
34
|
+
@block = block
|
|
35
|
+
|
|
36
|
+
instance_eval(&@block) if @block && type == :subcommand
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_h
|
|
40
|
+
data = {
|
|
41
|
+
name: @name,
|
|
42
|
+
description: @description,
|
|
43
|
+
type: OPTION_TYPES[@type] || @type
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
data[:required] = @attributes[:required] unless @attributes[:required].nil?
|
|
47
|
+
data[:min_length] = @attributes[:min_length] if @attributes[:min_length]
|
|
48
|
+
data[:max_length] = @attributes[:max_length] if @attributes[:max_length]
|
|
49
|
+
data[:min_value] = @attributes[:min_value] if @attributes[:min_value]
|
|
50
|
+
data[:max_value] = @attributes[:max_value] if @attributes[:max_value]
|
|
51
|
+
data[:autocomplete] = @attributes[:autocomplete] unless @attributes[:autocomplete].nil?
|
|
52
|
+
data[:channel_types] = @attributes[:channel_types] if @attributes[:channel_types]
|
|
53
|
+
|
|
54
|
+
if @attributes[:choices]
|
|
55
|
+
data[:choices] = @attributes[:choices].map do |name, value|
|
|
56
|
+
{ name: name.to_s, value: value }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
data[:options] = @options.map(&:to_h) unless @options.empty?
|
|
61
|
+
|
|
62
|
+
data
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def subcommand(name, description, **attrs, &block)
|
|
66
|
+
sub = Option.new(name, description, :subcommand, **attrs, &block)
|
|
67
|
+
@options << sub
|
|
68
|
+
sub
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
OPTION_METHODS.each do |method_name, option_type|
|
|
72
|
+
define_method(method_name) do |name, description = '', **attrs, &blk|
|
|
73
|
+
opt = Option.new(name, description, option_type, **attrs, &blk)
|
|
74
|
+
@options << opt
|
|
75
|
+
opt
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
module ApplicationCommands
|
|
5
|
+
class Registry
|
|
6
|
+
attr_reader :bot, :commands
|
|
7
|
+
|
|
8
|
+
def initialize(bot)
|
|
9
|
+
@bot = bot
|
|
10
|
+
@commands = {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def slash(name, description:, **attributes, &block)
|
|
14
|
+
register(Command.chat_input(name, description: description, **attributes, &block))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def user(name, **attributes, &block)
|
|
18
|
+
register(Command.user(name, **attributes, &block))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def message(name, **attributes, &block)
|
|
22
|
+
register(Command.message(name, **attributes, &block))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def register(command)
|
|
26
|
+
@commands[command.name] = command
|
|
27
|
+
wire_handler(command)
|
|
28
|
+
command
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def sync!(server_id: nil, delete_unknown: false)
|
|
32
|
+
payload = @commands.values.map(&:to_h)
|
|
33
|
+
|
|
34
|
+
if server_id
|
|
35
|
+
@bot.bulk_overwrite_guild_application_commands(server_id, payload)
|
|
36
|
+
else
|
|
37
|
+
@bot.bulk_overwrite_global_application_commands(payload)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def wire_handler(command)
|
|
44
|
+
@bot.application_command(command.name) do |event|
|
|
45
|
+
command.call(Context.new(event, command))
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'onyxcord/application_commands/option'
|
|
4
|
+
require 'onyxcord/application_commands/command'
|
|
5
|
+
require 'onyxcord/application_commands/context'
|
|
6
|
+
require 'onyxcord/application_commands/registry'
|
|
7
|
+
|
|
8
|
+
module OnyxCord
|
|
9
|
+
module ApplicationCommands
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'async'
|
|
4
|
+
|
|
5
|
+
module OnyxCord
|
|
6
|
+
module AsyncRuntime
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def run(&block)
|
|
10
|
+
current = Async::Task.current?
|
|
11
|
+
return yield current if current
|
|
12
|
+
|
|
13
|
+
Async(&block).wait
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def async(&block)
|
|
17
|
+
current = Async::Task.current?
|
|
18
|
+
return current.async(&block) if current
|
|
19
|
+
|
|
20
|
+
Async(&block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def sleep(duration)
|
|
24
|
+
task = Async::Task.current?
|
|
25
|
+
return task.sleep(duration) if task.respond_to?(:sleep)
|
|
26
|
+
|
|
27
|
+
Kernel.sleep(duration)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'onyxcord/async/runtime'
|
|
5
|
+
|
|
6
|
+
module OnyxCord
|
|
7
|
+
module RateLimiter
|
|
8
|
+
class AsyncRest
|
|
9
|
+
DEFAULT_ENTRY_TTL = 3600
|
|
10
|
+
DEFAULT_PRUNE_INTERVAL = 100
|
|
11
|
+
|
|
12
|
+
def initialize(clock: -> { Time.now }, entry_ttl: DEFAULT_ENTRY_TTL, prune_interval: DEFAULT_PRUNE_INTERVAL)
|
|
13
|
+
@route_buckets = {}
|
|
14
|
+
@bucket_locks = {}
|
|
15
|
+
@bucket_last_used = {}
|
|
16
|
+
@global_lock = Mutex.new
|
|
17
|
+
@clock = clock
|
|
18
|
+
@entry_ttl = entry_ttl
|
|
19
|
+
@prune_interval = prune_interval
|
|
20
|
+
@requests_since_prune = 0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def before_request(route, major_parameter)
|
|
24
|
+
wait_for(mutex_for(route, major_parameter))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def record_response(route, major_parameter, headers)
|
|
28
|
+
headers = normalize_headers(headers)
|
|
29
|
+
bucket = headers[:x_ratelimit_bucket]
|
|
30
|
+
key = route_key(route, major_parameter)
|
|
31
|
+
touch(key)
|
|
32
|
+
|
|
33
|
+
if bucket
|
|
34
|
+
bucket = bucket_key(bucket, major_parameter)
|
|
35
|
+
@route_buckets[key] = bucket
|
|
36
|
+
touch(bucket)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
return unless headers[:x_ratelimit_remaining] == '0'
|
|
40
|
+
|
|
41
|
+
wait_seconds = headers[:x_ratelimit_reset_after].to_f
|
|
42
|
+
return unless wait_seconds.positive?
|
|
43
|
+
|
|
44
|
+
async_wait(wait_seconds, mutex_for(route, major_parameter))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def handle_rate_limit(route, major_parameter, response)
|
|
48
|
+
headers = normalize_headers(response.headers)
|
|
49
|
+
wait_seconds = retry_after(response, headers)
|
|
50
|
+
|
|
51
|
+
return unless wait_seconds.positive?
|
|
52
|
+
|
|
53
|
+
if headers[:x_ratelimit_global] == 'true' || headers[:x_ratelimit_scope] == 'global'
|
|
54
|
+
global_wait(wait_seconds)
|
|
55
|
+
else
|
|
56
|
+
async_wait(wait_seconds, mutex_for(route, major_parameter))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def stats
|
|
61
|
+
{
|
|
62
|
+
route_buckets: @route_buckets.size,
|
|
63
|
+
bucket_locks: @bucket_locks.size,
|
|
64
|
+
tracked_keys: @bucket_last_used.size
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def prune!
|
|
69
|
+
return 0 unless @entry_ttl
|
|
70
|
+
|
|
71
|
+
cutoff = @clock.call - @entry_ttl
|
|
72
|
+
stale_keys = @bucket_last_used.select { |_, last_used| last_used < cutoff }.keys
|
|
73
|
+
|
|
74
|
+
stale_keys.each do |key|
|
|
75
|
+
@bucket_locks.delete(key)
|
|
76
|
+
@bucket_last_used.delete(key)
|
|
77
|
+
@route_buckets.delete(key)
|
|
78
|
+
@route_buckets.delete_if { |_, bucket_key| bucket_key == key }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
@requests_since_prune = 0
|
|
82
|
+
stale_keys.length
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def mutex_for(route, major_parameter)
|
|
88
|
+
key = resolved_key(route, major_parameter)
|
|
89
|
+
touch(key)
|
|
90
|
+
@bucket_locks[key] ||= Mutex.new
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def resolved_key(route, major_parameter)
|
|
94
|
+
@route_buckets[route_key(route, major_parameter)] || route_key(route, major_parameter)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def route_key(route, major_parameter)
|
|
98
|
+
[route, major_parameter].freeze
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def bucket_key(bucket, major_parameter)
|
|
102
|
+
[:bucket, bucket, major_parameter].freeze
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def retry_after(response, headers)
|
|
106
|
+
body = response.respond_to?(:body) ? response.body : response.to_s
|
|
107
|
+
if body && !body.empty?
|
|
108
|
+
data = JSON.parse(body)
|
|
109
|
+
return data['retry_after'].to_f if data['retry_after']
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
(headers[:retry_after] || 0).to_f
|
|
113
|
+
rescue JSON::ParserError
|
|
114
|
+
(headers[:retry_after] || 0).to_f
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def normalize_headers(headers)
|
|
118
|
+
headers.each_with_object({}) do |(key, value), memo|
|
|
119
|
+
memo[key.to_s.tr('-', '_').downcase.to_sym] = value.to_s
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def touch(key)
|
|
124
|
+
@bucket_last_used[key] = @clock.call
|
|
125
|
+
prune_if_needed
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def prune_if_needed
|
|
129
|
+
return unless @prune_interval
|
|
130
|
+
|
|
131
|
+
@requests_since_prune += 1
|
|
132
|
+
prune! if @requests_since_prune >= @prune_interval
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def wait_for(mutex)
|
|
136
|
+
mutex.lock
|
|
137
|
+
mutex.unlock
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def async_wait(time, mutex)
|
|
141
|
+
mutex.synchronize { OnyxCord::AsyncRuntime.sleep(time) }
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def global_wait(time)
|
|
145
|
+
OnyxCord::AsyncRuntime.sleep(time)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
data/lib/onyxcord/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: onyxcord
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gustavo Silva
|
|
@@ -396,6 +396,12 @@ files:
|
|
|
396
396
|
- lib/onyxcord/api/server.rb
|
|
397
397
|
- lib/onyxcord/api/user.rb
|
|
398
398
|
- lib/onyxcord/api/webhook.rb
|
|
399
|
+
- lib/onyxcord/application_commands.rb
|
|
400
|
+
- lib/onyxcord/application_commands/command.rb
|
|
401
|
+
- lib/onyxcord/application_commands/context.rb
|
|
402
|
+
- lib/onyxcord/application_commands/option.rb
|
|
403
|
+
- lib/onyxcord/application_commands/registry.rb
|
|
404
|
+
- lib/onyxcord/async/runtime.rb
|
|
399
405
|
- lib/onyxcord/await.rb
|
|
400
406
|
- lib/onyxcord/bot.rb
|
|
401
407
|
- lib/onyxcord/cache.rb
|
|
@@ -482,6 +488,7 @@ files:
|
|
|
482
488
|
- lib/onyxcord/message_components.rb
|
|
483
489
|
- lib/onyxcord/paginator.rb
|
|
484
490
|
- lib/onyxcord/permissions.rb
|
|
491
|
+
- lib/onyxcord/rate_limiter/async_rest.rb
|
|
485
492
|
- lib/onyxcord/rate_limiter/gateway.rb
|
|
486
493
|
- lib/onyxcord/rate_limiter/rest.rb
|
|
487
494
|
- lib/onyxcord/version.rb
|