@gakr-gakr/discord 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/account-inspect-api.ts +6 -0
- package/action-runtime-api.ts +1 -0
- package/api.ts +130 -0
- package/autobot.plugin.json +15 -0
- package/channel-config-api.ts +1 -0
- package/channel-plugin-api.ts +3 -0
- package/config-api.ts +4 -0
- package/configured-state.ts +6 -0
- package/contract-api.ts +21 -0
- package/directory-contract-api.ts +4 -0
- package/doctor-contract-api.ts +1 -0
- package/index.ts +24 -0
- package/package.json +79 -0
- package/runtime-api.actions.ts +15 -0
- package/runtime-api.lookup.ts +22 -0
- package/runtime-api.monitor.ts +50 -0
- package/runtime-api.send.ts +79 -0
- package/runtime-api.threads.ts +31 -0
- package/runtime-api.ts +181 -0
- package/runtime-setter-api.ts +3 -0
- package/secret-contract-api.ts +4 -0
- package/security-audit-contract-api.ts +1 -0
- package/security-contract-api.ts +4 -0
- package/session-key-api.ts +1 -0
- package/setup-entry.ts +9 -0
- package/setup-plugin-api.ts +3 -0
- package/src/account-inspect.ts +131 -0
- package/src/accounts.ts +205 -0
- package/src/actions/handle-action.guild-admin.ts +421 -0
- package/src/actions/handle-action.ts +402 -0
- package/src/actions/runtime.guild.ts +446 -0
- package/src/actions/runtime.messaging.messages.ts +226 -0
- package/src/actions/runtime.messaging.reactions.ts +67 -0
- package/src/actions/runtime.messaging.runtime.ts +73 -0
- package/src/actions/runtime.messaging.send.ts +336 -0
- package/src/actions/runtime.messaging.shared.ts +97 -0
- package/src/actions/runtime.messaging.ts +37 -0
- package/src/actions/runtime.moderation-shared.ts +48 -0
- package/src/actions/runtime.moderation.ts +116 -0
- package/src/actions/runtime.presence.ts +117 -0
- package/src/actions/runtime.shared.ts +86 -0
- package/src/actions/runtime.ts +87 -0
- package/src/api.ts +219 -0
- package/src/approval-handler.runtime.ts +636 -0
- package/src/approval-native.ts +219 -0
- package/src/approval-runtime.ts +14 -0
- package/src/approval-shared.ts +56 -0
- package/src/audit-core.ts +178 -0
- package/src/audit.ts +32 -0
- package/src/channel-actions.runtime.ts +1 -0
- package/src/channel-actions.ts +254 -0
- package/src/channel-api.ts +29 -0
- package/src/channel.conversation.ts +159 -0
- package/src/channel.loaders.ts +50 -0
- package/src/channel.runtime.ts +1 -0
- package/src/channel.setup.ts +12 -0
- package/src/channel.ts +728 -0
- package/src/chunk.ts +321 -0
- package/src/client.ts +143 -0
- package/src/component-custom-id.ts +72 -0
- package/src/components-registry.ts +356 -0
- package/src/components.builders.ts +410 -0
- package/src/components.modal.ts +124 -0
- package/src/components.parse.ts +407 -0
- package/src/components.ts +54 -0
- package/src/components.types.ts +187 -0
- package/src/config-schema.ts +6 -0
- package/src/config-ui-hints.ts +354 -0
- package/src/conversation-identity.ts +58 -0
- package/src/delivery-retry.ts +56 -0
- package/src/directory-cache.ts +116 -0
- package/src/directory-config.ts +58 -0
- package/src/directory-live.ts +135 -0
- package/src/doctor-contract.ts +477 -0
- package/src/doctor-shared.ts +5 -0
- package/src/doctor.ts +340 -0
- package/src/draft-chunking.ts +43 -0
- package/src/draft-stream.ts +162 -0
- package/src/error-body.ts +38 -0
- package/src/exec-approvals.ts +110 -0
- package/src/gateway-logging.ts +67 -0
- package/src/group-policy.ts +113 -0
- package/src/guilds.ts +29 -0
- package/src/inbound-event-delivery.ts +135 -0
- package/src/interactive-dispatch.ts +104 -0
- package/src/internal/api.commands.ts +51 -0
- package/src/internal/api.guild.ts +164 -0
- package/src/internal/api.interactions.ts +53 -0
- package/src/internal/api.messages.ts +113 -0
- package/src/internal/api.reactions.ts +38 -0
- package/src/internal/api.ts +61 -0
- package/src/internal/api.users.ts +19 -0
- package/src/internal/api.webhooks.ts +13 -0
- package/src/internal/client.ts +310 -0
- package/src/internal/command-deploy.ts +352 -0
- package/src/internal/commands.ts +188 -0
- package/src/internal/components.base.ts +65 -0
- package/src/internal/components.message.ts +279 -0
- package/src/internal/components.modal.ts +95 -0
- package/src/internal/components.ts +31 -0
- package/src/internal/discord.ts +11 -0
- package/src/internal/embeds.ts +35 -0
- package/src/internal/entity-cache.ts +98 -0
- package/src/internal/event-queue.ts +185 -0
- package/src/internal/gateway-close-codes.ts +25 -0
- package/src/internal/gateway-dispatch.ts +96 -0
- package/src/internal/gateway-identify-limiter.ts +26 -0
- package/src/internal/gateway-lifecycle.ts +75 -0
- package/src/internal/gateway-rate-limit.ts +104 -0
- package/src/internal/gateway.ts +479 -0
- package/src/internal/interaction-dispatch.ts +162 -0
- package/src/internal/interaction-options.ts +98 -0
- package/src/internal/interaction-response.ts +53 -0
- package/src/internal/interactions.ts +378 -0
- package/src/internal/listeners.ts +91 -0
- package/src/internal/modal-fields.ts +95 -0
- package/src/internal/payload.ts +69 -0
- package/src/internal/rest-body.ts +115 -0
- package/src/internal/rest-errors.ts +88 -0
- package/src/internal/rest-routes.ts +50 -0
- package/src/internal/rest-scheduler.ts +557 -0
- package/src/internal/rest.ts +322 -0
- package/src/internal/schemas.ts +36 -0
- package/src/internal/structures.ts +280 -0
- package/src/internal/test-builders.test-support.ts +167 -0
- package/src/internal/voice.ts +49 -0
- package/src/media-detection.ts +28 -0
- package/src/mentions.ts +147 -0
- package/src/monitor/ack-reactions.ts +70 -0
- package/src/monitor/agent-components-auth.ts +7 -0
- package/src/monitor/agent-components-context.ts +154 -0
- package/src/monitor/agent-components-data.ts +224 -0
- package/src/monitor/agent-components-dm-auth.ts +177 -0
- package/src/monitor/agent-components-guild-auth.ts +322 -0
- package/src/monitor/agent-components-helpers.runtime.ts +3 -0
- package/src/monitor/agent-components-helpers.ts +34 -0
- package/src/monitor/agent-components-reply.ts +10 -0
- package/src/monitor/agent-components.deps.runtime.ts +2 -0
- package/src/monitor/agent-components.dispatch.ts +359 -0
- package/src/monitor/agent-components.handlers.ts +303 -0
- package/src/monitor/agent-components.modal.ts +160 -0
- package/src/monitor/agent-components.plugin-interactive.ts +187 -0
- package/src/monitor/agent-components.runtime.ts +14 -0
- package/src/monitor/agent-components.system-controls.ts +215 -0
- package/src/monitor/agent-components.ts +70 -0
- package/src/monitor/agent-components.types.ts +58 -0
- package/src/monitor/agent-components.wildcard-controls.ts +171 -0
- package/src/monitor/allow-list.ts +631 -0
- package/src/monitor/auto-presence.ts +356 -0
- package/src/monitor/channel-access.ts +102 -0
- package/src/monitor/commands.ts +9 -0
- package/src/monitor/dm-command-auth.ts +259 -0
- package/src/monitor/dm-command-decision.ts +49 -0
- package/src/monitor/exec-approvals.ts +161 -0
- package/src/monitor/format.ts +45 -0
- package/src/monitor/gateway-handle.ts +34 -0
- package/src/monitor/gateway-metadata.ts +298 -0
- package/src/monitor/gateway-plugin.ts +302 -0
- package/src/monitor/gateway-registry.ts +37 -0
- package/src/monitor/gateway-supervisor.ts +206 -0
- package/src/monitor/inbound-context.ts +95 -0
- package/src/monitor/inbound-dedupe.ts +79 -0
- package/src/monitor/inbound-job.ts +118 -0
- package/src/monitor/listeners.queue.ts +91 -0
- package/src/monitor/listeners.reactions.ts +594 -0
- package/src/monitor/listeners.ts +150 -0
- package/src/monitor/message-channel-info.ts +96 -0
- package/src/monitor/message-forwarded.ts +114 -0
- package/src/monitor/message-handler.batch-gate.ts +19 -0
- package/src/monitor/message-handler.context.ts +492 -0
- package/src/monitor/message-handler.dm-preflight.ts +119 -0
- package/src/monitor/message-handler.draft-preview.ts +436 -0
- package/src/monitor/message-handler.hydration.ts +198 -0
- package/src/monitor/message-handler.module-test-helpers.ts +31 -0
- package/src/monitor/message-handler.preflight-channel-access.ts +86 -0
- package/src/monitor/message-handler.preflight-channel-context.ts +58 -0
- package/src/monitor/message-handler.preflight-context.ts +54 -0
- package/src/monitor/message-handler.preflight-helpers.ts +164 -0
- package/src/monitor/message-handler.preflight-history.ts +23 -0
- package/src/monitor/message-handler.preflight-logging.ts +36 -0
- package/src/monitor/message-handler.preflight-pluralkit.ts +28 -0
- package/src/monitor/message-handler.preflight-runtime.ts +28 -0
- package/src/monitor/message-handler.preflight-thread.ts +49 -0
- package/src/monitor/message-handler.preflight.ts +822 -0
- package/src/monitor/message-handler.preflight.types.ts +115 -0
- package/src/monitor/message-handler.process.ts +1033 -0
- package/src/monitor/message-handler.routing-preflight.ts +112 -0
- package/src/monitor/message-handler.ts +309 -0
- package/src/monitor/message-media.ts +536 -0
- package/src/monitor/message-run-queue.ts +101 -0
- package/src/monitor/message-text.ts +171 -0
- package/src/monitor/message-utils.ts +34 -0
- package/src/monitor/model-picker-preferences.ts +184 -0
- package/src/monitor/model-picker.state.ts +364 -0
- package/src/monitor/model-picker.test-utils.ts +26 -0
- package/src/monitor/model-picker.ts +38 -0
- package/src/monitor/model-picker.view.ts +722 -0
- package/src/monitor/native-command-agent-reply.ts +125 -0
- package/src/monitor/native-command-arg-ui.ts +233 -0
- package/src/monitor/native-command-auth.ts +309 -0
- package/src/monitor/native-command-bypass.ts +13 -0
- package/src/monitor/native-command-context.ts +109 -0
- package/src/monitor/native-command-dispatch.ts +35 -0
- package/src/monitor/native-command-model-picker-apply.ts +209 -0
- package/src/monitor/native-command-model-picker-interaction.ts +516 -0
- package/src/monitor/native-command-model-picker-ui.ts +357 -0
- package/src/monitor/native-command-reply.ts +185 -0
- package/src/monitor/native-command-route.ts +91 -0
- package/src/monitor/native-command-status.ts +76 -0
- package/src/monitor/native-command-ui.ts +26 -0
- package/src/monitor/native-command-ui.types.ts +20 -0
- package/src/monitor/native-command.args.ts +45 -0
- package/src/monitor/native-command.options.ts +153 -0
- package/src/monitor/native-command.runtime.ts +51 -0
- package/src/monitor/native-command.ts +747 -0
- package/src/monitor/native-command.types.ts +9 -0
- package/src/monitor/native-interaction-channel-context.ts +50 -0
- package/src/monitor/preflight-audio.runtime.ts +9 -0
- package/src/monitor/preflight-audio.ts +130 -0
- package/src/monitor/presence-cache.ts +61 -0
- package/src/monitor/presence.ts +50 -0
- package/src/monitor/provider-session.runtime.ts +12 -0
- package/src/monitor/provider.acp.ts +89 -0
- package/src/monitor/provider.allowlist.ts +398 -0
- package/src/monitor/provider.cleanup.ts +41 -0
- package/src/monitor/provider.commands.ts +129 -0
- package/src/monitor/provider.config-log.ts +45 -0
- package/src/monitor/provider.deploy-errors.ts +362 -0
- package/src/monitor/provider.deploy.ts +221 -0
- package/src/monitor/provider.interactions.ts +160 -0
- package/src/monitor/provider.lifecycle.ts +562 -0
- package/src/monitor/provider.runtime.ts +1 -0
- package/src/monitor/provider.startup-log.ts +32 -0
- package/src/monitor/provider.startup.ts +323 -0
- package/src/monitor/provider.ts +688 -0
- package/src/monitor/reply-context.ts +64 -0
- package/src/monitor/reply-delivery.ts +216 -0
- package/src/monitor/reply-safety.ts +96 -0
- package/src/monitor/rest-fetch.ts +97 -0
- package/src/monitor/route-resolution.ts +140 -0
- package/src/monitor/sender-identity.ts +81 -0
- package/src/monitor/startup-status.ts +10 -0
- package/src/monitor/status.ts +22 -0
- package/src/monitor/system-events.ts +55 -0
- package/src/monitor/thread-bindings.config.ts +35 -0
- package/src/monitor/thread-bindings.discord-api.ts +310 -0
- package/src/monitor/thread-bindings.lifecycle.ts +354 -0
- package/src/monitor/thread-bindings.manager.ts +554 -0
- package/src/monitor/thread-bindings.messages.ts +6 -0
- package/src/monitor/thread-bindings.persona.ts +25 -0
- package/src/monitor/thread-bindings.session-adapter.ts +229 -0
- package/src/monitor/thread-bindings.session-shared.ts +59 -0
- package/src/monitor/thread-bindings.session-updates.ts +35 -0
- package/src/monitor/thread-bindings.state.ts +540 -0
- package/src/monitor/thread-bindings.ts +48 -0
- package/src/monitor/thread-bindings.types.ts +83 -0
- package/src/monitor/thread-channel-context.ts +112 -0
- package/src/monitor/thread-session-close.ts +63 -0
- package/src/monitor/thread-title.ts +181 -0
- package/src/monitor/threading.auto-thread.ts +287 -0
- package/src/monitor/threading.cache.ts +45 -0
- package/src/monitor/threading.starter.ts +288 -0
- package/src/monitor/threading.ts +20 -0
- package/src/monitor/threading.types.ts +102 -0
- package/src/monitor/timeouts.ts +84 -0
- package/src/monitor/typing.ts +17 -0
- package/src/monitor.gateway.ts +75 -0
- package/src/monitor.ts +28 -0
- package/src/network-config.ts +79 -0
- package/src/normalize.ts +86 -0
- package/src/outbound-adapter.ts +327 -0
- package/src/outbound-approval.ts +29 -0
- package/src/outbound-components.ts +86 -0
- package/src/outbound-payload.ts +208 -0
- package/src/outbound-send-context.ts +92 -0
- package/src/outbound-session-route.ts +72 -0
- package/src/pluralkit.ts +58 -0
- package/src/preview-streaming.ts +18 -0
- package/src/probe.runtime.ts +1 -0
- package/src/probe.ts +237 -0
- package/src/proxy-fetch.ts +92 -0
- package/src/proxy-request-client.ts +21 -0
- package/src/recipient-resolution.ts +39 -0
- package/src/resolve-allowlist-common.ts +39 -0
- package/src/resolve-channels.ts +369 -0
- package/src/resolve-users.ts +184 -0
- package/src/retry.ts +98 -0
- package/src/runtime-api.ts +64 -0
- package/src/runtime-config.ts +16 -0
- package/src/runtime.ts +23 -0
- package/src/secret-config-contract.ts +140 -0
- package/src/security-audit.runtime.ts +1 -0
- package/src/security-audit.ts +208 -0
- package/src/security-contract.ts +47 -0
- package/src/security-doctor.ts +20 -0
- package/src/security.ts +60 -0
- package/src/send-target-parsing.ts +14 -0
- package/src/send.channels.ts +139 -0
- package/src/send.components.ts +391 -0
- package/src/send.emojis-stickers.ts +57 -0
- package/src/send.guild.ts +170 -0
- package/src/send.message-request.ts +112 -0
- package/src/send.messages.ts +229 -0
- package/src/send.outbound.ts +459 -0
- package/src/send.permissions.ts +283 -0
- package/src/send.reactions.ts +155 -0
- package/src/send.receipt.ts +69 -0
- package/src/send.shared.ts +469 -0
- package/src/send.ts +82 -0
- package/src/send.types.ts +191 -0
- package/src/send.typing.ts +9 -0
- package/src/send.voice.ts +140 -0
- package/src/send.webhook.ts +137 -0
- package/src/session-contract.ts +3 -0
- package/src/session-key-normalization.ts +47 -0
- package/src/setup-account-state.ts +144 -0
- package/src/setup-adapter.ts +14 -0
- package/src/setup-core.ts +215 -0
- package/src/setup-runtime-helpers.ts +10 -0
- package/src/setup-surface.ts +132 -0
- package/src/shared-interactive.ts +167 -0
- package/src/shared.ts +197 -0
- package/src/status-issues.ts +201 -0
- package/src/subagent-hooks.ts +232 -0
- package/src/target-parsing.ts +70 -0
- package/src/target-resolver.ts +129 -0
- package/src/targets.ts +12 -0
- package/src/token.ts +107 -0
- package/src/ui-colors.ts +27 -0
- package/src/ui.ts +20 -0
- package/src/voice/access.ts +126 -0
- package/src/voice/audio.ts +249 -0
- package/src/voice/capture-state.ts +120 -0
- package/src/voice/command.ts +284 -0
- package/src/voice/config.ts +8 -0
- package/src/voice/ingress.ts +164 -0
- package/src/voice/manager.runtime.ts +14 -0
- package/src/voice/manager.ts +1155 -0
- package/src/voice/prompt.ts +22 -0
- package/src/voice/realtime.ts +1370 -0
- package/src/voice/receive-recovery.ts +159 -0
- package/src/voice/sanitize.ts +29 -0
- package/src/voice/sdk-runtime.ts +14 -0
- package/src/voice/segment.ts +160 -0
- package/src/voice/session.ts +81 -0
- package/src/voice/speaker-context.ts +127 -0
- package/src/voice/tts.ts +151 -0
- package/src/voice-message.ts +474 -0
- package/subagent-hooks-api.ts +27 -0
- package/test-api.ts +4 -0
- package/thread-binding-api.ts +1 -0
- package/timeouts.ts +6 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import { inspect } from "node:util";
|
|
2
|
+
import { formatDurationSeconds } from "autobot/plugin-sdk/runtime-env";
|
|
3
|
+
import { formatErrorMessage } from "autobot/plugin-sdk/ssrf-runtime";
|
|
4
|
+
import { RateLimitError } from "../internal/discord.js";
|
|
5
|
+
|
|
6
|
+
const DISCORD_DEPLOY_REJECTED_ENTRY_LIMIT = 3;
|
|
7
|
+
|
|
8
|
+
type DiscordDeployErrorLike = {
|
|
9
|
+
status?: unknown;
|
|
10
|
+
statusCode?: unknown;
|
|
11
|
+
discordCode?: unknown;
|
|
12
|
+
retryAfter?: unknown;
|
|
13
|
+
scope?: unknown;
|
|
14
|
+
rawBody?: unknown;
|
|
15
|
+
deployRequestBody?: unknown;
|
|
16
|
+
deployRestMethod?: unknown;
|
|
17
|
+
deployRestPath?: unknown;
|
|
18
|
+
deployRequestMs?: unknown;
|
|
19
|
+
deployTimeoutMs?: unknown;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type DiscordDeployRateLimitDetails = {
|
|
23
|
+
status?: number;
|
|
24
|
+
retryAfterMs?: number;
|
|
25
|
+
scope?: string;
|
|
26
|
+
discordCode?: number | string;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function attachDiscordDeployRequestBody(err: unknown, body: unknown) {
|
|
30
|
+
if (!err || typeof err !== "object" || body === undefined) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const deployErr = err as DiscordDeployErrorLike;
|
|
34
|
+
if (deployErr.deployRequestBody === undefined) {
|
|
35
|
+
deployErr.deployRequestBody = body;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function attachDiscordDeployRestContext(
|
|
40
|
+
err: unknown,
|
|
41
|
+
context: {
|
|
42
|
+
method: string;
|
|
43
|
+
path: string;
|
|
44
|
+
requestMs: number;
|
|
45
|
+
timeoutMs?: number;
|
|
46
|
+
},
|
|
47
|
+
) {
|
|
48
|
+
if (!err || typeof err !== "object") {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const deployErr = err as DiscordDeployErrorLike;
|
|
52
|
+
deployErr.deployRestMethod = context.method;
|
|
53
|
+
deployErr.deployRestPath = context.path;
|
|
54
|
+
deployErr.deployRequestMs = context.requestMs;
|
|
55
|
+
if (typeof context.timeoutMs === "number" && Number.isFinite(context.timeoutMs)) {
|
|
56
|
+
deployErr.deployTimeoutMs = context.timeoutMs;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function stringifyDiscordDeployField(value: unknown): string {
|
|
61
|
+
if (typeof value === "string") {
|
|
62
|
+
return JSON.stringify(value);
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
return JSON.stringify(value);
|
|
66
|
+
} catch {
|
|
67
|
+
return inspect(value, { depth: 2, breakLength: 120 });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function readDiscordDeployRejectedFields(value: unknown): string[] {
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
return value.filter((entry): entry is string => typeof entry === "string").slice(0, 6);
|
|
74
|
+
}
|
|
75
|
+
if (!value || typeof value !== "object") {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
return Object.keys(value).slice(0, 6);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveDiscordRejectedDeployEntriesSource(
|
|
82
|
+
rawBody: unknown,
|
|
83
|
+
): Record<string, unknown> | null {
|
|
84
|
+
if (!rawBody || typeof rawBody !== "object") {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const payload = rawBody as { errors?: unknown };
|
|
88
|
+
const errors = payload.errors && typeof payload.errors === "object" ? payload.errors : undefined;
|
|
89
|
+
const source = errors ?? rawBody;
|
|
90
|
+
return source && typeof source === "object" ? (source as Record<string, unknown>) : null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function readDiscordDeployObjectField(value: unknown, field: string): unknown {
|
|
94
|
+
return value && typeof value === "object" && field in value
|
|
95
|
+
? (value as Record<string, unknown>)[field]
|
|
96
|
+
: undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function readFiniteNumber(value: unknown): number | undefined {
|
|
100
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
104
|
+
const parsed = Number(value);
|
|
105
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function formatDurationMs(ms: number): string {
|
|
111
|
+
return formatDurationSeconds(ms, { decimals: ms >= 1000 ? 1 : 0 });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function isAbortLikeError(err: unknown): boolean {
|
|
115
|
+
if (!err || typeof err !== "object") {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
const name = "name" in err && typeof err.name === "string" ? err.name : undefined;
|
|
119
|
+
const message = formatErrorMessage(err);
|
|
120
|
+
return (
|
|
121
|
+
name === "AbortError" ||
|
|
122
|
+
message === "This operation was aborted" ||
|
|
123
|
+
message === "The operation was aborted" ||
|
|
124
|
+
/\boperation was aborted\b/i.test(message)
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function formatDiscordDeployRestOperation(err: DiscordDeployErrorLike): string {
|
|
129
|
+
const method =
|
|
130
|
+
typeof err.deployRestMethod === "string" && err.deployRestMethod.trim().length > 0
|
|
131
|
+
? err.deployRestMethod.toUpperCase()
|
|
132
|
+
: undefined;
|
|
133
|
+
const path =
|
|
134
|
+
typeof err.deployRestPath === "string" && err.deployRestPath.trim().length > 0
|
|
135
|
+
? err.deployRestPath
|
|
136
|
+
: undefined;
|
|
137
|
+
if (method && path) {
|
|
138
|
+
return `${method} ${path}`;
|
|
139
|
+
}
|
|
140
|
+
if (method) {
|
|
141
|
+
return method;
|
|
142
|
+
}
|
|
143
|
+
if (path) {
|
|
144
|
+
return path;
|
|
145
|
+
}
|
|
146
|
+
return "request";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function formatDiscordDeployErrorMessage(err: unknown): string {
|
|
150
|
+
if (!isAbortLikeError(err)) {
|
|
151
|
+
return formatErrorMessage(err);
|
|
152
|
+
}
|
|
153
|
+
const deployErr =
|
|
154
|
+
err && typeof err === "object"
|
|
155
|
+
? (err as DiscordDeployErrorLike)
|
|
156
|
+
: ({} as DiscordDeployErrorLike);
|
|
157
|
+
const requestMs = readFiniteNumber(deployErr.deployRequestMs);
|
|
158
|
+
const timeoutMs = readFiniteNumber(deployErr.deployTimeoutMs);
|
|
159
|
+
const operation = formatDiscordDeployRestOperation(deployErr);
|
|
160
|
+
const hasRestContext =
|
|
161
|
+
requestMs !== undefined ||
|
|
162
|
+
timeoutMs !== undefined ||
|
|
163
|
+
deployErr.deployRestMethod !== undefined ||
|
|
164
|
+
deployErr.deployRestPath !== undefined;
|
|
165
|
+
if (!hasRestContext) {
|
|
166
|
+
return "Discord REST request was aborted";
|
|
167
|
+
}
|
|
168
|
+
const timing: string[] = [];
|
|
169
|
+
if (timeoutMs !== undefined) {
|
|
170
|
+
timing.push(`timeout=${formatDurationMs(timeoutMs)}`);
|
|
171
|
+
}
|
|
172
|
+
if (requestMs !== undefined) {
|
|
173
|
+
timing.push(`observed=${formatDurationMs(requestMs)}`);
|
|
174
|
+
}
|
|
175
|
+
const timingText = timing.length > 0 ? ` (${timing.join(", ")})` : "";
|
|
176
|
+
if (timeoutMs !== undefined && requestMs !== undefined && requestMs >= timeoutMs) {
|
|
177
|
+
return `Discord REST ${operation} timed out${timingText}`;
|
|
178
|
+
}
|
|
179
|
+
return `Discord REST ${operation} was aborted${timingText}`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function resolveDiscordDeployRateLimitDetails(
|
|
183
|
+
err: unknown,
|
|
184
|
+
): DiscordDeployRateLimitDetails | undefined {
|
|
185
|
+
if (!err || typeof err !== "object") {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
const deployErr = err as DiscordDeployErrorLike;
|
|
189
|
+
const status = readFiniteNumber(deployErr.status) ?? readFiniteNumber(deployErr.statusCode);
|
|
190
|
+
const retryAfterSeconds =
|
|
191
|
+
readFiniteNumber(deployErr.retryAfter) ??
|
|
192
|
+
readFiniteNumber(readDiscordDeployObjectField(deployErr.rawBody, "retry_after"));
|
|
193
|
+
const isRateLimit =
|
|
194
|
+
err instanceof RateLimitError || status === 429 || retryAfterSeconds !== undefined;
|
|
195
|
+
if (!isRateLimit) {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
const rawGlobal = readDiscordDeployObjectField(deployErr.rawBody, "global");
|
|
199
|
+
const scope =
|
|
200
|
+
typeof deployErr.scope === "string" && deployErr.scope.trim().length > 0
|
|
201
|
+
? deployErr.scope
|
|
202
|
+
: rawGlobal === true
|
|
203
|
+
? "global"
|
|
204
|
+
: rawGlobal === false
|
|
205
|
+
? "route"
|
|
206
|
+
: undefined;
|
|
207
|
+
const discordCode =
|
|
208
|
+
typeof deployErr.discordCode === "number" || typeof deployErr.discordCode === "string"
|
|
209
|
+
? deployErr.discordCode
|
|
210
|
+
: undefined;
|
|
211
|
+
return {
|
|
212
|
+
status,
|
|
213
|
+
retryAfterMs:
|
|
214
|
+
retryAfterSeconds === undefined ? undefined : Math.max(0, retryAfterSeconds * 1000),
|
|
215
|
+
scope,
|
|
216
|
+
discordCode,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function formatDiscordDeployRateLimitDetails(err: unknown): string {
|
|
221
|
+
const rateLimit = resolveDiscordDeployRateLimitDetails(err);
|
|
222
|
+
if (!rateLimit) {
|
|
223
|
+
return "";
|
|
224
|
+
}
|
|
225
|
+
const details: string[] = [];
|
|
226
|
+
if (typeof rateLimit.status === "number") {
|
|
227
|
+
details.push(`status=${rateLimit.status}`);
|
|
228
|
+
}
|
|
229
|
+
if (typeof rateLimit.retryAfterMs === "number") {
|
|
230
|
+
details.push(
|
|
231
|
+
`retryAfter=${formatDurationSeconds(rateLimit.retryAfterMs, {
|
|
232
|
+
decimals: 1,
|
|
233
|
+
})}`,
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (rateLimit.scope) {
|
|
237
|
+
details.push(`scope=${rateLimit.scope}`);
|
|
238
|
+
}
|
|
239
|
+
if (typeof rateLimit.discordCode === "number" || typeof rateLimit.discordCode === "string") {
|
|
240
|
+
details.push(`code=${rateLimit.discordCode}`);
|
|
241
|
+
}
|
|
242
|
+
return details.length > 0 ? ` (${details.join(", ")})` : "";
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function formatDiscordDeployRateLimitWarning(
|
|
246
|
+
err: unknown,
|
|
247
|
+
accountId: string,
|
|
248
|
+
): string | undefined {
|
|
249
|
+
const rateLimit = resolveDiscordDeployRateLimitDetails(err);
|
|
250
|
+
if (!rateLimit) {
|
|
251
|
+
return undefined;
|
|
252
|
+
}
|
|
253
|
+
const parts = [`discord: native slash command deploy rate limited for ${accountId}`];
|
|
254
|
+
if (typeof rateLimit.retryAfterMs === "number") {
|
|
255
|
+
parts.push(
|
|
256
|
+
`retry after ${formatDurationSeconds(rateLimit.retryAfterMs, {
|
|
257
|
+
decimals: 1,
|
|
258
|
+
})}`,
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
if (rateLimit.scope) {
|
|
262
|
+
parts.push(`scope=${rateLimit.scope}`);
|
|
263
|
+
}
|
|
264
|
+
if (typeof rateLimit.discordCode === "number" || typeof rateLimit.discordCode === "string") {
|
|
265
|
+
parts.push(`code=${rateLimit.discordCode}`);
|
|
266
|
+
}
|
|
267
|
+
return `${parts.join("; ")}. Existing slash commands stay active. Message send/receive is unaffected.`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function formatDiscordRejectedDeployEntries(params: {
|
|
271
|
+
rawBody: unknown;
|
|
272
|
+
requestBody: unknown;
|
|
273
|
+
}): string[] {
|
|
274
|
+
const requestBody = Array.isArray(params.requestBody) ? params.requestBody : null;
|
|
275
|
+
const rejectedEntriesSource = resolveDiscordRejectedDeployEntriesSource(params.rawBody);
|
|
276
|
+
if (!rejectedEntriesSource || !requestBody || requestBody.length === 0) {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
const rawEntries = Object.entries(rejectedEntriesSource).filter(([key]) => /^\d+$/.test(key));
|
|
280
|
+
return rawEntries.slice(0, DISCORD_DEPLOY_REJECTED_ENTRY_LIMIT).flatMap(([key, value]) => {
|
|
281
|
+
const index = Number.parseInt(key, 10);
|
|
282
|
+
if (!Number.isFinite(index) || index < 0 || index >= requestBody.length) {
|
|
283
|
+
return [];
|
|
284
|
+
}
|
|
285
|
+
const command = requestBody[index];
|
|
286
|
+
if (!command || typeof command !== "object") {
|
|
287
|
+
return [`#${index} fields=${readDiscordDeployRejectedFields(value).join("|") || "unknown"}`];
|
|
288
|
+
}
|
|
289
|
+
const payload = command as {
|
|
290
|
+
name?: unknown;
|
|
291
|
+
description?: unknown;
|
|
292
|
+
options?: unknown;
|
|
293
|
+
};
|
|
294
|
+
const parts = [
|
|
295
|
+
`#${index}`,
|
|
296
|
+
`fields=${readDiscordDeployRejectedFields(value).join("|") || "unknown"}`,
|
|
297
|
+
];
|
|
298
|
+
if (typeof payload.name === "string" && payload.name.trim().length > 0) {
|
|
299
|
+
parts.push(`name=${payload.name}`);
|
|
300
|
+
}
|
|
301
|
+
if (payload.description !== undefined) {
|
|
302
|
+
parts.push(`description=${stringifyDiscordDeployField(payload.description)}`);
|
|
303
|
+
}
|
|
304
|
+
if (Array.isArray(payload.options) && payload.options.length > 0) {
|
|
305
|
+
parts.push(`options=${payload.options.length}`);
|
|
306
|
+
}
|
|
307
|
+
return [parts.join(" ")];
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export function formatDiscordDeployErrorDetails(err: unknown): string {
|
|
312
|
+
if (!err || typeof err !== "object") {
|
|
313
|
+
return "";
|
|
314
|
+
}
|
|
315
|
+
const rateLimitDetails = formatDiscordDeployRateLimitDetails(err);
|
|
316
|
+
if (rateLimitDetails) {
|
|
317
|
+
return rateLimitDetails;
|
|
318
|
+
}
|
|
319
|
+
const status = (err as DiscordDeployErrorLike).status;
|
|
320
|
+
const discordCode = (err as DiscordDeployErrorLike).discordCode;
|
|
321
|
+
const rawBody = (err as DiscordDeployErrorLike).rawBody;
|
|
322
|
+
const requestBody = (err as DiscordDeployErrorLike).deployRequestBody;
|
|
323
|
+
const details: string[] = [];
|
|
324
|
+
if (typeof status === "number") {
|
|
325
|
+
details.push(`status=${status}`);
|
|
326
|
+
}
|
|
327
|
+
if (typeof discordCode === "number" || typeof discordCode === "string") {
|
|
328
|
+
details.push(`code=${discordCode}`);
|
|
329
|
+
}
|
|
330
|
+
if (rawBody !== undefined) {
|
|
331
|
+
let bodyText = "";
|
|
332
|
+
try {
|
|
333
|
+
bodyText = JSON.stringify(rawBody);
|
|
334
|
+
} catch {
|
|
335
|
+
bodyText =
|
|
336
|
+
typeof rawBody === "string" ? rawBody : inspect(rawBody, { depth: 3, breakLength: 120 });
|
|
337
|
+
}
|
|
338
|
+
if (bodyText) {
|
|
339
|
+
const maxLen = 800;
|
|
340
|
+
const trimmed = bodyText.length > maxLen ? `${bodyText.slice(0, maxLen)}...` : bodyText;
|
|
341
|
+
details.push(`body=${trimmed}`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const rejectedEntries = formatDiscordRejectedDeployEntries({ rawBody, requestBody });
|
|
345
|
+
if (rejectedEntries.length > 0) {
|
|
346
|
+
details.push(`rejected=${rejectedEntries.join("; ")}`);
|
|
347
|
+
}
|
|
348
|
+
return details.length > 0 ? ` (${details.join(", ")})` : "";
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function isDiscordDeployDailyCreateLimit(err: unknown): boolean {
|
|
352
|
+
if (!err || typeof err !== "object") {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
const deployErr = err as DiscordDeployErrorLike;
|
|
356
|
+
const discordCode = readFiniteNumber(deployErr.discordCode);
|
|
357
|
+
const rawCode = readFiniteNumber(readDiscordDeployObjectField(deployErr.rawBody, "code"));
|
|
358
|
+
return (
|
|
359
|
+
(discordCode === 30034 || rawCode === 30034) &&
|
|
360
|
+
/daily application command creates/i.test(formatErrorMessage(err))
|
|
361
|
+
);
|
|
362
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { warn, type RuntimeEnv } from "autobot/plugin-sdk/runtime-env";
|
|
2
|
+
import { formatErrorMessage } from "autobot/plugin-sdk/ssrf-runtime";
|
|
3
|
+
import { Client, overwriteApplicationCommands, type RequestClient } from "../internal/discord.js";
|
|
4
|
+
import {
|
|
5
|
+
attachDiscordDeployRestContext,
|
|
6
|
+
attachDiscordDeployRequestBody,
|
|
7
|
+
formatDiscordDeployErrorDetails,
|
|
8
|
+
formatDiscordDeployErrorMessage,
|
|
9
|
+
formatDiscordDeployRateLimitDetails,
|
|
10
|
+
formatDiscordDeployRateLimitWarning,
|
|
11
|
+
isDiscordDeployDailyCreateLimit,
|
|
12
|
+
} from "./provider.deploy-errors.js";
|
|
13
|
+
import { logDiscordStartupPhase } from "./provider.startup-log.js";
|
|
14
|
+
|
|
15
|
+
type RestMethodName = "get" | "post" | "put" | "patch" | "delete";
|
|
16
|
+
type RestMethod = RequestClient[RestMethodName];
|
|
17
|
+
type RestMethodMap = Record<RestMethodName, RestMethod>;
|
|
18
|
+
|
|
19
|
+
function readDeployRequestBody(data?: unknown): unknown {
|
|
20
|
+
return data && typeof data === "object" && "body" in data
|
|
21
|
+
? (data as { body?: unknown }).body
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function wrapDeployRestMethod(params: {
|
|
26
|
+
method: RestMethodName;
|
|
27
|
+
original: RestMethodMap;
|
|
28
|
+
runtime: RuntimeEnv;
|
|
29
|
+
accountId: string;
|
|
30
|
+
startupStartedAt: number;
|
|
31
|
+
timeoutMs?: number;
|
|
32
|
+
shouldLogVerbose: () => boolean;
|
|
33
|
+
}) {
|
|
34
|
+
return async (path: string, data?: never, query?: never) => {
|
|
35
|
+
const startedAt = Date.now();
|
|
36
|
+
const body = readDeployRequestBody(data);
|
|
37
|
+
const commandCount = Array.isArray(body) ? body.length : undefined;
|
|
38
|
+
const bodyBytes =
|
|
39
|
+
body === undefined
|
|
40
|
+
? undefined
|
|
41
|
+
: Buffer.byteLength(typeof body === "string" ? body : JSON.stringify(body), "utf8");
|
|
42
|
+
if (params.shouldLogVerbose()) {
|
|
43
|
+
params.runtime.log?.(
|
|
44
|
+
`discord startup [${params.accountId}] native-slash-command-deploy-rest:${params.method}:start ${Math.max(0, Date.now() - params.startupStartedAt)}ms path=${path}${typeof commandCount === "number" ? ` commands=${commandCount}` : ""}${typeof bodyBytes === "number" ? ` bytes=${bodyBytes}` : ""}`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const result = await params.original[params.method](path, data, query);
|
|
49
|
+
if (params.shouldLogVerbose()) {
|
|
50
|
+
params.runtime.log?.(
|
|
51
|
+
`discord startup [${params.accountId}] native-slash-command-deploy-rest:${params.method}:done ${Math.max(0, Date.now() - params.startupStartedAt)}ms path=${path} requestMs=${Date.now() - startedAt}`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
} catch (err) {
|
|
56
|
+
const requestMs = Date.now() - startedAt;
|
|
57
|
+
attachDiscordDeployRequestBody(err, body);
|
|
58
|
+
attachDiscordDeployRestContext(err, {
|
|
59
|
+
method: params.method,
|
|
60
|
+
path,
|
|
61
|
+
requestMs,
|
|
62
|
+
timeoutMs: params.timeoutMs,
|
|
63
|
+
});
|
|
64
|
+
const rateLimitDetails = formatDiscordDeployRateLimitDetails(err);
|
|
65
|
+
if (rateLimitDetails) {
|
|
66
|
+
if (params.shouldLogVerbose()) {
|
|
67
|
+
params.runtime.log?.(
|
|
68
|
+
warn(
|
|
69
|
+
`discord startup [${params.accountId}] native-slash-command-deploy-rest:${params.method}:rate-limited ${Math.max(0, Date.now() - params.startupStartedAt)}ms path=${path} requestMs=${requestMs}${rateLimitDetails}`,
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
const details = formatDiscordDeployErrorDetails(err);
|
|
75
|
+
params.runtime.error?.(
|
|
76
|
+
`discord startup [${params.accountId}] native-slash-command-deploy-rest:${params.method}:error ${Math.max(0, Date.now() - params.startupStartedAt)}ms path=${path} requestMs=${requestMs} error=${formatDiscordDeployErrorMessage(err)}${details}`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function installDeployRestLogging(params: {
|
|
85
|
+
rest: RequestClient;
|
|
86
|
+
runtime: RuntimeEnv;
|
|
87
|
+
accountId: string;
|
|
88
|
+
startupStartedAt: number;
|
|
89
|
+
shouldLogVerbose: () => boolean;
|
|
90
|
+
}): () => void {
|
|
91
|
+
const original: RestMethodMap = {
|
|
92
|
+
get: params.rest.get.bind(params.rest),
|
|
93
|
+
post: params.rest.post.bind(params.rest),
|
|
94
|
+
put: params.rest.put.bind(params.rest),
|
|
95
|
+
patch: params.rest.patch.bind(params.rest),
|
|
96
|
+
delete: params.rest.delete.bind(params.rest),
|
|
97
|
+
};
|
|
98
|
+
for (const method of Object.keys(original) as RestMethodName[]) {
|
|
99
|
+
const timeout = (params.rest as { options?: { timeout?: unknown } }).options?.timeout;
|
|
100
|
+
params.rest[method] = wrapDeployRestMethod({
|
|
101
|
+
method,
|
|
102
|
+
original,
|
|
103
|
+
runtime: params.runtime,
|
|
104
|
+
accountId: params.accountId,
|
|
105
|
+
startupStartedAt: params.startupStartedAt,
|
|
106
|
+
timeoutMs: typeof timeout === "number" ? timeout : undefined,
|
|
107
|
+
shouldLogVerbose: params.shouldLogVerbose,
|
|
108
|
+
}) as RequestClient[typeof method];
|
|
109
|
+
}
|
|
110
|
+
return () => {
|
|
111
|
+
params.rest.get = original.get;
|
|
112
|
+
params.rest.post = original.post;
|
|
113
|
+
params.rest.put = original.put;
|
|
114
|
+
params.rest.patch = original.patch;
|
|
115
|
+
params.rest.delete = original.delete;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function deployDiscordCommands(params: {
|
|
120
|
+
client: Client;
|
|
121
|
+
runtime: RuntimeEnv;
|
|
122
|
+
enabled: boolean;
|
|
123
|
+
accountId?: string;
|
|
124
|
+
startupStartedAt?: number;
|
|
125
|
+
shouldLogVerbose: () => boolean;
|
|
126
|
+
}) {
|
|
127
|
+
if (!params.enabled) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const startupStartedAt = params.startupStartedAt ?? Date.now();
|
|
131
|
+
const accountId = params.accountId ?? "default";
|
|
132
|
+
const restoreDeployRestLogging = installDeployRestLogging({
|
|
133
|
+
rest: params.client.rest,
|
|
134
|
+
runtime: params.runtime,
|
|
135
|
+
accountId,
|
|
136
|
+
startupStartedAt,
|
|
137
|
+
shouldLogVerbose: params.shouldLogVerbose,
|
|
138
|
+
});
|
|
139
|
+
try {
|
|
140
|
+
try {
|
|
141
|
+
await params.client.deployCommands({ mode: "reconcile" });
|
|
142
|
+
return;
|
|
143
|
+
} catch (err) {
|
|
144
|
+
if (isDiscordDeployDailyCreateLimit(err)) {
|
|
145
|
+
params.runtime.log?.(
|
|
146
|
+
warn(
|
|
147
|
+
`discord: native slash command deploy skipped for ${accountId}; daily application command create limit reached. Existing slash commands stay active until Discord resets the quota. Message send/receive is unaffected.`,
|
|
148
|
+
),
|
|
149
|
+
);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const rateLimitWarning = formatDiscordDeployRateLimitWarning(err, accountId);
|
|
153
|
+
if (rateLimitWarning) {
|
|
154
|
+
params.runtime.log?.(warn(rateLimitWarning));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
throw err;
|
|
158
|
+
}
|
|
159
|
+
} catch (err) {
|
|
160
|
+
params.runtime.log?.(
|
|
161
|
+
warn(
|
|
162
|
+
`discord: native slash command deploy warning (not message send): ${formatDiscordDeployErrorMessage(err)}${formatDiscordDeployErrorDetails(err)}`,
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
} finally {
|
|
166
|
+
restoreDeployRestLogging();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function runDiscordCommandDeployInBackground(params: {
|
|
171
|
+
client: Client;
|
|
172
|
+
runtime: RuntimeEnv;
|
|
173
|
+
enabled: boolean;
|
|
174
|
+
accountId: string;
|
|
175
|
+
startupStartedAt: number;
|
|
176
|
+
shouldLogVerbose: () => boolean;
|
|
177
|
+
isVerbose: () => boolean;
|
|
178
|
+
}) {
|
|
179
|
+
if (!params.enabled) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
logDiscordStartupPhase({
|
|
183
|
+
runtime: params.runtime,
|
|
184
|
+
accountId: params.accountId,
|
|
185
|
+
phase: "deploy-commands:scheduled",
|
|
186
|
+
startAt: params.startupStartedAt,
|
|
187
|
+
details: "mode=reconcile background=true",
|
|
188
|
+
isVerbose: params.isVerbose,
|
|
189
|
+
});
|
|
190
|
+
void deployDiscordCommands(params)
|
|
191
|
+
.then(() => {
|
|
192
|
+
logDiscordStartupPhase({
|
|
193
|
+
runtime: params.runtime,
|
|
194
|
+
accountId: params.accountId,
|
|
195
|
+
phase: "deploy-commands:done",
|
|
196
|
+
startAt: params.startupStartedAt,
|
|
197
|
+
details: "background=true",
|
|
198
|
+
isVerbose: params.isVerbose,
|
|
199
|
+
});
|
|
200
|
+
})
|
|
201
|
+
.catch((err: unknown) => {
|
|
202
|
+
params.runtime.log?.(
|
|
203
|
+
warn(
|
|
204
|
+
`discord: native slash command deploy background warning (not message send): ${formatErrorMessage(err)}`,
|
|
205
|
+
),
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export async function clearDiscordNativeCommands(params: {
|
|
211
|
+
client: Client;
|
|
212
|
+
applicationId: string;
|
|
213
|
+
runtime: RuntimeEnv;
|
|
214
|
+
}) {
|
|
215
|
+
try {
|
|
216
|
+
await overwriteApplicationCommands(params.client.rest, params.applicationId, []);
|
|
217
|
+
params.runtime.log?.("discord: cleared native commands (commands.native=false)");
|
|
218
|
+
} catch (err) {
|
|
219
|
+
params.runtime.error?.(`discord: failed to clear native commands: ${String(err)}`);
|
|
220
|
+
}
|
|
221
|
+
}
|