@openclaw/discord 2026.10.1 → 2026.10.5-beta.1
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/dist/.setup/account-inspect-8cCu6uPG.mjs +31 -0
- package/dist/.setup/{accounts-HE9-mj1L.mjs → accounts-ljrzXBJi.mjs} +47 -45
- package/dist/.setup/{allow-list-vxkG9_JD.mjs → allow-list-B_ToXtew.mjs} +34 -101
- package/dist/.setup/{api-DlNUkDqj.mjs → api-CtmE1OUN.mjs} +25 -31
- package/dist/.setup/{approval-handler.runtime-DmnEa54W.mjs → approval-handler.runtime-D7FoZSn0.mjs} +30 -53
- package/dist/.setup/{approval-message-updates-B0jdSqOj.mjs → approval-message-updates-CIGByUcE.mjs} +2 -2
- package/dist/.setup/{audit-BpikUwN_.mjs → audit-zSawfbsN.mjs} +5 -8
- package/dist/.setup/{channel-Dr-AUnGt.mjs → channel-DI7DMzu0.mjs} +136 -215
- package/dist/.setup/{channel-access-BRp3Y-rF.mjs → channel-access-DasWY_OV.mjs} +6 -7
- package/dist/.setup/{channel.setup-BmNvkidb.mjs → channel.setup-DdFVN1mr.mjs} +35 -64
- package/dist/.setup/{components-DLJR0xU-.mjs → components-HN9052L1.mjs} +123 -146
- package/dist/.setup/{config-schema-BQWfnSCx.mjs → config-schema-_uBILpQf.mjs} +7 -3
- package/dist/.setup/{conversation-binding-route-DicJC1Lj.mjs → conversation-binding-route-DTjCBx-O.mjs} +1 -1
- package/dist/.setup/{directory-config-gqsdcplU.mjs → directory-config-3iVub-3m.mjs} +1 -1
- package/dist/.setup/{directory-live-Bipr0eUJ.mjs → directory-live-DLygQVtW.mjs} +18 -22
- package/dist/.setup/{discord-9gysrhzp.mjs → discord-BGqgx-yd.mjs} +686 -854
- package/dist/.setup/{doctor-B2bskDcF.mjs → doctor-DSrNJ7m2.mjs} +36 -47
- package/dist/.setup/{doctor-contract-Bg3NPAMw.mjs → doctor-contract-Bwv8EuQ_.mjs} +7 -16
- package/dist/.setup/{handle-action-UmkjXBfo.mjs → handle-action-CXH1h1tq.mjs} +25 -38
- package/dist/.setup/{handle-action.guild-admin-CB4sc9VV.mjs → handle-action.guild-admin-CHKW6PIs.mjs} +25 -31
- package/dist/.setup/{live-policy-config-VxexfRKo.mjs → live-policy-config-BPoB3eQi.mjs} +1 -1
- package/dist/.setup/{message-handler-BK69A-NB.mjs → message-handler-Ii_etru1.mjs} +9 -14
- package/dist/.setup/{message-handler.preflight-DFpsh90H.mjs → message-handler.preflight-C7YuSRl_.mjs} +79 -128
- package/dist/.setup/{message-handler.preflight-pluralkit-BXGGVmpe.mjs → message-handler.preflight-pluralkit-C3iAG--b.mjs} +6 -6
- package/dist/.setup/{message-handler.process-TKoqcqIP.mjs → message-handler.process-ClgWYH6o.mjs} +234 -206
- package/dist/.setup/{outbound-adapter-D4wRAb5S.mjs → outbound-adapter-D8OOIuKn.mjs} +73 -112
- package/dist/.setup/{outbound-session-route-BvBH4LC6.mjs → outbound-session-route-B0Hpwn3Q.mjs} +57 -115
- package/dist/.setup/output-activity-uBpMSX75.mjs +11 -0
- package/dist/.setup/{pluralkit-a6_NLfH9.mjs → pluralkit-B64dfq_j.mjs} +3 -1
- package/dist/.setup/{preflight-audio-DHGIHEpv.mjs → preflight-audio-wWgsZG5F.mjs} +1 -5
- package/dist/.setup/{presence-cache-Dg3_dADn.mjs → presence-cache-DCeTsL73.mjs} +3 -6
- package/dist/.setup/{probe-BwSKpnZf.mjs → probe-D3P1x4aN.mjs} +10 -18
- package/dist/.setup/{provider-YP8gN9_o.mjs → provider-D9EzOfG8.mjs} +2990 -3903
- package/dist/.setup/{provider-session.runtime-D1gkPxHT.mjs → provider-session.runtime-CsnRvddI.mjs} +5 -5
- package/dist/.setup/provider.runtime-BQVcM7Pg.mjs +2 -0
- package/dist/.setup/{realtime-session.runtime-BKUQBy1u.mjs → realtime-session.runtime-CxGBk8H-.mjs} +69 -98
- package/dist/.setup/{receive-recovery-DgkX7Qvi.mjs → receive-recovery-eVmK2_hl.mjs} +2 -12
- package/dist/.setup/resolve-allowlist-common-DNSsUQRF.mjs +66 -0
- package/dist/.setup/resolve-channels-UdT38DzU.mjs +173 -0
- package/dist/.setup/{resolve-users-DNrwvunm.mjs → resolve-users-DnCsrXZ_.mjs} +12 -41
- package/dist/.setup/{runtime-CESTexGn.mjs → runtime-CRTkKU1G.mjs} +202 -313
- package/dist/.setup/{runtime-DPcmPST9.mjs → runtime-DPm3gZXk.mjs} +2 -2
- package/dist/.setup/{secret-config-contract-uOE2J7yM.mjs → secret-config-contract-CIsH7R3B.mjs} +9 -18
- package/dist/.setup/{security-audit-D42cp5N7.mjs → security-audit-BFT84Uny.mjs} +1 -2
- package/dist/.setup/security-contract-DNyyjTZZ.mjs +19 -0
- package/dist/.setup/{send-CJk3VP5q.mjs → send-DbILKgcm.mjs} +184 -241
- package/dist/.setup/{send.components-dPljuV24.mjs → send.components-FxOS3CeP.mjs} +47 -63
- package/dist/.setup/{send.outbound-rOboMO_6.mjs → send.outbound-_jx4Xpd3.mjs} +178 -202
- package/dist/.setup/{send.receipt-DVOg2Oaw.mjs → send.receipt-BAlzXd8e.mjs} +33 -109
- package/dist/.setup/{send.shared-C4CN24D9.mjs → send.shared-CjQ4jbMA.mjs} +97 -153
- package/dist/.setup/{sender-identity-AHpUNr72.mjs → sender-identity-BNBvGt1l.mjs} +1 -1
- package/dist/.setup/setup-plugin-api-xfOFmxHP.mjs +3 -0
- package/dist/.setup/{shared-BoBnM5kM.mjs → shared-CestGDpq.mjs} +30 -20
- package/dist/.setup/{subagent-hooks-HH8Uy9cx.mjs → subagent-hooks-CME7dSGf.mjs} +5 -10
- package/dist/.setup/{system-events-Cwxaww8i.mjs → system-events-BwwSDCw4.mjs} +2 -2
- package/dist/.setup/target-parsing-C-HyNxcE.mjs +48 -0
- package/dist/.setup/{target-resolver-CSFoPQ12.mjs → target-resolver-Bse8fuTi.mjs} +11 -27
- package/dist/.setup/targets-DZJjkzwv.mjs +3 -0
- package/dist/.setup/{thread-bindings-DjQCkmsd.mjs → thread-bindings-0hPTSK14.mjs} +61 -52
- package/dist/.setup/{thread-bindings.manager-D2-GYZ5s.mjs → thread-bindings.manager-CdNa6UIs.mjs} +138 -211
- package/dist/.setup/{thread-bindings.session-updates-Bu_CGr_O.mjs → thread-bindings.session-updates-DGSljVf6.mjs} +60 -99
- package/dist/.setup/threading-BKe3E3tp.mjs +246 -0
- package/dist/.setup/{timeouts-pun7VJ02.mjs → timeouts-CuNARfyw.mjs} +10 -18
- package/dist/.setup/{transcripts-source-CaZQnGRH.mjs → transcripts-source-0qQYVu2H.mjs} +50 -368
- package/dist/.setup/{voice-runtime-DDymtIw8.mjs → voice-runtime-QlZJ4sHv.mjs} +166 -322
- package/dist/account-inspect-api.js +1 -1
- package/dist/action-runtime-api.js +1 -1
- package/dist/activities-api.js +77 -120
- package/dist/api.js +19 -18
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +1 -1
- package/dist/runtime-api.js +21 -20
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/src/voice/audio-worker.runtime.js +38 -57
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/node_modules/discord-api-types/_generated_/rest/v10/interfaces.d.ts +21 -0
- package/node_modules/discord-api-types/_generated_/rest/v10/interfaces.d.ts.map +1 -1
- package/node_modules/discord-api-types/_generated_/rest/v9/interfaces.d.ts +21 -0
- package/node_modules/discord-api-types/_generated_/rest/v9/interfaces.d.ts.map +1 -1
- package/node_modules/discord-api-types/globals.d.ts +6 -0
- package/node_modules/discord-api-types/globals.d.ts.map +1 -1
- package/node_modules/discord-api-types/globals.js +6 -0
- package/node_modules/discord-api-types/globals.js.map +1 -1
- package/node_modules/discord-api-types/package.json +3 -3
- package/node_modules/discord-api-types/payloads/index.mjs +1 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.d.ts +207 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.js +25 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/payloads/v10/autoModeration.d.ts +1 -1
- package/node_modules/discord-api-types/payloads/v10/autoModeration.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/guild.d.ts +27 -23
- package/node_modules/discord-api-types/payloads/v10/guild.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/guild.js +26 -22
- package/node_modules/discord-api-types/payloads/v10/guild.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/index.d.ts +1 -0
- package/node_modules/discord-api-types/payloads/v10/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/index.js +1 -0
- package/node_modules/discord-api-types/payloads/v10/index.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/index.mjs +1 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.d.ts +207 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.js +25 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/payloads/v9/autoModeration.d.ts +1 -1
- package/node_modules/discord-api-types/payloads/v9/autoModeration.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/guild.d.ts +27 -23
- package/node_modules/discord-api-types/payloads/v9/guild.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/guild.js +26 -22
- package/node_modules/discord-api-types/payloads/v9/guild.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/index.d.ts +1 -0
- package/node_modules/discord-api-types/payloads/v9/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/index.js +1 -0
- package/node_modules/discord-api-types/payloads/v9/index.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/index.mjs +1 -0
- package/node_modules/discord-api-types/rest/common.d.ts +2 -0
- package/node_modules/discord-api-types/rest/common.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/common.js +2 -0
- package/node_modules/discord-api-types/rest/common.js.map +1 -1
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.d.ts +70 -0
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.js +3 -0
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/rest/v10/index.d.ts +1 -0
- package/node_modules/discord-api-types/rest/v10/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v10/index.js +29 -0
- package/node_modules/discord-api-types/rest/v10/index.js.map +1 -1
- package/node_modules/discord-api-types/rest/v10/interactions.d.ts +4 -2
- package/node_modules/discord-api-types/rest/v10/interactions.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v10/user.d.ts +2 -2
- package/node_modules/discord-api-types/rest/v10/user.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.d.ts +70 -0
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.js +3 -0
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/rest/v9/index.d.ts +1 -0
- package/node_modules/discord-api-types/rest/v9/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v9/index.js +29 -0
- package/node_modules/discord-api-types/rest/v9/index.js.map +1 -1
- package/node_modules/discord-api-types/rest/v9/interactions.d.ts +4 -2
- package/node_modules/discord-api-types/rest/v9/interactions.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v9/user.d.ts +2 -2
- package/node_modules/discord-api-types/rest/v9/user.d.ts.map +1 -1
- package/node_modules/discord-api-types/v10.mjs +1 -0
- package/node_modules/discord-api-types/v9.mjs +1 -0
- package/node_modules/ws/lib/websocket.js +17 -3
- package/node_modules/ws/package.json +1 -1
- package/openclaw.plugin.json +3 -6
- package/package.json +7 -12
- package/dist/.setup/account-inspect-DsER5ILV.mjs +0 -45
- package/dist/.setup/provider.runtime-CZ51OIgD.mjs +0 -2
- package/dist/.setup/resolve-allowlist-common-BUyU3C-T.mjs +0 -27
- package/dist/.setup/resolve-channels-DA6QlhZN.mjs +0 -246
- package/dist/.setup/security-contract-DSHk7I2w.mjs +0 -26
- package/dist/.setup/setup-plugin-api-BVlCz3fm.mjs +0 -3
- package/dist/.setup/targets-bqXQENmX.mjs +0 -3
- package/dist/control-ui/2afbdab1d3aa65a789d8a3eba666f4b1ec5df07073538fe30d6cf32093a1fb2d/index.js +0 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { i as listDiscordAccountIds, n as inspectDiscordAccountConfig, v as resolveDiscordAccountAvailability } from "./accounts-ljrzXBJi.mjs";
|
|
2
|
+
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
3
|
+
import { normalizeSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
4
|
+
//#region extensions/discord/src/account-inspect.ts
|
|
5
|
+
function inspectDiscordAccountPrimary(params) {
|
|
6
|
+
return inspectDiscordAccountConfig(params, {
|
|
7
|
+
includeName: true,
|
|
8
|
+
resolveFallbackToken: (accountId) => {
|
|
9
|
+
const envToken = accountId === DEFAULT_ACCOUNT_ID ? normalizeSecretInputString(params.envToken ?? process.env.DISCORD_BOT_TOKEN) : void 0;
|
|
10
|
+
return {
|
|
11
|
+
token: envToken?.replace(/^Bot\s+/i, "") ?? "",
|
|
12
|
+
source: envToken ? "env" : "none"
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function inspectDiscordAccount(params) {
|
|
18
|
+
const account = inspectDiscordAccountPrimary(params);
|
|
19
|
+
return {
|
|
20
|
+
...account,
|
|
21
|
+
...resolveDiscordAccountAvailability({
|
|
22
|
+
account,
|
|
23
|
+
resolveAccounts: () => listDiscordAccountIds(params.cfg).map((accountId) => inspectDiscordAccountPrimary({
|
|
24
|
+
...params,
|
|
25
|
+
accountId
|
|
26
|
+
}))
|
|
27
|
+
})
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { inspectDiscordAccount as t };
|
|
@@ -1,23 +1,18 @@
|
|
|
1
1
|
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
2
2
|
import { hasConfiguredSecretInput, normalizeResolvedSecretInputString, normalizeSecretInputString, resolveSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
|
3
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
3
|
import { createAccountActionGate, createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers";
|
|
5
4
|
import { mapAllowFromEntries, normalizeChannelDmPolicy } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
6
5
|
import { resolveConfiguredFromCredentialStatuses } from "openclaw/plugin-sdk/channel-status";
|
|
7
6
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, normalizeAccountId as normalizeAccountId$1, resolveAccountEntry } from "openclaw/plugin-sdk/routing";
|
|
7
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import { getRuntimeConfigSnapshot, getRuntimeConfigSourceSnapshot, selectApplicableRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
|
|
9
9
|
//#region extensions/discord/src/account-token-inspect.ts
|
|
10
10
|
function inspectDiscordConfiguredToken(value) {
|
|
11
11
|
const normalized = normalizeSecretInputString(value);
|
|
12
|
-
if (normalized) return {
|
|
13
|
-
token: normalized.replace(/^Bot\s+/i, ""),
|
|
12
|
+
if (normalized || hasConfiguredSecretInput(value)) return {
|
|
13
|
+
token: normalized ? normalized.replace(/^Bot\s+/i, "") : "",
|
|
14
14
|
tokenSource: "config",
|
|
15
|
-
tokenStatus: "available"
|
|
16
|
-
};
|
|
17
|
-
if (hasConfiguredSecretInput(value)) return {
|
|
18
|
-
token: "",
|
|
19
|
-
tokenSource: "config",
|
|
20
|
-
tokenStatus: "configured_unavailable"
|
|
15
|
+
tokenStatus: normalized ? "available" : "configured_unavailable"
|
|
21
16
|
};
|
|
22
17
|
return null;
|
|
23
18
|
}
|
|
@@ -106,8 +101,7 @@ function normalizeDiscordToken(raw, path) {
|
|
|
106
101
|
value: raw,
|
|
107
102
|
path
|
|
108
103
|
});
|
|
109
|
-
|
|
110
|
-
return stripDiscordBotPrefix(trimmed);
|
|
104
|
+
return trimmed ? stripDiscordBotPrefix(trimmed) : void 0;
|
|
111
105
|
}
|
|
112
106
|
function resolveDiscordTokenValue(params) {
|
|
113
107
|
const resolved = resolveSecretInputString({
|
|
@@ -116,12 +110,19 @@ function resolveDiscordTokenValue(params) {
|
|
|
116
110
|
defaults: params.cfg.secrets?.defaults,
|
|
117
111
|
mode: "inspect"
|
|
118
112
|
});
|
|
119
|
-
if (resolved.status === "available")
|
|
120
|
-
|
|
121
|
-
|
|
113
|
+
if (resolved.status === "available") {
|
|
114
|
+
const token = stripDiscordBotPrefix(resolved.value);
|
|
115
|
+
return token ? {
|
|
116
|
+
token,
|
|
117
|
+
source: "config",
|
|
118
|
+
tokenStatus: "available"
|
|
119
|
+
} : void 0;
|
|
120
|
+
}
|
|
121
|
+
if (resolved.status === "configured_unavailable") return {
|
|
122
|
+
token: "",
|
|
123
|
+
source: "config",
|
|
124
|
+
tokenStatus: "configured_unavailable"
|
|
122
125
|
};
|
|
123
|
-
if (resolved.status === "configured_unavailable") return { status: "configured_unavailable" };
|
|
124
|
-
return { status: "missing" };
|
|
125
126
|
}
|
|
126
127
|
function resolveDiscordToken(cfg, opts = {}) {
|
|
127
128
|
const selectedCfg = selectDiscordRuntimeConfig(cfg);
|
|
@@ -134,16 +135,7 @@ function resolveDiscordToken(cfg, opts = {}) {
|
|
|
134
135
|
value: accountCfg?.token,
|
|
135
136
|
path: `channels.discord.accounts.${accountId}.token`
|
|
136
137
|
});
|
|
137
|
-
if (accountToken
|
|
138
|
-
token: accountToken.value,
|
|
139
|
-
source: "config",
|
|
140
|
-
tokenStatus: "available"
|
|
141
|
-
};
|
|
142
|
-
if (accountToken.status === "configured_unavailable") return {
|
|
143
|
-
token: "",
|
|
144
|
-
source: "config",
|
|
145
|
-
tokenStatus: "configured_unavailable"
|
|
146
|
-
};
|
|
138
|
+
if (accountToken) return accountToken;
|
|
147
139
|
if (hasAccountToken) return {
|
|
148
140
|
token: "",
|
|
149
141
|
source: "none",
|
|
@@ -154,16 +146,7 @@ function resolveDiscordToken(cfg, opts = {}) {
|
|
|
154
146
|
value: discordCfg?.token,
|
|
155
147
|
path: "channels.discord.token"
|
|
156
148
|
});
|
|
157
|
-
if (configToken
|
|
158
|
-
token: configToken.value,
|
|
159
|
-
source: "config",
|
|
160
|
-
tokenStatus: "available"
|
|
161
|
-
};
|
|
162
|
-
if (configToken.status === "configured_unavailable") return {
|
|
163
|
-
token: "",
|
|
164
|
-
source: "config",
|
|
165
|
-
tokenStatus: "configured_unavailable"
|
|
166
|
-
};
|
|
149
|
+
if (configToken) return configToken;
|
|
167
150
|
const envToken = accountId === DEFAULT_ACCOUNT_ID$1 ? normalizeDiscordToken(opts.envToken ?? process.env.DISCORD_BOT_TOKEN, "DISCORD_BOT_TOKEN") : void 0;
|
|
168
151
|
if (envToken) return {
|
|
169
152
|
token: envToken,
|
|
@@ -178,7 +161,7 @@ function resolveDiscordToken(cfg, opts = {}) {
|
|
|
178
161
|
}
|
|
179
162
|
//#endregion
|
|
180
163
|
//#region extensions/discord/src/accounts.ts
|
|
181
|
-
const { listAccountIds, resolveDefaultAccountId, resolveAccountConfig: mergeDiscordAccountConfig } = createAccountListHelpers("discord", {
|
|
164
|
+
const { listAccountIds: listDiscordAccountIds, resolveDefaultAccountId: resolveDefaultDiscordAccountId, resolveAccountConfig: mergeDiscordAccountConfig } = createAccountListHelpers("discord", {
|
|
182
165
|
implicitDefaultAccount: {
|
|
183
166
|
channelKeys: ["token"],
|
|
184
167
|
envVars: ["DISCORD_BOT_TOKEN"]
|
|
@@ -189,29 +172,48 @@ const { listAccountIds, resolveDefaultAccountId, resolveAccountConfig: mergeDisc
|
|
|
189
172
|
"botLoopProtection"
|
|
190
173
|
]
|
|
191
174
|
});
|
|
192
|
-
const listDiscordAccountIds = listAccountIds;
|
|
193
|
-
const resolveDefaultDiscordAccountId = resolveDefaultAccountId;
|
|
194
175
|
function resolveDiscordAccountConfig(cfg, accountId) {
|
|
195
176
|
return resolveAccountEntry(cfg.channels?.discord?.accounts, accountId);
|
|
196
177
|
}
|
|
197
|
-
function
|
|
178
|
+
function inspectDiscordAccountConfig(params, options) {
|
|
198
179
|
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
|
|
180
|
+
const config = mergeDiscordAccountConfig(params.cfg, accountId);
|
|
181
|
+
const enabled = params.cfg.channels?.discord?.enabled !== false && config.enabled !== false;
|
|
199
182
|
const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
|
|
183
|
+
const hasAccountToken = Boolean(accountConfig && Object.hasOwn(accountConfig, "token"));
|
|
184
|
+
return inspectDiscordAccountTokenState({
|
|
185
|
+
base: {
|
|
186
|
+
accountId,
|
|
187
|
+
enabled,
|
|
188
|
+
...options.includeName ? { name: normalizeOptionalString(config.name) } : {}
|
|
189
|
+
},
|
|
190
|
+
config,
|
|
191
|
+
accountToken: accountConfig?.token,
|
|
192
|
+
hasAccountToken,
|
|
193
|
+
channelToken: params.cfg.channels?.discord?.token,
|
|
194
|
+
resolveFallbackToken: () => options.resolveFallbackToken(accountId)
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function readConfiguredAccount(params) {
|
|
198
|
+
const accountId = normalizeAccountId(params.accountId ?? resolveDefaultDiscordAccountId(params.cfg));
|
|
199
|
+
return resolveDiscordAccountConfig(params.cfg, accountId);
|
|
200
|
+
}
|
|
201
|
+
function resolveDiscordAccountAllowFrom(params) {
|
|
202
|
+
const accountConfig = readConfiguredAccount(params);
|
|
200
203
|
const rootConfig = params.cfg.channels?.discord;
|
|
201
204
|
const allowFrom = accountConfig?.allowFrom ?? rootConfig?.allowFrom;
|
|
202
205
|
return allowFrom ? mapAllowFromEntries(allowFrom) : void 0;
|
|
203
206
|
}
|
|
204
207
|
function resolveDiscordAccountDmPolicy(params) {
|
|
205
|
-
const
|
|
206
|
-
const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
|
|
208
|
+
const accountConfig = readConfiguredAccount(params);
|
|
207
209
|
const rootConfig = params.cfg.channels?.discord;
|
|
208
210
|
return normalizeChannelDmPolicy(accountConfig?.dmPolicy ?? rootConfig?.dmPolicy ?? "pairing");
|
|
209
211
|
}
|
|
210
212
|
function createDiscordActionGate(params) {
|
|
211
|
-
const
|
|
213
|
+
const accountConfig = readConfiguredAccount(params);
|
|
212
214
|
return createAccountActionGate({
|
|
213
215
|
baseActions: params.cfg.channels?.discord?.actions,
|
|
214
|
-
accountActions:
|
|
216
|
+
accountActions: accountConfig?.actions
|
|
215
217
|
});
|
|
216
218
|
}
|
|
217
219
|
function resolveDiscordAccount(params) {
|
|
@@ -267,4 +269,4 @@ function listDiscordStartupAccountIds(cfg) {
|
|
|
267
269
|
return [defaultAccountId, ...startupAccountIds.filter((candidateId) => candidateId !== defaultAccountId)];
|
|
268
270
|
}
|
|
269
271
|
//#endregion
|
|
270
|
-
export {
|
|
272
|
+
export { selectDiscordActivitiesRuntimeConfig as _, listDiscordStartupAccountIds as a, resolveDefaultDiscordAccountId as c, resolveDiscordAccountConfig as d, resolveDiscordAccountDisabledReason as f, resolveDiscordToken as g, normalizeDiscordToken as h, listDiscordAccountIds as i, resolveDiscordAccount as l, resolveDiscordMaxLinesPerMessage as m, inspectDiscordAccountConfig as n, listEnabledDiscordAccounts as o, resolveDiscordAccountDmPolicy as p, isDiscordAccountEnabledForRuntime as r, mergeDiscordAccountConfig as s, createDiscordActionGate as t, resolveDiscordAccountAllowFrom as u, resolveDiscordAccountAvailability as v };
|
|
@@ -30,27 +30,16 @@ function normalizeRestApiBaseUrl(value) {
|
|
|
30
30
|
url.pathname = url.pathname.replace(/\/+$/u, "") || "/";
|
|
31
31
|
return url;
|
|
32
32
|
}
|
|
33
|
-
function normalizeGatewayOrigin(value) {
|
|
34
|
-
let url;
|
|
35
|
-
try {
|
|
36
|
-
url = new URL(value);
|
|
37
|
-
} catch {
|
|
38
|
-
throw new Error("Discord endpoint Gateway origin must be a valid URL");
|
|
39
|
-
}
|
|
40
|
-
if (url.protocol !== "wss:" && !(url.protocol === "ws:" && isLoopbackHost(url.hostname))) throw new Error("Discord endpoint Gateway origin must use WSS or loopback WS");
|
|
41
|
-
if (url.protocol === "wss:" && isBlockedHostnameOrIp(url.hostname)) throw new Error("Discord endpoint Gateway origin must not target a private/internal/special-use hostname or IP address");
|
|
42
|
-
if (url.username || url.password || url.hash || url.pathname !== "/" || url.search) throw new Error("Discord endpoint Gateway origin must be an origin without credentials, path, query, or fragment");
|
|
43
|
-
return url.origin;
|
|
44
|
-
}
|
|
45
33
|
function resolveDescriptor(apiUrl) {
|
|
46
34
|
const restApiBaseUrl = normalizeRestApiBaseUrl(apiUrl);
|
|
47
35
|
const gatewayBotUrl = new URL(`${restApiBaseUrl.pathname.replace(/\/+$/u, "")}/gateway/bot`, restApiBaseUrl.origin);
|
|
48
36
|
const gatewayOriginUrl = new URL(restApiBaseUrl.origin);
|
|
49
37
|
gatewayOriginUrl.protocol = gatewayOriginUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
38
|
+
if (gatewayOriginUrl.protocol === "wss:" && isBlockedHostnameOrIp(gatewayOriginUrl.hostname)) throw new Error("Discord endpoint Gateway origin must not target a private/internal/special-use hostname or IP address");
|
|
50
39
|
return Object.freeze({
|
|
51
40
|
restApiBaseUrl: restApiBaseUrl.toString().replace(/\/$/u, ""),
|
|
52
41
|
gatewayBotUrl: gatewayBotUrl.toString(),
|
|
53
|
-
gatewayOrigin:
|
|
42
|
+
gatewayOrigin: gatewayOriginUrl.origin
|
|
54
43
|
});
|
|
55
44
|
}
|
|
56
45
|
function isWithinRestApiBase(target, restApiBaseUrl) {
|
|
@@ -121,27 +110,22 @@ function getDiscordEndpointRuntime(env = process.env) {
|
|
|
121
110
|
});
|
|
122
111
|
}
|
|
123
112
|
function resolveDiscordEndpointMediaGuard(url, retainedRuntime) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (target.origin !== restOrigin) throw new Error("Discord endpoint media URL is outside the configured REST origin");
|
|
130
|
-
return {
|
|
131
|
-
maxRedirects: 0,
|
|
132
|
-
ssrfPolicy: {
|
|
133
|
-
allowedOrigins: [restOrigin],
|
|
134
|
-
hostnameAllowlist: [target.hostname]
|
|
135
|
-
}
|
|
136
|
-
};
|
|
113
|
+
const guard = resolveEndpointResourceGuard(url, "media", retainedRuntime);
|
|
114
|
+
return guard ? {
|
|
115
|
+
maxRedirects: guard.maxRedirects,
|
|
116
|
+
ssrfPolicy: guard.policy
|
|
117
|
+
} : void 0;
|
|
137
118
|
}
|
|
138
119
|
function resolveDiscordEndpointAttachmentGuard(url, retainedRuntime) {
|
|
120
|
+
return resolveEndpointResourceGuard(url, "attachment upload", retainedRuntime);
|
|
121
|
+
}
|
|
122
|
+
function resolveEndpointResourceGuard(url, kind, retainedRuntime) {
|
|
139
123
|
if (retainedRuntime === null) return;
|
|
140
124
|
const runtime = retainedRuntime ?? getDiscordEndpointRuntime();
|
|
141
125
|
if (!runtime) return;
|
|
142
|
-
const target = parseHttpAnchor(url,
|
|
126
|
+
const target = parseHttpAnchor(url, `Discord endpoint ${kind} URL`);
|
|
143
127
|
const restOrigin = new URL(runtime.descriptor.restApiBaseUrl).origin;
|
|
144
|
-
if (target.origin !== restOrigin) throw new Error(
|
|
128
|
+
if (target.origin !== restOrigin) throw new Error(`Discord endpoint ${kind} URL is outside the configured REST origin`);
|
|
145
129
|
return {
|
|
146
130
|
maxRedirects: 0,
|
|
147
131
|
policy: {
|
|
@@ -234,19 +218,6 @@ function normalizeDiscordSlug(value) {
|
|
|
234
218
|
function normalizeDiscordDisplaySlug(value) {
|
|
235
219
|
return normalizeLowercaseStringOrEmpty(value).normalize("NFC").replace(/^#/, "").replace(/[\s_]+/g, "-").replace(/[^\p{L}\p{M}\p{N}-]+/gu, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
236
220
|
}
|
|
237
|
-
function resolveDiscordAllowListNameMatch(list, candidate) {
|
|
238
|
-
const nameSlug = candidate.name ? normalizeDiscordSlug(candidate.name) : "";
|
|
239
|
-
if (nameSlug && list.names.has(nameSlug)) return {
|
|
240
|
-
matchKey: nameSlug,
|
|
241
|
-
matchSource: "name"
|
|
242
|
-
};
|
|
243
|
-
const tagSlug = candidate.tag ? normalizeDiscordSlug(candidate.tag) : "";
|
|
244
|
-
if (tagSlug && list.names.has(tagSlug)) return {
|
|
245
|
-
matchKey: tagSlug,
|
|
246
|
-
matchSource: "tag"
|
|
247
|
-
};
|
|
248
|
-
return null;
|
|
249
|
-
}
|
|
250
221
|
function allowListMatches(list, candidate, params) {
|
|
251
222
|
return resolveDiscordAllowListMatch({
|
|
252
223
|
allowList: list,
|
|
@@ -266,11 +237,13 @@ function resolveDiscordAllowListMatch(params) {
|
|
|
266
237
|
matchKey: candidate.id,
|
|
267
238
|
matchSource: "id"
|
|
268
239
|
};
|
|
269
|
-
if (params.allowNameMatching === true) {
|
|
270
|
-
const
|
|
271
|
-
|
|
240
|
+
if (params.allowNameMatching === true) for (const matchSource of ["name", "tag"]) {
|
|
241
|
+
const value = candidate[matchSource];
|
|
242
|
+
const matchKey = value ? normalizeDiscordSlug(value) : "";
|
|
243
|
+
if (matchKey && allowList.names.has(matchKey)) return {
|
|
272
244
|
allowed: true,
|
|
273
|
-
|
|
245
|
+
matchKey,
|
|
246
|
+
matchSource
|
|
274
247
|
};
|
|
275
248
|
}
|
|
276
249
|
return { allowed: false };
|
|
@@ -288,27 +261,16 @@ function resolveDiscordUserAllowed(params) {
|
|
|
288
261
|
tag: params.userTag
|
|
289
262
|
}, { allowNameMatching: params.allowNameMatching });
|
|
290
263
|
}
|
|
291
|
-
function resolveDiscordRoleAllowed(params) {
|
|
292
|
-
const allowList = normalizeDiscordAllowList(params.allowList, ["role:"]);
|
|
293
|
-
if (!allowList) return true;
|
|
294
|
-
if (allowList.allowAll) return true;
|
|
295
|
-
return params.memberRoleIds.some((roleId) => allowList.ids.has(roleId));
|
|
296
|
-
}
|
|
297
264
|
function resolveDiscordMemberAllowed(params) {
|
|
298
265
|
const hasUserRestriction = Array.isArray(params.userAllowList) && params.userAllowList.length > 0;
|
|
299
266
|
const hasRoleRestriction = Array.isArray(params.roleAllowList) && params.roleAllowList.length > 0;
|
|
300
267
|
if (!hasUserRestriction && !hasRoleRestriction) return true;
|
|
301
268
|
const userOk = hasUserRestriction ? resolveDiscordUserAllowed({
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
userName: params.userName,
|
|
305
|
-
userTag: params.userTag,
|
|
306
|
-
allowNameMatching: params.allowNameMatching
|
|
307
|
-
}) : false;
|
|
308
|
-
const roleOk = hasRoleRestriction ? resolveDiscordRoleAllowed({
|
|
309
|
-
allowList: params.roleAllowList,
|
|
310
|
-
memberRoleIds: params.memberRoleIds
|
|
269
|
+
...params,
|
|
270
|
+
allowList: params.userAllowList
|
|
311
271
|
}) : false;
|
|
272
|
+
const roles = hasRoleRestriction ? normalizeDiscordAllowList(params.roleAllowList, ["role:"]) : null;
|
|
273
|
+
const roleOk = Boolean(roles && (roles.allowAll || params.memberRoleIds.some((roleId) => roles.ids.has(roleId))));
|
|
312
274
|
return userOk || roleOk;
|
|
313
275
|
}
|
|
314
276
|
function resolveDiscordMemberAccessState(params) {
|
|
@@ -340,11 +302,7 @@ function resolveDiscordOwnerAllowFrom(params) {
|
|
|
340
302
|
if (!allowList) return;
|
|
341
303
|
const match = resolveDiscordAllowListMatch({
|
|
342
304
|
allowList,
|
|
343
|
-
candidate:
|
|
344
|
-
id: params.sender.id,
|
|
345
|
-
name: params.sender.name,
|
|
346
|
-
tag: params.sender.tag
|
|
347
|
-
},
|
|
305
|
+
candidate: params.sender,
|
|
348
306
|
allowNameMatching: params.allowNameMatching
|
|
349
307
|
});
|
|
350
308
|
if (!match.allowed || !match.matchKey || match.matchKey === "*") return;
|
|
@@ -379,33 +337,12 @@ function resolveDiscordGuildEntry(params) {
|
|
|
379
337
|
};
|
|
380
338
|
if (!guild) return null;
|
|
381
339
|
const slug = normalizeDiscordSlug(guild.name ?? "");
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
...
|
|
385
|
-
id: guildId ?? guild.id,
|
|
386
|
-
slug: slug || bySlug.slug
|
|
387
|
-
};
|
|
388
|
-
const wildcard = entries["*"];
|
|
389
|
-
if (wildcard) return {
|
|
390
|
-
...wildcard,
|
|
340
|
+
const byName = entries[slug] || entries["*"];
|
|
341
|
+
return byName ? {
|
|
342
|
+
...byName,
|
|
391
343
|
id: guildId ?? guild.id,
|
|
392
|
-
slug: slug ||
|
|
393
|
-
};
|
|
394
|
-
return null;
|
|
395
|
-
}
|
|
396
|
-
function buildDiscordChannelKeys(params) {
|
|
397
|
-
const allowNameMatch = params.allowNameMatch !== false;
|
|
398
|
-
return buildChannelKeyCandidates(params.id, allowNameMatch ? params.slug : void 0, allowNameMatch ? params.name : void 0);
|
|
399
|
-
}
|
|
400
|
-
function resolveDiscordChannelEntryMatch(channels, params, parentParams) {
|
|
401
|
-
const keys = buildDiscordChannelKeys(params);
|
|
402
|
-
const parentKeys = parentParams ? buildDiscordChannelKeys(parentParams) : void 0;
|
|
403
|
-
return resolveChannelEntryMatchWithFallback({
|
|
404
|
-
entries: channels,
|
|
405
|
-
keys,
|
|
406
|
-
parentKeys,
|
|
407
|
-
wildcardKey: "*"
|
|
408
|
-
});
|
|
344
|
+
slug: slug || byName.slug
|
|
345
|
+
} : null;
|
|
409
346
|
}
|
|
410
347
|
function hasConfiguredDiscordChannels(channels) {
|
|
411
348
|
return Boolean(channels && Object.keys(channels).length > 0);
|
|
@@ -440,16 +377,12 @@ function resolveDiscordChannelConfigWithFallback(params) {
|
|
|
440
377
|
const channels = guildInfo?.channels;
|
|
441
378
|
if (!hasConfiguredDiscordChannels(channels)) return null;
|
|
442
379
|
const resolvedParentSlug = parentSlug ?? (parentName ? normalizeDiscordSlug(parentName) : "");
|
|
443
|
-
const match =
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
id: parentId ?? "",
|
|
450
|
-
name: parentName,
|
|
451
|
-
slug: resolvedParentSlug
|
|
452
|
-
} : void 0);
|
|
380
|
+
const match = resolveChannelEntryMatchWithFallback({
|
|
381
|
+
entries: channels,
|
|
382
|
+
keys: buildChannelKeyCandidates(channelId, scope === "thread" ? void 0 : channelSlug, scope === "thread" ? void 0 : channelName),
|
|
383
|
+
parentKeys: parentId || parentName || parentSlug ? buildChannelKeyCandidates(parentId ?? "", resolvedParentSlug, parentName) : void 0,
|
|
384
|
+
wildcardKey: "*"
|
|
385
|
+
});
|
|
453
386
|
return resolveChannelMatchConfig(match, resolveDiscordChannelConfigEntry) ?? { allowed: false };
|
|
454
387
|
}
|
|
455
388
|
/** Boolean runtime API retained for plugins built against OpenClaw 2026.9.6. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { D as getDiscordEndpointRuntime, T as parseDiscordRetryAfterBodySeconds } from "./allow-list-
|
|
1
|
+
import { D as getDiscordEndpointRuntime, T as parseDiscordRetryAfterBodySeconds } from "./allow-list-B_ToXtew.mjs";
|
|
2
2
|
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
3
3
|
import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
|
-
import { captureChannelReadAuthority, resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
|
|
4
|
+
import { captureChannelReadAuthority, captureEffectAuthority, resolveFetch } from "openclaw/plugin-sdk/fetch-runtime";
|
|
5
5
|
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
6
6
|
import { redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
7
7
|
import { parseRetryAfterHeaderSeconds, resolveRetryConfig, retryAsync } from "openclaw/plugin-sdk/retry-runtime";
|
|
@@ -23,11 +23,10 @@ function summarizeDiscordResponseBody(body, opts = {}) {
|
|
|
23
23
|
return truncateUtf16Safe(redactToolPayloadText(summary), DISCORD_RESPONSE_BODY_SUMMARY_MAX_CHARS);
|
|
24
24
|
}
|
|
25
25
|
function isDiscordHtmlResponseBody(body, contentType) {
|
|
26
|
-
return /\bhtml\b/i.test(contentType ?? "") || /^\s
|
|
26
|
+
return /\bhtml\b/i.test(contentType ?? "") || /^\s*(?:<!doctype\s+html\b|<html\b)/i.test(body);
|
|
27
27
|
}
|
|
28
28
|
function isDiscordRateLimitResponseBody(body) {
|
|
29
|
-
|
|
30
|
-
return normalized.includes("error 1015") || normalized.includes("cloudflare") || normalized.includes("rate limit");
|
|
29
|
+
return /error 1015|cloudflare|rate limit/i.test(body);
|
|
31
30
|
}
|
|
32
31
|
//#endregion
|
|
33
32
|
//#region extensions/discord/src/api.ts
|
|
@@ -46,23 +45,21 @@ function parseDiscordApiErrorPayload(text) {
|
|
|
46
45
|
const trimmed = text.trim();
|
|
47
46
|
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) return null;
|
|
48
47
|
try {
|
|
49
|
-
|
|
50
|
-
if (payload && typeof payload === "object") return payload;
|
|
48
|
+
return JSON.parse(trimmed);
|
|
51
49
|
} catch {
|
|
52
50
|
return null;
|
|
53
51
|
}
|
|
54
|
-
return null;
|
|
55
52
|
}
|
|
56
53
|
function parseRetryAfterSeconds(text, response) {
|
|
57
54
|
const payload = parseDiscordApiErrorPayload(text);
|
|
58
55
|
const retryAfter = parseDiscordRetryAfterBodySeconds(payload?.retry_after);
|
|
59
56
|
if (retryAfter !== void 0) return retryAfter;
|
|
60
57
|
const header = response.headers.get("Retry-After");
|
|
61
|
-
|
|
62
|
-
return parseRetryAfterHeaderSeconds(header);
|
|
58
|
+
return header ? parseRetryAfterHeaderSeconds(header) : void 0;
|
|
63
59
|
}
|
|
64
|
-
function formatRetryAfterSeconds(
|
|
65
|
-
|
|
60
|
+
function formatRetryAfterSeconds(raw) {
|
|
61
|
+
const value = parseDiscordRetryAfterBodySeconds(raw);
|
|
62
|
+
if (value === void 0) return;
|
|
66
63
|
return `${value < 10 ? value.toFixed(1) : Math.round(value).toString()}s`;
|
|
67
64
|
}
|
|
68
65
|
function formatDiscordApiErrorTextUntrusted(text, response) {
|
|
@@ -79,13 +76,9 @@ function formatDiscordApiErrorTextUntrusted(text, response) {
|
|
|
79
76
|
return summary;
|
|
80
77
|
}
|
|
81
78
|
const message = typeof payload.message === "string" && payload.message.trim() ? payload.message.trim() : "unknown error";
|
|
82
|
-
const retryAfter = formatRetryAfterSeconds(
|
|
79
|
+
const retryAfter = formatRetryAfterSeconds(payload.retry_after);
|
|
83
80
|
return retryAfter ? `${message} (retry after ${retryAfter})` : message;
|
|
84
81
|
}
|
|
85
|
-
function formatDiscordApiErrorText(text, response) {
|
|
86
|
-
const detail = formatDiscordApiErrorTextUntrusted(text, response);
|
|
87
|
-
return detail ? redactToolPayloadText(detail) : detail;
|
|
88
|
-
}
|
|
89
82
|
var DiscordApiError = class extends Error {
|
|
90
83
|
constructor(message, status, retryAfter) {
|
|
91
84
|
super(message);
|
|
@@ -93,13 +86,8 @@ var DiscordApiError = class extends Error {
|
|
|
93
86
|
this.retryAfter = retryAfter;
|
|
94
87
|
}
|
|
95
88
|
};
|
|
96
|
-
function getDiscordApiRetryAfterMs(err, retryConfig) {
|
|
97
|
-
if (!(err instanceof DiscordApiError) || typeof err.retryAfter !== "number") return;
|
|
98
|
-
return Math.min(Math.max(0, err.retryAfter * 1e3), retryConfig.maxDelayMs);
|
|
99
|
-
}
|
|
100
89
|
function normalizeDiscordRequestBody(body, headers) {
|
|
101
|
-
if (body === void 0) return;
|
|
102
|
-
if (typeof body === "string" || body instanceof Blob || body instanceof FormData || body instanceof URLSearchParams || body instanceof ArrayBuffer) return body;
|
|
90
|
+
if (body === void 0 || typeof body === "string" || body instanceof Blob || body instanceof FormData || body instanceof URLSearchParams || body instanceof ArrayBuffer) return body;
|
|
103
91
|
headers.set("Content-Type", headers.get("Content-Type") ?? "application/json");
|
|
104
92
|
return JSON.stringify(body);
|
|
105
93
|
}
|
|
@@ -118,6 +106,7 @@ function createDiscordRequestSignal(options) {
|
|
|
118
106
|
}
|
|
119
107
|
async function requestDiscord(path, token, options) {
|
|
120
108
|
const assertReadAuthority = captureChannelReadAuthority();
|
|
109
|
+
const effect = captureEffectAuthority();
|
|
121
110
|
const endpoint = options?.endpointRuntime === void 0 ? getDiscordEndpointRuntime() : options.endpointRuntime;
|
|
122
111
|
const fetchImpl = resolveFetch(endpoint ? (input, init) => endpoint.fetch(input, init, assertReadAuthority) : options?.fetcher ?? fetch);
|
|
123
112
|
if (!fetchImpl) throw new Error("fetch is not available");
|
|
@@ -129,15 +118,20 @@ async function requestDiscord(path, token, options) {
|
|
|
129
118
|
const requestSignal = createDiscordRequestSignal(options ?? {});
|
|
130
119
|
try {
|
|
131
120
|
assertReadAuthority?.();
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
121
|
+
const request = () => {
|
|
122
|
+
assertReadAuthority?.();
|
|
123
|
+
return fetchImpl(`${endpoint?.descriptor.restApiBaseUrl ?? DISCORD_API_BASE}${path}`, {
|
|
124
|
+
method: options?.method ?? (body === void 0 ? "GET" : "POST"),
|
|
125
|
+
headers,
|
|
126
|
+
body,
|
|
127
|
+
signal: requestSignal.signal
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
const res = endpoint ? await effect.run(request) : await effect.initiate(request);
|
|
138
131
|
if (!res.ok) {
|
|
139
132
|
const text = await readResponseTextLimited(res, DISCORD_API_ERROR_BODY_LIMIT_BYTES).catch(() => "");
|
|
140
|
-
const
|
|
133
|
+
const untrustedDetail = formatDiscordApiErrorTextUntrusted(text, res);
|
|
134
|
+
const detail = untrustedDetail ? redactToolPayloadText(untrustedDetail) : untrustedDetail;
|
|
141
135
|
const suffix = detail ? `: ${detail}` : "";
|
|
142
136
|
const retryAfter = res.status === 429 ? parseRetryAfterSeconds(text, res) ?? DISCORD_API_429_FALLBACK_RETRY_AFTER_SECONDS : void 0;
|
|
143
137
|
throw new DiscordApiError(`Discord API ${path} failed (${res.status})${suffix}`, res.status, retryAfter);
|
|
@@ -157,7 +151,7 @@ async function requestDiscord(path, token, options) {
|
|
|
157
151
|
...retryConfig,
|
|
158
152
|
label: options?.label ?? path,
|
|
159
153
|
shouldRetry: (err) => err instanceof DiscordApiError && err.status === 429,
|
|
160
|
-
retryAfterMs: (err) =>
|
|
154
|
+
retryAfterMs: (err) => err instanceof DiscordApiError && typeof err.retryAfter === "number" ? Math.min(Math.max(0, err.retryAfter * 1e3), retryConfig.maxDelayMs) : void 0,
|
|
161
155
|
sleep: (ms) => sleepWithAbort(ms, options?.signal)
|
|
162
156
|
});
|
|
163
157
|
}
|