@neontechspace/fluxerly 1000.0.0-nightly.12
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.
- package/CHANGELOG.md +833 -0
- package/LICENSE +201 -0
- package/README.md +129 -0
- package/agents/AGENTS.md +195 -0
- package/dist/api/default/application.d.ts +34 -0
- package/dist/api/default/application.d.ts.map +1 -0
- package/dist/api/default/application.js +2 -0
- package/dist/api/default/application.js.map +1 -0
- package/dist/api/default/attachments.d.ts +89 -0
- package/dist/api/default/attachments.d.ts.map +1 -0
- package/dist/api/default/attachments.js +2 -0
- package/dist/api/default/attachments.js.map +1 -0
- package/dist/api/default/audit-logs.d.ts +48 -0
- package/dist/api/default/audit-logs.d.ts.map +1 -0
- package/dist/api/default/audit-logs.js +2 -0
- package/dist/api/default/audit-logs.js.map +1 -0
- package/dist/api/default/bot.d.ts +200 -0
- package/dist/api/default/bot.d.ts.map +1 -0
- package/dist/api/default/bot.js +309 -0
- package/dist/api/default/bot.js.map +1 -0
- package/dist/api/default/cache.d.ts +105 -0
- package/dist/api/default/cache.d.ts.map +1 -0
- package/dist/api/default/cache.js +2 -0
- package/dist/api/default/cache.js.map +1 -0
- package/dist/api/default/channels.d.ts +249 -0
- package/dist/api/default/channels.d.ts.map +1 -0
- package/dist/api/default/channels.js +2 -0
- package/dist/api/default/channels.js.map +1 -0
- package/dist/api/default/client.d.ts +528 -0
- package/dist/api/default/client.d.ts.map +1 -0
- package/dist/api/default/client.js +301 -0
- package/dist/api/default/client.js.map +1 -0
- package/dist/api/default/collectors.d.ts +76 -0
- package/dist/api/default/collectors.d.ts.map +1 -0
- package/dist/api/default/collectors.js +2 -0
- package/dist/api/default/collectors.js.map +1 -0
- package/dist/api/default/commands.d.ts +91 -0
- package/dist/api/default/commands.d.ts.map +1 -0
- package/dist/api/default/commands.js +92 -0
- package/dist/api/default/commands.js.map +1 -0
- package/dist/api/default/direct-messages.d.ts +111 -0
- package/dist/api/default/direct-messages.d.ts.map +1 -0
- package/dist/api/default/direct-messages.js +2 -0
- package/dist/api/default/direct-messages.js.map +1 -0
- package/dist/api/default/discovery.d.ts +76 -0
- package/dist/api/default/discovery.d.ts.map +1 -0
- package/dist/api/default/discovery.js +2 -0
- package/dist/api/default/discovery.js.map +1 -0
- package/dist/api/default/emojis.d.ts +88 -0
- package/dist/api/default/emojis.d.ts.map +1 -0
- package/dist/api/default/emojis.js +2 -0
- package/dist/api/default/emojis.js.map +1 -0
- package/dist/api/default/events.d.ts +127 -0
- package/dist/api/default/events.d.ts.map +1 -0
- package/dist/api/default/events.js +2 -0
- package/dist/api/default/events.js.map +1 -0
- package/dist/api/default/gateway.d.ts +62 -0
- package/dist/api/default/gateway.d.ts.map +1 -0
- package/dist/api/default/gateway.js +2 -0
- package/dist/api/default/gateway.js.map +1 -0
- package/dist/api/default/guards.d.ts +87 -0
- package/dist/api/default/guards.d.ts.map +1 -0
- package/dist/api/default/guards.js +78 -0
- package/dist/api/default/guards.js.map +1 -0
- package/dist/api/default/guilds.d.ts +230 -0
- package/dist/api/default/guilds.d.ts.map +1 -0
- package/dist/api/default/guilds.js +2 -0
- package/dist/api/default/guilds.js.map +1 -0
- package/dist/api/default/helpers.d.ts +79 -0
- package/dist/api/default/helpers.d.ts.map +1 -0
- package/dist/api/default/helpers.js +79 -0
- package/dist/api/default/helpers.js.map +1 -0
- package/dist/api/default/instance.d.ts +47 -0
- package/dist/api/default/instance.d.ts.map +1 -0
- package/dist/api/default/instance.js +2 -0
- package/dist/api/default/instance.js.map +1 -0
- package/dist/api/default/invites.d.ts +57 -0
- package/dist/api/default/invites.d.ts.map +1 -0
- package/dist/api/default/invites.js +2 -0
- package/dist/api/default/invites.js.map +1 -0
- package/dist/api/default/logging.d.ts +37 -0
- package/dist/api/default/logging.d.ts.map +1 -0
- package/dist/api/default/logging.js +2 -0
- package/dist/api/default/logging.js.map +1 -0
- package/dist/api/default/members.d.ts +442 -0
- package/dist/api/default/members.d.ts.map +1 -0
- package/dist/api/default/members.js +2 -0
- package/dist/api/default/members.js.map +1 -0
- package/dist/api/default/messages.d.ts +898 -0
- package/dist/api/default/messages.d.ts.map +1 -0
- package/dist/api/default/messages.js +2 -0
- package/dist/api/default/messages.js.map +1 -0
- package/dist/api/default/oauth.d.ts +168 -0
- package/dist/api/default/oauth.d.ts.map +1 -0
- package/dist/api/default/oauth.js +84 -0
- package/dist/api/default/oauth.js.map +1 -0
- package/dist/api/default/permissions.d.ts +44 -0
- package/dist/api/default/permissions.d.ts.map +1 -0
- package/dist/api/default/permissions.js +2 -0
- package/dist/api/default/permissions.js.map +1 -0
- package/dist/api/default/presence.d.ts +88 -0
- package/dist/api/default/presence.d.ts.map +1 -0
- package/dist/api/default/presence.js +2 -0
- package/dist/api/default/presence.js.map +1 -0
- package/dist/api/default/rest.d.ts +28 -0
- package/dist/api/default/rest.d.ts.map +1 -0
- package/dist/api/default/rest.js +2 -0
- package/dist/api/default/rest.js.map +1 -0
- package/dist/api/default/results.d.ts +31 -0
- package/dist/api/default/results.d.ts.map +1 -0
- package/dist/api/default/results.js +14 -0
- package/dist/api/default/results.js.map +1 -0
- package/dist/api/default/roles.d.ts +119 -0
- package/dist/api/default/roles.d.ts.map +1 -0
- package/dist/api/default/roles.js +2 -0
- package/dist/api/default/roles.js.map +1 -0
- package/dist/api/default/stickers.d.ts +92 -0
- package/dist/api/default/stickers.d.ts.map +1 -0
- package/dist/api/default/stickers.js +2 -0
- package/dist/api/default/stickers.js.map +1 -0
- package/dist/api/default/supervisor.d.ts +51 -0
- package/dist/api/default/supervisor.d.ts.map +1 -0
- package/dist/api/default/supervisor.js +53 -0
- package/dist/api/default/supervisor.js.map +1 -0
- package/dist/api/default/threads.d.ts +158 -0
- package/dist/api/default/threads.d.ts.map +1 -0
- package/dist/api/default/threads.js +2 -0
- package/dist/api/default/threads.js.map +1 -0
- package/dist/api/default/users.d.ts +73 -0
- package/dist/api/default/users.d.ts.map +1 -0
- package/dist/api/default/users.js +2 -0
- package/dist/api/default/users.js.map +1 -0
- package/dist/api/default/webhook-client.d.ts +149 -0
- package/dist/api/default/webhook-client.d.ts.map +1 -0
- package/dist/api/default/webhook-client.js +69 -0
- package/dist/api/default/webhook-client.js.map +1 -0
- package/dist/api/default/webhooks.d.ts +62 -0
- package/dist/api/default/webhooks.d.ts.map +1 -0
- package/dist/api/default/webhooks.js +2 -0
- package/dist/api/default/webhooks.js.map +1 -0
- package/dist/api/effect/application.d.ts +29 -0
- package/dist/api/effect/application.d.ts.map +1 -0
- package/dist/api/effect/application.js +2 -0
- package/dist/api/effect/application.js.map +1 -0
- package/dist/api/effect/attachments.d.ts +84 -0
- package/dist/api/effect/attachments.d.ts.map +1 -0
- package/dist/api/effect/attachments.js +2 -0
- package/dist/api/effect/attachments.js.map +1 -0
- package/dist/api/effect/audit-logs.d.ts +42 -0
- package/dist/api/effect/audit-logs.d.ts.map +1 -0
- package/dist/api/effect/audit-logs.js +2 -0
- package/dist/api/effect/audit-logs.js.map +1 -0
- package/dist/api/effect/bot.d.ts +233 -0
- package/dist/api/effect/bot.d.ts.map +1 -0
- package/dist/api/effect/bot.js +230 -0
- package/dist/api/effect/bot.js.map +1 -0
- package/dist/api/effect/cache.d.ts +103 -0
- package/dist/api/effect/cache.d.ts.map +1 -0
- package/dist/api/effect/cache.js +2 -0
- package/dist/api/effect/cache.js.map +1 -0
- package/dist/api/effect/channels.d.ts +231 -0
- package/dist/api/effect/channels.d.ts.map +1 -0
- package/dist/api/effect/channels.js +2 -0
- package/dist/api/effect/channels.js.map +1 -0
- package/dist/api/effect/client.d.ts +622 -0
- package/dist/api/effect/client.d.ts.map +1 -0
- package/dist/api/effect/client.js +191 -0
- package/dist/api/effect/client.js.map +1 -0
- package/dist/api/effect/collectors.d.ts +90 -0
- package/dist/api/effect/collectors.d.ts.map +1 -0
- package/dist/api/effect/collectors.js +2 -0
- package/dist/api/effect/collectors.js.map +1 -0
- package/dist/api/effect/commands.d.ts +86 -0
- package/dist/api/effect/commands.d.ts.map +1 -0
- package/dist/api/effect/commands.js +87 -0
- package/dist/api/effect/commands.js.map +1 -0
- package/dist/api/effect/direct-messages.d.ts +102 -0
- package/dist/api/effect/direct-messages.d.ts.map +1 -0
- package/dist/api/effect/direct-messages.js +2 -0
- package/dist/api/effect/direct-messages.js.map +1 -0
- package/dist/api/effect/discovery.d.ts +68 -0
- package/dist/api/effect/discovery.d.ts.map +1 -0
- package/dist/api/effect/discovery.js +2 -0
- package/dist/api/effect/discovery.js.map +1 -0
- package/dist/api/effect/emojis.d.ts +77 -0
- package/dist/api/effect/emojis.d.ts.map +1 -0
- package/dist/api/effect/emojis.js +2 -0
- package/dist/api/effect/emojis.js.map +1 -0
- package/dist/api/effect/events.d.ts +78 -0
- package/dist/api/effect/events.d.ts.map +1 -0
- package/dist/api/effect/events.js +12 -0
- package/dist/api/effect/events.js.map +1 -0
- package/dist/api/effect/failures.d.ts +14 -0
- package/dist/api/effect/failures.d.ts.map +1 -0
- package/dist/api/effect/failures.js +2 -0
- package/dist/api/effect/failures.js.map +1 -0
- package/dist/api/effect/gateway.d.ts +63 -0
- package/dist/api/effect/gateway.d.ts.map +1 -0
- package/dist/api/effect/gateway.js +2 -0
- package/dist/api/effect/gateway.js.map +1 -0
- package/dist/api/effect/guards.d.ts +91 -0
- package/dist/api/effect/guards.d.ts.map +1 -0
- package/dist/api/effect/guards.js +94 -0
- package/dist/api/effect/guards.js.map +1 -0
- package/dist/api/effect/guilds.d.ts +221 -0
- package/dist/api/effect/guilds.d.ts.map +1 -0
- package/dist/api/effect/guilds.js +2 -0
- package/dist/api/effect/guilds.js.map +1 -0
- package/dist/api/effect/helpers.d.ts +300 -0
- package/dist/api/effect/helpers.d.ts.map +1 -0
- package/dist/api/effect/helpers.js +156 -0
- package/dist/api/effect/helpers.js.map +1 -0
- package/dist/api/effect/hierarchy.d.ts +26 -0
- package/dist/api/effect/hierarchy.d.ts.map +1 -0
- package/dist/api/effect/hierarchy.js +26 -0
- package/dist/api/effect/hierarchy.js.map +1 -0
- package/dist/api/effect/instance.d.ts +46 -0
- package/dist/api/effect/instance.d.ts.map +1 -0
- package/dist/api/effect/instance.js +8 -0
- package/dist/api/effect/instance.js.map +1 -0
- package/dist/api/effect/invites.d.ts +49 -0
- package/dist/api/effect/invites.d.ts.map +1 -0
- package/dist/api/effect/invites.js +2 -0
- package/dist/api/effect/invites.js.map +1 -0
- package/dist/api/effect/logging.d.ts +37 -0
- package/dist/api/effect/logging.d.ts.map +1 -0
- package/dist/api/effect/logging.js +2 -0
- package/dist/api/effect/logging.js.map +1 -0
- package/dist/api/effect/members.d.ts +433 -0
- package/dist/api/effect/members.d.ts.map +1 -0
- package/dist/api/effect/members.js +2 -0
- package/dist/api/effect/members.js.map +1 -0
- package/dist/api/effect/messages.d.ts +877 -0
- package/dist/api/effect/messages.d.ts.map +1 -0
- package/dist/api/effect/messages.js +2 -0
- package/dist/api/effect/messages.js.map +1 -0
- package/dist/api/effect/oauth.d.ts +148 -0
- package/dist/api/effect/oauth.d.ts.map +1 -0
- package/dist/api/effect/oauth.js +51 -0
- package/dist/api/effect/oauth.js.map +1 -0
- package/dist/api/effect/permissions.d.ts +41 -0
- package/dist/api/effect/permissions.d.ts.map +1 -0
- package/dist/api/effect/permissions.js +2 -0
- package/dist/api/effect/permissions.js.map +1 -0
- package/dist/api/effect/presence.d.ts +83 -0
- package/dist/api/effect/presence.d.ts.map +1 -0
- package/dist/api/effect/presence.js +2 -0
- package/dist/api/effect/presence.js.map +1 -0
- package/dist/api/effect/rest.d.ts +27 -0
- package/dist/api/effect/rest.d.ts.map +1 -0
- package/dist/api/effect/rest.js +2 -0
- package/dist/api/effect/rest.js.map +1 -0
- package/dist/api/effect/roles.d.ts +104 -0
- package/dist/api/effect/roles.d.ts.map +1 -0
- package/dist/api/effect/roles.js +2 -0
- package/dist/api/effect/roles.js.map +1 -0
- package/dist/api/effect/service.d.ts +76 -0
- package/dist/api/effect/service.d.ts.map +1 -0
- package/dist/api/effect/service.js +79 -0
- package/dist/api/effect/service.js.map +1 -0
- package/dist/api/effect/stickers.d.ts +81 -0
- package/dist/api/effect/stickers.d.ts.map +1 -0
- package/dist/api/effect/stickers.js +2 -0
- package/dist/api/effect/stickers.js.map +1 -0
- package/dist/api/effect/supervisor.d.ts +56 -0
- package/dist/api/effect/supervisor.d.ts.map +1 -0
- package/dist/api/effect/supervisor.js +58 -0
- package/dist/api/effect/supervisor.js.map +1 -0
- package/dist/api/effect/threads.d.ts +154 -0
- package/dist/api/effect/threads.d.ts.map +1 -0
- package/dist/api/effect/threads.js +2 -0
- package/dist/api/effect/threads.js.map +1 -0
- package/dist/api/effect/users.d.ts +62 -0
- package/dist/api/effect/users.d.ts.map +1 -0
- package/dist/api/effect/users.js +2 -0
- package/dist/api/effect/users.js.map +1 -0
- package/dist/api/effect/webhook-client.d.ts +140 -0
- package/dist/api/effect/webhook-client.d.ts.map +1 -0
- package/dist/api/effect/webhook-client.js +50 -0
- package/dist/api/effect/webhook-client.js.map +1 -0
- package/dist/api/effect/webhooks.d.ts +54 -0
- package/dist/api/effect/webhooks.d.ts.map +1 -0
- package/dist/api/effect/webhooks.js +2 -0
- package/dist/api/effect/webhooks.js.map +1 -0
- package/dist/api-errors.d.ts +609 -0
- package/dist/api-errors.d.ts.map +1 -0
- package/dist/api-errors.js +589 -0
- package/dist/api-errors.js.map +1 -0
- package/dist/application.d.ts +85 -0
- package/dist/application.d.ts.map +1 -0
- package/dist/application.js +44 -0
- package/dist/application.js.map +1 -0
- package/dist/assets.d.ts +197 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +419 -0
- package/dist/assets.js.map +1 -0
- package/dist/attachments.d.ts +400 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +88 -0
- package/dist/attachments.js.map +1 -0
- package/dist/audit-logs.d.ts +292 -0
- package/dist/audit-logs.d.ts.map +1 -0
- package/dist/audit-logs.js +46 -0
- package/dist/audit-logs.js.map +1 -0
- package/dist/bot-runner.d.ts +69 -0
- package/dist/bot-runner.d.ts.map +1 -0
- package/dist/bot-runner.js +41 -0
- package/dist/bot-runner.js.map +1 -0
- package/dist/builders.d.ts +153 -0
- package/dist/builders.d.ts.map +1 -0
- package/dist/builders.js +326 -0
- package/dist/builders.js.map +1 -0
- package/dist/cache.d.ts +187 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +2 -0
- package/dist/cache.js.map +1 -0
- package/dist/channels.d.ts +903 -0
- package/dist/channels.d.ts.map +1 -0
- package/dist/channels.js +125 -0
- package/dist/channels.js.map +1 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +65 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +645 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2 -0
- package/dist/client.js.map +1 -0
- package/dist/collectors.d.ts +205 -0
- package/dist/collectors.d.ts.map +1 -0
- package/dist/collectors.js +71 -0
- package/dist/collectors.js.map +1 -0
- package/dist/colors.d.ts +55 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +40 -0
- package/dist/colors.js.map +1 -0
- package/dist/command-arguments.d.ts +353 -0
- package/dist/command-arguments.d.ts.map +1 -0
- package/dist/command-arguments.js +2 -0
- package/dist/command-arguments.js.map +1 -0
- package/dist/command-help.d.ts +54 -0
- package/dist/command-help.d.ts.map +1 -0
- package/dist/command-help.js +2 -0
- package/dist/command-help.js.map +1 -0
- package/dist/commands.d.ts +328 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +62 -0
- package/dist/commands.js.map +1 -0
- package/dist/counts.d.ts +124 -0
- package/dist/counts.d.ts.map +1 -0
- package/dist/counts.js +52 -0
- package/dist/counts.js.map +1 -0
- package/dist/default-commands.d.ts +400 -0
- package/dist/default-commands.d.ts.map +1 -0
- package/dist/default-commands.js +488 -0
- package/dist/default-commands.js.map +1 -0
- package/dist/default-supervisor.d.ts +111 -0
- package/dist/default-supervisor.d.ts.map +1 -0
- package/dist/default-supervisor.js +277 -0
- package/dist/default-supervisor.js.map +1 -0
- package/dist/discovery.d.ts +223 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +18 -0
- package/dist/discovery.js.map +1 -0
- package/dist/effect-testing.d.ts +388 -0
- package/dist/effect-testing.d.ts.map +1 -0
- package/dist/effect-testing.js +261 -0
- package/dist/effect-testing.js.map +1 -0
- package/dist/effect.d.ts +220 -0
- package/dist/effect.d.ts.map +1 -0
- package/dist/effect.js +101 -0
- package/dist/effect.js.map +1 -0
- package/dist/embeds.d.ts +243 -0
- package/dist/embeds.d.ts.map +1 -0
- package/dist/embeds.js +2 -0
- package/dist/embeds.js.map +1 -0
- package/dist/error-tools.d.ts +101 -0
- package/dist/error-tools.d.ts.map +1 -0
- package/dist/error-tools.js +125 -0
- package/dist/error-tools.js.map +1 -0
- package/dist/errors.d.ts +386 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +440 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +798 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +2 -0
- package/dist/events.js.map +1 -0
- package/dist/expressions.d.ts +188 -0
- package/dist/expressions.d.ts.map +1 -0
- package/dist/expressions.js +2 -0
- package/dist/expressions.js.map +1 -0
- package/dist/failures.d.ts +53 -0
- package/dist/failures.d.ts.map +1 -0
- package/dist/failures.js +2 -0
- package/dist/failures.js.map +1 -0
- package/dist/gateway.d.ts +48 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +60 -0
- package/dist/gateway.js.map +1 -0
- package/dist/guilds.d.ts +923 -0
- package/dist/guilds.d.ts.map +1 -0
- package/dist/guilds.js +204 -0
- package/dist/guilds.js.map +1 -0
- package/dist/helpers.d.ts +423 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +434 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +228 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/input-validation.d.ts +51 -0
- package/dist/input-validation.d.ts.map +1 -0
- package/dist/input-validation.js +34 -0
- package/dist/input-validation.js.map +1 -0
- package/dist/instance.d.ts +101 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +2 -0
- package/dist/instance.js.map +1 -0
- package/dist/internal/agents-section.d.ts +22 -0
- package/dist/internal/agents-section.d.ts.map +1 -0
- package/dist/internal/agents-section.js +101 -0
- package/dist/internal/agents-section.js.map +1 -0
- package/dist/internal/application.d.ts +16 -0
- package/dist/internal/application.d.ts.map +1 -0
- package/dist/internal/application.js +33 -0
- package/dist/internal/application.js.map +1 -0
- package/dist/internal/attachment-refresh.d.ts +18 -0
- package/dist/internal/attachment-refresh.d.ts.map +1 -0
- package/dist/internal/attachment-refresh.js +39 -0
- package/dist/internal/attachment-refresh.js.map +1 -0
- package/dist/internal/attachments.d.ts +45 -0
- package/dist/internal/attachments.d.ts.map +1 -0
- package/dist/internal/attachments.js +230 -0
- package/dist/internal/attachments.js.map +1 -0
- package/dist/internal/audit-logs.d.ts +13 -0
- package/dist/internal/audit-logs.d.ts.map +1 -0
- package/dist/internal/audit-logs.js +295 -0
- package/dist/internal/audit-logs.js.map +1 -0
- package/dist/internal/audit.d.ts +12 -0
- package/dist/internal/audit.d.ts.map +1 -0
- package/dist/internal/audit.js +22 -0
- package/dist/internal/audit.js.map +1 -0
- package/dist/internal/binding/default-adapters.d.ts +22 -0
- package/dist/internal/binding/default-adapters.d.ts.map +1 -0
- package/dist/internal/binding/default-adapters.js +304 -0
- package/dist/internal/binding/default-adapters.js.map +1 -0
- package/dist/internal/binding/default.d.ts +45 -0
- package/dist/internal/binding/default.d.ts.map +1 -0
- package/dist/internal/binding/default.js +86 -0
- package/dist/internal/binding/default.js.map +1 -0
- package/dist/internal/binding/execute.d.ts +51 -0
- package/dist/internal/binding/execute.d.ts.map +1 -0
- package/dist/internal/binding/execute.js +123 -0
- package/dist/internal/binding/execute.js.map +1 -0
- package/dist/internal/binding/native-adapters.d.ts +23 -0
- package/dist/internal/binding/native-adapters.d.ts.map +1 -0
- package/dist/internal/binding/native-adapters.js +90 -0
- package/dist/internal/binding/native-adapters.js.map +1 -0
- package/dist/internal/binding/native.d.ts +41 -0
- package/dist/internal/binding/native.d.ts.map +1 -0
- package/dist/internal/binding/native.js +34 -0
- package/dist/internal/binding/native.js.map +1 -0
- package/dist/internal/binding/operations.d.ts +361 -0
- package/dist/internal/binding/operations.d.ts.map +1 -0
- package/dist/internal/binding/operations.js +272 -0
- package/dist/internal/binding/operations.js.map +1 -0
- package/dist/internal/bot-runner.d.ts +65 -0
- package/dist/internal/bot-runner.d.ts.map +1 -0
- package/dist/internal/bot-runner.js +363 -0
- package/dist/internal/bot-runner.js.map +1 -0
- package/dist/internal/cache-changes.d.ts +43 -0
- package/dist/internal/cache-changes.d.ts.map +1 -0
- package/dist/internal/cache-changes.js +320 -0
- package/dist/internal/cache-changes.js.map +1 -0
- package/dist/internal/cache.d.ts +57 -0
- package/dist/internal/cache.d.ts.map +1 -0
- package/dist/internal/cache.js +318 -0
- package/dist/internal/cache.js.map +1 -0
- package/dist/internal/calls.d.ts +16 -0
- package/dist/internal/calls.d.ts.map +1 -0
- package/dist/internal/calls.js +108 -0
- package/dist/internal/calls.js.map +1 -0
- package/dist/internal/channel-cache.d.ts +69 -0
- package/dist/internal/channel-cache.d.ts.map +1 -0
- package/dist/internal/channel-cache.js +413 -0
- package/dist/internal/channel-cache.js.map +1 -0
- package/dist/internal/channel-decode.d.ts +44 -0
- package/dist/internal/channel-decode.d.ts.map +1 -0
- package/dist/internal/channel-decode.js +377 -0
- package/dist/internal/channel-decode.js.map +1 -0
- package/dist/internal/channels.d.ts +60 -0
- package/dist/internal/channels.d.ts.map +1 -0
- package/dist/internal/channels.js +605 -0
- package/dist/internal/channels.js.map +1 -0
- package/dist/internal/client/backoff.d.ts +42 -0
- package/dist/internal/client/backoff.d.ts.map +1 -0
- package/dist/internal/client/backoff.js +36 -0
- package/dist/internal/client/backoff.js.map +1 -0
- package/dist/internal/client/configuration-fields.d.ts +14 -0
- package/dist/internal/client/configuration-fields.d.ts.map +1 -0
- package/dist/internal/client/configuration-fields.js +11 -0
- package/dist/internal/client/configuration-fields.js.map +1 -0
- package/dist/internal/client/drain.d.ts +33 -0
- package/dist/internal/client/drain.d.ts.map +1 -0
- package/dist/internal/client/drain.js +109 -0
- package/dist/internal/client/drain.js.map +1 -0
- package/dist/internal/client/intake.d.ts +27 -0
- package/dist/internal/client/intake.d.ts.map +1 -0
- package/dist/internal/client/intake.js +198 -0
- package/dist/internal/client/intake.js.map +1 -0
- package/dist/internal/client/lifetime.d.ts +35 -0
- package/dist/internal/client/lifetime.d.ts.map +1 -0
- package/dist/internal/client/lifetime.js +109 -0
- package/dist/internal/client/lifetime.js.map +1 -0
- package/dist/internal/client/shard-loop.d.ts +93 -0
- package/dist/internal/client/shard-loop.d.ts.map +1 -0
- package/dist/internal/client/shard-loop.js +452 -0
- package/dist/internal/client/shard-loop.js.map +1 -0
- package/dist/internal/client-registry.d.ts +26 -0
- package/dist/internal/client-registry.d.ts.map +1 -0
- package/dist/internal/client-registry.js +11 -0
- package/dist/internal/client-registry.js.map +1 -0
- package/dist/internal/client.d.ts +189 -0
- package/dist/internal/client.d.ts.map +1 -0
- package/dist/internal/client.js +1935 -0
- package/dist/internal/client.js.map +1 -0
- package/dist/internal/clock.d.ts +9 -0
- package/dist/internal/clock.d.ts.map +1 -0
- package/dist/internal/clock.js +5 -0
- package/dist/internal/clock.js.map +1 -0
- package/dist/internal/code-catalogue.d.ts +712 -0
- package/dist/internal/code-catalogue.d.ts.map +1 -0
- package/dist/internal/code-catalogue.js +655 -0
- package/dist/internal/code-catalogue.js.map +1 -0
- package/dist/internal/collector.d.ts +34 -0
- package/dist/internal/collector.d.ts.map +1 -0
- package/dist/internal/collector.js +400 -0
- package/dist/internal/collector.js.map +1 -0
- package/dist/internal/command-arguments.d.ts +29 -0
- package/dist/internal/command-arguments.d.ts.map +1 -0
- package/dist/internal/command-arguments.js +484 -0
- package/dist/internal/command-arguments.js.map +1 -0
- package/dist/internal/command-guards.d.ts +57 -0
- package/dist/internal/command-guards.d.ts.map +1 -0
- package/dist/internal/command-guards.js +81 -0
- package/dist/internal/command-guards.js.map +1 -0
- package/dist/internal/command-help.d.ts +15 -0
- package/dist/internal/command-help.d.ts.map +1 -0
- package/dist/internal/command-help.js +121 -0
- package/dist/internal/command-help.js.map +1 -0
- package/dist/internal/commands.d.ts +212 -0
- package/dist/internal/commands.d.ts.map +1 -0
- package/dist/internal/commands.js +1004 -0
- package/dist/internal/commands.js.map +1 -0
- package/dist/internal/configuration.d.ts +86 -0
- package/dist/internal/configuration.d.ts.map +1 -0
- package/dist/internal/configuration.js +401 -0
- package/dist/internal/configuration.js.map +1 -0
- package/dist/internal/counts.d.ts +33 -0
- package/dist/internal/counts.d.ts.map +1 -0
- package/dist/internal/counts.js +348 -0
- package/dist/internal/counts.js.map +1 -0
- package/dist/internal/decode/primitives.d.ts +30 -0
- package/dist/internal/decode/primitives.d.ts.map +1 -0
- package/dist/internal/decode/primitives.js +56 -0
- package/dist/internal/decode/primitives.js.map +1 -0
- package/dist/internal/decode/timestamp.d.ts +13 -0
- package/dist/internal/decode/timestamp.d.ts.map +1 -0
- package/dist/internal/decode/timestamp.js +27 -0
- package/dist/internal/decode/timestamp.js.map +1 -0
- package/dist/internal/decode/trace.d.ts +11 -0
- package/dist/internal/decode/trace.d.ts.map +1 -0
- package/dist/internal/decode/trace.js +69 -0
- package/dist/internal/decode/trace.js.map +1 -0
- package/dist/internal/defects.d.ts +48 -0
- package/dist/internal/defects.d.ts.map +1 -0
- package/dist/internal/defects.js +100 -0
- package/dist/internal/defects.js.map +1 -0
- package/dist/internal/effect-failures.d.ts +12 -0
- package/dist/internal/effect-failures.d.ts.map +1 -0
- package/dist/internal/effect-failures.js +45 -0
- package/dist/internal/effect-failures.js.map +1 -0
- package/dist/internal/embeds.d.ts +12 -0
- package/dist/internal/embeds.d.ts.map +1 -0
- package/dist/internal/embeds.js +308 -0
- package/dist/internal/embeds.js.map +1 -0
- package/dist/internal/events.d.ts +156 -0
- package/dist/internal/events.d.ts.map +1 -0
- package/dist/internal/events.js +1071 -0
- package/dist/internal/events.js.map +1 -0
- package/dist/internal/expiry-queue.d.ts +42 -0
- package/dist/internal/expiry-queue.d.ts.map +1 -0
- package/dist/internal/expiry-queue.js +138 -0
- package/dist/internal/expiry-queue.js.map +1 -0
- package/dist/internal/expressions.d.ts +35 -0
- package/dist/internal/expressions.d.ts.map +1 -0
- package/dist/internal/expressions.js +311 -0
- package/dist/internal/expressions.js.map +1 -0
- package/dist/internal/failures.d.ts +107 -0
- package/dist/internal/failures.d.ts.map +1 -0
- package/dist/internal/failures.js +416 -0
- package/dist/internal/failures.js.map +1 -0
- package/dist/internal/field-text.d.ts +10 -0
- package/dist/internal/field-text.d.ts.map +1 -0
- package/dist/internal/field-text.js +37 -0
- package/dist/internal/field-text.js.map +1 -0
- package/dist/internal/gateway/commands.d.ts +92 -0
- package/dist/internal/gateway/commands.d.ts.map +1 -0
- package/dist/internal/gateway/commands.js +223 -0
- package/dist/internal/gateway/commands.js.map +1 -0
- package/dist/internal/gateway/dispatch-table.d.ts +42 -0
- package/dist/internal/gateway/dispatch-table.d.ts.map +1 -0
- package/dist/internal/gateway/dispatch-table.js +288 -0
- package/dist/internal/gateway/dispatch-table.js.map +1 -0
- package/dist/internal/gateway/event-dispatches.d.ts +97 -0
- package/dist/internal/gateway/event-dispatches.d.ts.map +1 -0
- package/dist/internal/gateway/event-dispatches.js +172 -0
- package/dist/internal/gateway/event-dispatches.js.map +1 -0
- package/dist/internal/gateway/frames.d.ts +45 -0
- package/dist/internal/gateway/frames.d.ts.map +1 -0
- package/dist/internal/gateway/frames.js +121 -0
- package/dist/internal/gateway/frames.js.map +1 -0
- package/dist/internal/gateway/options.d.ts +24 -0
- package/dist/internal/gateway/options.d.ts.map +1 -0
- package/dist/internal/gateway/options.js +103 -0
- package/dist/internal/gateway/options.js.map +1 -0
- package/dist/internal/gateway/session.d.ts +104 -0
- package/dist/internal/gateway/session.d.ts.map +1 -0
- package/dist/internal/gateway/session.js +420 -0
- package/dist/internal/gateway/session.js.map +1 -0
- package/dist/internal/gateway-requests.d.ts +10 -0
- package/dist/internal/gateway-requests.d.ts.map +1 -0
- package/dist/internal/gateway-requests.js +26 -0
- package/dist/internal/gateway-requests.js.map +1 -0
- package/dist/internal/gateway.d.ts +19 -0
- package/dist/internal/gateway.d.ts.map +1 -0
- package/dist/internal/gateway.js +11 -0
- package/dist/internal/gateway.js.map +1 -0
- package/dist/internal/guild-cache.d.ts +69 -0
- package/dist/internal/guild-cache.d.ts.map +1 -0
- package/dist/internal/guild-cache.js +402 -0
- package/dist/internal/guild-cache.js.map +1 -0
- package/dist/internal/guild-discovery.d.ts +15 -0
- package/dist/internal/guild-discovery.d.ts.map +1 -0
- package/dist/internal/guild-discovery.js +258 -0
- package/dist/internal/guild-discovery.js.map +1 -0
- package/dist/internal/guild-lifecycle.d.ts +18 -0
- package/dist/internal/guild-lifecycle.d.ts.map +1 -0
- package/dist/internal/guild-lifecycle.js +119 -0
- package/dist/internal/guild-lifecycle.js.map +1 -0
- package/dist/internal/guild-settings.d.ts +11 -0
- package/dist/internal/guild-settings.d.ts.map +1 -0
- package/dist/internal/guild-settings.js +150 -0
- package/dist/internal/guild-settings.js.map +1 -0
- package/dist/internal/guilds.d.ts +94 -0
- package/dist/internal/guilds.d.ts.map +1 -0
- package/dist/internal/guilds.js +785 -0
- package/dist/internal/guilds.js.map +1 -0
- package/dist/internal/init-command.d.ts +54 -0
- package/dist/internal/init-command.d.ts.map +1 -0
- package/dist/internal/init-command.js +248 -0
- package/dist/internal/init-command.js.map +1 -0
- package/dist/internal/instance.d.ts +69 -0
- package/dist/internal/instance.d.ts.map +1 -0
- package/dist/internal/instance.js +455 -0
- package/dist/internal/instance.js.map +1 -0
- package/dist/internal/invalid-callback-return.d.ts +3 -0
- package/dist/internal/invalid-callback-return.d.ts.map +1 -0
- package/dist/internal/invalid-callback-return.js +26 -0
- package/dist/internal/invalid-callback-return.js.map +1 -0
- package/dist/internal/invites.d.ts +19 -0
- package/dist/internal/invites.d.ts.map +1 -0
- package/dist/internal/invites.js +182 -0
- package/dist/internal/invites.js.map +1 -0
- package/dist/internal/logging.d.ts +129 -0
- package/dist/internal/logging.d.ts.map +1 -0
- package/dist/internal/logging.js +868 -0
- package/dist/internal/logging.js.map +1 -0
- package/dist/internal/logical-scheduler.d.ts +27 -0
- package/dist/internal/logical-scheduler.d.ts.map +1 -0
- package/dist/internal/logical-scheduler.js +102 -0
- package/dist/internal/logical-scheduler.js.map +1 -0
- package/dist/internal/masking.d.ts +13 -0
- package/dist/internal/masking.d.ts.map +1 -0
- package/dist/internal/masking.js +235 -0
- package/dist/internal/masking.js.map +1 -0
- package/dist/internal/member-chunks.d.ts +96 -0
- package/dist/internal/member-chunks.d.ts.map +1 -0
- package/dist/internal/member-chunks.js +557 -0
- package/dist/internal/member-chunks.js.map +1 -0
- package/dist/internal/member-search-workflow.d.ts +19 -0
- package/dist/internal/member-search-workflow.d.ts.map +1 -0
- package/dist/internal/member-search-workflow.js +143 -0
- package/dist/internal/member-search-workflow.js.map +1 -0
- package/dist/internal/member-search.d.ts +20 -0
- package/dist/internal/member-search.d.ts.map +1 -0
- package/dist/internal/member-search.js +201 -0
- package/dist/internal/member-search.js.map +1 -0
- package/dist/internal/message-cleanup.d.ts +9 -0
- package/dist/internal/message-cleanup.d.ts.map +1 -0
- package/dist/internal/message-cleanup.js +368 -0
- package/dist/internal/message-cleanup.js.map +1 -0
- package/dist/internal/message-fields.d.ts +9 -0
- package/dist/internal/message-fields.d.ts.map +1 -0
- package/dist/internal/message-fields.js +55 -0
- package/dist/internal/message-fields.js.map +1 -0
- package/dist/internal/message-search-workflow.d.ts +14 -0
- package/dist/internal/message-search-workflow.d.ts.map +1 -0
- package/dist/internal/message-search-workflow.js +101 -0
- package/dist/internal/message-search-workflow.js.map +1 -0
- package/dist/internal/message-search.d.ts +19 -0
- package/dist/internal/message-search.d.ts.map +1 -0
- package/dist/internal/message-search.js +317 -0
- package/dist/internal/message-search.js.map +1 -0
- package/dist/internal/message.d.ts +34 -0
- package/dist/internal/message.d.ts.map +1 -0
- package/dist/internal/message.js +723 -0
- package/dist/internal/message.js.map +1 -0
- package/dist/internal/metrics.d.ts +16 -0
- package/dist/internal/metrics.d.ts.map +1 -0
- package/dist/internal/metrics.js +49 -0
- package/dist/internal/metrics.js.map +1 -0
- package/dist/internal/moderation.d.ts +20 -0
- package/dist/internal/moderation.d.ts.map +1 -0
- package/dist/internal/moderation.js +219 -0
- package/dist/internal/moderation.js.map +1 -0
- package/dist/internal/multipart.d.ts +10 -0
- package/dist/internal/multipart.d.ts.map +1 -0
- package/dist/internal/multipart.js +156 -0
- package/dist/internal/multipart.js.map +1 -0
- package/dist/internal/node-version.d.ts +10 -0
- package/dist/internal/node-version.d.ts.map +1 -0
- package/dist/internal/node-version.js +21 -0
- package/dist/internal/node-version.js.map +1 -0
- package/dist/internal/oauth.d.ts +29 -0
- package/dist/internal/oauth.d.ts.map +1 -0
- package/dist/internal/oauth.js +721 -0
- package/dist/internal/oauth.js.map +1 -0
- package/dist/internal/observer.d.ts +21 -0
- package/dist/internal/observer.d.ts.map +1 -0
- package/dist/internal/observer.js +48 -0
- package/dist/internal/observer.js.map +1 -0
- package/dist/internal/operation-signal.d.ts +9 -0
- package/dist/internal/operation-signal.d.ts.map +1 -0
- package/dist/internal/operation-signal.js +19 -0
- package/dist/internal/operation-signal.js.map +1 -0
- package/dist/internal/pagination.d.ts +67 -0
- package/dist/internal/pagination.d.ts.map +1 -0
- package/dist/internal/pagination.js +306 -0
- package/dist/internal/pagination.js.map +1 -0
- package/dist/internal/permission-requirements.d.ts +34 -0
- package/dist/internal/permission-requirements.d.ts.map +1 -0
- package/dist/internal/permission-requirements.js +204 -0
- package/dist/internal/permission-requirements.js.map +1 -0
- package/dist/internal/permissions.d.ts +28 -0
- package/dist/internal/permissions.d.ts.map +1 -0
- package/dist/internal/permissions.js +314 -0
- package/dist/internal/permissions.js.map +1 -0
- package/dist/internal/pins.d.ts +24 -0
- package/dist/internal/pins.d.ts.map +1 -0
- package/dist/internal/pins.js +83 -0
- package/dist/internal/pins.js.map +1 -0
- package/dist/internal/presence.d.ts +101 -0
- package/dist/internal/presence.d.ts.map +1 -0
- package/dist/internal/presence.js +581 -0
- package/dist/internal/presence.js.map +1 -0
- package/dist/internal/protocol/gateway.d.ts +116 -0
- package/dist/internal/protocol/gateway.d.ts.map +1 -0
- package/dist/internal/protocol/gateway.js +258 -0
- package/dist/internal/protocol/gateway.js.map +1 -0
- package/dist/internal/rate-limit-templates.d.ts +2 -0
- package/dist/internal/rate-limit-templates.d.ts.map +1 -0
- package/dist/internal/rate-limit-templates.js +132 -0
- package/dist/internal/rate-limit-templates.js.map +1 -0
- package/dist/internal/rate-limits.d.ts +32 -0
- package/dist/internal/rate-limits.d.ts.map +1 -0
- package/dist/internal/rate-limits.js +306 -0
- package/dist/internal/rate-limits.js.map +1 -0
- package/dist/internal/reaction-collector.d.ts +39 -0
- package/dist/internal/reaction-collector.d.ts.map +1 -0
- package/dist/internal/reaction-collector.js +441 -0
- package/dist/internal/reaction-collector.js.map +1 -0
- package/dist/internal/reaction-pages.d.ts +18 -0
- package/dist/internal/reaction-pages.d.ts.map +1 -0
- package/dist/internal/reaction-pages.js +213 -0
- package/dist/internal/reaction-pages.js.map +1 -0
- package/dist/internal/reactions.d.ts +30 -0
- package/dist/internal/reactions.d.ts.map +1 -0
- package/dist/internal/reactions.js +160 -0
- package/dist/internal/reactions.js.map +1 -0
- package/dist/internal/rejection-scope.d.ts +25 -0
- package/dist/internal/rejection-scope.d.ts.map +1 -0
- package/dist/internal/rejection-scope.js +103 -0
- package/dist/internal/rejection-scope.js.map +1 -0
- package/dist/internal/response-json.d.ts +12 -0
- package/dist/internal/response-json.d.ts.map +1 -0
- package/dist/internal/response-json.js +74 -0
- package/dist/internal/response-json.js.map +1 -0
- package/dist/internal/rest/admission.d.ts +77 -0
- package/dist/internal/rest/admission.d.ts.map +1 -0
- package/dist/internal/rest/admission.js +178 -0
- package/dist/internal/rest/admission.js.map +1 -0
- package/dist/internal/rest/attempt.d.ts +124 -0
- package/dist/internal/rest/attempt.d.ts.map +1 -0
- package/dist/internal/rest/attempt.js +410 -0
- package/dist/internal/rest/attempt.js.map +1 -0
- package/dist/internal/rest/classify.d.ts +93 -0
- package/dist/internal/rest/classify.d.ts.map +1 -0
- package/dist/internal/rest/classify.js +304 -0
- package/dist/internal/rest/classify.js.map +1 -0
- package/dist/internal/rest/download.d.ts +66 -0
- package/dist/internal/rest/download.d.ts.map +1 -0
- package/dist/internal/rest/download.js +552 -0
- package/dist/internal/rest/download.js.map +1 -0
- package/dist/internal/rest/options.d.ts +42 -0
- package/dist/internal/rest/options.d.ts.map +1 -0
- package/dist/internal/rest/options.js +99 -0
- package/dist/internal/rest/options.js.map +1 -0
- package/dist/internal/rest/owner.d.ts +154 -0
- package/dist/internal/rest/owner.d.ts.map +1 -0
- package/dist/internal/rest/owner.js +1292 -0
- package/dist/internal/rest/owner.js.map +1 -0
- package/dist/internal/rest/request.d.ts +31 -0
- package/dist/internal/rest/request.d.ts.map +1 -0
- package/dist/internal/rest/request.js +227 -0
- package/dist/internal/rest/request.js.map +1 -0
- package/dist/internal/rest.d.ts +10 -0
- package/dist/internal/rest.d.ts.map +1 -0
- package/dist/internal/rest.js +9 -0
- package/dist/internal/rest.js.map +1 -0
- package/dist/internal/retention-age.d.ts +11 -0
- package/dist/internal/retention-age.d.ts.map +1 -0
- package/dist/internal/retention-age.js +29 -0
- package/dist/internal/retention-age.js.map +1 -0
- package/dist/internal/role-hierarchy-workflow.d.ts +15 -0
- package/dist/internal/role-hierarchy-workflow.d.ts.map +1 -0
- package/dist/internal/role-hierarchy-workflow.js +122 -0
- package/dist/internal/role-hierarchy-workflow.js.map +1 -0
- package/dist/internal/role-hierarchy.d.ts +11 -0
- package/dist/internal/role-hierarchy.d.ts.map +1 -0
- package/dist/internal/role-hierarchy.js +87 -0
- package/dist/internal/role-hierarchy.js.map +1 -0
- package/dist/internal/scheduled-tasks.d.ts +46 -0
- package/dist/internal/scheduled-tasks.d.ts.map +1 -0
- package/dist/internal/scheduled-tasks.js +190 -0
- package/dist/internal/scheduled-tasks.js.map +1 -0
- package/dist/internal/sharding.d.ts +62 -0
- package/dist/internal/sharding.d.ts.map +1 -0
- package/dist/internal/sharding.js +205 -0
- package/dist/internal/sharding.js.map +1 -0
- package/dist/internal/starter-project.d.ts +27 -0
- package/dist/internal/starter-project.d.ts.map +1 -0
- package/dist/internal/starter-project.js +224 -0
- package/dist/internal/starter-project.js.map +1 -0
- package/dist/internal/suggest.d.ts +12 -0
- package/dist/internal/suggest.d.ts.map +1 -0
- package/dist/internal/suggest.js +51 -0
- package/dist/internal/suggest.js.map +1 -0
- package/dist/internal/supervisor.d.ts +95 -0
- package/dist/internal/supervisor.d.ts.map +1 -0
- package/dist/internal/supervisor.js +1829 -0
- package/dist/internal/supervisor.js.map +1 -0
- package/dist/internal/testing/discovery.d.ts +24 -0
- package/dist/internal/testing/discovery.d.ts.map +1 -0
- package/dist/internal/testing/discovery.js +22 -0
- package/dist/internal/testing/discovery.js.map +1 -0
- package/dist/internal/testing/errors.d.ts +43 -0
- package/dist/internal/testing/errors.d.ts.map +1 -0
- package/dist/internal/testing/errors.js +63 -0
- package/dist/internal/testing/errors.js.map +1 -0
- package/dist/internal/testing/fixtures.d.ts +477 -0
- package/dist/internal/testing/fixtures.d.ts.map +1 -0
- package/dist/internal/testing/fixtures.js +233 -0
- package/dist/internal/testing/fixtures.js.map +1 -0
- package/dist/internal/testing/gateway.d.ts +51 -0
- package/dist/internal/testing/gateway.d.ts.map +1 -0
- package/dist/internal/testing/gateway.js +265 -0
- package/dist/internal/testing/gateway.js.map +1 -0
- package/dist/internal/testing/harness.d.ts +60 -0
- package/dist/internal/testing/harness.d.ts.map +1 -0
- package/dist/internal/testing/harness.js +280 -0
- package/dist/internal/testing/harness.js.map +1 -0
- package/dist/internal/testing/http.d.ts +31 -0
- package/dist/internal/testing/http.d.ts.map +1 -0
- package/dist/internal/testing/http.js +347 -0
- package/dist/internal/testing/http.js.map +1 -0
- package/dist/internal/testing/types.d.ts +222 -0
- package/dist/internal/testing/types.d.ts.map +1 -0
- package/dist/internal/testing/types.js +2 -0
- package/dist/internal/testing/types.js.map +1 -0
- package/dist/internal/testing/wait.d.ts +16 -0
- package/dist/internal/testing/wait.d.ts.map +1 -0
- package/dist/internal/testing/wait.js +55 -0
- package/dist/internal/testing/wait.js.map +1 -0
- package/dist/internal/thread-events.d.ts +40 -0
- package/dist/internal/thread-events.d.ts.map +1 -0
- package/dist/internal/thread-events.js +121 -0
- package/dist/internal/thread-events.js.map +1 -0
- package/dist/internal/threads.d.ts +47 -0
- package/dist/internal/threads.d.ts.map +1 -0
- package/dist/internal/threads.js +587 -0
- package/dist/internal/threads.js.map +1 -0
- package/dist/internal/transfer-source.d.ts +29 -0
- package/dist/internal/transfer-source.d.ts.map +1 -0
- package/dist/internal/transfer-source.js +347 -0
- package/dist/internal/transfer-source.js.map +1 -0
- package/dist/internal/transport/http.d.ts +12 -0
- package/dist/internal/transport/http.d.ts.map +1 -0
- package/dist/internal/transport/http.js +44 -0
- package/dist/internal/transport/http.js.map +1 -0
- package/dist/internal/transport/index.d.ts +21 -0
- package/dist/internal/transport/index.d.ts.map +1 -0
- package/dist/internal/transport/index.js +15 -0
- package/dist/internal/transport/index.js.map +1 -0
- package/dist/internal/transport/socket.d.ts +51 -0
- package/dist/internal/transport/socket.d.ts.map +1 -0
- package/dist/internal/transport/socket.js +27 -0
- package/dist/internal/transport/socket.js.map +1 -0
- package/dist/internal/transport/user-agent.d.ts +7 -0
- package/dist/internal/transport/user-agent.d.ts.map +1 -0
- package/dist/internal/transport/user-agent.js +42 -0
- package/dist/internal/transport/user-agent.js.map +1 -0
- package/dist/internal/uploads.d.ts +23 -0
- package/dist/internal/uploads.d.ts.map +1 -0
- package/dist/internal/uploads.js +89 -0
- package/dist/internal/uploads.js.map +1 -0
- package/dist/internal/user-cache.d.ts +50 -0
- package/dist/internal/user-cache.d.ts.map +1 -0
- package/dist/internal/user-cache.js +273 -0
- package/dist/internal/user-cache.js.map +1 -0
- package/dist/internal/users.d.ts +41 -0
- package/dist/internal/users.d.ts.map +1 -0
- package/dist/internal/users.js +333 -0
- package/dist/internal/users.js.map +1 -0
- package/dist/internal/vanity-url.d.ts +11 -0
- package/dist/internal/vanity-url.d.ts.map +1 -0
- package/dist/internal/vanity-url.js +58 -0
- package/dist/internal/vanity-url.js.map +1 -0
- package/dist/internal/webhooks.d.ts +58 -0
- package/dist/internal/webhooks.d.ts.map +1 -0
- package/dist/internal/webhooks.js +490 -0
- package/dist/internal/webhooks.js.map +1 -0
- package/dist/invites.d.ts +86 -0
- package/dist/invites.d.ts.map +1 -0
- package/dist/invites.js +2 -0
- package/dist/invites.js.map +1 -0
- package/dist/logging.d.ts +228 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +2 -0
- package/dist/logging.js.map +1 -0
- package/dist/member-chunks.d.ts +145 -0
- package/dist/member-chunks.d.ts.map +1 -0
- package/dist/member-chunks.js +68 -0
- package/dist/member-chunks.js.map +1 -0
- package/dist/member-search.d.ts +140 -0
- package/dist/member-search.d.ts.map +1 -0
- package/dist/member-search.js +14 -0
- package/dist/member-search.js.map +1 -0
- package/dist/message-cleanup.d.ts +227 -0
- package/dist/message-cleanup.d.ts.map +1 -0
- package/dist/message-cleanup.js +101 -0
- package/dist/message-cleanup.js.map +1 -0
- package/dist/message-errors.d.ts +172 -0
- package/dist/message-errors.d.ts.map +1 -0
- package/dist/message-errors.js +173 -0
- package/dist/message-errors.js.map +1 -0
- package/dist/message-search.d.ts +201 -0
- package/dist/message-search.d.ts.map +1 -0
- package/dist/message-search.js +2 -0
- package/dist/message-search.js.map +1 -0
- package/dist/messages.d.ts +694 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +37 -0
- package/dist/messages.js.map +1 -0
- package/dist/native-commands.d.ts +451 -0
- package/dist/native-commands.d.ts.map +1 -0
- package/dist/native-commands.js +432 -0
- package/dist/native-commands.js.map +1 -0
- package/dist/native-supervisor.d.ts +125 -0
- package/dist/native-supervisor.d.ts.map +1 -0
- package/dist/native-supervisor.js +126 -0
- package/dist/native-supervisor.js.map +1 -0
- package/dist/oauth.d.ts +298 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +128 -0
- package/dist/oauth.js.map +1 -0
- package/dist/observer.d.ts +111 -0
- package/dist/observer.d.ts.map +1 -0
- package/dist/observer.js +2 -0
- package/dist/observer.js.map +1 -0
- package/dist/pagination.d.ts +117 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +61 -0
- package/dist/pagination.js.map +1 -0
- package/dist/permissions.d.ts +73 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +2 -0
- package/dist/permissions.js.map +1 -0
- package/dist/pins.d.ts +62 -0
- package/dist/pins.d.ts.map +1 -0
- package/dist/pins.js +2 -0
- package/dist/pins.js.map +1 -0
- package/dist/presence.d.ts +84 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +46 -0
- package/dist/presence.js.map +1 -0
- package/dist/reaction-pages.d.ts +99 -0
- package/dist/reaction-pages.d.ts.map +1 -0
- package/dist/reaction-pages.js +2 -0
- package/dist/reaction-pages.js.map +1 -0
- package/dist/reactions.d.ts +118 -0
- package/dist/reactions.d.ts.map +1 -0
- package/dist/reactions.js +2 -0
- package/dist/reactions.js.map +1 -0
- package/dist/rest.d.ts +260 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +46 -0
- package/dist/rest.js.map +1 -0
- package/dist/role-hierarchy.d.ts +81 -0
- package/dist/role-hierarchy.d.ts.map +1 -0
- package/dist/role-hierarchy.js +53 -0
- package/dist/role-hierarchy.js.map +1 -0
- package/dist/sharding.d.ts +219 -0
- package/dist/sharding.d.ts.map +1 -0
- package/dist/sharding.js +86 -0
- package/dist/sharding.js.map +1 -0
- package/dist/supervisor.d.ts +392 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +101 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/testing.d.ts +258 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +202 -0
- package/dist/testing.js.map +1 -0
- package/dist/text.d.ts +38 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +46 -0
- package/dist/text.js.map +1 -0
- package/dist/threads.d.ts +258 -0
- package/dist/threads.d.ts.map +1 -0
- package/dist/threads.js +2 -0
- package/dist/threads.js.map +1 -0
- package/dist/users.d.ts +204 -0
- package/dist/users.d.ts.map +1 -0
- package/dist/users.js +44 -0
- package/dist/users.js.map +1 -0
- package/dist/webhooks.d.ts +423 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +68 -0
- package/dist/webhooks.js.map +1 -0
- package/esm-only.cjs +3 -0
- package/examples/starter/bot-effect.ts +17 -0
- package/examples/starter/bot.js +13 -0
- package/examples/starter/bot.ts +13 -0
- package/package.json +82 -0
- package/src/api/default/application.ts +40 -0
- package/src/api/default/attachments.ts +106 -0
- package/src/api/default/audit-logs.ts +58 -0
- package/src/api/default/bot.ts +586 -0
- package/src/api/default/cache.ts +106 -0
- package/src/api/default/channels.ts +317 -0
- package/src/api/default/client.ts +829 -0
- package/src/api/default/collectors.ts +81 -0
- package/src/api/default/commands.ts +92 -0
- package/src/api/default/direct-messages.ts +143 -0
- package/src/api/default/discovery.ts +103 -0
- package/src/api/default/emojis.ts +125 -0
- package/src/api/default/events.ts +144 -0
- package/src/api/default/gateway.ts +67 -0
- package/src/api/default/guards.ts +173 -0
- package/src/api/default/guilds.ts +271 -0
- package/src/api/default/helpers.ts +97 -0
- package/src/api/default/instance.ts +49 -0
- package/src/api/default/invites.ts +73 -0
- package/src/api/default/logging.ts +37 -0
- package/src/api/default/members.ts +550 -0
- package/src/api/default/messages.ts +1053 -0
- package/src/api/default/oauth.ts +293 -0
- package/src/api/default/permissions.ts +47 -0
- package/src/api/default/presence.ts +88 -0
- package/src/api/default/rest.ts +30 -0
- package/src/api/default/results.ts +44 -0
- package/src/api/default/roles.ts +154 -0
- package/src/api/default/stickers.ts +129 -0
- package/src/api/default/supervisor.ts +53 -0
- package/src/api/default/threads.ts +233 -0
- package/src/api/default/users.ts +82 -0
- package/src/api/default/webhook-client.ts +266 -0
- package/src/api/default/webhooks.ts +89 -0
- package/src/api/effect/application.ts +29 -0
- package/src/api/effect/attachments.ts +100 -0
- package/src/api/effect/audit-logs.ts +50 -0
- package/src/api/effect/bot.ts +546 -0
- package/src/api/effect/cache.ts +110 -0
- package/src/api/effect/channels.ts +293 -0
- package/src/api/effect/client.ts +792 -0
- package/src/api/effect/collectors.ts +103 -0
- package/src/api/effect/commands.ts +87 -0
- package/src/api/effect/direct-messages.ts +119 -0
- package/src/api/effect/discovery.ts +87 -0
- package/src/api/effect/emojis.ts +108 -0
- package/src/api/effect/events.ts +92 -0
- package/src/api/effect/failures.ts +14 -0
- package/src/api/effect/gateway.ts +63 -0
- package/src/api/effect/guards.ts +194 -0
- package/src/api/effect/guilds.ts +247 -0
- package/src/api/effect/helpers.ts +359 -0
- package/src/api/effect/hierarchy.ts +26 -0
- package/src/api/effect/instance.ts +50 -0
- package/src/api/effect/invites.ts +59 -0
- package/src/api/effect/logging.ts +37 -0
- package/src/api/effect/members.ts +521 -0
- package/src/api/effect/messages.ts +1003 -0
- package/src/api/effect/oauth.ts +208 -0
- package/src/api/effect/permissions.ts +44 -0
- package/src/api/effect/presence.ts +83 -0
- package/src/api/effect/rest.ts +27 -0
- package/src/api/effect/roles.ts +136 -0
- package/src/api/effect/service.ts +104 -0
- package/src/api/effect/stickers.ts +112 -0
- package/src/api/effect/supervisor.ts +58 -0
- package/src/api/effect/threads.ts +221 -0
- package/src/api/effect/users.ts +66 -0
- package/src/api/effect/webhook-client.ts +206 -0
- package/src/api/effect/webhooks.ts +75 -0
- package/src/api-errors.ts +985 -0
- package/src/application.ts +103 -0
- package/src/assets.ts +731 -0
- package/src/attachments.ts +469 -0
- package/src/audit-logs.ts +355 -0
- package/src/bot-runner.ts +91 -0
- package/src/builders.ts +390 -0
- package/src/cache.ts +190 -0
- package/src/channels.ts +1051 -0
- package/src/cli.ts +60 -0
- package/src/client.ts +663 -0
- package/src/collectors.ts +248 -0
- package/src/colors.ts +91 -0
- package/src/command-arguments.ts +432 -0
- package/src/command-help.ts +55 -0
- package/src/commands.ts +403 -0
- package/src/counts.ts +160 -0
- package/src/default-commands.ts +1147 -0
- package/src/default-supervisor.ts +484 -0
- package/src/discovery.ts +241 -0
- package/src/effect-testing.ts +603 -0
- package/src/effect.ts +751 -0
- package/src/embeds.ts +253 -0
- package/src/error-tools.ts +191 -0
- package/src/errors.ts +849 -0
- package/src/events.ts +830 -0
- package/src/expressions.ts +198 -0
- package/src/failures.ts +55 -0
- package/src/gateway.ts +86 -0
- package/src/guilds.ts +1108 -0
- package/src/helpers.ts +836 -0
- package/src/index.ts +796 -0
- package/src/input-validation.ts +94 -0
- package/src/instance.ts +111 -0
- package/src/internal/agents-section.ts +114 -0
- package/src/internal/application.ts +51 -0
- package/src/internal/attachment-refresh.ts +57 -0
- package/src/internal/attachments.ts +313 -0
- package/src/internal/audit-logs.ts +336 -0
- package/src/internal/audit.ts +33 -0
- package/src/internal/binding/default-adapters.ts +482 -0
- package/src/internal/binding/default.ts +155 -0
- package/src/internal/binding/execute.ts +221 -0
- package/src/internal/binding/native-adapters.ts +199 -0
- package/src/internal/binding/native.ts +72 -0
- package/src/internal/binding/operations.ts +1171 -0
- package/src/internal/bot-runner.ts +480 -0
- package/src/internal/cache-changes.ts +363 -0
- package/src/internal/cache.ts +323 -0
- package/src/internal/calls.ts +119 -0
- package/src/internal/channel-cache.ts +435 -0
- package/src/internal/channel-decode.ts +399 -0
- package/src/internal/channels.ts +874 -0
- package/src/internal/client/backoff.ts +69 -0
- package/src/internal/client/configuration-fields.ts +18 -0
- package/src/internal/client/drain.ts +150 -0
- package/src/internal/client/intake.ts +228 -0
- package/src/internal/client/lifetime.ts +165 -0
- package/src/internal/client/shard-loop.ts +586 -0
- package/src/internal/client-registry.ts +35 -0
- package/src/internal/client.ts +2448 -0
- package/src/internal/clock.ts +11 -0
- package/src/internal/code-catalogue.ts +739 -0
- package/src/internal/collector.ts +452 -0
- package/src/internal/command-arguments.ts +585 -0
- package/src/internal/command-guards.ts +96 -0
- package/src/internal/command-help.ts +156 -0
- package/src/internal/commands.ts +1319 -0
- package/src/internal/configuration.ts +529 -0
- package/src/internal/counts.ts +471 -0
- package/src/internal/decode/primitives.ts +67 -0
- package/src/internal/decode/timestamp.ts +29 -0
- package/src/internal/decode/trace.ts +65 -0
- package/src/internal/defects.ts +115 -0
- package/src/internal/effect-failures.ts +65 -0
- package/src/internal/embeds.ts +355 -0
- package/src/internal/events.ts +1345 -0
- package/src/internal/expiry-queue.ts +148 -0
- package/src/internal/expressions.ts +415 -0
- package/src/internal/failures.ts +492 -0
- package/src/internal/field-text.ts +40 -0
- package/src/internal/gateway/commands.ts +328 -0
- package/src/internal/gateway/dispatch-table.ts +383 -0
- package/src/internal/gateway/event-dispatches.ts +201 -0
- package/src/internal/gateway/frames.ts +176 -0
- package/src/internal/gateway/options.ts +144 -0
- package/src/internal/gateway/session.ts +625 -0
- package/src/internal/gateway-requests.ts +26 -0
- package/src/internal/gateway.ts +22 -0
- package/src/internal/guild-cache.ts +424 -0
- package/src/internal/guild-discovery.ts +332 -0
- package/src/internal/guild-lifecycle.ts +128 -0
- package/src/internal/guild-settings.ts +209 -0
- package/src/internal/guilds.ts +949 -0
- package/src/internal/init-command.ts +305 -0
- package/src/internal/instance.ts +645 -0
- package/src/internal/invalid-callback-return.ts +28 -0
- package/src/internal/invites.ts +234 -0
- package/src/internal/logging.ts +1007 -0
- package/src/internal/logical-scheduler.ts +139 -0
- package/src/internal/masking.ts +224 -0
- package/src/internal/member-chunks.ts +649 -0
- package/src/internal/member-search-workflow.ts +237 -0
- package/src/internal/member-search.ts +272 -0
- package/src/internal/message-cleanup.ts +515 -0
- package/src/internal/message-fields.ts +71 -0
- package/src/internal/message-search-workflow.ts +166 -0
- package/src/internal/message-search.ts +476 -0
- package/src/internal/message.ts +879 -0
- package/src/internal/metrics.ts +55 -0
- package/src/internal/moderation.ts +288 -0
- package/src/internal/multipart.ts +171 -0
- package/src/internal/node-version.ts +22 -0
- package/src/internal/oauth.ts +1146 -0
- package/src/internal/observer.ts +62 -0
- package/src/internal/operation-signal.ts +26 -0
- package/src/internal/pagination.ts +494 -0
- package/src/internal/permission-requirements.ts +359 -0
- package/src/internal/permissions.ts +417 -0
- package/src/internal/pins.ts +115 -0
- package/src/internal/presence.ts +745 -0
- package/src/internal/protocol/gateway.ts +299 -0
- package/src/internal/rate-limit-templates.ts +138 -0
- package/src/internal/rate-limits.ts +346 -0
- package/src/internal/reaction-collector.ts +499 -0
- package/src/internal/reaction-pages.ts +260 -0
- package/src/internal/reactions.ts +174 -0
- package/src/internal/rejection-scope.ts +119 -0
- package/src/internal/response-json.ts +76 -0
- package/src/internal/rest/admission.ts +210 -0
- package/src/internal/rest/attempt.ts +617 -0
- package/src/internal/rest/classify.ts +391 -0
- package/src/internal/rest/download.ts +658 -0
- package/src/internal/rest/options.ts +145 -0
- package/src/internal/rest/owner.ts +1828 -0
- package/src/internal/rest/request.ts +289 -0
- package/src/internal/rest.ts +9 -0
- package/src/internal/retention-age.ts +33 -0
- package/src/internal/role-hierarchy-workflow.ts +150 -0
- package/src/internal/role-hierarchy.ts +93 -0
- package/src/internal/scheduled-tasks.ts +217 -0
- package/src/internal/sharding.ts +270 -0
- package/src/internal/starter-project.ts +251 -0
- package/src/internal/suggest.ts +50 -0
- package/src/internal/supervisor.ts +2253 -0
- package/src/internal/testing/discovery.ts +23 -0
- package/src/internal/testing/errors.ts +67 -0
- package/src/internal/testing/fixtures.ts +714 -0
- package/src/internal/testing/gateway.ts +305 -0
- package/src/internal/testing/harness.ts +328 -0
- package/src/internal/testing/http.ts +395 -0
- package/src/internal/testing/types.ts +240 -0
- package/src/internal/testing/wait.ts +63 -0
- package/src/internal/thread-events.ts +128 -0
- package/src/internal/threads.ts +718 -0
- package/src/internal/transfer-source.ts +359 -0
- package/src/internal/transport/http.ts +46 -0
- package/src/internal/transport/index.ts +23 -0
- package/src/internal/transport/socket.ts +71 -0
- package/src/internal/transport/user-agent.ts +46 -0
- package/src/internal/uploads.ts +111 -0
- package/src/internal/user-cache.ts +294 -0
- package/src/internal/users.ts +402 -0
- package/src/internal/vanity-url.ts +80 -0
- package/src/internal/webhooks.ts +690 -0
- package/src/invites.ts +87 -0
- package/src/logging.ts +247 -0
- package/src/member-chunks.ts +195 -0
- package/src/member-search.ts +152 -0
- package/src/message-cleanup.ts +308 -0
- package/src/message-errors.ts +245 -0
- package/src/message-search.ts +213 -0
- package/src/messages.ts +768 -0
- package/src/native-commands.ts +1249 -0
- package/src/native-supervisor.ts +345 -0
- package/src/oauth.ts +413 -0
- package/src/observer.ts +118 -0
- package/src/pagination.ts +172 -0
- package/src/permissions.ts +74 -0
- package/src/pins.ts +65 -0
- package/src/presence.ts +124 -0
- package/src/reaction-pages.ts +106 -0
- package/src/reactions.ts +126 -0
- package/src/rest.ts +282 -0
- package/src/role-hierarchy.ts +127 -0
- package/src/sharding.ts +272 -0
- package/src/supervisor.ts +460 -0
- package/src/testing.ts +424 -0
- package/src/text.ts +76 -0
- package/src/threads.ts +274 -0
- package/src/users.ts +237 -0
- package/src/webhooks.ts +512 -0
|
@@ -0,0 +1,1828 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One client's REST owner: Request validation per operation group, instance resolution, uploads, bounded read retries,
|
|
3
|
+
* rate-limit waits and cache guards around each operation.
|
|
4
|
+
* Invariant: Every operation registers its cache guards before discovery and queue or rate waits, releases upload
|
|
5
|
+
* reservations and transfer sources however it ends, and no rate-limit learning crosses REST owners, credentials or
|
|
6
|
+
* instance selections. Reads retry only under the bounded read policy, and mutations retry only after a confirmed
|
|
7
|
+
* rate-limit rejection. Implements
|
|
8
|
+
* [SDK contracts: Delivery, requests and caches](/docs/SDK-CONTRACTS.md#delivery-requests-and-caches)
|
|
9
|
+
*/
|
|
10
|
+
import { randomUUID } from "node:crypto"
|
|
11
|
+
import * as Cause from "effect/Cause"
|
|
12
|
+
import * as Clock from "effect/Clock"
|
|
13
|
+
import * as Deferred from "effect/Deferred"
|
|
14
|
+
import * as Effect from "effect/Effect"
|
|
15
|
+
import * as Exit from "effect/Exit"
|
|
16
|
+
import * as Random from "effect/Random"
|
|
17
|
+
import type * as Redacted from "effect/Redacted"
|
|
18
|
+
import { ClientClosedError } from "#sdk/errors"
|
|
19
|
+
import { responseFieldText } from "#sdk/api-errors"
|
|
20
|
+
import { MessageError, MessageOperationError, type MessageOperationFailure, type SendError } from "#sdk/message-errors"
|
|
21
|
+
import { InputValidationFailure, unsupportedKeyFailure } from "#sdk/input-validation"
|
|
22
|
+
import type {
|
|
23
|
+
EditMessageInput,
|
|
24
|
+
ForwardMessageInput,
|
|
25
|
+
Message,
|
|
26
|
+
MessageCore,
|
|
27
|
+
MessageInput,
|
|
28
|
+
MessageHistoryQuery,
|
|
29
|
+
MessageOperationOptions,
|
|
30
|
+
MessageAuditOperationOptions,
|
|
31
|
+
MessageReference,
|
|
32
|
+
SendOptions,
|
|
33
|
+
} from "#sdk/messages"
|
|
34
|
+
import type {
|
|
35
|
+
Attachment,
|
|
36
|
+
AttachmentDownloadFailure,
|
|
37
|
+
AttachmentDownloadOptions,
|
|
38
|
+
AttachmentRefreshFailure,
|
|
39
|
+
AttachmentRefreshOptions,
|
|
40
|
+
RefreshedAttachmentUrl,
|
|
41
|
+
} from "#sdk/attachments"
|
|
42
|
+
import { AttachmentRefreshError } from "#sdk/attachments"
|
|
43
|
+
import type { ReactionEmojiInput, ReactionUsersQuery, ReactionUsersPage } from "#sdk/reactions"
|
|
44
|
+
import type { MessagePinsPage, MessagePinsQuery } from "#sdk/pins"
|
|
45
|
+
import type { MessageSearchContext, MessageSearchPage, MessageSearchQuery } from "#sdk/message-search"
|
|
46
|
+
import { GuildOperationError, type GuildOperation, type GuildOperationOptions } from "#sdk/guilds"
|
|
47
|
+
import { ChannelOperationError, type ChannelOperation, type ChannelOperationOptions } from "#sdk/channels"
|
|
48
|
+
import { WebhookOperationError, type WebhookOperation, type WebhookOperationOptions } from "#sdk/webhooks"
|
|
49
|
+
import { UserOperationError, type UserOperation, type UserOperationOptions } from "#sdk/users"
|
|
50
|
+
import {
|
|
51
|
+
BotApplicationOperationError,
|
|
52
|
+
type BotApplicationOperation,
|
|
53
|
+
type BotApplicationOperationOptions,
|
|
54
|
+
} from "#sdk/application"
|
|
55
|
+
import { identifier, record, snapshotArray } from "../decode/primitives.js"
|
|
56
|
+
import { failingFieldPath } from "../decode/trace.js"
|
|
57
|
+
import { inputDefect, suspendInput } from "../defects.js"
|
|
58
|
+
import { mapFailureCause, withDeadline } from "../effect-failures.js"
|
|
59
|
+
import {
|
|
60
|
+
decodeCrosspostSource,
|
|
61
|
+
encodeEdit,
|
|
62
|
+
encodeForward,
|
|
63
|
+
encodeHistory,
|
|
64
|
+
encodeMessage,
|
|
65
|
+
snapshotReference,
|
|
66
|
+
} from "../message.js"
|
|
67
|
+
import type { MessageDecoder } from "../message-fields.js"
|
|
68
|
+
import type { MessageCache, CacheRequest } from "../cache.js"
|
|
69
|
+
import type { EncodedBody } from "../attachments.js"
|
|
70
|
+
import { decodeUploadPlans, type UploadPlan } from "../uploads.js"
|
|
71
|
+
import { readResponseJson } from "../response-json.js"
|
|
72
|
+
import { AttachmentTransferSource } from "../transfer-source.js"
|
|
73
|
+
import type { InstanceEndpointContext } from "../instance.js"
|
|
74
|
+
import { encodeReactionEmoji, encodeReactionUsersQuery, decodeReactionUsersPage } from "../reactions.js"
|
|
75
|
+
import { decodePinsPage, encodePinsQuery } from "../pins.js"
|
|
76
|
+
import { decodeMessageSearchPage, encodeMessageSearch } from "../message-search.js"
|
|
77
|
+
import type { GuildRequest } from "../guilds.js"
|
|
78
|
+
import type { GuildCache } from "../guild-cache.js"
|
|
79
|
+
import type { ChannelRequest } from "../channels.js"
|
|
80
|
+
import type { ChannelCache } from "../channel-cache.js"
|
|
81
|
+
import { auditSettings } from "../audit.js"
|
|
82
|
+
import type { WebhookRequest } from "../webhooks.js"
|
|
83
|
+
import type { UserRequest } from "../users.js"
|
|
84
|
+
import { directMessageOpen } from "../users.js"
|
|
85
|
+
import type { UserCache } from "../user-cache.js"
|
|
86
|
+
import type { BotApplicationRequest } from "../application.js"
|
|
87
|
+
import { attachmentRefresh } from "../attachment-refresh.js"
|
|
88
|
+
import type { ClientLogger } from "../logging.js"
|
|
89
|
+
import type { LogicalScheduler } from "../logical-scheduler.js"
|
|
90
|
+
import { metrics } from "../metrics.js"
|
|
91
|
+
import { emitObservation } from "../observer.js"
|
|
92
|
+
import { linkRejectionError } from "../rejection-scope.js"
|
|
93
|
+
import { rateRoute, routeTemplate } from "../rate-limits.js"
|
|
94
|
+
import { defaultHttpTransport, type HttpTransport } from "../transport/index.js"
|
|
95
|
+
import { RestAdmission } from "./admission.js"
|
|
96
|
+
import { defaultRestConfiguration, type RestConfiguration } from "./options.js"
|
|
97
|
+
import {
|
|
98
|
+
RestRequestError,
|
|
99
|
+
type DefaultRestRequest,
|
|
100
|
+
type RestRequest,
|
|
101
|
+
type RestRequestFailure,
|
|
102
|
+
type RestResponse,
|
|
103
|
+
} from "#sdk/rest"
|
|
104
|
+
import { completeCleanup, runAttempt, type Request } from "./attempt.js"
|
|
105
|
+
import { encodeRestRequest, readRestResponse } from "./request.js"
|
|
106
|
+
import {
|
|
107
|
+
inputFailure,
|
|
108
|
+
instanceFailure,
|
|
109
|
+
localInputFailure,
|
|
110
|
+
operationFailure,
|
|
111
|
+
RestFailure,
|
|
112
|
+
type Outcome,
|
|
113
|
+
} from "./classify.js"
|
|
114
|
+
import {
|
|
115
|
+
UnobservedDownloadDefects,
|
|
116
|
+
downloadAttachment,
|
|
117
|
+
openAttachmentStream,
|
|
118
|
+
type AttachmentDownloadSource,
|
|
119
|
+
} from "./download.js"
|
|
120
|
+
|
|
121
|
+
/** Longest single timer delay, and the largest accepted timeoutMs */
|
|
122
|
+
const maximumTimerMs = 2_147_483_647
|
|
123
|
+
/** Bounded retries for a GET after a transient failure */
|
|
124
|
+
const maximumReadRetries = 2
|
|
125
|
+
/** Minimum backoff before the first and later read retries, before jitter */
|
|
126
|
+
const firstReadRetryMs = 125
|
|
127
|
+
const laterReadRetryMs = 250
|
|
128
|
+
/** Rate-limit waits of at least this long are logged at Warn */
|
|
129
|
+
const longRateLimitWaitMs = 1_000
|
|
130
|
+
/** Largest upload-planning and upload-completion response */
|
|
131
|
+
const uploadResponseMaxBytes = 1_048_576
|
|
132
|
+
/** Least time between two rest.busy Warn records of one client */
|
|
133
|
+
const busyWarnIntervalMs = 60_000
|
|
134
|
+
|
|
135
|
+
/** Construction settings for one REST owner */
|
|
136
|
+
export interface RestOwnerOptions<M extends MessageCore> {
|
|
137
|
+
/** Message cache coordinated with message reads and writes, when enabled */
|
|
138
|
+
readonly cache?: MessageCache<M> | undefined
|
|
139
|
+
/** Total bytes of attachment files that may be reserved by running operations */
|
|
140
|
+
readonly uploadMaxBytes: number
|
|
141
|
+
readonly resources?: GuildCache | undefined
|
|
142
|
+
readonly channels?: ChannelCache | undefined
|
|
143
|
+
readonly users?: UserCache | undefined
|
|
144
|
+
/** The owner's instance resolver. The first successful result is kept for the owner's lifetime */
|
|
145
|
+
readonly resolveInstance: () => Effect.Effect<InstanceEndpointContext, unknown>
|
|
146
|
+
readonly decodeMessage: MessageDecoder<M>
|
|
147
|
+
readonly logical: LogicalScheduler
|
|
148
|
+
readonly logging?: ClientLogger | undefined
|
|
149
|
+
/** HTTP transport, defaulting to the platform fetch */
|
|
150
|
+
readonly http?: HttpTransport | undefined
|
|
151
|
+
/** Scheduling limits and default deadline, defaulting to the built-in limits */
|
|
152
|
+
readonly settings?: RestConfiguration | undefined
|
|
153
|
+
/** Passes a global pause learned from Fluxer to a supervisor's other children, in milliseconds from now */
|
|
154
|
+
readonly shareGlobalPause?: ((waitMs: number) => void) | undefined
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Mutable state shared by one owner's operations, attempts and downloads */
|
|
158
|
+
export class RestRuntime<M extends MessageCore> {
|
|
159
|
+
/** Set by stop. No operation starts or continues its request after closure */
|
|
160
|
+
closed = false
|
|
161
|
+
/** The owner's resolved instance, kept after the first successful discovery */
|
|
162
|
+
instance: InstanceEndpointContext | undefined
|
|
163
|
+
/** Attachment file bytes reserved by running operations */
|
|
164
|
+
uploadBytes = 0
|
|
165
|
+
/** Stream cleanup failures that no caller observed, surfaced by shutdown */
|
|
166
|
+
readonly unobservedDownloadDefects = new UnobservedDownloadDefects()
|
|
167
|
+
readonly controllers = new Set<AbortController>()
|
|
168
|
+
readonly downloads = new Set<AttachmentDownloadSource>()
|
|
169
|
+
/** Completion signals for every running operation, awaited by shutdown */
|
|
170
|
+
readonly operations = new Set<Deferred.Deferred<void>>()
|
|
171
|
+
readonly admission: RestAdmission
|
|
172
|
+
readonly http: HttpTransport
|
|
173
|
+
/** Scheduling limits and the default deadline for operations and downloads that omit timeoutMs */
|
|
174
|
+
readonly settings: RestConfiguration
|
|
175
|
+
readonly cache: MessageCache<M> | undefined
|
|
176
|
+
readonly resources: GuildCache | undefined
|
|
177
|
+
readonly channels: ChannelCache | undefined
|
|
178
|
+
readonly users: UserCache | undefined
|
|
179
|
+
readonly logical: LogicalScheduler
|
|
180
|
+
readonly logging: ClientLogger | undefined
|
|
181
|
+
readonly resolveInstance: () => Effect.Effect<InstanceEndpointContext, unknown>
|
|
182
|
+
|
|
183
|
+
/** Logical time of the last rest.busy Warn, repeated at most once per busyWarnIntervalMs */
|
|
184
|
+
#busyWarnedAt: number | undefined
|
|
185
|
+
/**
|
|
186
|
+
* Logical time of the last ratelimit.deadline Warn for requests refused before dispatch, per route template.
|
|
187
|
+
* Each new Warn first removes entries older than busyWarnIntervalMs, which no longer hold back a Warn, so the map
|
|
188
|
+
* holds only routes warned within one interval of the latest Warn
|
|
189
|
+
*/
|
|
190
|
+
readonly deadlineWarnedAt = new Map<string, number>()
|
|
191
|
+
|
|
192
|
+
constructor(options: RestOwnerOptions<M>) {
|
|
193
|
+
this.settings = options.settings ?? defaultRestConfiguration
|
|
194
|
+
this.admission = new RestAdmission(
|
|
195
|
+
options.logical,
|
|
196
|
+
this.settings,
|
|
197
|
+
() => this.busy("queue"),
|
|
198
|
+
options.shareGlobalPause,
|
|
199
|
+
)
|
|
200
|
+
this.http = options.http ?? defaultHttpTransport
|
|
201
|
+
this.cache = options.cache
|
|
202
|
+
this.resources = options.resources
|
|
203
|
+
this.channels = options.channels
|
|
204
|
+
this.users = options.users
|
|
205
|
+
this.logical = options.logical
|
|
206
|
+
this.logging = options.logging
|
|
207
|
+
this.resolveInstance = options.resolveInstance
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Count a request that failed with busy, and warn at most once a minute that a REST budget is full, naming the full
|
|
212
|
+
* budget. Busy failures are returned to the caller, so the Warn exists only to make a saturated client visible
|
|
213
|
+
*/
|
|
214
|
+
busy(budget: "queue" | "uploads") {
|
|
215
|
+
this.logging?.count("restBusy")
|
|
216
|
+
const now = this.logical.now()
|
|
217
|
+
if (this.#busyWarnedAt !== undefined && now - this.#busyWarnedAt < busyWarnIntervalMs) return
|
|
218
|
+
this.#busyWarnedAt = now
|
|
219
|
+
const queue = this.admission.diagnostics()
|
|
220
|
+
const full =
|
|
221
|
+
budget === "uploads"
|
|
222
|
+
? "attachments reserved by running uploads reached uploads.maxBytes"
|
|
223
|
+
: queue.queuedRequests >= queue.queuedCapacity
|
|
224
|
+
? `${queue.queuedRequests} requests already wait for a slot (rest.maxQueued)`
|
|
225
|
+
: "the bodies of waiting requests reached rest.queuedJsonMaxBytes"
|
|
226
|
+
this.logging?.log({
|
|
227
|
+
level: "warn",
|
|
228
|
+
category: "rest",
|
|
229
|
+
code: "rest.busy",
|
|
230
|
+
message: `The REST queue is full because ${full}, so new requests fail with reason busy until it drains. Send fewer requests at once, or raise that limit. Further busy failures within a minute are counted in diagnostics().counters.restBusy without another record`,
|
|
231
|
+
fields: {
|
|
232
|
+
budget,
|
|
233
|
+
activeRequests: queue.activeRequests,
|
|
234
|
+
queuedRequests: queue.queuedRequests,
|
|
235
|
+
queuedCapacity: queue.queuedCapacity,
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function readMessage<M extends MessageCore>(
|
|
242
|
+
response: Response,
|
|
243
|
+
channel: string,
|
|
244
|
+
id: string | undefined,
|
|
245
|
+
signal: AbortSignal | undefined,
|
|
246
|
+
decode: MessageDecoder<M>,
|
|
247
|
+
): Promise<M> {
|
|
248
|
+
const decoded = await readDecoded(response, signal, decode)
|
|
249
|
+
if (decoded.channelId !== channel) throw responseFailure(response, "channelMismatch")
|
|
250
|
+
if (id !== undefined && decoded.id !== id) throw responseFailure(response, "idMismatch")
|
|
251
|
+
return decoded
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function readHistory<M extends MessageCore>(
|
|
255
|
+
response: Response,
|
|
256
|
+
channel: string,
|
|
257
|
+
query: { readonly limit: number; readonly params: URLSearchParams },
|
|
258
|
+
signal: AbortSignal,
|
|
259
|
+
decode: MessageDecoder<M>,
|
|
260
|
+
) {
|
|
261
|
+
const body: unknown = await readResponseJson(response, undefined, signal)
|
|
262
|
+
const invalid = (field: string) => responseFailure(response, field)
|
|
263
|
+
if (!Array.isArray(body)) throw invalid("body")
|
|
264
|
+
if (body.length > query.limit) throw invalid("tooMany")
|
|
265
|
+
const messages: M[] = []
|
|
266
|
+
const before = query.params.get("before")
|
|
267
|
+
const after = query.params.get("after")
|
|
268
|
+
let previous: bigint | undefined
|
|
269
|
+
for (const [index, item] of body.entries()) {
|
|
270
|
+
const message = decode(item)
|
|
271
|
+
if (!message) throw invalid(`${index}.${failingFieldPath(decode, item) ?? "message"}`)
|
|
272
|
+
if (message.channelId !== channel) throw invalid("channelMismatch")
|
|
273
|
+
const id = BigInt(message.id)
|
|
274
|
+
if (
|
|
275
|
+
(previous !== undefined && id >= previous) ||
|
|
276
|
+
(before !== null && id >= BigInt(before)) ||
|
|
277
|
+
(after !== null && id <= BigInt(after))
|
|
278
|
+
)
|
|
279
|
+
throw invalid("order")
|
|
280
|
+
previous = id
|
|
281
|
+
messages.push(message)
|
|
282
|
+
}
|
|
283
|
+
return Object.freeze(messages)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** A response failure for a decoded value that did not match the operation's expected shape. The field names the
|
|
287
|
+
* response field path or check that failed, never a value
|
|
288
|
+
*/
|
|
289
|
+
const responseFailure = (response: Response, field?: string) =>
|
|
290
|
+
new RestFailure({ reason: "response", outcome: "unknown", status: response.status, responseField: field ?? null })
|
|
291
|
+
|
|
292
|
+
/** Read and decode a JSON response with a pure decoder, failing with the field where the decoder stopped */
|
|
293
|
+
async function readDecoded<A>(
|
|
294
|
+
response: Response,
|
|
295
|
+
signal: AbortSignal | undefined,
|
|
296
|
+
decode: (value: unknown) => A | undefined,
|
|
297
|
+
): Promise<A> {
|
|
298
|
+
const value: unknown = await readResponseJson(response, undefined, signal)
|
|
299
|
+
const decoded = decode(value)
|
|
300
|
+
if (decoded === undefined) throw responseFailure(response, failingFieldPath(decode, value))
|
|
301
|
+
return decoded
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Read operation options and their requested deadline once. Only an application getter or proxy can throw here */
|
|
305
|
+
function deadlineOption(options: unknown): { readonly valid: boolean; readonly timeoutMs: unknown } {
|
|
306
|
+
if (options !== undefined && !record(options)) return { valid: false, timeoutMs: undefined }
|
|
307
|
+
return { valid: true, timeoutMs: options?.timeoutMs }
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Options every REST operation accepts. The Effect API has no signal, but accepting it keeps both APIs' checks equal */
|
|
311
|
+
const operationOptionKeys: readonly string[] = ["timeoutMs", "signal"]
|
|
312
|
+
|
|
313
|
+
/** Reject the first options key outside keys, naming it with the closest supported key */
|
|
314
|
+
function unsupportedOptionFailure(options: unknown, keys: readonly string[]): RestFailure | undefined {
|
|
315
|
+
const unsupported = record(options)
|
|
316
|
+
? unsupportedKeyFailure(options, keys, "options", "the operation options")
|
|
317
|
+
: undefined
|
|
318
|
+
return unsupported && inputFailure(unsupported.detail)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Reject options that are not an object or contain fields other than timeoutMs and signal */
|
|
322
|
+
function timeoutOptionsFailure(options: unknown): RestFailure | undefined {
|
|
323
|
+
if (options !== undefined && !record(options))
|
|
324
|
+
return localInputFailure("options", "type", "the operation options must be an object")
|
|
325
|
+
return unsupportedOptionFailure(options, operationOptionKeys)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/** How one operation is scheduled through repeated attempts */
|
|
329
|
+
interface ExchangeOptions<A> {
|
|
330
|
+
readonly request: Request<A>
|
|
331
|
+
readonly progress: { outcome: Outcome }
|
|
332
|
+
readonly generation: number
|
|
333
|
+
/** Logical deadline for the whole operation */
|
|
334
|
+
readonly deadline: number
|
|
335
|
+
/** Extra queued bytes charged while waiting, such as retained upload plans */
|
|
336
|
+
readonly retainedBytes?: number
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** One client's transient REST scheduler, without shared-token coordination or durable delivery */
|
|
340
|
+
export class RestOwner<M extends MessageCore = Message> {
|
|
341
|
+
readonly #runtime: RestRuntime<M>
|
|
342
|
+
readonly #uploadMaxBytes: number
|
|
343
|
+
readonly #decodeMessage: MessageDecoder<M>
|
|
344
|
+
|
|
345
|
+
constructor(options: RestOwnerOptions<M>) {
|
|
346
|
+
this.#runtime = new RestRuntime(options)
|
|
347
|
+
this.#uploadMaxBytes = options.uploadMaxBytes
|
|
348
|
+
this.#decodeMessage = options.decodeMessage
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** The client's default operation deadline in milliseconds, from rest.defaultTimeoutMs */
|
|
352
|
+
get defaultTimeoutMs(): number {
|
|
353
|
+
return this.#runtime.settings.defaultTimeoutMs
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** Size the default API request slots for the client's local shard count */
|
|
357
|
+
scaleConcurrency(localShards: number) {
|
|
358
|
+
this.#runtime.admission.scaleConcurrency(localShards)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Apply a global pause another process learned, lasting waitMs from now, without sharing it again */
|
|
362
|
+
pauseGlobal(waitMs: number) {
|
|
363
|
+
this.#runtime.admission.pauseGlobal(this.#runtime.logical.now() + waitMs, true)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** Completion signals of the operations and downloads running now, queued ones included, for a draining shutdown */
|
|
367
|
+
inFlight(): readonly Deferred.Deferred<void>[] {
|
|
368
|
+
return [...this.#runtime.operations]
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
diagnostics() {
|
|
372
|
+
return {
|
|
373
|
+
...this.#runtime.admission.diagnostics(),
|
|
374
|
+
reservedUploadBytes: this.#runtime.uploadBytes,
|
|
375
|
+
uploadByteCapacity: this.#uploadMaxBytes,
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
refreshAttachmentUrls(
|
|
380
|
+
token: Redacted.Redacted<string>,
|
|
381
|
+
urls: readonly string[],
|
|
382
|
+
options?: AttachmentRefreshOptions,
|
|
383
|
+
): Effect.Effect<readonly RefreshedAttachmentUrl[], AttachmentRefreshFailure> {
|
|
384
|
+
return suspendInput((): Effect.Effect<readonly RefreshedAttachmentUrl[], RestFailure | ClientClosedError> => {
|
|
385
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
386
|
+
const input = attachmentRefresh(urls)
|
|
387
|
+
if (input instanceof InputValidationFailure) return Effect.fail(inputFailure(input.detail))
|
|
388
|
+
const invalid = timeoutOptionsFailure(options)
|
|
389
|
+
if (invalid) return Effect.fail(invalid)
|
|
390
|
+
return this.#execute(
|
|
391
|
+
token,
|
|
392
|
+
{
|
|
393
|
+
channel: "attachments",
|
|
394
|
+
bucket: "attachments:refresh",
|
|
395
|
+
cache: false,
|
|
396
|
+
path: input.path,
|
|
397
|
+
method: input.method,
|
|
398
|
+
status: input.status,
|
|
399
|
+
body: { json: input.json, files: [] },
|
|
400
|
+
decode: async (response, _instance, signal) => {
|
|
401
|
+
return readDecoded(response, signal, (value) => input.decode(value))
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
options,
|
|
405
|
+
)
|
|
406
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, AttachmentRefreshError, "attachments.refreshUrls")))
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
openDownload(
|
|
410
|
+
attachment: Attachment,
|
|
411
|
+
options?: AttachmentDownloadOptions,
|
|
412
|
+
): Effect.Effect<AttachmentDownloadSource, AttachmentDownloadFailure> {
|
|
413
|
+
return openAttachmentStream(this.#runtime, attachment, options)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
download(
|
|
417
|
+
attachment: Attachment,
|
|
418
|
+
options?: AttachmentDownloadOptions,
|
|
419
|
+
): Effect.Effect<Uint8Array, AttachmentDownloadFailure> {
|
|
420
|
+
return downloadAttachment(this.#runtime, attachment, options)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
reply(
|
|
424
|
+
token: Redacted.Redacted<string>,
|
|
425
|
+
target: MessageReference,
|
|
426
|
+
input: MessageInput | string,
|
|
427
|
+
options?: SendOptions,
|
|
428
|
+
) {
|
|
429
|
+
return this.#send(
|
|
430
|
+
token,
|
|
431
|
+
target.channelId,
|
|
432
|
+
() => encodeMessage(target.channelId, input, randomUUID().replaceAll("-", ""), target),
|
|
433
|
+
options,
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
send(
|
|
438
|
+
token: Redacted.Redacted<string>,
|
|
439
|
+
channel: string,
|
|
440
|
+
input: MessageInput | string,
|
|
441
|
+
options?: SendOptions,
|
|
442
|
+
directMessageUser?: string,
|
|
443
|
+
): Effect.Effect<M, SendError> {
|
|
444
|
+
return this.#send(
|
|
445
|
+
token,
|
|
446
|
+
channel,
|
|
447
|
+
() =>
|
|
448
|
+
encodeMessage(
|
|
449
|
+
channel,
|
|
450
|
+
input,
|
|
451
|
+
randomUUID().replaceAll("-", ""),
|
|
452
|
+
undefined,
|
|
453
|
+
directMessageUser !== undefined,
|
|
454
|
+
),
|
|
455
|
+
options,
|
|
456
|
+
directMessageUser,
|
|
457
|
+
)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
forward(token: Redacted.Redacted<string>, channel: string, input: ForwardMessageInput, options?: SendOptions) {
|
|
461
|
+
return this.#send(
|
|
462
|
+
token,
|
|
463
|
+
channel,
|
|
464
|
+
() => encodeForward(channel, input, randomUUID().replaceAll("-", "")),
|
|
465
|
+
options,
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
#send(
|
|
470
|
+
token: Redacted.Redacted<string>,
|
|
471
|
+
channel: string,
|
|
472
|
+
encode: () => EncodedBody | MessageError,
|
|
473
|
+
options?: SendOptions,
|
|
474
|
+
directMessageUser?: string,
|
|
475
|
+
): Effect.Effect<M, SendError> {
|
|
476
|
+
return suspendInput((): Effect.Effect<M, SendError> => {
|
|
477
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
478
|
+
const body = encode()
|
|
479
|
+
if (body instanceof MessageError) return Effect.fail(body)
|
|
480
|
+
return this.#execute(
|
|
481
|
+
token,
|
|
482
|
+
{
|
|
483
|
+
method: "POST",
|
|
484
|
+
channel,
|
|
485
|
+
body,
|
|
486
|
+
path: `/channels/${channel}/messages`,
|
|
487
|
+
...(directMessageUser === undefined ? {} : { directMessageUser }),
|
|
488
|
+
decodeDirectMessage: (response, channelId, signal) =>
|
|
489
|
+
readMessage(response, channelId, undefined, signal, this.#decodeMessage),
|
|
490
|
+
observe: (message, guard) => this.#runtime.cache!.complete(guard, [message]),
|
|
491
|
+
decode: (response, _instance, signal) =>
|
|
492
|
+
readMessage(response, channel, undefined, signal, this.#decodeMessage),
|
|
493
|
+
},
|
|
494
|
+
options,
|
|
495
|
+
).pipe(
|
|
496
|
+
mapFailureCause((error) =>
|
|
497
|
+
error instanceof RestFailure
|
|
498
|
+
? linkRejectionError(
|
|
499
|
+
new MessageError({
|
|
500
|
+
reason: error.reason === "notFound" ? "rejected" : error.reason,
|
|
501
|
+
outcome: error.outcome,
|
|
502
|
+
status: error.status,
|
|
503
|
+
retryAfterMs: error.retryAfterMs,
|
|
504
|
+
apiError: error.apiError,
|
|
505
|
+
inputValidation: error.inputValidation,
|
|
506
|
+
providerCode: error.providerCode,
|
|
507
|
+
responseField: error.responseField,
|
|
508
|
+
// Keep the transport failure visible, as the other operation errors do
|
|
509
|
+
...(error.cause === undefined ? {} : { cause: error.cause }),
|
|
510
|
+
}),
|
|
511
|
+
error,
|
|
512
|
+
)
|
|
513
|
+
: error,
|
|
514
|
+
),
|
|
515
|
+
)
|
|
516
|
+
})
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
fetch(token: Redacted.Redacted<string>, target: MessageReference, options?: MessageOperationOptions) {
|
|
520
|
+
return this.#manage(
|
|
521
|
+
token,
|
|
522
|
+
"fetch",
|
|
523
|
+
target,
|
|
524
|
+
undefined,
|
|
525
|
+
options,
|
|
526
|
+
(response, ref, signal) => readMessage(response, ref.channelId, ref.id, signal, this.#decodeMessage),
|
|
527
|
+
(message, guard) => this.#runtime.cache!.complete(guard, [message]),
|
|
528
|
+
)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
publish(token: Redacted.Redacted<string>, target: MessageReference, options?: MessageOperationOptions) {
|
|
532
|
+
return this.#manage(
|
|
533
|
+
token,
|
|
534
|
+
"publish",
|
|
535
|
+
target,
|
|
536
|
+
undefined,
|
|
537
|
+
options,
|
|
538
|
+
(response, ref, signal) => readMessage(response, ref.channelId, ref.id, signal, this.#decodeMessage),
|
|
539
|
+
(message, guard) => this.#runtime.cache!.complete(guard, [message]),
|
|
540
|
+
)
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
fetchCrosspostSource(
|
|
544
|
+
token: Redacted.Redacted<string>,
|
|
545
|
+
target: MessageReference,
|
|
546
|
+
options?: MessageOperationOptions,
|
|
547
|
+
) {
|
|
548
|
+
return this.#manage(token, "fetchCrosspostSource", target, undefined, options, (response, _ref, signal) =>
|
|
549
|
+
readDecoded(response, signal, decodeCrosspostSource),
|
|
550
|
+
)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
typing(
|
|
554
|
+
token: Redacted.Redacted<string>,
|
|
555
|
+
channel: string,
|
|
556
|
+
options?: MessageOperationOptions,
|
|
557
|
+
): Effect.Effect<void, MessageOperationFailure> {
|
|
558
|
+
return suspendInput((): Effect.Effect<void, RestFailure | ClientClosedError> => {
|
|
559
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
560
|
+
if (!identifier(channel))
|
|
561
|
+
return Effect.fail(localInputFailure("channelId", "format", "Channel IDs must be decimal strings"))
|
|
562
|
+
const invalid = timeoutOptionsFailure(options)
|
|
563
|
+
if (invalid) return Effect.fail(invalid)
|
|
564
|
+
return this.#execute(
|
|
565
|
+
token,
|
|
566
|
+
{
|
|
567
|
+
method: "POST",
|
|
568
|
+
channel,
|
|
569
|
+
bucket: "typing",
|
|
570
|
+
cache: false,
|
|
571
|
+
path: `/channels/${channel}/typing`,
|
|
572
|
+
body: undefined,
|
|
573
|
+
status: 204,
|
|
574
|
+
decode: async () => {},
|
|
575
|
+
},
|
|
576
|
+
options,
|
|
577
|
+
)
|
|
578
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "typing")))
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
fetchHistory(
|
|
582
|
+
token: Redacted.Redacted<string>,
|
|
583
|
+
channel: string,
|
|
584
|
+
query?: MessageHistoryQuery,
|
|
585
|
+
options?: MessageOperationOptions,
|
|
586
|
+
): Effect.Effect<readonly M[], MessageOperationFailure> {
|
|
587
|
+
return suspendInput((): Effect.Effect<readonly M[], RestFailure | ClientClosedError> => {
|
|
588
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
589
|
+
const encoded = encodeHistory(channel, query)
|
|
590
|
+
if (encoded instanceof InputValidationFailure) return Effect.fail(inputFailure(encoded.detail))
|
|
591
|
+
return this.#execute(
|
|
592
|
+
token,
|
|
593
|
+
{
|
|
594
|
+
method: "GET",
|
|
595
|
+
channel,
|
|
596
|
+
bucket: "history",
|
|
597
|
+
path: `/channels/${channel}/messages?${encoded.params}`,
|
|
598
|
+
body: undefined,
|
|
599
|
+
status: 200,
|
|
600
|
+
decode: (response, _instance, signal) =>
|
|
601
|
+
readHistory(response, channel, encoded, signal, this.#decodeMessage),
|
|
602
|
+
observe: (messages, guard) => this.#runtime.cache!.complete(guard, messages),
|
|
603
|
+
},
|
|
604
|
+
options,
|
|
605
|
+
)
|
|
606
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "fetchHistory")))
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
search(
|
|
610
|
+
token: Redacted.Redacted<string>,
|
|
611
|
+
context: MessageSearchContext,
|
|
612
|
+
query?: MessageSearchQuery,
|
|
613
|
+
options?: MessageOperationOptions,
|
|
614
|
+
): Effect.Effect<MessageSearchPage<M>, MessageOperationFailure> {
|
|
615
|
+
return suspendInput((): Effect.Effect<MessageSearchPage<M>, RestFailure | ClientClosedError> => {
|
|
616
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
617
|
+
const encoded = encodeMessageSearch(context, query)
|
|
618
|
+
if (encoded instanceof InputValidationFailure) return Effect.fail(inputFailure(encoded.detail))
|
|
619
|
+
return this.#execute(
|
|
620
|
+
token,
|
|
621
|
+
{
|
|
622
|
+
method: "POST",
|
|
623
|
+
channel: encoded.context.channelId ?? encoded.context.guildId!,
|
|
624
|
+
bucket: "search",
|
|
625
|
+
cache: false,
|
|
626
|
+
path: "/search/messages",
|
|
627
|
+
body: { json: encoded.json, files: [] },
|
|
628
|
+
status: 200,
|
|
629
|
+
decode: async (response, _instance, signal) => {
|
|
630
|
+
return readDecoded(response, signal, (value) =>
|
|
631
|
+
decodeMessageSearchPage(value, this.#decodeMessage),
|
|
632
|
+
)
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
options,
|
|
636
|
+
)
|
|
637
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "search")))
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
edit(
|
|
641
|
+
token: Redacted.Redacted<string>,
|
|
642
|
+
target: MessageReference,
|
|
643
|
+
input: EditMessageInput | string,
|
|
644
|
+
options?: MessageOperationOptions,
|
|
645
|
+
) {
|
|
646
|
+
return this.#manage(
|
|
647
|
+
token,
|
|
648
|
+
"edit",
|
|
649
|
+
target,
|
|
650
|
+
input,
|
|
651
|
+
options,
|
|
652
|
+
(response, ref, signal) => readMessage(response, ref.channelId, ref.id, signal, this.#decodeMessage),
|
|
653
|
+
(message, guard) => this.#runtime.cache!.complete(guard, [message]),
|
|
654
|
+
)
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
delete(token: Redacted.Redacted<string>, target: MessageReference, options?: MessageAuditOperationOptions) {
|
|
658
|
+
return this.#manage(token, "delete", target, undefined, options, async () => {})
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
deleteAttachment(
|
|
662
|
+
token: Redacted.Redacted<string>,
|
|
663
|
+
target: MessageReference,
|
|
664
|
+
attachmentId: string,
|
|
665
|
+
options?: MessageOperationOptions,
|
|
666
|
+
): Effect.Effect<void, MessageOperationFailure> {
|
|
667
|
+
return suspendInput((): Effect.Effect<void, RestFailure | ClientClosedError> => {
|
|
668
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
669
|
+
const ref = snapshotReference(target)
|
|
670
|
+
if (ref === undefined)
|
|
671
|
+
return Effect.fail(
|
|
672
|
+
localInputFailure("target", "format", "Message targets require decimal id and channelId strings"),
|
|
673
|
+
)
|
|
674
|
+
if (!identifier(attachmentId))
|
|
675
|
+
return Effect.fail(
|
|
676
|
+
localInputFailure("attachmentId", "format", "Attachment IDs must be decimal strings"),
|
|
677
|
+
)
|
|
678
|
+
return this.#execute(
|
|
679
|
+
token,
|
|
680
|
+
{
|
|
681
|
+
method: "DELETE",
|
|
682
|
+
channel: ref.channelId,
|
|
683
|
+
target: ref.id,
|
|
684
|
+
path: `/channels/${ref.channelId}/messages/${ref.id}/attachments/${attachmentId}`,
|
|
685
|
+
body: undefined,
|
|
686
|
+
status: 204,
|
|
687
|
+
decode: async () => {},
|
|
688
|
+
},
|
|
689
|
+
options,
|
|
690
|
+
)
|
|
691
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "deleteAttachment")))
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
deleteMany(
|
|
695
|
+
token: Redacted.Redacted<string>,
|
|
696
|
+
channelId: string,
|
|
697
|
+
ids: readonly string[],
|
|
698
|
+
options?: MessageAuditOperationOptions,
|
|
699
|
+
): Effect.Effect<void, MessageOperationFailure> {
|
|
700
|
+
return suspendInput((): Effect.Effect<void, RestFailure | ClientClosedError> => {
|
|
701
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
702
|
+
if (!identifier(channelId))
|
|
703
|
+
return Effect.fail(localInputFailure("channelId", "format", "Channel IDs must be decimal strings"))
|
|
704
|
+
if (!Array.isArray(ids))
|
|
705
|
+
return Effect.fail(localInputFailure("messageIds", "type", "Message IDs must be an array"))
|
|
706
|
+
// Copy the caller array once and validate the copy, so the validated IDs are the ones sent
|
|
707
|
+
const snapshot = snapshotArray(ids, 100)
|
|
708
|
+
if (snapshot === undefined || snapshot.length < 1)
|
|
709
|
+
return Effect.fail(
|
|
710
|
+
localInputFailure("messageIds", "length", "Bulk deletion requires 1 through 100 message IDs"),
|
|
711
|
+
)
|
|
712
|
+
if (!snapshot.every(identifier))
|
|
713
|
+
return Effect.fail(localInputFailure("messageIds[]", "format", "Message IDs must be decimal strings"))
|
|
714
|
+
if (new Set(snapshot).size !== snapshot.length)
|
|
715
|
+
return Effect.fail(localInputFailure("messageIds", "unique", "Message IDs must be unique"))
|
|
716
|
+
const audit = auditSettings(options)
|
|
717
|
+
if (audit instanceof InputValidationFailure) return Effect.fail(inputFailure(audit.detail))
|
|
718
|
+
return this.#execute(
|
|
719
|
+
token,
|
|
720
|
+
{
|
|
721
|
+
method: "POST",
|
|
722
|
+
channel: channelId,
|
|
723
|
+
bucket: "bulk-delete",
|
|
724
|
+
...(audit.auditReason === undefined ? {} : { auditReason: audit.auditReason }),
|
|
725
|
+
cache: false,
|
|
726
|
+
deleteIds: snapshot as readonly string[],
|
|
727
|
+
path: `/channels/${channelId}/messages/bulk-delete`,
|
|
728
|
+
body: { json: JSON.stringify({ message_ids: snapshot }), files: [] },
|
|
729
|
+
status: 204,
|
|
730
|
+
decode: async () => {},
|
|
731
|
+
},
|
|
732
|
+
options,
|
|
733
|
+
[...operationOptionKeys, "auditReason"],
|
|
734
|
+
)
|
|
735
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "deleteMany")))
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
deleteOwnMessages(
|
|
739
|
+
token: Redacted.Redacted<string>,
|
|
740
|
+
channelId: string,
|
|
741
|
+
options?: MessageOperationOptions,
|
|
742
|
+
): Effect.Effect<void, MessageOperationFailure> {
|
|
743
|
+
return suspendInput((): Effect.Effect<void, RestFailure | ClientClosedError> => {
|
|
744
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
745
|
+
if (!identifier(channelId))
|
|
746
|
+
return Effect.fail(localInputFailure("channelId", "format", "Channel IDs must be decimal strings"))
|
|
747
|
+
const invalid = timeoutOptionsFailure(options)
|
|
748
|
+
if (invalid) return Effect.fail(invalid)
|
|
749
|
+
return this.#execute(
|
|
750
|
+
token,
|
|
751
|
+
{
|
|
752
|
+
method: "POST",
|
|
753
|
+
channel: channelId,
|
|
754
|
+
bucket: "bulk-delete-mine",
|
|
755
|
+
cache: false,
|
|
756
|
+
invalidateMessages: true,
|
|
757
|
+
path: `/channels/${channelId}/messages/bulk-delete-mine`,
|
|
758
|
+
body: undefined,
|
|
759
|
+
status: 202,
|
|
760
|
+
decode: async () => {},
|
|
761
|
+
},
|
|
762
|
+
options,
|
|
763
|
+
)
|
|
764
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "deleteOwnMessages")))
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
fetchReactionUsers(
|
|
768
|
+
token: Redacted.Redacted<string>,
|
|
769
|
+
target: MessageReference,
|
|
770
|
+
emoji: ReactionEmojiInput,
|
|
771
|
+
query?: ReactionUsersQuery,
|
|
772
|
+
options?: MessageOperationOptions,
|
|
773
|
+
): Effect.Effect<ReactionUsersPage, MessageOperationFailure> {
|
|
774
|
+
return suspendInput((): Effect.Effect<ReactionUsersPage, RestFailure | ClientClosedError> => {
|
|
775
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
776
|
+
const encoded = encodeReactionEmoji(emoji)
|
|
777
|
+
const page = encodeReactionUsersQuery(query)
|
|
778
|
+
const ref = snapshotReference(target)
|
|
779
|
+
if (ref === undefined)
|
|
780
|
+
return Effect.fail(
|
|
781
|
+
localInputFailure("target", "format", "Message targets require decimal id and channelId strings"),
|
|
782
|
+
)
|
|
783
|
+
if (encoded === undefined)
|
|
784
|
+
return Effect.fail(
|
|
785
|
+
localInputFailure(
|
|
786
|
+
"emoji",
|
|
787
|
+
"format",
|
|
788
|
+
"Reaction emoji must be Unicode text or a custom emoji with a decimal ID",
|
|
789
|
+
),
|
|
790
|
+
)
|
|
791
|
+
if (page instanceof InputValidationFailure) return Effect.fail(inputFailure(page.detail))
|
|
792
|
+
return this.#execute(
|
|
793
|
+
token,
|
|
794
|
+
{
|
|
795
|
+
method: "GET",
|
|
796
|
+
channel: ref.channelId,
|
|
797
|
+
bucket: "reaction",
|
|
798
|
+
path: `/channels/${ref.channelId}/messages/${ref.id}/reactions/${encoded}/users?${page.params}`,
|
|
799
|
+
body: undefined,
|
|
800
|
+
status: 200,
|
|
801
|
+
decode: async (response, _instance, signal) => {
|
|
802
|
+
return readDecoded(response, signal, (value) => decodeReactionUsersPage(value, page))
|
|
803
|
+
},
|
|
804
|
+
},
|
|
805
|
+
options,
|
|
806
|
+
)
|
|
807
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "fetchReactionUsers")))
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
fetchPins(
|
|
811
|
+
token: Redacted.Redacted<string>,
|
|
812
|
+
channel: string,
|
|
813
|
+
query?: MessagePinsQuery,
|
|
814
|
+
options?: MessageOperationOptions,
|
|
815
|
+
): Effect.Effect<MessagePinsPage<M>, MessageOperationFailure> {
|
|
816
|
+
return suspendInput((): Effect.Effect<MessagePinsPage<M>, RestFailure | ClientClosedError> => {
|
|
817
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
818
|
+
const page = encodePinsQuery(channel, query)
|
|
819
|
+
if (page instanceof InputValidationFailure) return Effect.fail(inputFailure(page.detail))
|
|
820
|
+
return this.#execute(
|
|
821
|
+
token,
|
|
822
|
+
{
|
|
823
|
+
method: "GET",
|
|
824
|
+
channel,
|
|
825
|
+
bucket: "pins",
|
|
826
|
+
path: `/channels/${channel}/messages/pins?${page.params}`,
|
|
827
|
+
body: undefined,
|
|
828
|
+
status: 200,
|
|
829
|
+
decode: async (response, _instance, signal) => {
|
|
830
|
+
return readDecoded(response, signal, (value) =>
|
|
831
|
+
decodePinsPage(value, channel, page, this.#decodeMessage),
|
|
832
|
+
)
|
|
833
|
+
},
|
|
834
|
+
},
|
|
835
|
+
options,
|
|
836
|
+
)
|
|
837
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, "fetchPins")))
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
pin(
|
|
841
|
+
token: Redacted.Redacted<string>,
|
|
842
|
+
operation: "pin" | "unpin",
|
|
843
|
+
target: MessageReference,
|
|
844
|
+
options?: MessageAuditOperationOptions,
|
|
845
|
+
): Effect.Effect<void, MessageOperationFailure> {
|
|
846
|
+
return suspendInput((): Effect.Effect<void, RestFailure | ClientClosedError> => {
|
|
847
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
848
|
+
const ref = snapshotReference(target)
|
|
849
|
+
if (ref === undefined)
|
|
850
|
+
return Effect.fail(
|
|
851
|
+
localInputFailure("target", "format", "Message targets require decimal id and channelId strings"),
|
|
852
|
+
)
|
|
853
|
+
const audit = auditSettings(options)
|
|
854
|
+
if (audit instanceof InputValidationFailure) return Effect.fail(inputFailure(audit.detail))
|
|
855
|
+
return this.#execute(
|
|
856
|
+
token,
|
|
857
|
+
{
|
|
858
|
+
method: operation === "pin" ? "PUT" : "DELETE",
|
|
859
|
+
...(audit.auditReason === undefined ? {} : { auditReason: audit.auditReason }),
|
|
860
|
+
channel: ref.channelId,
|
|
861
|
+
target: ref.id,
|
|
862
|
+
bucket: "pins",
|
|
863
|
+
path: `/channels/${ref.channelId}/pins/${ref.id}`,
|
|
864
|
+
body: undefined,
|
|
865
|
+
status: 204,
|
|
866
|
+
decode: async () => {},
|
|
867
|
+
},
|
|
868
|
+
options,
|
|
869
|
+
[...operationOptionKeys, "auditReason"],
|
|
870
|
+
)
|
|
871
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, operation)))
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
reaction(
|
|
875
|
+
token: Redacted.Redacted<string>,
|
|
876
|
+
operation: "addReaction" | "removeReaction" | "removeUserReaction" | "clearReaction" | "clearReactions",
|
|
877
|
+
target: MessageReference,
|
|
878
|
+
emoji: ReactionEmojiInput | undefined,
|
|
879
|
+
options?: MessageOperationOptions,
|
|
880
|
+
userId?: string,
|
|
881
|
+
): Effect.Effect<void, MessageOperationFailure> {
|
|
882
|
+
return suspendInput((): Effect.Effect<void, RestFailure | ClientClosedError> => {
|
|
883
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
884
|
+
const encoded = operation === "clearReactions" ? "" : encodeReactionEmoji(emoji as ReactionEmojiInput)
|
|
885
|
+
const ref = snapshotReference(target)
|
|
886
|
+
if (ref === undefined)
|
|
887
|
+
return Effect.fail(
|
|
888
|
+
localInputFailure("target", "format", "Message targets require decimal id and channelId strings"),
|
|
889
|
+
)
|
|
890
|
+
if (encoded === undefined)
|
|
891
|
+
return Effect.fail(
|
|
892
|
+
localInputFailure(
|
|
893
|
+
"emoji",
|
|
894
|
+
"format",
|
|
895
|
+
"Reaction emoji must be Unicode text or a custom emoji with a decimal ID",
|
|
896
|
+
),
|
|
897
|
+
)
|
|
898
|
+
if (operation === "removeUserReaction" && !identifier(userId))
|
|
899
|
+
return Effect.fail(localInputFailure("userId", "format", "User IDs must be decimal strings"))
|
|
900
|
+
const suffix =
|
|
901
|
+
operation === "clearReactions"
|
|
902
|
+
? ""
|
|
903
|
+
: operation === "clearReaction"
|
|
904
|
+
? `/${encoded}`
|
|
905
|
+
: `/${encoded}/${operation === "removeUserReaction" ? userId : "@me"}`
|
|
906
|
+
return this.#execute(
|
|
907
|
+
token,
|
|
908
|
+
{
|
|
909
|
+
method: operation === "addReaction" ? "PUT" : "DELETE",
|
|
910
|
+
channel: ref.channelId,
|
|
911
|
+
bucket: "reaction",
|
|
912
|
+
path: `/channels/${ref.channelId}/messages/${ref.id}/reactions${suffix}`,
|
|
913
|
+
body: undefined,
|
|
914
|
+
status: 204,
|
|
915
|
+
decode: async () => {},
|
|
916
|
+
},
|
|
917
|
+
options,
|
|
918
|
+
)
|
|
919
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, operation)))
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
#manage<A>(
|
|
923
|
+
token: Redacted.Redacted<string>,
|
|
924
|
+
operation: "fetch" | "edit" | "delete" | "publish" | "fetchCrosspostSource",
|
|
925
|
+
target: MessageReference,
|
|
926
|
+
input: EditMessageInput | string | undefined,
|
|
927
|
+
options: MessageOperationOptions | undefined,
|
|
928
|
+
decode: (response: Response, ref: MessageReference, signal: AbortSignal) => Promise<A>,
|
|
929
|
+
observe?: (value: A, guard: CacheRequest) => void,
|
|
930
|
+
): Effect.Effect<A, MessageOperationFailure> {
|
|
931
|
+
return suspendInput((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
932
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
933
|
+
const ref = snapshotReference(target)
|
|
934
|
+
if (ref === undefined)
|
|
935
|
+
return Effect.fail(
|
|
936
|
+
localInputFailure("target", "format", "Message targets require decimal id and channelId strings"),
|
|
937
|
+
)
|
|
938
|
+
const body = operation === "edit" ? encodeEdit(input) : undefined
|
|
939
|
+
if (body instanceof InputValidationFailure) return Effect.fail(inputFailure(body.detail))
|
|
940
|
+
const audit = operation === "delete" ? auditSettings(options) : undefined
|
|
941
|
+
if (audit instanceof InputValidationFailure) return Effect.fail(inputFailure(audit.detail))
|
|
942
|
+
return this.#execute(
|
|
943
|
+
token,
|
|
944
|
+
{
|
|
945
|
+
method:
|
|
946
|
+
operation === "fetch" || operation === "fetchCrosspostSource"
|
|
947
|
+
? "GET"
|
|
948
|
+
: operation === "publish"
|
|
949
|
+
? "POST"
|
|
950
|
+
: operation === "edit"
|
|
951
|
+
? "PATCH"
|
|
952
|
+
: "DELETE",
|
|
953
|
+
channel: ref.channelId,
|
|
954
|
+
target: ref.id,
|
|
955
|
+
...(operation === "publish"
|
|
956
|
+
? { bucket: "channel:message:crosspost", messageMutation: true as const }
|
|
957
|
+
: operation === "fetchCrosspostSource"
|
|
958
|
+
? { bucket: "channel:message:crosspost_source", cache: false as const }
|
|
959
|
+
: {}),
|
|
960
|
+
path: `/channels/${ref.channelId}/messages/${ref.id}${
|
|
961
|
+
operation === "publish"
|
|
962
|
+
? "/crosspost"
|
|
963
|
+
: operation === "fetchCrosspostSource"
|
|
964
|
+
? "/crosspost-source"
|
|
965
|
+
: ""
|
|
966
|
+
}`,
|
|
967
|
+
body,
|
|
968
|
+
status: operation === "delete" ? 204 : 200,
|
|
969
|
+
...(audit?.auditReason === undefined ? {} : { auditReason: audit.auditReason }),
|
|
970
|
+
decode: (response, _instance, signal) => decode(response, ref, signal),
|
|
971
|
+
...(observe === undefined ? {} : { observe }),
|
|
972
|
+
},
|
|
973
|
+
options,
|
|
974
|
+
operation === "delete" ? [...operationOptionKeys, "auditReason"] : operationOptionKeys,
|
|
975
|
+
)
|
|
976
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, MessageOperationError, operation)))
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/** Run attempts for one request until it succeeds, fails permanently, runs out of read retries or passes its deadline */
|
|
980
|
+
#exchange<A>(
|
|
981
|
+
token: Redacted.Redacted<string>,
|
|
982
|
+
options: ExchangeOptions<A>,
|
|
983
|
+
): Effect.Effect<A, RestFailure | ClientClosedError> {
|
|
984
|
+
const runtime = this.#runtime
|
|
985
|
+
const { request, progress, generation, deadline, retainedBytes = 0 } = options
|
|
986
|
+
// A long pause can refuse every request on a route, so only the first refusal per route and minute is a Warn
|
|
987
|
+
const deadlineLevel = (template: string, retryAfterMs: number): "warn" | "debug" => {
|
|
988
|
+
if (retryAfterMs < longRateLimitWaitMs) return "debug"
|
|
989
|
+
const now = runtime.logical.now()
|
|
990
|
+
const last = runtime.deadlineWarnedAt.get(template)
|
|
991
|
+
if (last !== undefined && now - last < busyWarnIntervalMs) return "debug"
|
|
992
|
+
for (const [warned, at] of runtime.deadlineWarnedAt)
|
|
993
|
+
if (now - at >= busyWarnIntervalMs) runtime.deadlineWarnedAt.delete(warned)
|
|
994
|
+
runtime.deadlineWarnedAt.set(template, now)
|
|
995
|
+
return "warn"
|
|
996
|
+
}
|
|
997
|
+
const route = rateRoute(request.method, request.path, request.channel, request.bucket, request.webhookId)
|
|
998
|
+
const template =
|
|
999
|
+
request.template ?? routeTemplate(request.put ? "/attachments/upload" : request.path, request.webhookId)
|
|
1000
|
+
const bytes = retainedBytes + Buffer.byteLength(request.body?.json ?? "")
|
|
1001
|
+
return Effect.gen(function* () {
|
|
1002
|
+
const fiber = yield* Effect.withFiber((fiber) => Effect.succeed(fiber))
|
|
1003
|
+
let retries = 0
|
|
1004
|
+
let attempts = 0
|
|
1005
|
+
let until = 0
|
|
1006
|
+
while (true) {
|
|
1007
|
+
const retryCount = attempts++
|
|
1008
|
+
const attempt = yield* Effect.uninterruptibleMask((restore) =>
|
|
1009
|
+
Effect.exit(
|
|
1010
|
+
restore(
|
|
1011
|
+
Effect.acquireUseRelease(
|
|
1012
|
+
Effect.interruptible(
|
|
1013
|
+
runtime.admission.acquire({ route: route.key, bytes, until, deadline }),
|
|
1014
|
+
).pipe(
|
|
1015
|
+
mapFailureCause((error) =>
|
|
1016
|
+
error instanceof RestFailure ? error.withOutcome(progress.outcome) : error,
|
|
1017
|
+
),
|
|
1018
|
+
),
|
|
1019
|
+
() =>
|
|
1020
|
+
runtime.logical.now() >= deadline
|
|
1021
|
+
? Effect.fail(new RestFailure({ reason: "timeout", outcome: progress.outcome }))
|
|
1022
|
+
: runAttempt({
|
|
1023
|
+
runtime,
|
|
1024
|
+
token,
|
|
1025
|
+
request,
|
|
1026
|
+
route,
|
|
1027
|
+
progress,
|
|
1028
|
+
generation,
|
|
1029
|
+
fiber,
|
|
1030
|
+
retryCount,
|
|
1031
|
+
}),
|
|
1032
|
+
(release) => Effect.sync(release),
|
|
1033
|
+
),
|
|
1034
|
+
),
|
|
1035
|
+
).pipe(
|
|
1036
|
+
Effect.flatMap((exit) =>
|
|
1037
|
+
Exit.isFailure(exit) && (Cause.hasDies(exit.cause) || Cause.hasInterrupts(exit.cause))
|
|
1038
|
+
? Effect.failCause(exit.cause)
|
|
1039
|
+
: Effect.succeed(exit),
|
|
1040
|
+
),
|
|
1041
|
+
),
|
|
1042
|
+
)
|
|
1043
|
+
if (Exit.isFailure(attempt)) {
|
|
1044
|
+
const reason = attempt.cause.reasons.find((reason) => reason._tag === "Fail")
|
|
1045
|
+
if (reason?._tag !== "Fail")
|
|
1046
|
+
return yield* Effect.die(new Error("REST request failed without a cause"))
|
|
1047
|
+
const error = reason.error
|
|
1048
|
+
// Admission fails a request whose learned wait outlasts its deadline. That is the only rate-limit
|
|
1049
|
+
// failure without an HTTP status, and it is logged like a 429 whose wait passes the deadline
|
|
1050
|
+
if (
|
|
1051
|
+
error instanceof RestFailure &&
|
|
1052
|
+
error.reason === "rateLimit" &&
|
|
1053
|
+
error.status === null &&
|
|
1054
|
+
error.retryAfterMs !== null
|
|
1055
|
+
)
|
|
1056
|
+
runtime.logging?.log(
|
|
1057
|
+
{
|
|
1058
|
+
level: deadlineLevel(template, error.retryAfterMs),
|
|
1059
|
+
category: "ratelimit",
|
|
1060
|
+
code: "ratelimit.deadline",
|
|
1061
|
+
message: `${request.method} ${template} is rate-limited for another ${error.retryAfterMs} ms, which is past its timeout, so it fails without waiting`,
|
|
1062
|
+
route: template,
|
|
1063
|
+
delayMs: error.retryAfterMs,
|
|
1064
|
+
fields: { method: request.method },
|
|
1065
|
+
},
|
|
1066
|
+
fiber.context,
|
|
1067
|
+
)
|
|
1068
|
+
// An unusable success response usually means a Fluxer schema change or a wrong test fixture,
|
|
1069
|
+
// so it is logged once per route and field, mirroring gateway.dispatchRejected. A caller-described
|
|
1070
|
+
// route has no expected shape, so its failure is only returned to the caller
|
|
1071
|
+
if (error instanceof RestFailure && error.reason === "response" && !request.callerDescribed)
|
|
1072
|
+
runtime.logging?.log(
|
|
1073
|
+
{
|
|
1074
|
+
level: "warn",
|
|
1075
|
+
category: "rest",
|
|
1076
|
+
code: "rest.responseRejected",
|
|
1077
|
+
message: `${request.method} ${template} returned an answer in an unexpected format${error.responseField === null ? "" : `: ${responseFieldText(error.responseField)}`}`,
|
|
1078
|
+
route: template,
|
|
1079
|
+
...(error.status === null ? {} : { status: error.status }),
|
|
1080
|
+
fields: { method: request.method, field: error.responseField ?? undefined },
|
|
1081
|
+
},
|
|
1082
|
+
fiber.context,
|
|
1083
|
+
)
|
|
1084
|
+
if (
|
|
1085
|
+
request.method !== "GET" ||
|
|
1086
|
+
!(error instanceof RestFailure) ||
|
|
1087
|
+
!error.retryableRead ||
|
|
1088
|
+
retries === maximumReadRetries
|
|
1089
|
+
)
|
|
1090
|
+
return yield* Effect.fail(error)
|
|
1091
|
+
const minimum = retries++ === 0 ? firstReadRetryMs : laterReadRetryMs
|
|
1092
|
+
const delay = Math.max(minimum * (1 + (yield* Random.next)), error.retryAfterMs ?? 0)
|
|
1093
|
+
// A retry that cannot start before the deadline would only end as a timeout, so the received failure is returned now
|
|
1094
|
+
if (runtime.logical.now() + Math.ceil(delay) >= deadline) return yield* Effect.fail(error)
|
|
1095
|
+
until = runtime.logical.now() + Math.ceil(delay)
|
|
1096
|
+
runtime.logging?.drop(
|
|
1097
|
+
"restRetries",
|
|
1098
|
+
{
|
|
1099
|
+
level: "debug",
|
|
1100
|
+
category: "rest",
|
|
1101
|
+
code: "rest.retry",
|
|
1102
|
+
message: `Retrying ${request.method} ${template} after ${error.status === null ? `a ${error.reason} failure` : `HTTP ${error.status}`} in ${Math.ceil(delay)} ms`,
|
|
1103
|
+
route: template,
|
|
1104
|
+
attempt: attempts + 1,
|
|
1105
|
+
delayMs: Math.ceil(delay),
|
|
1106
|
+
...(error.status === null ? {} : { status: error.status }),
|
|
1107
|
+
fields: { method: request.method, reason: error.reason },
|
|
1108
|
+
},
|
|
1109
|
+
fiber.context,
|
|
1110
|
+
)
|
|
1111
|
+
continue
|
|
1112
|
+
}
|
|
1113
|
+
const response = attempt.value
|
|
1114
|
+
if (response.kind === "success") return response.value
|
|
1115
|
+
if (
|
|
1116
|
+
(request.inlineAttachments || request.webhookId) &&
|
|
1117
|
+
request.sources?.some((source) => !source.replayable)
|
|
1118
|
+
)
|
|
1119
|
+
return yield* Effect.fail(
|
|
1120
|
+
new RestFailure({
|
|
1121
|
+
reason: "rateLimit",
|
|
1122
|
+
outcome: progress.outcome,
|
|
1123
|
+
status: 429,
|
|
1124
|
+
retryAfterMs: response.retry,
|
|
1125
|
+
apiError: response.apiError,
|
|
1126
|
+
providerCode: response.providerCode ?? null,
|
|
1127
|
+
}),
|
|
1128
|
+
)
|
|
1129
|
+
until = runtime.logical.now() + response.retry
|
|
1130
|
+
if (response.global) runtime.admission.pauseGlobal(until)
|
|
1131
|
+
if (until >= deadline) {
|
|
1132
|
+
// No wait happens: The request fails now, so this is not counted as a rate-limit wait
|
|
1133
|
+
runtime.logging?.log(
|
|
1134
|
+
{
|
|
1135
|
+
level: response.retry >= longRateLimitWaitMs ? "warn" : "debug",
|
|
1136
|
+
category: "ratelimit",
|
|
1137
|
+
code: "ratelimit.deadline",
|
|
1138
|
+
message: `${request.method} ${template} was rate-limited${response.global ? " globally" : ""} for ${response.retry} ms, which is past its timeout, so it fails without waiting`,
|
|
1139
|
+
route: template,
|
|
1140
|
+
status: 429,
|
|
1141
|
+
delayMs: response.retry,
|
|
1142
|
+
attempt: attempts,
|
|
1143
|
+
fields: { method: request.method, global: response.global },
|
|
1144
|
+
},
|
|
1145
|
+
fiber.context,
|
|
1146
|
+
)
|
|
1147
|
+
return yield* Effect.fail(
|
|
1148
|
+
new RestFailure({
|
|
1149
|
+
reason: "rateLimit",
|
|
1150
|
+
outcome: progress.outcome,
|
|
1151
|
+
status: 429,
|
|
1152
|
+
retryAfterMs: response.retry,
|
|
1153
|
+
apiError: response.apiError,
|
|
1154
|
+
providerCode: response.providerCode ?? null,
|
|
1155
|
+
}),
|
|
1156
|
+
)
|
|
1157
|
+
}
|
|
1158
|
+
metrics.rateLimitWait(response.retry, fiber.context)
|
|
1159
|
+
emitObservation(runtime.logging, {
|
|
1160
|
+
type: "rateLimit",
|
|
1161
|
+
method: request.method,
|
|
1162
|
+
route: template,
|
|
1163
|
+
waitMs: response.retry,
|
|
1164
|
+
global: response.global,
|
|
1165
|
+
})
|
|
1166
|
+
runtime.logging?.drop(
|
|
1167
|
+
"rateLimitWaits",
|
|
1168
|
+
{
|
|
1169
|
+
level: response.retry >= longRateLimitWaitMs ? "warn" : "debug",
|
|
1170
|
+
category: "ratelimit",
|
|
1171
|
+
code: "ratelimit.wait",
|
|
1172
|
+
message: `${request.method} ${template} was rate-limited${response.global ? " globally" : ""}, so it waits ${response.retry} ms before retrying`,
|
|
1173
|
+
route: template,
|
|
1174
|
+
status: 429,
|
|
1175
|
+
delayMs: response.retry,
|
|
1176
|
+
attempt: attempts,
|
|
1177
|
+
fields: { method: request.method, global: response.global },
|
|
1178
|
+
},
|
|
1179
|
+
fiber.context,
|
|
1180
|
+
)
|
|
1181
|
+
}
|
|
1182
|
+
})
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
/** Plan and upload attachment files through presigned destinations, or fall back to inline multipart */
|
|
1186
|
+
#prepareUploads(
|
|
1187
|
+
token: Redacted.Redacted<string>,
|
|
1188
|
+
body: EncodedBody,
|
|
1189
|
+
sources: readonly AttachmentTransferSource[],
|
|
1190
|
+
context: {
|
|
1191
|
+
readonly channel: string
|
|
1192
|
+
readonly instance: InstanceEndpointContext
|
|
1193
|
+
readonly progress: { outcome: Outcome }
|
|
1194
|
+
readonly generation: number
|
|
1195
|
+
readonly deadline: number
|
|
1196
|
+
},
|
|
1197
|
+
): Effect.Effect<"preuploaded" | "inline", RestFailure | ClientClosedError> {
|
|
1198
|
+
const owner = this
|
|
1199
|
+
const { channel, instance, progress, generation, deadline } = context
|
|
1200
|
+
return Effect.gen(function* () {
|
|
1201
|
+
const inline = (): "inline" => {
|
|
1202
|
+
const payload = JSON.parse(body.json) as { attachments: Record<string, unknown>[] }
|
|
1203
|
+
payload.attachments = payload.attachments.map((item) => {
|
|
1204
|
+
const file = body.files.find((file) => file.id === item.id)
|
|
1205
|
+
if (!file) return item
|
|
1206
|
+
return { ...item, filename: file.filename, content_type: file.contentType }
|
|
1207
|
+
})
|
|
1208
|
+
body.json = JSON.stringify(payload)
|
|
1209
|
+
return "inline"
|
|
1210
|
+
}
|
|
1211
|
+
if (!instance.presignedAttachmentUploads) return inline()
|
|
1212
|
+
const retainedBytes = Buffer.byteLength(body.json)
|
|
1213
|
+
const attachments = body.files.map((file) => ({
|
|
1214
|
+
id: file.id,
|
|
1215
|
+
filename: file.filename,
|
|
1216
|
+
file_size: file.size,
|
|
1217
|
+
content_type: file.contentType,
|
|
1218
|
+
}))
|
|
1219
|
+
const planned = yield* owner.#exchange<{ kind: "plans"; plans: UploadPlan[] } | { kind: "disabled" }>(
|
|
1220
|
+
token,
|
|
1221
|
+
{
|
|
1222
|
+
request: {
|
|
1223
|
+
method: "POST",
|
|
1224
|
+
channel,
|
|
1225
|
+
bucket: "upload",
|
|
1226
|
+
preparation: true,
|
|
1227
|
+
instance,
|
|
1228
|
+
path: `/channels/${channel}/attachments`,
|
|
1229
|
+
body: { json: JSON.stringify({ attachments }), files: [] },
|
|
1230
|
+
decode: async (
|
|
1231
|
+
response,
|
|
1232
|
+
_instance,
|
|
1233
|
+
signal,
|
|
1234
|
+
): Promise<{ kind: "plans"; plans: UploadPlan[] }> => {
|
|
1235
|
+
const plans = decodeUploadPlans(
|
|
1236
|
+
await readResponseJson(response, uploadResponseMaxBytes, signal),
|
|
1237
|
+
body.files,
|
|
1238
|
+
instance.allowInsecure,
|
|
1239
|
+
)
|
|
1240
|
+
if (!plans)
|
|
1241
|
+
throw new RestFailure({
|
|
1242
|
+
reason: "response",
|
|
1243
|
+
outcome: "notDispatched",
|
|
1244
|
+
status: response.status,
|
|
1245
|
+
})
|
|
1246
|
+
return { kind: "plans" as const, plans }
|
|
1247
|
+
},
|
|
1248
|
+
featureDisabled: () => ({ kind: "disabled" as const }),
|
|
1249
|
+
},
|
|
1250
|
+
progress,
|
|
1251
|
+
generation,
|
|
1252
|
+
deadline,
|
|
1253
|
+
retainedBytes,
|
|
1254
|
+
},
|
|
1255
|
+
)
|
|
1256
|
+
if (planned.kind === "disabled") return inline()
|
|
1257
|
+
const plans = planned.plans
|
|
1258
|
+
// Charge retained plan capabilities too while queued. They are never exposed as diagnostics
|
|
1259
|
+
const queuedBytes = retainedBytes + Buffer.byteLength(JSON.stringify(plans))
|
|
1260
|
+
for (const plan of plans) {
|
|
1261
|
+
const file = body.files.find((file) => file.id === plan.id)!
|
|
1262
|
+
const source = sources[body.files.indexOf(file)]
|
|
1263
|
+
if (!source)
|
|
1264
|
+
return yield* Effect.fail(new RestFailure({ reason: "response", outcome: "notDispatched" }))
|
|
1265
|
+
for (const part of plan.parts) {
|
|
1266
|
+
yield* owner.#exchange(token, {
|
|
1267
|
+
request: {
|
|
1268
|
+
method: "PUT",
|
|
1269
|
+
channel,
|
|
1270
|
+
preparation: true,
|
|
1271
|
+
instance,
|
|
1272
|
+
path: "",
|
|
1273
|
+
body: undefined,
|
|
1274
|
+
put: {
|
|
1275
|
+
...part,
|
|
1276
|
+
source,
|
|
1277
|
+
...(plan.uploadId ? {} : { contentType: plan.contentType }),
|
|
1278
|
+
},
|
|
1279
|
+
decode: async () => {},
|
|
1280
|
+
},
|
|
1281
|
+
progress,
|
|
1282
|
+
generation,
|
|
1283
|
+
deadline,
|
|
1284
|
+
retainedBytes: queuedBytes,
|
|
1285
|
+
})
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
const uploads = plans
|
|
1289
|
+
.filter((plan) => plan.uploadId !== undefined)
|
|
1290
|
+
.map((plan) => ({ upload_filename: plan.key, upload_id: plan.uploadId! }))
|
|
1291
|
+
if (uploads.length)
|
|
1292
|
+
yield* owner.#exchange(token, {
|
|
1293
|
+
request: {
|
|
1294
|
+
method: "POST",
|
|
1295
|
+
channel,
|
|
1296
|
+
bucket: "upload",
|
|
1297
|
+
preparation: true,
|
|
1298
|
+
instance,
|
|
1299
|
+
path: `/channels/${channel}/attachments/complete`,
|
|
1300
|
+
body: { json: JSON.stringify({ uploads }), files: [] },
|
|
1301
|
+
decode: async (response, _instance, signal) => {
|
|
1302
|
+
const value = await readResponseJson(response, uploadResponseMaxBytes, signal)
|
|
1303
|
+
if (
|
|
1304
|
+
!record(value) ||
|
|
1305
|
+
!Array.isArray(value.uploads) ||
|
|
1306
|
+
value.uploads.length !== uploads.length ||
|
|
1307
|
+
uploads.some(
|
|
1308
|
+
(upload) =>
|
|
1309
|
+
!Array.isArray(value.uploads) ||
|
|
1310
|
+
value.uploads.filter(
|
|
1311
|
+
(item) => record(item) && item.upload_filename === upload.upload_filename,
|
|
1312
|
+
).length !== 1,
|
|
1313
|
+
)
|
|
1314
|
+
)
|
|
1315
|
+
throw new RestFailure({
|
|
1316
|
+
reason: "response",
|
|
1317
|
+
outcome: "notDispatched",
|
|
1318
|
+
status: response.status,
|
|
1319
|
+
})
|
|
1320
|
+
},
|
|
1321
|
+
},
|
|
1322
|
+
progress,
|
|
1323
|
+
generation,
|
|
1324
|
+
deadline,
|
|
1325
|
+
retainedBytes: queuedBytes,
|
|
1326
|
+
})
|
|
1327
|
+
const payload = JSON.parse(body.json) as { attachments: Record<string, unknown>[] }
|
|
1328
|
+
payload.attachments = payload.attachments.map((item) => {
|
|
1329
|
+
const plan = plans.find((plan) => plan.id === item.id)
|
|
1330
|
+
if (!plan) return item
|
|
1331
|
+
const file = body.files.find((file) => file.id === plan.id)!
|
|
1332
|
+
return {
|
|
1333
|
+
...item,
|
|
1334
|
+
filename: plan.filename,
|
|
1335
|
+
content_type: plan.contentType,
|
|
1336
|
+
file_size: file.size,
|
|
1337
|
+
upload_filename: plan.key,
|
|
1338
|
+
}
|
|
1339
|
+
})
|
|
1340
|
+
body.json = JSON.stringify(payload)
|
|
1341
|
+
return "preuploaded" as const
|
|
1342
|
+
})
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
guild<A>(
|
|
1346
|
+
token: Redacted.Redacted<string>,
|
|
1347
|
+
operation: GuildOperation,
|
|
1348
|
+
build: () => GuildRequest<A> | InputValidationFailure,
|
|
1349
|
+
options?: GuildOperationOptions,
|
|
1350
|
+
) {
|
|
1351
|
+
return suspendInput((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
1352
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1353
|
+
const input = build()
|
|
1354
|
+
if (input instanceof InputValidationFailure) return Effect.fail(inputFailure(input.detail))
|
|
1355
|
+
if (options !== undefined && !record(options))
|
|
1356
|
+
return Effect.fail(localInputFailure("options", "type", "Operation options must be an object"))
|
|
1357
|
+
const audit = input.audited ? auditSettings(options) : undefined
|
|
1358
|
+
if (audit instanceof InputValidationFailure) return Effect.fail(inputFailure(audit.detail))
|
|
1359
|
+
const auditReason = input.auditReason ?? audit?.auditReason
|
|
1360
|
+
const acceptedOptions = [
|
|
1361
|
+
"timeoutMs",
|
|
1362
|
+
"signal",
|
|
1363
|
+
...(input.moderation || input.audited ? ["auditReason"] : []),
|
|
1364
|
+
...(input.timeoutReason ? ["timeoutReason"] : []),
|
|
1365
|
+
...(input.method === "DELETE" && ["guild:emojis", "guild:stickers"].includes(input.bucket)
|
|
1366
|
+
? ["purge"]
|
|
1367
|
+
: []),
|
|
1368
|
+
]
|
|
1369
|
+
return this.#execute(
|
|
1370
|
+
token,
|
|
1371
|
+
{
|
|
1372
|
+
// The scheduler's major-resource key is the guild here, never a message-cache channel
|
|
1373
|
+
channel: input.guildId,
|
|
1374
|
+
bucket: input.bucket,
|
|
1375
|
+
cache: false,
|
|
1376
|
+
...(input.cache === undefined ? {} : { resourceCache: input.cache }),
|
|
1377
|
+
...(input.channelCache === undefined ? {} : { channelCache: input.channelCache }),
|
|
1378
|
+
...(input.moderation === undefined ? {} : { moderation: input.moderation }),
|
|
1379
|
+
...(auditReason === undefined ? {} : { auditReason }),
|
|
1380
|
+
...(input.deleteAuthorId === undefined ? {} : { deleteAuthorId: input.deleteAuthorId }),
|
|
1381
|
+
...(input.invalidateMessages === undefined ? {} : { invalidateMessages: input.invalidateMessages }),
|
|
1382
|
+
...(input.features === undefined ? {} : { features: input.features }),
|
|
1383
|
+
path: input.path,
|
|
1384
|
+
method: input.method,
|
|
1385
|
+
status: input.status,
|
|
1386
|
+
body: input.json === undefined ? undefined : { json: input.json, files: [] },
|
|
1387
|
+
decode: async (response, instance, signal) => {
|
|
1388
|
+
if (input.status === 202 || input.status === 204) return undefined as A
|
|
1389
|
+
return readDecoded(response, signal, (value) => input.decode(value, instance))
|
|
1390
|
+
},
|
|
1391
|
+
},
|
|
1392
|
+
options,
|
|
1393
|
+
acceptedOptions,
|
|
1394
|
+
)
|
|
1395
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, GuildOperationError, operation)))
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
channel<A>(
|
|
1399
|
+
token: Redacted.Redacted<string>,
|
|
1400
|
+
operation: ChannelOperation,
|
|
1401
|
+
build: () => ChannelRequest<A> | InputValidationFailure,
|
|
1402
|
+
options?: ChannelOperationOptions,
|
|
1403
|
+
) {
|
|
1404
|
+
return suspendInput((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
1405
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1406
|
+
const input = build()
|
|
1407
|
+
if (input instanceof InputValidationFailure) return Effect.fail(inputFailure(input.detail))
|
|
1408
|
+
if (options !== undefined && !record(options))
|
|
1409
|
+
return Effect.fail(localInputFailure("options", "type", "Operation options must be an object"))
|
|
1410
|
+
const audit = input.audited ? auditSettings(options) : undefined
|
|
1411
|
+
if (audit instanceof InputValidationFailure) return Effect.fail(inputFailure(audit.detail))
|
|
1412
|
+
const acceptedOptions = input.audited ? [...operationOptionKeys, "auditReason"] : operationOptionKeys
|
|
1413
|
+
const accepted = input.accepted
|
|
1414
|
+
return this.#execute(
|
|
1415
|
+
token,
|
|
1416
|
+
{
|
|
1417
|
+
channel: input.majorId,
|
|
1418
|
+
bucket: input.bucket,
|
|
1419
|
+
cache: false,
|
|
1420
|
+
...(input.cache === undefined ? {} : { channelCache: input.cache }),
|
|
1421
|
+
...(audit?.auditReason === undefined ? {} : { auditReason: audit.auditReason }),
|
|
1422
|
+
...(input.features === undefined ? {} : { features: input.features }),
|
|
1423
|
+
path: input.path,
|
|
1424
|
+
method: input.method,
|
|
1425
|
+
// A route that can also answer 202 has its status checked here instead
|
|
1426
|
+
...(accepted === undefined ? { status: input.status } : {}),
|
|
1427
|
+
body: input.body ?? (input.json === undefined ? undefined : { json: input.json, files: [] }),
|
|
1428
|
+
// Presigned uploads rewrite top-level attachments, while a forum post nests them in its message
|
|
1429
|
+
...(input.body?.files.length ? { inlineAttachments: true as const } : {}),
|
|
1430
|
+
decode: async (response, _instance, signal) => {
|
|
1431
|
+
if (input.status === 204) return undefined as A
|
|
1432
|
+
if (accepted !== undefined && response.status === 202)
|
|
1433
|
+
return readDecoded(response, signal, (value) => accepted(value))
|
|
1434
|
+
if (response.status !== input.status) throw responseFailure(response, "status")
|
|
1435
|
+
return readDecoded(response, signal, (value) => input.decode(value))
|
|
1436
|
+
},
|
|
1437
|
+
},
|
|
1438
|
+
options,
|
|
1439
|
+
acceptedOptions,
|
|
1440
|
+
)
|
|
1441
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, ChannelOperationError, operation)))
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
user<A>(
|
|
1445
|
+
token: Redacted.Redacted<string>,
|
|
1446
|
+
operation: UserOperation,
|
|
1447
|
+
build: () => UserRequest<A> | InputValidationFailure,
|
|
1448
|
+
options?: UserOperationOptions,
|
|
1449
|
+
) {
|
|
1450
|
+
return suspendInput((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
1451
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1452
|
+
const input = build()
|
|
1453
|
+
if (input instanceof InputValidationFailure) return Effect.fail(inputFailure(input.detail))
|
|
1454
|
+
const invalid = timeoutOptionsFailure(options)
|
|
1455
|
+
if (invalid) return Effect.fail(invalid)
|
|
1456
|
+
return this.#execute(
|
|
1457
|
+
token,
|
|
1458
|
+
{
|
|
1459
|
+
channel: input.majorId,
|
|
1460
|
+
bucket: `user:${operation}`,
|
|
1461
|
+
cache: false,
|
|
1462
|
+
path: input.path,
|
|
1463
|
+
method: input.method,
|
|
1464
|
+
status: input.status,
|
|
1465
|
+
body: input.json === undefined ? undefined : { json: input.json, files: [] },
|
|
1466
|
+
decode: async (response, _instance, signal) => {
|
|
1467
|
+
if (input.status === 204) return undefined as A
|
|
1468
|
+
return readDecoded(response, signal, (value) => input.decode(value))
|
|
1469
|
+
},
|
|
1470
|
+
},
|
|
1471
|
+
options,
|
|
1472
|
+
)
|
|
1473
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, UserOperationError, operation)))
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
application<A>(
|
|
1477
|
+
token: Redacted.Redacted<string>,
|
|
1478
|
+
operation: BotApplicationOperation,
|
|
1479
|
+
build: () => BotApplicationRequest<A>,
|
|
1480
|
+
options?: BotApplicationOperationOptions,
|
|
1481
|
+
) {
|
|
1482
|
+
return suspendInput((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
1483
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1484
|
+
const input = build()
|
|
1485
|
+
const invalid = timeoutOptionsFailure(options)
|
|
1486
|
+
if (invalid) return Effect.fail(invalid)
|
|
1487
|
+
return this.#execute(
|
|
1488
|
+
token,
|
|
1489
|
+
{
|
|
1490
|
+
channel: "application",
|
|
1491
|
+
bucket: "application:current",
|
|
1492
|
+
cache: false,
|
|
1493
|
+
path: input.path,
|
|
1494
|
+
method: input.method,
|
|
1495
|
+
status: input.status,
|
|
1496
|
+
body: undefined,
|
|
1497
|
+
decode: async (response, _instance, signal) => {
|
|
1498
|
+
return readDecoded(response, signal, (value) => input.decode(value))
|
|
1499
|
+
},
|
|
1500
|
+
},
|
|
1501
|
+
options,
|
|
1502
|
+
)
|
|
1503
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, BotApplicationOperationError, operation)))
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
webhook<A>(
|
|
1507
|
+
token: Redacted.Redacted<string>,
|
|
1508
|
+
operation: WebhookOperation,
|
|
1509
|
+
build: () => WebhookRequest<A> | InputValidationFailure,
|
|
1510
|
+
options?: WebhookOperationOptions,
|
|
1511
|
+
) {
|
|
1512
|
+
return suspendInput((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
1513
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1514
|
+
const input = build()
|
|
1515
|
+
if (input instanceof InputValidationFailure) return Effect.fail(inputFailure(input.detail))
|
|
1516
|
+
if (options !== undefined && !record(options))
|
|
1517
|
+
return Effect.fail(localInputFailure("options", "type", "Operation options must be an object"))
|
|
1518
|
+
const acceptedOptions =
|
|
1519
|
+
input.method !== "GET" && !input.tokenAuth
|
|
1520
|
+
? [...operationOptionKeys, "auditReason"]
|
|
1521
|
+
: input.threadOption
|
|
1522
|
+
? [...operationOptionKeys, "threadId"]
|
|
1523
|
+
: operationOptionKeys
|
|
1524
|
+
return this.#execute(
|
|
1525
|
+
token,
|
|
1526
|
+
{
|
|
1527
|
+
channel: input.majorId,
|
|
1528
|
+
bucket: `webhook:${input.tokenAuth ? "token" : operation}`,
|
|
1529
|
+
cache: false,
|
|
1530
|
+
...(input.tokenAuth ? { webhookId: input.majorId } : {}),
|
|
1531
|
+
...(input.auditReason === undefined ? {} : { auditReason: input.auditReason }),
|
|
1532
|
+
path: input.path,
|
|
1533
|
+
method: input.method,
|
|
1534
|
+
status: input.status,
|
|
1535
|
+
body: input.body,
|
|
1536
|
+
decode: async (response, _instance, signal) => {
|
|
1537
|
+
if (input.status === 204) return undefined as A
|
|
1538
|
+
return readDecoded(response, signal, (value) => input.decode(value))
|
|
1539
|
+
},
|
|
1540
|
+
},
|
|
1541
|
+
options,
|
|
1542
|
+
acceptedOptions,
|
|
1543
|
+
)
|
|
1544
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, WebhookOperationError, operation)))
|
|
1545
|
+
}
|
|
1546
|
+
|
|
1547
|
+
/**
|
|
1548
|
+
* Validate the options and deadline, reserve upload bytes, register cache guards and run the operation to completion.
|
|
1549
|
+
* The options may contain only optionKeys, which each operation family lists beside its own validation
|
|
1550
|
+
*/
|
|
1551
|
+
#execute<A>(
|
|
1552
|
+
token: Redacted.Redacted<string>,
|
|
1553
|
+
request: Request<A>,
|
|
1554
|
+
options?: MessageOperationOptions,
|
|
1555
|
+
optionKeys: readonly string[] = operationOptionKeys,
|
|
1556
|
+
): Effect.Effect<A, RestFailure | ClientClosedError> {
|
|
1557
|
+
const owner = this
|
|
1558
|
+
const runtime = this.#runtime
|
|
1559
|
+
return Effect.suspend((): Effect.Effect<A, RestFailure | ClientClosedError> => {
|
|
1560
|
+
if (runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1561
|
+
let requested: ReturnType<typeof deadlineOption>
|
|
1562
|
+
let unsupported: RestFailure | undefined
|
|
1563
|
+
try {
|
|
1564
|
+
requested = deadlineOption(options)
|
|
1565
|
+
unsupported = unsupportedOptionFailure(options, optionKeys)
|
|
1566
|
+
} catch (error) {
|
|
1567
|
+
return Effect.failCause(inputDefect(error))
|
|
1568
|
+
}
|
|
1569
|
+
if (!requested.valid)
|
|
1570
|
+
return Effect.fail(localInputFailure("options", "type", "Operation options must be an object"))
|
|
1571
|
+
if (unsupported) return Effect.fail(unsupported)
|
|
1572
|
+
const timeout = requested.timeoutMs === undefined ? runtime.settings.defaultTimeoutMs : requested.timeoutMs
|
|
1573
|
+
if (
|
|
1574
|
+
typeof timeout !== "number" ||
|
|
1575
|
+
!Number.isSafeInteger(timeout) ||
|
|
1576
|
+
timeout <= 0 ||
|
|
1577
|
+
timeout > maximumTimerMs
|
|
1578
|
+
)
|
|
1579
|
+
return Effect.fail(
|
|
1580
|
+
localInputFailure(
|
|
1581
|
+
"options.timeoutMs",
|
|
1582
|
+
"range",
|
|
1583
|
+
"Operation timeoutMs must be an integer from 1 through 2,147,483,647 ms",
|
|
1584
|
+
),
|
|
1585
|
+
)
|
|
1586
|
+
const bytes = Buffer.byteLength(request.body?.json ?? "")
|
|
1587
|
+
const uploadBytes = request.body?.files.reduce((sum, file) => sum + file.size, 0) ?? 0
|
|
1588
|
+
if (!Number.isSafeInteger(uploadBytes) || uploadBytes > owner.#uploadMaxBytes - runtime.uploadBytes) {
|
|
1589
|
+
runtime.busy("uploads")
|
|
1590
|
+
return Effect.fail(new RestFailure({ reason: "busy", outcome: "notDispatched" }))
|
|
1591
|
+
}
|
|
1592
|
+
// Check JSON/count admission before allocating binary snapshots, then reserve before any wait
|
|
1593
|
+
if (!runtime.admission.hasRoom(bytes)) {
|
|
1594
|
+
runtime.busy("queue")
|
|
1595
|
+
return Effect.fail(new RestFailure({ reason: "busy", outcome: "notDispatched" }))
|
|
1596
|
+
}
|
|
1597
|
+
runtime.uploadBytes += uploadBytes
|
|
1598
|
+
try {
|
|
1599
|
+
if (request.body) {
|
|
1600
|
+
request.body.files = request.body.files.map((file) => ({
|
|
1601
|
+
...file,
|
|
1602
|
+
source:
|
|
1603
|
+
file.source.kind === "bytes"
|
|
1604
|
+
? { kind: "bytes" as const, data: new Uint8Array(file.source.data) }
|
|
1605
|
+
: file.source,
|
|
1606
|
+
}))
|
|
1607
|
+
request.sources = request.body.files.map((file) => new AttachmentTransferSource(file))
|
|
1608
|
+
}
|
|
1609
|
+
} catch {
|
|
1610
|
+
// allow-silent: An unreadable caller source becomes the typed input failure returned below
|
|
1611
|
+
runtime.uploadBytes -= uploadBytes
|
|
1612
|
+
return Effect.fail(
|
|
1613
|
+
localInputFailure(
|
|
1614
|
+
"attachments[].data",
|
|
1615
|
+
"type",
|
|
1616
|
+
"Attachment byte data must stay readable until the operation has copied it",
|
|
1617
|
+
),
|
|
1618
|
+
)
|
|
1619
|
+
}
|
|
1620
|
+
const deadline = runtime.logical.now() + timeout
|
|
1621
|
+
const generation = runtime.cache?.generation ?? 0
|
|
1622
|
+
const progress: { outcome: Outcome } = { outcome: "notDispatched" }
|
|
1623
|
+
const deletionGuard =
|
|
1624
|
+
request.deleteIds && runtime.cache?.begin(request.channel, undefined, true, generation)
|
|
1625
|
+
// Register before discovery and queue/rate waits so events, writes and gaps invalidate the whole operation
|
|
1626
|
+
const resourceGuard = request.resourceCache && runtime.resources?.begin(request.resourceCache)
|
|
1627
|
+
if (resourceGuard) request = { ...request, resourceGuard }
|
|
1628
|
+
const channelGuard = request.channelCache && runtime.channels?.begin(request.channelCache)
|
|
1629
|
+
if (channelGuard) request = { ...request, channelGuard }
|
|
1630
|
+
const operation = Deferred.makeUnsafe<void>()
|
|
1631
|
+
runtime.operations.add(operation)
|
|
1632
|
+
return Effect.gen(function* () {
|
|
1633
|
+
const resolved = runtime.instance
|
|
1634
|
+
const instance =
|
|
1635
|
+
resolved ??
|
|
1636
|
+
(yield* Effect.acquireUseRelease(
|
|
1637
|
+
// Discovery is not an API request, so a global pause, such as one another child learned,
|
|
1638
|
+
// cannot hold it past the operation's deadline
|
|
1639
|
+
Effect.interruptible(
|
|
1640
|
+
runtime.admission.acquire({ route: "discovery", bytes, rateLimited: false }),
|
|
1641
|
+
),
|
|
1642
|
+
() => runtime.resolveInstance(),
|
|
1643
|
+
(release) => Effect.sync(release),
|
|
1644
|
+
).pipe(mapFailureCause(instanceFailure)))
|
|
1645
|
+
if (!resolved) runtime.instance = instance
|
|
1646
|
+
request = { ...request, instance }
|
|
1647
|
+
if (request.directMessageUser !== undefined) {
|
|
1648
|
+
const open = directMessageOpen(request.directMessageUser)!
|
|
1649
|
+
if (open instanceof InputValidationFailure) return yield* Effect.fail(inputFailure(open.detail))
|
|
1650
|
+
const userGuard = runtime.users?.begin("directMessages", { mutation: true })
|
|
1651
|
+
const channel = yield* owner
|
|
1652
|
+
.#exchange(token, {
|
|
1653
|
+
request: {
|
|
1654
|
+
method: "POST",
|
|
1655
|
+
channel: "@me",
|
|
1656
|
+
bucket: "user:directMessages.open",
|
|
1657
|
+
cache: false,
|
|
1658
|
+
instance,
|
|
1659
|
+
path: open.path,
|
|
1660
|
+
body: { json: open.json!, files: [] },
|
|
1661
|
+
status: 200,
|
|
1662
|
+
preparation: true,
|
|
1663
|
+
decode: async (response, _instance, signal) => {
|
|
1664
|
+
const channel = open.decode(await readResponseJson(response, undefined, signal))
|
|
1665
|
+
if (!channel)
|
|
1666
|
+
throw new RestFailure({
|
|
1667
|
+
reason: "response",
|
|
1668
|
+
outcome: "notDispatched",
|
|
1669
|
+
status: response.status,
|
|
1670
|
+
})
|
|
1671
|
+
return channel
|
|
1672
|
+
},
|
|
1673
|
+
},
|
|
1674
|
+
progress: { outcome: "notDispatched" },
|
|
1675
|
+
generation,
|
|
1676
|
+
deadline,
|
|
1677
|
+
retainedBytes: bytes,
|
|
1678
|
+
})
|
|
1679
|
+
.pipe(
|
|
1680
|
+
mapFailureCause((error) =>
|
|
1681
|
+
error instanceof RestFailure ? error.withOutcome("notDispatched") : error,
|
|
1682
|
+
),
|
|
1683
|
+
Effect.onExit((exit) =>
|
|
1684
|
+
Effect.sync(() => {
|
|
1685
|
+
if (exit._tag === "Failure" && userGuard !== undefined)
|
|
1686
|
+
runtime.users!.failed(userGuard)
|
|
1687
|
+
}),
|
|
1688
|
+
),
|
|
1689
|
+
)
|
|
1690
|
+
if (userGuard !== undefined) runtime.users!.complete(userGuard, [channel])
|
|
1691
|
+
request = {
|
|
1692
|
+
...request,
|
|
1693
|
+
channel: channel.id,
|
|
1694
|
+
path: `/channels/${channel.id}/messages`,
|
|
1695
|
+
decode: (response, _instance, signal) =>
|
|
1696
|
+
request.decodeDirectMessage!(response, channel.id, signal),
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
if (request.body?.files.length && !request.webhookId && !request.inlineAttachments) {
|
|
1700
|
+
const uploadMode = yield* owner.#prepareUploads(token, request.body, request.sources ?? [], {
|
|
1701
|
+
channel: request.channel,
|
|
1702
|
+
instance,
|
|
1703
|
+
progress,
|
|
1704
|
+
generation,
|
|
1705
|
+
deadline,
|
|
1706
|
+
})
|
|
1707
|
+
if (uploadMode === "inline") request = { ...request, inlineAttachments: true }
|
|
1708
|
+
}
|
|
1709
|
+
return yield* owner.#exchange(token, { request, progress, generation, deadline })
|
|
1710
|
+
}).pipe(
|
|
1711
|
+
withDeadline(timeout, () => new RestFailure({ reason: "timeout", outcome: progress.outcome })),
|
|
1712
|
+
Effect.provideService(Clock.Clock, runtime.logical.clock),
|
|
1713
|
+
Effect.ensuring(
|
|
1714
|
+
Effect.promise(() =>
|
|
1715
|
+
completeCleanup((request.sources ?? []).map((source) => () => source.close())),
|
|
1716
|
+
).pipe(
|
|
1717
|
+
Effect.ensuring(
|
|
1718
|
+
Effect.sync(() => {
|
|
1719
|
+
if (request.deleteIds && progress.outcome !== "notDispatched")
|
|
1720
|
+
runtime.cache?.deleteMany(request.channel, request.deleteIds)
|
|
1721
|
+
if (deletionGuard) runtime.cache!.end(deletionGuard)
|
|
1722
|
+
if (resourceGuard)
|
|
1723
|
+
runtime.resources!.end(
|
|
1724
|
+
resourceGuard,
|
|
1725
|
+
request.moderation
|
|
1726
|
+
? progress.outcome !== "notDispatched"
|
|
1727
|
+
: progress.outcome === "unknown",
|
|
1728
|
+
)
|
|
1729
|
+
if (request.deleteAuthorId && progress.outcome !== "notDispatched")
|
|
1730
|
+
runtime.cache?.deleteAuthor(request.deleteAuthorId)
|
|
1731
|
+
// A read begun after deletion dispatch can still observe pre-deletion data, so clear again at completion
|
|
1732
|
+
if (request.invalidateMessages && progress.outcome !== "notDispatched")
|
|
1733
|
+
runtime.cache?.gap()
|
|
1734
|
+
// A rejected multi-entry reorder can have applied earlier entries before its failure
|
|
1735
|
+
if (channelGuard)
|
|
1736
|
+
runtime.channels!.end(channelGuard, progress.outcome !== "notDispatched")
|
|
1737
|
+
if (
|
|
1738
|
+
request.channelCache?.mutation &&
|
|
1739
|
+
request.method === "DELETE" &&
|
|
1740
|
+
request.bucket === "channel:delete" &&
|
|
1741
|
+
progress.outcome === "unknown"
|
|
1742
|
+
)
|
|
1743
|
+
runtime.cache?.deleteChannel(request.channel)
|
|
1744
|
+
if (request.body) request.body.files.length = 0
|
|
1745
|
+
runtime.uploadBytes -= uploadBytes
|
|
1746
|
+
runtime.operations.delete(operation)
|
|
1747
|
+
Deferred.doneUnsafe(operation, Effect.void)
|
|
1748
|
+
}),
|
|
1749
|
+
),
|
|
1750
|
+
),
|
|
1751
|
+
),
|
|
1752
|
+
)
|
|
1753
|
+
}).pipe(
|
|
1754
|
+
// A read that failed after dispatch cannot have changed remote state, so its unknown outcome stays retryable.
|
|
1755
|
+
// Mark it in place: The failure's Cause, including any cleanup defects beside it, stays unchanged
|
|
1756
|
+
Effect.onExit((exit) =>
|
|
1757
|
+
Effect.sync(() => {
|
|
1758
|
+
if (request.method !== "GET" || Exit.isSuccess(exit)) return
|
|
1759
|
+
for (const reason of exit.cause.reasons)
|
|
1760
|
+
if (reason._tag === "Fail" && reason.error instanceof RestFailure) reason.error.read = true
|
|
1761
|
+
}),
|
|
1762
|
+
),
|
|
1763
|
+
)
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
/**
|
|
1767
|
+
* Send one caller-described request through the same discovery, admission, rate-limit learning, 429 waits,
|
|
1768
|
+
* deadline, logging and retry rules as wrapped operations, without message or resource cache coordination.
|
|
1769
|
+
* Files are always sent inline as multipart, never through presigned uploads, because the route is unknown
|
|
1770
|
+
*/
|
|
1771
|
+
request<T>(
|
|
1772
|
+
token: Redacted.Redacted<string>,
|
|
1773
|
+
input: RestRequest | DefaultRestRequest,
|
|
1774
|
+
): Effect.Effect<RestResponse<T>, RestRequestFailure> {
|
|
1775
|
+
return suspendInput((): Effect.Effect<RestResponse<T>, RestFailure | ClientClosedError> => {
|
|
1776
|
+
if (this.#runtime.closed) return Effect.fail(new ClientClosedError())
|
|
1777
|
+
const encoded = encodeRestRequest(input)
|
|
1778
|
+
if (encoded instanceof InputValidationFailure) return Effect.fail(inputFailure(encoded.detail))
|
|
1779
|
+
return this.#execute(
|
|
1780
|
+
token,
|
|
1781
|
+
{
|
|
1782
|
+
method: encoded.method,
|
|
1783
|
+
channel: encoded.major,
|
|
1784
|
+
// Requests to one caller route share provisional rate-limit state until Fluxer names its bucket
|
|
1785
|
+
bucket: `rest:${encoded.method} ${encoded.template}`,
|
|
1786
|
+
cache: false,
|
|
1787
|
+
callerDescribed: true,
|
|
1788
|
+
path: encoded.path,
|
|
1789
|
+
template: encoded.template,
|
|
1790
|
+
body: encoded.body,
|
|
1791
|
+
...(encoded.body?.files.length ? { inlineAttachments: true as const } : {}),
|
|
1792
|
+
...(encoded.auditReason === undefined ? {} : { auditReason: encoded.auditReason }),
|
|
1793
|
+
decode: (response, _instance, signal) => readRestResponse<T>(response, signal),
|
|
1794
|
+
},
|
|
1795
|
+
encoded.timeoutMs === undefined ? undefined : { timeoutMs: encoded.timeoutMs },
|
|
1796
|
+
)
|
|
1797
|
+
}).pipe(mapFailureCause((error) => operationFailure(error, RestRequestError, "rest.request")))
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
/** Close admission and abort every request and download without waiting */
|
|
1801
|
+
stop() {
|
|
1802
|
+
const runtime = this.#runtime
|
|
1803
|
+
runtime.closed = true
|
|
1804
|
+
runtime.instance = undefined
|
|
1805
|
+
runtime.admission.close()
|
|
1806
|
+
for (const source of runtime.downloads) source.fail(new ClientClosedError())
|
|
1807
|
+
for (const controller of runtime.controllers) controller.abort()
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
/** Stop, then wait for every running operation and surface unobserved stream cleanup failures */
|
|
1811
|
+
shutdown(): Effect.Effect<void> {
|
|
1812
|
+
return Effect.suspend(() => {
|
|
1813
|
+
this.stop()
|
|
1814
|
+
const runtime = this.#runtime
|
|
1815
|
+
return Effect.forEach([...runtime.operations], (operation) => Deferred.await(operation), {
|
|
1816
|
+
discard: true,
|
|
1817
|
+
concurrency: "unbounded",
|
|
1818
|
+
}).pipe(
|
|
1819
|
+
Effect.andThen(
|
|
1820
|
+
Effect.suspend(() => {
|
|
1821
|
+
const defects = runtime.unobservedDownloadDefects.take()
|
|
1822
|
+
return defects ? Effect.failCause(defects) : Effect.void
|
|
1823
|
+
}),
|
|
1824
|
+
),
|
|
1825
|
+
)
|
|
1826
|
+
})
|
|
1827
|
+
}
|
|
1828
|
+
}
|