onyxcord 2.0.13 → 3.2.0
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/lib/onyxcord/application_commands/command.rb +4 -97
- data/lib/onyxcord/application_commands/context.rb +4 -94
- data/lib/onyxcord/application_commands/option.rb +4 -75
- data/lib/onyxcord/application_commands/registry.rb +4 -45
- data/lib/onyxcord/application_commands.rb +8 -5
- data/lib/onyxcord/bot.rb +24 -1759
- data/lib/onyxcord/{cache.rb → cache/manager.rb} +16 -14
- data/lib/onyxcord/cache/stores/gateway.rb +272 -0
- data/lib/onyxcord/commands/bot/channels.rb +48 -0
- data/lib/onyxcord/commands/bot/execution.rb +174 -0
- data/lib/onyxcord/commands/bot/message_dispatch.rb +58 -0
- data/lib/onyxcord/commands/bot/permissions.rb +72 -0
- data/lib/onyxcord/commands/bot.rb +209 -0
- data/lib/onyxcord/commands/container.rb +21 -2
- data/lib/onyxcord/commands/parser.rb +30 -1
- data/lib/onyxcord/container.rb +16 -960
- data/lib/onyxcord/core/bot/application_commands.rb +210 -0
- data/lib/onyxcord/core/bot/awaits.rb +112 -0
- data/lib/onyxcord/core/bot/invites.rb +42 -0
- data/lib/onyxcord/core/bot/messaging.rb +161 -0
- data/lib/onyxcord/core/bot/oauth.rb +27 -0
- data/lib/onyxcord/core/bot/presence.rb +103 -0
- data/lib/onyxcord/core/bot/runtime.rb +183 -0
- data/lib/onyxcord/core/bot/voice.rb +69 -0
- data/lib/onyxcord/{errors.rb → core/errors.rb} +18 -3
- data/lib/onyxcord/{logger.rb → core/logger.rb} +5 -0
- data/lib/onyxcord/core/version.rb +5 -0
- data/lib/onyxcord/events/await/base.rb +48 -0
- data/lib/onyxcord/events/await.rb +1 -46
- data/lib/onyxcord/events/ban/base.rb +54 -0
- data/lib/onyxcord/events/ban/remove.rb +11 -0
- data/lib/onyxcord/events/bans.rb +2 -58
- data/lib/onyxcord/events/channels/base.rb +91 -0
- data/lib/onyxcord/events/channels/delete.rb +73 -0
- data/lib/onyxcord/events/channels/pins.rb +44 -0
- data/lib/onyxcord/events/channels/recipients.rb +77 -0
- data/lib/onyxcord/events/channels.rb +4 -239
- data/lib/onyxcord/events/guilds/audit_logs.rb +79 -0
- data/lib/onyxcord/events/guilds/base.rb +97 -0
- data/lib/onyxcord/events/guilds/emoji.rb +147 -0
- data/lib/onyxcord/events/guilds.rb +3 -267
- data/lib/onyxcord/events/handlers/channels.rb +133 -0
- data/lib/onyxcord/events/handlers/core.rb +146 -0
- data/lib/onyxcord/events/handlers/guilds.rb +375 -0
- data/lib/onyxcord/events/handlers/interactions.rb +238 -0
- data/lib/onyxcord/events/handlers/lifetime.rb +71 -0
- data/lib/onyxcord/events/handlers/messages.rb +218 -0
- data/lib/onyxcord/events/handlers/presence.rb +56 -0
- data/lib/onyxcord/events/handlers/raw.rb +39 -0
- data/lib/onyxcord/events/handlers/reactions.rb +98 -0
- data/lib/onyxcord/events/handlers/scheduled_events.rb +243 -0
- data/lib/onyxcord/events/handlers/voice.rb +46 -0
- data/lib/onyxcord/events/integration/base.rb +45 -0
- data/lib/onyxcord/events/integration/create.rb +11 -0
- data/lib/onyxcord/events/integration/delete.rb +48 -0
- data/lib/onyxcord/events/integration/update.rb +11 -0
- data/lib/onyxcord/events/integrations.rb +4 -98
- data/lib/onyxcord/events/interactions/application_commands.rb +185 -0
- data/lib/onyxcord/events/interactions/autocomplete.rb +62 -0
- data/lib/onyxcord/events/interactions/base.rb +175 -0
- data/lib/onyxcord/events/interactions/components.rb +221 -0
- data/lib/onyxcord/events/interactions/permissions.rb +53 -0
- data/lib/onyxcord/events/interactions.rb +5 -622
- data/lib/onyxcord/events/invite/create.rb +79 -0
- data/lib/onyxcord/events/invite/delete.rb +55 -0
- data/lib/onyxcord/events/invites.rb +2 -125
- data/lib/onyxcord/events/lifetime/base.rb +31 -0
- data/lib/onyxcord/events/lifetime.rb +1 -29
- data/lib/onyxcord/events/member/add.rb +12 -0
- data/lib/onyxcord/events/member/base.rb +67 -0
- data/lib/onyxcord/events/member/delete.rb +21 -0
- data/lib/onyxcord/events/member/update.rb +25 -0
- data/lib/onyxcord/events/members.rb +4 -108
- data/lib/onyxcord/events/message/base.rb +295 -0
- data/lib/onyxcord/events/message/ids.rb +71 -0
- data/lib/onyxcord/events/message/mentions.rb +55 -0
- data/lib/onyxcord/events/message/updates.rb +27 -0
- data/lib/onyxcord/events/message.rb +4 -397
- data/lib/onyxcord/events/poll/add.rb +11 -0
- data/lib/onyxcord/events/poll/base.rb +106 -0
- data/lib/onyxcord/events/poll/remove.rb +11 -0
- data/lib/onyxcord/events/polls.rb +3 -116
- data/lib/onyxcord/events/presence/playing.rb +77 -0
- data/lib/onyxcord/events/presence/status.rb +60 -0
- data/lib/onyxcord/events/presence.rb +2 -129
- data/lib/onyxcord/events/raw/base.rb +74 -0
- data/lib/onyxcord/events/raw.rb +1 -72
- data/lib/onyxcord/events/reactions/base.rb +143 -0
- data/lib/onyxcord/events/reactions/clear.rb +99 -0
- data/lib/onyxcord/events/reactions.rb +2 -216
- data/lib/onyxcord/events/role/create.rb +46 -0
- data/lib/onyxcord/events/role/delete.rb +40 -0
- data/lib/onyxcord/events/role/update.rb +11 -0
- data/lib/onyxcord/events/roles.rb +3 -85
- data/lib/onyxcord/events/scheduled_events/events.rb +112 -0
- data/lib/onyxcord/events/scheduled_events/users.rb +91 -0
- data/lib/onyxcord/events/scheduled_events.rb +2 -169
- data/lib/onyxcord/events/thread/base.rb +49 -0
- data/lib/onyxcord/events/thread/members.rb +44 -0
- data/lib/onyxcord/events/thread/update.rb +18 -0
- data/lib/onyxcord/events/threads.rb +3 -98
- data/lib/onyxcord/events/typing/base.rb +73 -0
- data/lib/onyxcord/events/typing.rb +1 -71
- data/lib/onyxcord/events/voice/server_update.rb +48 -0
- data/lib/onyxcord/events/voice/state_update.rb +137 -0
- data/lib/onyxcord/events/voice_server_update.rb +2 -46
- data/lib/onyxcord/events/voice_state_update.rb +2 -135
- data/lib/onyxcord/events/webhook/update.rb +65 -0
- data/lib/onyxcord/events/webhooks.rb +1 -63
- data/lib/onyxcord/gateway/client.rb +460 -0
- data/lib/onyxcord/interactions/command.rb +120 -0
- data/lib/onyxcord/interactions/context.rb +109 -0
- data/lib/onyxcord/interactions/internal/application_command.rb +203 -0
- data/lib/onyxcord/interactions/internal/message.rb +152 -0
- data/lib/onyxcord/interactions/internal/metadata.rb +109 -0
- data/lib/onyxcord/interactions/internal/option_builder.rb +230 -0
- data/lib/onyxcord/interactions/internal/permission_builder.rb +90 -0
- data/lib/onyxcord/interactions/option.rb +88 -0
- data/lib/onyxcord/interactions/registry.rb +50 -0
- data/lib/onyxcord/interactions.rb +16 -0
- data/lib/onyxcord/internal/async_runtime.rb +32 -0
- data/lib/onyxcord/internal/event_bus.rb +591 -0
- data/lib/onyxcord/internal/event_executor.rb +155 -0
- data/lib/onyxcord/internal/gateway/opcodes.rb +22 -0
- data/lib/onyxcord/internal/gateway/session.rb +45 -0
- data/lib/onyxcord/internal/http.rb +189 -0
- data/lib/onyxcord/internal/json.rb +51 -0
- data/lib/onyxcord/internal/message_payload.rb +78 -0
- data/lib/onyxcord/internal/rate_limiter/async_rest.rb +151 -0
- data/lib/onyxcord/internal/rate_limiter/gateway.rb +44 -0
- data/lib/onyxcord/internal/rate_limiter/rest.rb +144 -0
- data/lib/onyxcord/internal/upload.rb +39 -0
- data/lib/onyxcord/internal/websocket.rb +79 -0
- data/lib/onyxcord/light/data.rb +1 -1
- data/lib/onyxcord/light/integrations.rb +1 -1
- data/lib/onyxcord/light/light_bot.rb +7 -7
- data/lib/onyxcord/{data → models}/activity.rb +2 -2
- data/lib/onyxcord/{data → models}/application.rb +3 -3
- data/lib/onyxcord/{data → models}/avatar_decoration.rb +1 -1
- data/lib/onyxcord/{data → models}/channel.rb +23 -23
- data/lib/onyxcord/{data → models}/collectibles.rb +1 -1
- data/lib/onyxcord/{data → models}/emoji.rb +1 -1
- data/lib/onyxcord/models/interaction.rb +450 -0
- data/lib/onyxcord/{data → models}/invite.rb +1 -1
- data/lib/onyxcord/{data → models}/member.rb +11 -11
- data/lib/onyxcord/{data → models}/message.rb +22 -14
- data/lib/onyxcord/{data → models}/poll.rb +2 -2
- data/lib/onyxcord/{data → models}/primary_server.rb +1 -1
- data/lib/onyxcord/{data → models}/profile.rb +4 -4
- data/lib/onyxcord/{data → models}/role.rb +6 -12
- data/lib/onyxcord/{data → models}/scheduled_event.rb +5 -5
- data/lib/onyxcord/{data → models}/server.rb +41 -41
- data/lib/onyxcord/{data → models}/server_preview.rb +2 -2
- data/lib/onyxcord/{data → models}/team.rb +1 -1
- data/lib/onyxcord/{data → models}/user.rb +5 -5
- data/lib/onyxcord/{data → models}/webhook.rb +13 -11
- data/lib/onyxcord/models.rb +57 -0
- data/lib/onyxcord/{api.rb → rest/client.rb} +83 -27
- data/lib/onyxcord/{api → rest/routes}/application.rb +79 -57
- data/lib/onyxcord/rest/routes/channel/base.rb +73 -0
- data/lib/onyxcord/rest/routes/channel/groups.rb +78 -0
- data/lib/onyxcord/rest/routes/channel/messages.rb +130 -0
- data/lib/onyxcord/rest/routes/channel/permissions.rb +73 -0
- data/lib/onyxcord/rest/routes/channel/pins.rb +45 -0
- data/lib/onyxcord/rest/routes/channel/polls.rb +32 -0
- data/lib/onyxcord/rest/routes/channel/reactions.rb +86 -0
- data/lib/onyxcord/rest/routes/channel/threads.rb +176 -0
- data/lib/onyxcord/rest/routes/channel/webhooks.rb +47 -0
- data/lib/onyxcord/rest/routes/channel.rb +12 -0
- data/lib/onyxcord/{api/interaction.rb → rest/routes/interaction/base.rb} +10 -33
- data/lib/onyxcord/rest/routes/interaction/response.rb +24 -0
- data/lib/onyxcord/rest/routes/interaction.rb +4 -0
- data/lib/onyxcord/{api → rest/routes}/invite.rb +7 -7
- data/lib/onyxcord/rest/routes/server/admin.rb +174 -0
- data/lib/onyxcord/rest/routes/server/assets.rb +25 -0
- data/lib/onyxcord/rest/routes/server/bans.rb +67 -0
- data/lib/onyxcord/rest/routes/server/base.rb +77 -0
- data/lib/onyxcord/rest/routes/server/channels.rb +58 -0
- data/lib/onyxcord/rest/routes/server/emoji.rb +48 -0
- data/lib/onyxcord/rest/routes/server/members.rb +109 -0
- data/lib/onyxcord/rest/routes/server/messages.rb +19 -0
- data/lib/onyxcord/rest/routes/server/roles.rb +156 -0
- data/lib/onyxcord/rest/routes/server/scheduled_events.rb +86 -0
- data/lib/onyxcord/rest/routes/server.rb +12 -0
- data/lib/onyxcord/{api → rest/routes}/user.rb +23 -23
- data/lib/onyxcord/{api → rest/routes}/webhook.rb +30 -32
- data/lib/onyxcord/{allowed_mentions.rb → utils/allowed_mentions.rb} +9 -1
- data/lib/onyxcord/utils/timestamp.rb +69 -0
- data/lib/onyxcord/voice/{voice_bot.rb → client.rb} +4 -4
- data/lib/onyxcord/voice/encoder.rb +1 -1
- data/lib/onyxcord/voice/network/udp.rb +135 -0
- data/lib/onyxcord/voice/network/websocket.rb +225 -0
- data/lib/onyxcord/voice/network.rb +5 -357
- data/lib/onyxcord/webhooks/builder.rb +1 -1
- data/lib/onyxcord/webhooks/client.rb +13 -13
- data/lib/onyxcord/webhooks/modal/group_builder.rb +55 -0
- data/lib/onyxcord/webhooks/modal/label_builder.rb +183 -0
- data/lib/onyxcord/webhooks/modal.rb +2 -239
- data/lib/onyxcord/webhooks/version.rb +3 -3
- data/lib/onyxcord/webhooks/view/container_builder.rb +80 -0
- data/lib/onyxcord/webhooks/view/file_builder.rb +24 -0
- data/lib/onyxcord/webhooks/view/media_gallery_builder.rb +50 -0
- data/lib/onyxcord/webhooks/view/row_builder.rb +120 -0
- data/lib/onyxcord/webhooks/view/section_builder.rb +61 -0
- data/lib/onyxcord/webhooks/view/select_menu_builder.rb +77 -0
- data/lib/onyxcord/webhooks/view/separator_builder.rb +22 -0
- data/lib/onyxcord/webhooks/view/text_display_builder.rb +20 -0
- data/lib/onyxcord/webhooks/view.rb +9 -425
- data/lib/onyxcord.rb +106 -40
- metadata +208 -91
- data/.github/CONTRIBUTING.md +0 -13
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -24
- data/.github/pull_request_template.md +0 -37
- data/.github/workflows/ci.yml +0 -78
- data/.github/workflows/codeql.yml +0 -65
- data/.github/workflows/deploy.yml +0 -54
- data/.github/workflows/release.yml +0 -51
- data/.gitignore +0 -17
- data/.markdownlint.json +0 -4
- data/.overcommit.yml +0 -7
- data/.rspec +0 -2
- data/.rubocop.yml +0 -129
- data/.yardopts +0 -1
- data/CHANGELOG.md +0 -202
- data/Gemfile +0 -6
- data/LICENSE.txt +0 -21
- data/README.md +0 -448
- data/Rakefile +0 -13
- data/lib/onyxcord/api/channel.rb +0 -705
- data/lib/onyxcord/api/server.rb +0 -775
- data/lib/onyxcord/async/runtime.rb +0 -30
- data/lib/onyxcord/commands/command_bot.rb +0 -505
- data/lib/onyxcord/data/interaction.rb +0 -1143
- data/lib/onyxcord/data.rb +0 -57
- data/lib/onyxcord/event_executor.rb +0 -153
- data/lib/onyxcord/gateway.rb +0 -500
- data/lib/onyxcord/http.rb +0 -115
- data/lib/onyxcord/json.rb +0 -49
- data/lib/onyxcord/rate_limiter/async_rest.rb +0 -149
- data/lib/onyxcord/rate_limiter/gateway.rb +0 -42
- data/lib/onyxcord/rate_limiter/rest.rb +0 -142
- data/lib/onyxcord/version.rb +0 -7
- data/lib/onyxcord/websocket.rb +0 -77
- data/onyxcord.gemspec +0 -63
- /data/lib/onyxcord/{configuration.rb → core/configuration.rb} +0 -0
- /data/lib/onyxcord/{data → models}/attachment.rb +0 -0
- /data/lib/onyxcord/{data → models}/audit_logs.rb +0 -0
- /data/lib/onyxcord/{data → models}/call.rb +0 -0
- /data/lib/onyxcord/{data → models}/channel_tag.rb +0 -0
- /data/lib/onyxcord/{data → models}/component.rb +0 -0
- /data/lib/onyxcord/{data → models}/embed.rb +0 -0
- /data/lib/onyxcord/{data → models}/install_params.rb +0 -0
- /data/lib/onyxcord/{data → models}/integration.rb +0 -0
- /data/lib/onyxcord/{data → models}/message_activity.rb +0 -0
- /data/lib/onyxcord/{data → models}/overwrite.rb +0 -0
- /data/lib/onyxcord/{data → models}/reaction.rb +0 -0
- /data/lib/onyxcord/{data → models}/recipient.rb +0 -0
- /data/lib/onyxcord/{data → models}/role_connection_data.rb +0 -0
- /data/lib/onyxcord/{data → models}/role_subscription.rb +0 -0
- /data/lib/onyxcord/{data → models}/snapshot.rb +0 -0
- /data/lib/onyxcord/{data → models}/timestamp.rb +0 -0
- /data/lib/onyxcord/{data → models}/voice_region.rb +0 -0
- /data/lib/onyxcord/{data → models}/voice_state.rb +0 -0
- /data/lib/onyxcord/{colour_rgb.rb → utils/colour_rgb.rb} +0 -0
- /data/lib/onyxcord/{id_object.rb → utils/id_object.rb} +0 -0
- /data/lib/onyxcord/{message_components.rb → utils/message_components.rb} +0 -0
- /data/lib/onyxcord/{paginator.rb → utils/paginator.rb} +0 -0
- /data/lib/onyxcord/{permissions.rb → utils/permissions.rb} +0 -0
data/lib/onyxcord/http.rb
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'httpx'
|
|
4
|
-
require 'onyxcord/json'
|
|
5
|
-
|
|
6
|
-
module OnyxCord
|
|
7
|
-
# Modern HTTP adapter wrapping HTTPX with persistent connections, automatic
|
|
8
|
-
# retries on 502, and a response interface compatible with the rest of OnyxCord.
|
|
9
|
-
module HTTP
|
|
10
|
-
# Lightweight response wrapper so call-sites that relied on RestClient's
|
|
11
|
-
# `.body`, `.headers`, `.code` interface keep working unchanged.
|
|
12
|
-
class Response
|
|
13
|
-
# @return [String] the response body
|
|
14
|
-
attr_reader :body
|
|
15
|
-
|
|
16
|
-
# @return [Integer] the HTTP status code
|
|
17
|
-
attr_reader :code
|
|
18
|
-
|
|
19
|
-
# @return [Hash] the response headers (symbol keys, underscored)
|
|
20
|
-
attr_reader :headers
|
|
21
|
-
|
|
22
|
-
def initialize(httpx_response)
|
|
23
|
-
@raw = httpx_response
|
|
24
|
-
@body = httpx_response.body.to_s
|
|
25
|
-
@code = httpx_response.status
|
|
26
|
-
@headers = normalize_headers(httpx_response.headers)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def to_s
|
|
30
|
-
@body
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# RestClient compatibility — some code calls `response` directly as a
|
|
34
|
-
# string (implicit to_s).
|
|
35
|
-
alias_method :to_str, :to_s
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def normalize_headers(headers)
|
|
40
|
-
headers.to_h.transform_keys do |key|
|
|
41
|
-
key.to_s.tr('-', '_').downcase.to_sym
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
module_function
|
|
47
|
-
|
|
48
|
-
# The shared HTTPX session with persistent connections for the current thread.
|
|
49
|
-
def session
|
|
50
|
-
Thread.current[:onyxcord_http_session] ||= HTTPX.plugin(:persistent)
|
|
51
|
-
.plugin(:follow_redirects)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# Reset the HTTP session (useful for tests).
|
|
55
|
-
def reset!
|
|
56
|
-
Thread.current[:onyxcord_http_session] = nil
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Perform a raw HTTP request and return a {Response}.
|
|
60
|
-
# @param type [Symbol] HTTP method (:get, :post, :put, :patch, :delete)
|
|
61
|
-
# @param url [String] The full URL.
|
|
62
|
-
# @param body [String, Hash, nil] The request body.
|
|
63
|
-
# @param headers [Hash] Request headers.
|
|
64
|
-
# @return [Response]
|
|
65
|
-
def request(type, url, body = nil, **headers)
|
|
66
|
-
http = session.with(headers: headers)
|
|
67
|
-
|
|
68
|
-
raw = case type
|
|
69
|
-
when :get
|
|
70
|
-
http.get(url)
|
|
71
|
-
when :post
|
|
72
|
-
if body.is_a?(Hash) && body.any? { |_, v| v.respond_to?(:read) || v.respond_to?(:path) }
|
|
73
|
-
# Multipart upload
|
|
74
|
-
http.plugin(:multipart).post(url, form: body)
|
|
75
|
-
else
|
|
76
|
-
http.post(url, body: body)
|
|
77
|
-
end
|
|
78
|
-
when :put
|
|
79
|
-
http.put(url, body: body)
|
|
80
|
-
when :patch
|
|
81
|
-
http.patch(url, body: body)
|
|
82
|
-
when :delete
|
|
83
|
-
http.delete(url)
|
|
84
|
-
else
|
|
85
|
-
raise ArgumentError, "Unknown HTTP method: #{type}"
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# HTTPX returns an error response object on network failures
|
|
89
|
-
raise raw.error if raw.is_a?(HTTPX::ErrorResponse)
|
|
90
|
-
|
|
91
|
-
Response.new(raw)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Convenience wrappers
|
|
95
|
-
def get(url, **headers)
|
|
96
|
-
request(:get, url, nil, **headers)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def post(url, body = nil, **headers)
|
|
100
|
-
request(:post, url, body, **headers)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def put(url, body = nil, **headers)
|
|
104
|
-
request(:put, url, body, **headers)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def patch(url, body = nil, **headers)
|
|
108
|
-
request(:patch, url, body, **headers)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def delete(url, **headers)
|
|
112
|
-
request(:delete, url, nil, **headers)
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
data/lib/onyxcord/json.rb
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'oj'
|
|
4
|
-
|
|
5
|
-
# Configure Oj in compat mode so that all stdlib JSON.parse / .to_json calls
|
|
6
|
-
# are transparently accelerated. This is loaded early by the main onyxcord.rb
|
|
7
|
-
# entry point so every module benefits automatically.
|
|
8
|
-
module OnyxCord
|
|
9
|
-
# Fast Oj-backed JSON wrapper providing compatibility with stdlib JSON methods.
|
|
10
|
-
module JSON
|
|
11
|
-
Oj.default_options = { mode: :compat, symbol_keys: false }
|
|
12
|
-
|
|
13
|
-
module_function
|
|
14
|
-
|
|
15
|
-
# Fast JSON decode using Oj via stdlib JSON compatibility.
|
|
16
|
-
# @param data [String] The JSON string to decode.
|
|
17
|
-
# @return [Hash, Array, String, Numeric, nil]
|
|
18
|
-
def decode(data, *args)
|
|
19
|
-
::JSON.parse(data, *args)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Fast JSON encode using Oj via stdlib JSON compatibility.
|
|
23
|
-
# @param data [Object] The object to encode as JSON.
|
|
24
|
-
# @return [String]
|
|
25
|
-
def encode(data, *args)
|
|
26
|
-
::JSON.generate(data, *args)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Alias parse to decode for standard library compatibility
|
|
30
|
-
def parse(data, *args)
|
|
31
|
-
::JSON.parse(data, *args)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Alias generate to encode for standard library compatibility
|
|
35
|
-
def generate(data, *args)
|
|
36
|
-
::JSON.generate(data, *args)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Alias load to decode for Oj/JSON compatibility
|
|
40
|
-
def load(data, *args)
|
|
41
|
-
::JSON.parse(data, *args)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Alias dump to encode for Oj/JSON compatibility
|
|
45
|
-
def dump(data, *args)
|
|
46
|
-
::JSON.generate(data, *args)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,149 +0,0 @@
|
|
|
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
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OnyxCord
|
|
4
|
-
module RateLimiter
|
|
5
|
-
# Sliding-window limiter for Gateway sends.
|
|
6
|
-
class Gateway
|
|
7
|
-
DEFAULT_LIMIT = 120
|
|
8
|
-
DEFAULT_INTERVAL = 60
|
|
9
|
-
|
|
10
|
-
def initialize(limit: DEFAULT_LIMIT, interval: DEFAULT_INTERVAL, clock: -> { Time.now }, sleeper: ->(duration) { sleep(duration) })
|
|
11
|
-
@limit = limit
|
|
12
|
-
@interval = interval
|
|
13
|
-
@clock = clock
|
|
14
|
-
@sleeper = sleeper
|
|
15
|
-
@sent_at = []
|
|
16
|
-
@mutex = Mutex.new
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def wait
|
|
20
|
-
@mutex.synchronize do
|
|
21
|
-
now = @clock.call
|
|
22
|
-
prune(now)
|
|
23
|
-
|
|
24
|
-
if @sent_at.length >= @limit
|
|
25
|
-
sleep_for = @interval - (now - @sent_at.first)
|
|
26
|
-
@sleeper.call(sleep_for) if sleep_for.positive?
|
|
27
|
-
now = @clock.call
|
|
28
|
-
prune(now)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
@sent_at << now
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def prune(now)
|
|
38
|
-
@sent_at.shift while @sent_at.any? && (now - @sent_at.first) >= @interval
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'onyxcord/json'
|
|
4
|
-
|
|
5
|
-
module OnyxCord
|
|
6
|
-
module RateLimiter
|
|
7
|
-
# Discord REST rate limiter keyed by route/major parameter and remapped to
|
|
8
|
-
# X-RateLimit-Bucket whenever Discord returns a concrete bucket id.
|
|
9
|
-
class Rest
|
|
10
|
-
DEFAULT_ENTRY_TTL = 3600
|
|
11
|
-
DEFAULT_PRUNE_INTERVAL = 100
|
|
12
|
-
|
|
13
|
-
def initialize(clock: -> { Time.now }, entry_ttl: DEFAULT_ENTRY_TTL, prune_interval: DEFAULT_PRUNE_INTERVAL)
|
|
14
|
-
@route_buckets = {}
|
|
15
|
-
@bucket_mutexes = {}
|
|
16
|
-
@bucket_last_used = {}
|
|
17
|
-
@global_mutex = Mutex.new
|
|
18
|
-
@clock = clock
|
|
19
|
-
@entry_ttl = entry_ttl
|
|
20
|
-
@prune_interval = prune_interval
|
|
21
|
-
@requests_since_prune = 0
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def before_request(route, major_parameter)
|
|
25
|
-
mutex_wait(mutex_for(route, major_parameter))
|
|
26
|
-
mutex_wait(@global_mutex) if @global_mutex.locked?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def record_response(route, major_parameter, headers)
|
|
30
|
-
headers = normalize_headers(headers)
|
|
31
|
-
bucket = headers[:x_ratelimit_bucket]
|
|
32
|
-
key = route_key(route, major_parameter)
|
|
33
|
-
touch(key)
|
|
34
|
-
|
|
35
|
-
if bucket
|
|
36
|
-
bucket = bucket_key(bucket, major_parameter)
|
|
37
|
-
@route_buckets[key] = bucket
|
|
38
|
-
touch(bucket)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
return unless headers[:x_ratelimit_remaining] == '0'
|
|
42
|
-
|
|
43
|
-
wait_seconds = headers[:x_ratelimit_reset_after].to_f
|
|
44
|
-
return unless wait_seconds.positive?
|
|
45
|
-
|
|
46
|
-
sync_wait(wait_seconds, mutex_for(route, major_parameter))
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def handle_rate_limit(route, major_parameter, response)
|
|
50
|
-
headers = normalize_headers(response.headers)
|
|
51
|
-
mutex = headers[:x_ratelimit_global] == 'true' || headers[:x_ratelimit_scope] == 'global' ? @global_mutex : mutex_for(route, major_parameter)
|
|
52
|
-
wait_seconds = retry_after(response, headers)
|
|
53
|
-
|
|
54
|
-
sync_wait(wait_seconds, mutex) if wait_seconds.positive?
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def stats
|
|
58
|
-
{
|
|
59
|
-
route_buckets: @route_buckets.size,
|
|
60
|
-
bucket_mutexes: @bucket_mutexes.size,
|
|
61
|
-
tracked_keys: @bucket_last_used.size
|
|
62
|
-
}
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def prune!
|
|
66
|
-
return 0 unless @entry_ttl
|
|
67
|
-
|
|
68
|
-
cutoff = @clock.call - @entry_ttl
|
|
69
|
-
stale_keys = @bucket_last_used.select { |_, last_used| last_used < cutoff }.keys
|
|
70
|
-
|
|
71
|
-
stale_keys.each do |key|
|
|
72
|
-
@bucket_mutexes.delete(key)
|
|
73
|
-
@bucket_last_used.delete(key)
|
|
74
|
-
@route_buckets.delete(key)
|
|
75
|
-
@route_buckets.delete_if { |_, bucket_key| bucket_key == key }
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
@requests_since_prune = 0
|
|
79
|
-
stale_keys.length
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
private
|
|
83
|
-
|
|
84
|
-
def mutex_for(route, major_parameter)
|
|
85
|
-
key = resolved_key(route, major_parameter)
|
|
86
|
-
touch(key)
|
|
87
|
-
@bucket_mutexes[key] ||= Mutex.new
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def resolved_key(route, major_parameter)
|
|
91
|
-
@route_buckets[route_key(route, major_parameter)] || route_key(route, major_parameter)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def route_key(route, major_parameter)
|
|
95
|
-
[route, major_parameter].freeze
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def bucket_key(bucket, major_parameter)
|
|
99
|
-
[:bucket, bucket, major_parameter].freeze
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def retry_after(response, headers)
|
|
103
|
-
body = response.respond_to?(:body) ? response.body : response.to_s
|
|
104
|
-
if body && !body.empty?
|
|
105
|
-
data = JSON.parse(body)
|
|
106
|
-
return data['retry_after'].to_f if data['retry_after']
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
(headers[:retry_after] || 0).to_f
|
|
110
|
-
rescue JSON::ParserError
|
|
111
|
-
(headers[:retry_after] || 0).to_f
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def normalize_headers(headers)
|
|
115
|
-
headers.each_with_object({}) do |(key, value), memo|
|
|
116
|
-
memo[key.to_s.tr('-', '_').downcase.to_sym] = value.to_s
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def touch(key)
|
|
121
|
-
@bucket_last_used[key] = @clock.call
|
|
122
|
-
prune_if_needed
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def prune_if_needed
|
|
126
|
-
return unless @prune_interval
|
|
127
|
-
|
|
128
|
-
@requests_since_prune += 1
|
|
129
|
-
prune! if @requests_since_prune >= @prune_interval
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def sync_wait(time, mutex)
|
|
133
|
-
mutex.synchronize { sleep time }
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def mutex_wait(mutex)
|
|
137
|
-
mutex.lock
|
|
138
|
-
mutex.unlock
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
data/lib/onyxcord/version.rb
DELETED
data/lib/onyxcord/websocket.rb
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'onyxcord/async/runtime'
|
|
4
|
-
require 'async/http/endpoint'
|
|
5
|
-
require 'async/http/protocol/http11'
|
|
6
|
-
require 'async/websocket/client'
|
|
7
|
-
|
|
8
|
-
module OnyxCord
|
|
9
|
-
class WebSocket
|
|
10
|
-
attr_reader :connected
|
|
11
|
-
|
|
12
|
-
alias_method :connected?, :connected
|
|
13
|
-
|
|
14
|
-
def initialize(host, open_handler, message_handler, error_handler, close_handler)
|
|
15
|
-
@host = host
|
|
16
|
-
@open_handler = open_handler
|
|
17
|
-
@message_handler = message_handler
|
|
18
|
-
@error_handler = error_handler
|
|
19
|
-
@close_handler = close_handler
|
|
20
|
-
|
|
21
|
-
@connection = nil
|
|
22
|
-
@connected = false
|
|
23
|
-
|
|
24
|
-
connect
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def send(data)
|
|
28
|
-
return unless @connection
|
|
29
|
-
|
|
30
|
-
data = data.to_json if data.is_a?(Hash)
|
|
31
|
-
@connection.write(Protocol::WebSocket::TextMessage.generate(data))
|
|
32
|
-
@connection.flush
|
|
33
|
-
rescue StandardError => e
|
|
34
|
-
@error_handler&.call(e)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def close
|
|
38
|
-
@connected = false
|
|
39
|
-
@connection&.close
|
|
40
|
-
rescue StandardError
|
|
41
|
-
# Ignore errors on close
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
|
|
46
|
-
def connect
|
|
47
|
-
endpoint = websocket_endpoint(@host)
|
|
48
|
-
|
|
49
|
-
@task = OnyxCord::AsyncRuntime.async do
|
|
50
|
-
Async::WebSocket::Client.connect(endpoint, extensions: nil) do |connection|
|
|
51
|
-
@connection = connection
|
|
52
|
-
@connected = true
|
|
53
|
-
@open_handler&.call
|
|
54
|
-
|
|
55
|
-
while (message = connection.read)
|
|
56
|
-
@message_handler&.call(message.to_str)
|
|
57
|
-
end
|
|
58
|
-
rescue StandardError => e
|
|
59
|
-
@error_handler&.call(e)
|
|
60
|
-
ensure
|
|
61
|
-
@connected = false
|
|
62
|
-
@close_handler&.call(nil)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
rescue StandardError => e
|
|
66
|
-
@error_handler&.call(e)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def websocket_endpoint(url)
|
|
70
|
-
Async::HTTP::Endpoint.parse(
|
|
71
|
-
url,
|
|
72
|
-
protocol: Async::HTTP::Protocol::HTTP11,
|
|
73
|
-
alpn_protocols: ['http/1.1']
|
|
74
|
-
)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
data/onyxcord.gemspec
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'lib/onyxcord/version'
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name = 'onyxcord'
|
|
7
|
-
spec.version = OnyxCord::VERSION
|
|
8
|
-
spec.authors = ['Gustavo Silva']
|
|
9
|
-
spec.email = ['gustavosilva8kt@gmail.com']
|
|
10
|
-
|
|
11
|
-
spec.summary = 'Discord API for Ruby with Components V2 support'
|
|
12
|
-
spec.description = 'OnyxCord is a Ruby Discord API library with Components V2, modern modals, raw-first events, and community support: https://discord.gg/Jy2tpCUtzM.'
|
|
13
|
-
spec.homepage = 'https://github.com/kruldevb/OnyxCord'
|
|
14
|
-
spec.license = 'MIT'
|
|
15
|
-
|
|
16
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples)/}) }
|
|
17
|
-
spec.bindir = 'exe'
|
|
18
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
|
-
spec.metadata = {
|
|
20
|
-
'bug_tracker_uri' => 'https://github.com/kruldevb/OnyxCord/issues',
|
|
21
|
-
'changelog_uri' => 'https://github.com/kruldevb/OnyxCord/blob/main/CHANGELOG.md',
|
|
22
|
-
'documentation_uri' => 'https://github.com/kruldevb/OnyxCord#readme',
|
|
23
|
-
'source_code_uri' => 'https://github.com/kruldevb/OnyxCord',
|
|
24
|
-
'rubygems_mfa_required' => 'true'
|
|
25
|
-
}
|
|
26
|
-
spec.require_paths = ['lib']
|
|
27
|
-
|
|
28
|
-
# Modern async runtime & networking
|
|
29
|
-
spec.add_dependency 'async', '>= 2.0', '< 3'
|
|
30
|
-
spec.add_dependency 'async-http', '>= 0.75', '< 1'
|
|
31
|
-
spec.add_dependency 'async-websocket', '>= 0.26', '< 1'
|
|
32
|
-
|
|
33
|
-
# HTTP client (modern, HTTP/2, persistent connections)
|
|
34
|
-
spec.add_dependency 'httpx', '>= 1.0', '< 2'
|
|
35
|
-
|
|
36
|
-
# Fast JSON parsing
|
|
37
|
-
spec.add_dependency 'oj', '>= 3.0', '< 4'
|
|
38
|
-
|
|
39
|
-
# Smart LRU caching
|
|
40
|
-
spec.add_dependency 'lru_redux', '>= 1.0', '< 2'
|
|
41
|
-
|
|
42
|
-
# Core dependencies
|
|
43
|
-
spec.add_dependency 'base64', '~> 0.2'
|
|
44
|
-
spec.add_dependency 'mime-types', '~> 3.0'
|
|
45
|
-
|
|
46
|
-
# Voice support
|
|
47
|
-
spec.add_dependency 'ffi', '>= 1.9.24', '< 2'
|
|
48
|
-
spec.add_dependency 'opus-ruby', '>= 0', '< 2'
|
|
49
|
-
|
|
50
|
-
spec.required_ruby_version = '>= 3.4'
|
|
51
|
-
|
|
52
|
-
spec.add_development_dependency 'bundler', '>= 1.10', '< 5'
|
|
53
|
-
spec.add_development_dependency 'rake', '~> 13.0'
|
|
54
|
-
spec.add_development_dependency 'redcarpet', '~> 3.5' # YARD markdown formatting
|
|
55
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
56
|
-
spec.add_development_dependency 'rspec_junit_formatter', '~> 0.6.0'
|
|
57
|
-
spec.add_development_dependency 'rspec-prof', '~> 0.0.7'
|
|
58
|
-
spec.add_development_dependency 'rubocop', '~> 1.77.0'
|
|
59
|
-
spec.add_development_dependency 'rubocop-performance', '~> 1.25.0'
|
|
60
|
-
spec.add_development_dependency 'rubocop-rake', '~> 0.7.0'
|
|
61
|
-
spec.add_development_dependency 'simplecov', '~> 0.21'
|
|
62
|
-
spec.add_development_dependency 'yard', '~> 0.9.37'
|
|
63
|
-
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|