@openclaw/discord 2026.9.8 → 2026.10.1-beta.2
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/README.md +7 -0
- package/dist/.setup/{account-inspect-De8hOUxG.mjs → account-inspect-CjKqkDnH.mjs} +2 -2
- package/dist/.setup/{accounts-ChaMcixG.mjs → accounts-DXHCL8Zm.mjs} +9 -32
- package/dist/.setup/{active-turn-thread-route-fmHl1HNd.mjs → active-turn-thread-route-C4tp9noA.mjs} +5 -9
- package/dist/.setup/{activities-api-tvbsU2e3.mjs → activities-api-BL_hJ0JQ.mjs} +15 -18
- package/dist/.setup/{api-DVbJwZVt.mjs → api-_oznjffB.mjs} +1 -1
- package/dist/.setup/{approval-handler.runtime-DxCK2Rux.mjs → approval-handler.runtime-BilYSrRF.mjs} +22 -61
- package/dist/.setup/{approval-message-updates-BKFqavHZ.mjs → approval-message-updates-CgRwc2_Q.mjs} +2 -2
- package/dist/.setup/{audit-CLg9I71N.mjs → audit-DtvzxONM.mjs} +4 -4
- package/dist/.setup/{channel-access-C12aDZ0p.mjs → channel-access-BRp3Y-rF.mjs} +4 -17
- package/dist/.setup/{channel-type-DRCrEMss.mjs → channel-type-D1_b5UhU.mjs} +12 -16
- package/dist/.setup/{channel-DxlUVU9t.mjs → channel-z5lQMS_9.mjs} +79 -75
- package/dist/.setup/{channel.setup-CRo1GjV7.mjs → channel.setup-DBJtugJO.mjs} +14 -34
- package/dist/.setup/{components-Cq1PvIpN.mjs → components-CzXLR3QH.mjs} +56 -72
- package/dist/.setup/{config-schema-oxELUSDx.mjs → config-schema-CsemBDpS.mjs} +6 -17
- package/dist/.setup/{conversation-binding-route-Caz_XuFH.mjs → conversation-binding-route-Bi62ApSt.mjs} +1 -1
- package/dist/.setup/{directory-config-esqNn0Eo.mjs → directory-config-BH1LA-gi.mjs} +1 -1
- package/dist/.setup/{directory-live-DtKRHuGV.mjs → directory-live-C9xz7IPm.mjs} +10 -13
- package/dist/.setup/{discord-0xJYfdDD.mjs → discord-J7aRzq2Q.mjs} +101 -381
- package/dist/.setup/{doctor-BCl1H5tl.mjs → doctor-DxSAngJq.mjs} +31 -70
- package/dist/.setup/doctor-contract-Bg3NPAMw.mjs +137 -0
- package/dist/.setup/{handle-action-CUvQWnE7.mjs → handle-action-DlmFX-_G.mjs} +10 -11
- package/dist/.setup/{handle-action.guild-admin-Df-8gVle.mjs → handle-action.guild-admin-BnyqTczR.mjs} +67 -129
- package/dist/.setup/{live-policy-config-8Pv20CHc.mjs → live-policy-config-emmPNyh4.mjs} +1 -1
- package/dist/.setup/{message-handler-B-Jk4oDk.mjs → message-handler-BNToPZrx.mjs} +7 -6
- package/dist/.setup/{message-handler.preflight-v-__NSDq.mjs → message-handler.preflight-D0BcCyI7.mjs} +13 -23
- package/dist/.setup/{message-handler.preflight-pluralkit-CWLUBVcx.mjs → message-handler.preflight-pluralkit-D1g3eq0B.mjs} +5 -8
- package/dist/.setup/{message-handler.process-BNFFuChn.mjs → message-handler.process-CThRmCWK.mjs} +57 -96
- package/dist/.setup/{outbound-adapter-BobT-kse.mjs → outbound-adapter-BPq0c2wY.mjs} +11 -17
- package/dist/.setup/{outbound-session-route-zVGxxceg.mjs → outbound-session-route-DGPPKA0z.mjs} +21 -46
- package/dist/.setup/{presence-cache-Di3H3DIU.mjs → presence-cache-Dg3_dADn.mjs} +2 -4
- package/dist/.setup/{probe-LYrIHlBF.mjs → probe-DIRY8vh7.mjs} +17 -27
- package/dist/.setup/{provider-B_G5hASF.mjs → provider-D2OKMo0f.mjs} +273 -446
- package/dist/.setup/{provider-session.runtime-BYlTBFD2.mjs → provider-session.runtime-BupCTZQv.mjs} +3 -3
- package/dist/.setup/provider.runtime-BaW_JnfU.mjs +2 -0
- package/dist/.setup/{realtime-session.runtime-oUd9DOcz.mjs → realtime-session.runtime-D5RSC8Mm.mjs} +6 -8
- package/dist/.setup/{receive-recovery-CHPOsnLc.mjs → receive-recovery-GqF2PUN_.mjs} +1 -4
- package/dist/.setup/{resolve-allowlist-common-DPdRggu5.mjs → resolve-allowlist-common-DUYRrrVB.mjs} +5 -9
- package/dist/.setup/{resolve-channels-BFPNRmVv.mjs → resolve-channels--MUatisx.mjs} +3 -3
- package/dist/.setup/{resolve-users-0-aBuCy3.mjs → resolve-users-CxLcDmM0.mjs} +6 -9
- package/dist/.setup/{retry-pz_cSha2.mjs → retry-BKzO25k4.mjs} +27 -51
- package/dist/.setup/{runtime-sUksZ--Q.mjs → runtime-CerRBfaa.mjs} +2 -2
- package/dist/.setup/{runtime-FN000lxA.mjs → runtime-CwUA0RLr.mjs} +228 -255
- package/dist/.setup/{runtime-doctor-migrations-CshUGl36.mjs → runtime-doctor-migrations-BPV-R4G9.mjs} +6 -0
- package/dist/.setup/{security-audit-Cdaegq7C.mjs → security-audit-D42cp5N7.mjs} +21 -48
- package/dist/.setup/{send-CrfEI6Bs.mjs → send-2X7m2Zmw.mjs} +45 -58
- package/dist/.setup/{send.components-DxQAMfES.mjs → send.components-RqvgmCs3.mjs} +44 -90
- package/dist/.setup/{send.outbound-BISKnb-a.mjs → send.outbound-B4QHSEzm.mjs} +60 -98
- package/dist/.setup/{send.shared-DGFkbkQR.mjs → send.shared-BQIUh6Vn.mjs} +13 -20
- package/dist/.setup/{sender-identity-B9X5Vb9R.mjs → sender-identity-CooeYfAn.mjs} +1 -1
- package/dist/.setup/{session-key-normalization-wJgsKPNF.mjs → session-key-normalization-CCHGNSQw.mjs} +3 -9
- package/dist/.setup/setup-plugin-api-nn_giXvZ.mjs +3 -0
- package/dist/.setup/{shared-B3wZ4hN-.mjs → shared-CIJn6AEC.mjs} +7 -7
- package/dist/.setup/{subagent-hooks-nlUE9ow7.mjs → subagent-hooks-BYlVnxzy.mjs} +4 -9
- package/dist/.setup/{system-events-CdeZnvPV.mjs → system-events-CQ3if_pS.mjs} +2 -2
- package/dist/.setup/{target-resolver-BuLapkhy.mjs → target-resolver-Dzxf80Y3.mjs} +5 -13
- package/dist/.setup/targets-Lf8D55w-.mjs +3 -0
- package/dist/.setup/{thread-bindings-D7TfgjR_.mjs → thread-bindings-yNNlcUWE.mjs} +5 -6
- package/dist/.setup/{thread-bindings.manager-DN-NissX.mjs → thread-bindings.manager-plk0zJAW.mjs} +14 -20
- package/dist/.setup/{thread-bindings.session-updates-CshfKghV.mjs → thread-bindings.session-updates-C9aKtVs6.mjs} +295 -5
- package/dist/.setup/{timeouts-D86uWLt_.mjs → timeouts-pun7VJ02.mjs} +2 -15
- package/dist/.setup/{transcripts-source-p8EV179h.mjs → transcripts-source-CNWswry-.mjs} +31 -79
- package/dist/.setup/typing-CNlSKY5S.mjs +11 -0
- package/dist/.setup/{voice-runtime-B46rcwrG.mjs → voice-runtime-Bc75quiH.mjs} +62 -110
- package/dist/account-inspect-api.js +1 -1
- package/dist/action-runtime-api.js +1 -1
- package/dist/activities-api.js +1 -1
- package/dist/api.js +18 -18
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/control-ui/2afbdab1d3aa65a789d8a3eba666f4b1ec5df07073538fe30d6cf32093a1fb2d/index.js +1 -0
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +19 -128
- package/dist/index.js +1 -1
- package/dist/runtime-api.js +20 -21
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/session-key-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 +6 -8
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/node_modules/libopus-wasm/CHANGELOG.md +8 -0
- package/node_modules/libopus-wasm/dist/discordjs.d.ts.map +1 -1
- package/node_modules/libopus-wasm/dist/discordjs.js +14 -2
- package/node_modules/libopus-wasm/dist/generated/libopus.generated.mjs +0 -0
- package/node_modules/libopus-wasm/dist/index.d.ts.map +1 -1
- package/node_modules/libopus-wasm/dist/index.js +55 -100
- package/node_modules/libopus-wasm/package.json +5 -5
- package/node_modules/undici/README.md +10 -1
- package/node_modules/undici/docs/docs/api/Agent.md +8 -8
- package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +9 -6
- package/node_modules/undici/docs/docs/api/Dispatcher.md +9 -0
- package/node_modules/undici/docs/docs/api/Errors.md +25 -0
- package/node_modules/undici/docs/docs/api/Fetch.md +10 -0
- package/node_modules/undici/docs/docs/api/Interceptors.md +4 -3
- package/node_modules/undici/docs/docs/api/Pool.md +5 -6
- package/node_modules/undici/docs/docs/index.md +10 -1
- package/node_modules/undici/lib/api/readable.js +1 -2
- package/node_modules/undici/lib/core/request.js +23 -2
- package/node_modules/undici/lib/core/util.js +0 -39
- package/node_modules/undici/lib/dispatcher/client-h1.js +11 -4
- package/node_modules/undici/lib/dispatcher/client-h2.js +52 -8
- package/node_modules/undici/lib/dispatcher/client.js +6 -1
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +21 -6
- package/node_modules/undici/lib/dispatcher/pool-base.js +63 -2
- package/node_modules/undici/lib/dispatcher/pool.js +90 -7
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +16 -3
- package/node_modules/undici/lib/handler/deduplication-handler.js +24 -11
- package/node_modules/undici/lib/handler/redirect-handler.js +5 -0
- package/node_modules/undici/lib/handler/retry-handler.js +72 -13
- package/node_modules/undici/lib/interceptor/cache.js +4 -1
- package/node_modules/undici/lib/interceptor/decompress.js +236 -69
- package/node_modules/undici/lib/web/cache/cache.js +17 -8
- package/node_modules/undici/lib/web/cache/cachestorage.js +11 -5
- package/node_modules/undici/lib/web/cookies/index.js +19 -7
- package/node_modules/undici/lib/web/cookies/util.js +3 -1
- package/node_modules/undici/lib/web/eventsource/eventsource.js +25 -1
- package/node_modules/undici/lib/web/fetch/body.js +22 -15
- package/node_modules/undici/lib/web/fetch/data-url.js +6 -6
- package/node_modules/undici/lib/web/fetch/formdata.js +30 -36
- package/node_modules/undici/lib/web/fetch/headers.js +34 -31
- package/node_modules/undici/lib/web/fetch/index.js +46 -25
- package/node_modules/undici/lib/web/fetch/request.js +74 -79
- package/node_modules/undici/lib/web/fetch/response.js +43 -44
- package/node_modules/undici/lib/web/fetch/util.js +7 -7
- package/node_modules/undici/lib/web/infra/index.js +16 -1
- package/node_modules/undici/lib/web/webidl/index.js +2 -14
- package/node_modules/undici/lib/web/websocket/connection.js +33 -12
- package/node_modules/undici/lib/web/websocket/events.js +43 -26
- package/node_modules/undici/lib/web/websocket/receiver.js +2 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketerror.js +13 -10
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +19 -4
- package/node_modules/undici/lib/web/websocket/websocket.js +44 -41
- package/node_modules/undici/package.json +1 -1
- package/node_modules/undici/types/diagnostics-channel.d.ts +2 -1
- package/node_modules/undici/types/interceptors.d.ts +1 -1
- package/node_modules/undici/types/webidl.d.ts +13 -7
- package/openclaw.plugin.json +6 -0
- package/package.json +12 -7
- package/dist/.setup/doctor-contract-CvvgwrrG.mjs +0 -409
- package/dist/.setup/model-picker-preference-primitives-BHT1LkR_.mjs +0 -37
- package/dist/.setup/provider.runtime-CUE3UxER.mjs +0 -2
- package/dist/.setup/setup-plugin-api-BQUBxbhe.mjs +0 -3
- package/dist/.setup/targets-0KUcEIYx.mjs +0 -3
- package/dist/.setup/thread-bindings.state-g6v9zAym.mjs +0 -331
- package/dist/.setup/typing-BiHCzBRu.mjs +0 -15
|
@@ -99,6 +99,12 @@ function createLegacyWebhookListenerDoctorContract(params) {
|
|
|
99
99
|
};
|
|
100
100
|
const prefix = `channels.${params.channelKey}`;
|
|
101
101
|
return {
|
|
102
|
+
historicalWebhookListener: {
|
|
103
|
+
channelId: params.channelKey,
|
|
104
|
+
port: params.defaultPort,
|
|
105
|
+
preserveAuthoredActivation: params.preserveAuthoredActivation,
|
|
106
|
+
...params.defaultHost === void 0 ? {} : { host: params.defaultHost }
|
|
107
|
+
},
|
|
102
108
|
legacyConfigRules: [{
|
|
103
109
|
path: ["channels", params.channelKey],
|
|
104
110
|
message: `${prefix} webhook listeners moved to Gateway routes. Run "openclaw doctor --fix" to preserve explicitly configured listener settings as legacyWebhook.`,
|
|
@@ -32,11 +32,6 @@ function listBroadMemberTargetPaths(params) {
|
|
|
32
32
|
}
|
|
33
33
|
return paths.toSorted();
|
|
34
34
|
}
|
|
35
|
-
function addDiscordNameBasedEntries(params) {
|
|
36
|
-
if (!Array.isArray(params.values)) return;
|
|
37
|
-
const entries = new Set(params.values.map((value) => String(value).trim()).filter(isDiscordMutableAllowEntry));
|
|
38
|
-
if (entries.size > 0) params.target.set(params.source, entries.size);
|
|
39
|
-
}
|
|
40
35
|
async function collectDiscordSecurityAuditFindings(params) {
|
|
41
36
|
const findings = [];
|
|
42
37
|
const discordCfg = params.account.config ?? {};
|
|
@@ -44,8 +39,14 @@ async function collectDiscordSecurityAuditFindings(params) {
|
|
|
44
39
|
const dangerousNameMatchingEnabled = isDangerousNameMatchingEnabled(discordCfg);
|
|
45
40
|
const storeAllowFrom = await readChannelAllowFromStore("discord", process.env, accountId).catch(() => []);
|
|
46
41
|
const discordNameBasedAllowEntries = /* @__PURE__ */ new Map();
|
|
42
|
+
const addNameBasedEntries = (values, source) => {
|
|
43
|
+
if (!Array.isArray(values)) return;
|
|
44
|
+
const entries = new Set(values.map((value) => String(value).trim()).filter(isDiscordMutableAllowEntry));
|
|
45
|
+
if (entries.size > 0) discordNameBasedAllowEntries.set(source, entries.size);
|
|
46
|
+
};
|
|
47
47
|
const discordPathPrefix = params.orderedAccountIds.length > 1 || params.hasExplicitAccountPath ? `channels.discord.accounts.${accountId}` : "channels.discord";
|
|
48
|
-
|
|
48
|
+
const effectiveGroupPolicy = discordCfg.groupPolicy ?? params.cfg.channels?.defaults?.groupPolicy ?? "allowlist";
|
|
49
|
+
if (effectiveGroupPolicy === "allowlist") {
|
|
49
50
|
const broadMemberPaths = listBroadMemberTargetPaths({
|
|
50
51
|
discordCfg,
|
|
51
52
|
pathPrefix: discordPathPrefix
|
|
@@ -58,39 +59,25 @@ async function collectDiscordSecurityAuditFindings(params) {
|
|
|
58
59
|
remediation: "Add users or roles restrictions at each listed guild/channel when only specific members should trigger the agent."
|
|
59
60
|
});
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
});
|
|
66
|
-
addDiscordNameBasedEntries({
|
|
67
|
-
target: discordNameBasedAllowEntries,
|
|
68
|
-
values: discordCfg.dm?.allowFrom,
|
|
69
|
-
source: `${discordPathPrefix}.dm.allowFrom`
|
|
70
|
-
});
|
|
71
|
-
addDiscordNameBasedEntries({
|
|
72
|
-
target: discordNameBasedAllowEntries,
|
|
73
|
-
values: storeAllowFrom,
|
|
74
|
-
source: "Discord pairing store"
|
|
75
|
-
});
|
|
62
|
+
addNameBasedEntries(discordCfg.allowFrom, `${discordPathPrefix}.allowFrom`);
|
|
63
|
+
const dmAllowFromRaw = discordCfg.dm?.allowFrom;
|
|
64
|
+
addNameBasedEntries(dmAllowFromRaw, `${discordPathPrefix}.dm.allowFrom`);
|
|
65
|
+
addNameBasedEntries(storeAllowFrom, "Discord pairing store");
|
|
76
66
|
const guildEntries = discordCfg.guilds ?? {};
|
|
67
|
+
let hasAnyUserAllowlist = false;
|
|
68
|
+
const addUserEntries = (values, source) => {
|
|
69
|
+
hasAnyUserAllowlist ||= Array.isArray(values) && values.length > 0;
|
|
70
|
+
addNameBasedEntries(values, source);
|
|
71
|
+
};
|
|
77
72
|
for (const [guildKey, guildValue] of Object.entries(guildEntries)) {
|
|
78
73
|
if (!guildValue || typeof guildValue !== "object") continue;
|
|
79
74
|
const guild = guildValue;
|
|
80
|
-
|
|
81
|
-
target: discordNameBasedAllowEntries,
|
|
82
|
-
values: guild.users,
|
|
83
|
-
source: `${discordPathPrefix}.guilds.${guildKey}.users`
|
|
84
|
-
});
|
|
75
|
+
addUserEntries(guild.users, `${discordPathPrefix}.guilds.${guildKey}.users`);
|
|
85
76
|
const channels = guild.channels;
|
|
86
77
|
if (!channels || typeof channels !== "object") continue;
|
|
87
78
|
for (const [channelKey, channelValue] of Object.entries(channels)) {
|
|
88
79
|
if (!channelValue || typeof channelValue !== "object") continue;
|
|
89
|
-
|
|
90
|
-
target: discordNameBasedAllowEntries,
|
|
91
|
-
values: channelValue.users,
|
|
92
|
-
source: `${discordPathPrefix}.guilds.${guildKey}.channels.${channelKey}.users`
|
|
93
|
-
});
|
|
80
|
+
addUserEntries(channelValue.users, `${discordPathPrefix}.guilds.${guildKey}.channels.${channelKey}.users`);
|
|
94
81
|
}
|
|
95
82
|
}
|
|
96
83
|
if (discordNameBasedAllowEntries.size > 0) {
|
|
@@ -118,24 +105,10 @@ async function collectDiscordSecurityAuditFindings(params) {
|
|
|
118
105
|
globalSetting: params.cfg.commands?.nativeSkills
|
|
119
106
|
});
|
|
120
107
|
if (!nativeEnabled && !nativeSkillsEnabled) return findings;
|
|
121
|
-
const defaultGroupPolicy = params.cfg.channels?.defaults?.groupPolicy;
|
|
122
|
-
const groupPolicy = discordCfg.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
|
|
123
108
|
const guildsConfigured = Object.keys(guildEntries).length > 0;
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if (Array.isArray(record.users) && record.users.length > 0) return true;
|
|
128
|
-
const channels = record.channels;
|
|
129
|
-
if (!channels || typeof channels !== "object") return false;
|
|
130
|
-
return Object.values(channels).some((channel) => {
|
|
131
|
-
if (!channel || typeof channel !== "object") return false;
|
|
132
|
-
const channelRecord = channel;
|
|
133
|
-
return Array.isArray(channelRecord.users) && channelRecord.users.length > 0;
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
const dmAllowFromRaw = discordCfg.dm?.allowFrom;
|
|
137
|
-
const ownerAllowFromConfigured = normalizeAllowFromList([...Array.isArray(dmAllowFromRaw) ? dmAllowFromRaw : [], ...storeAllowFrom]).length > 0;
|
|
138
|
-
if (groupPolicy !== "disabled" && guildsConfigured && !ownerAllowFromConfigured && !hasAnyUserAllowlist) findings.push({
|
|
109
|
+
const dmAllowFrom = Array.isArray(dmAllowFromRaw) ? dmAllowFromRaw : [];
|
|
110
|
+
const ownerAllowFromConfigured = normalizeAllowFromList([...discordCfg.allowFrom ?? dmAllowFrom, ...storeAllowFrom]).length > 0;
|
|
111
|
+
if (effectiveGroupPolicy !== "disabled" && guildsConfigured && !ownerAllowFromConfigured && !hasAnyUserAllowlist) findings.push({
|
|
139
112
|
checkId: "channels.discord.commands.native.no_allowlists",
|
|
140
113
|
severity: "warn",
|
|
141
114
|
title: "Discord slash commands have no allowlists",
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { o as parseDiscordHttpErrorBody } from "./api-
|
|
5
|
-
import { a as recordDiscordMessageCreateAmbiguity, f as createReusableDiscordReplyReference, l as createDiscordSendReceiptFromResults, n as classifyDiscordDeliveryFailure, o as chunkDiscordTextWithMode, p as resolveDiscordReplyMessageId, r as createDiscordRetryRunner, u as createDiscordSendResult } from "./retry-
|
|
6
|
-
import { C as hasAnyChannelPermissionDiscord, D as createDiscordMessageNonce, F as resolveDiscordClientAccountContext, G as parseAndResolveChannelRecipient, I as resolveDiscordRest, L as DISCORD_REST_TIMEOUT_MS, M as createDiscordClient, O as resolveDiscordMessageFlags, S as hasAllGuildPermissionsDiscord, _ as canManageGuildMemberRoleDiscord, a as normalizeEmojiName, b as fetchChannelPermissionsDiscord, c as resolveChannelId, f as sendDiscordText, g as DiscordSendError, h as DISCORD_MAX_STICKER_BYTES, j as resolveDiscordSuppressEmbeds, m as DISCORD_MAX_EVENT_COVER_BYTES, n as buildDiscordTextChunks, o as normalizeReactionEmoji, p as DISCORD_MAX_EMOJI_BYTES, r as buildReactionIdentifier, t as buildDiscordSendError, v as canManageGuildRoleDiscord, w as hasAnyGuildPermissionDiscord, x as fetchMemberGuildPermissionsDiscord, y as canViewDiscordGuildChannel } from "./send.shared-
|
|
7
|
-
import { i as prepareDiscordOutboundText, n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-
|
|
8
|
-
import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS } from "./timeouts-
|
|
2
|
+
import { C as withDiscordRequestAuthority, S as readRetryAfter, _ as DiscordError, _t as getGuildMember, at as createOwnMessageReaction, b as readDiscordCode, ct as createThread, dt as getChannel, ft as getChannelMessage, gt as getGuild, ht as unpinChannelMessage, lt as deleteChannelMessage, mt as pinChannelMessage, ot as deleteOwnMessageReaction, st as listMessageReactionUsers, tt as stripUndefinedFields, ut as editChannelMessage, v as RateLimitError, vt as getGuildVoiceState, x as readDiscordMessage, y as isUnknownDiscordVoiceStateError, yt as listGuildEmojis } from "./discord-J7aRzq2Q.mjs";
|
|
3
|
+
import { E as parseDiscordRetryAfterBodySeconds, O as getDiscordEndpointRuntime, k as resolveDiscordEndpointAttachmentGuard } from "./channel-type-D1_b5UhU.mjs";
|
|
4
|
+
import { o as parseDiscordHttpErrorBody } from "./api-_oznjffB.mjs";
|
|
5
|
+
import { a as recordDiscordMessageCreateAmbiguity, f as createReusableDiscordReplyReference, l as createDiscordSendReceiptFromResults, n as classifyDiscordDeliveryFailure, o as chunkDiscordTextWithMode, p as resolveDiscordReplyMessageId, r as createDiscordRetryRunner, u as createDiscordSendResult } from "./retry-BKzO25k4.mjs";
|
|
6
|
+
import { C as hasAnyChannelPermissionDiscord, D as createDiscordMessageNonce, F as resolveDiscordClientAccountContext, G as parseAndResolveChannelRecipient, I as resolveDiscordRest, L as DISCORD_REST_TIMEOUT_MS, M as createDiscordClient, O as resolveDiscordMessageFlags, S as hasAllGuildPermissionsDiscord, _ as canManageGuildMemberRoleDiscord, a as normalizeEmojiName, b as fetchChannelPermissionsDiscord, c as resolveChannelId, f as sendDiscordText, g as DiscordSendError, h as DISCORD_MAX_STICKER_BYTES, j as resolveDiscordSuppressEmbeds, m as DISCORD_MAX_EVENT_COVER_BYTES, n as buildDiscordTextChunks, o as normalizeReactionEmoji, p as DISCORD_MAX_EMOJI_BYTES, r as buildReactionIdentifier, t as buildDiscordSendError, v as canManageGuildRoleDiscord, w as hasAnyGuildPermissionDiscord, x as fetchMemberGuildPermissionsDiscord, y as canViewDiscordGuildChannel } from "./send.shared-BQIUh6Vn.mjs";
|
|
7
|
+
import { i as prepareDiscordOutboundText, n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-B4QHSEzm.mjs";
|
|
8
|
+
import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS } from "./timeouts-pun7VJ02.mjs";
|
|
9
9
|
import fs from "node:fs/promises";
|
|
10
|
-
import {
|
|
10
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
|
+
import { ChannelType, Routes } from "discord-api-types/v10";
|
|
11
12
|
import crypto from "node:crypto";
|
|
12
|
-
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
13
13
|
import { parseStrictFiniteNumber, resolveExpiresAtMsFromDurationMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
14
14
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
15
15
|
import { formatErrorMessage as formatErrorMessage$1 } from "openclaw/plugin-sdk/error-runtime";
|
|
16
16
|
import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
|
17
|
-
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
18
17
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
19
18
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
19
|
+
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
20
20
|
import { recordOutboundMessageIdentity } from "openclaw/plugin-sdk/channel-outbound";
|
|
21
21
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, buildOutboundMediaLoadOptions, extensionForMime, maxBytesForKind, parseFfprobeCodecAndSampleRate, runFfmpeg, runFfprobe, unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
|
|
22
|
-
import { loadWebMediaRaw } from "openclaw/plugin-sdk/web-media";
|
|
23
22
|
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
23
|
+
import { loadWebMediaRaw } from "openclaw/plugin-sdk/web-media";
|
|
24
24
|
import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
|
|
25
25
|
import path from "node:path";
|
|
26
26
|
import { writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
|
|
@@ -35,7 +35,7 @@ async function createChannelDiscord(payload, opts) {
|
|
|
35
35
|
position: payload.position,
|
|
36
36
|
nsfw: payload.nsfw
|
|
37
37
|
});
|
|
38
|
-
return await
|
|
38
|
+
return await rest.post(Routes.guildChannels(payload.guildId), { body });
|
|
39
39
|
}
|
|
40
40
|
async function editChannelDiscord(payload, opts) {
|
|
41
41
|
const rest = resolveDiscordRest(opts);
|
|
@@ -57,11 +57,10 @@ async function editChannelDiscord(payload, opts) {
|
|
|
57
57
|
emoji_name: tag.emoji_name
|
|
58
58
|
}))
|
|
59
59
|
});
|
|
60
|
-
return await
|
|
60
|
+
return await rest.patch(Routes.channel(payload.channelId), { body });
|
|
61
61
|
}
|
|
62
62
|
async function deleteChannelDiscord(channelId, opts) {
|
|
63
|
-
|
|
64
|
-
await deleteChannel(rest, channelId);
|
|
63
|
+
await resolveDiscordRest(opts).delete(Routes.channel(channelId));
|
|
65
64
|
return {
|
|
66
65
|
ok: true,
|
|
67
66
|
channelId
|
|
@@ -74,7 +73,7 @@ async function moveChannelDiscord(payload, opts) {
|
|
|
74
73
|
...payload.parentId !== void 0 && { parent_id: payload.parentId },
|
|
75
74
|
...payload.position !== void 0 && { position: payload.position }
|
|
76
75
|
}];
|
|
77
|
-
await
|
|
76
|
+
await rest.patch(Routes.guildChannels(payload.guildId), { body });
|
|
78
77
|
return { ok: true };
|
|
79
78
|
}
|
|
80
79
|
async function setChannelPermissionDiscord(payload, opts) {
|
|
@@ -84,12 +83,11 @@ async function setChannelPermissionDiscord(payload, opts) {
|
|
|
84
83
|
allow: payload.allow,
|
|
85
84
|
deny: payload.deny
|
|
86
85
|
});
|
|
87
|
-
await
|
|
86
|
+
await rest.put(Routes.channelPermission(payload.channelId, payload.targetId), { body });
|
|
88
87
|
return { ok: true };
|
|
89
88
|
}
|
|
90
89
|
async function removeChannelPermissionDiscord(channelId, targetId, opts) {
|
|
91
|
-
|
|
92
|
-
await deleteChannelPermission(rest, channelId, targetId);
|
|
90
|
+
await resolveDiscordRest(opts).delete(Routes.channelPermission(channelId, targetId));
|
|
93
91
|
return { ok: true };
|
|
94
92
|
}
|
|
95
93
|
//#endregion
|
|
@@ -115,7 +113,7 @@ async function uploadEmojiDiscord(payload, opts) {
|
|
|
115
113
|
].includes(contentType)) throw new Error("Discord emoji uploads require a PNG, JPG, or GIF image");
|
|
116
114
|
const image = `data:${contentType};base64,${media.buffer.toString("base64")}`;
|
|
117
115
|
const roleIds = normalizeStringEntries(payload.roleIds ?? []);
|
|
118
|
-
return await
|
|
116
|
+
return await rest.post(Routes.guildEmojis(payload.guildId), { body: {
|
|
119
117
|
name: normalizeEmojiName(payload.name, "Emoji name"),
|
|
120
118
|
image,
|
|
121
119
|
roles: roleIds.length ? roleIds : void 0
|
|
@@ -135,7 +133,7 @@ async function uploadStickerDiscord(payload, opts) {
|
|
|
135
133
|
"image/apng",
|
|
136
134
|
"application/json"
|
|
137
135
|
].includes(contentType)) throw new Error("Discord sticker uploads require a PNG, APNG, or Lottie JSON file");
|
|
138
|
-
return await
|
|
136
|
+
return await rest.post(Routes.guildStickers(payload.guildId), {
|
|
139
137
|
multipartStyle: "form",
|
|
140
138
|
body: {
|
|
141
139
|
name: normalizeEmojiName(payload.name, "Sticker name"),
|
|
@@ -157,17 +155,14 @@ async function fetchMemberInfoDiscord(guildId, userId, opts) {
|
|
|
157
155
|
return await getGuildMember(rest, guildId, userId);
|
|
158
156
|
}
|
|
159
157
|
async function fetchRoleInfoDiscord(guildId, opts) {
|
|
160
|
-
|
|
161
|
-
return await listGuildRoles(rest, guildId);
|
|
158
|
+
return await resolveDiscordRest(opts).get(Routes.guildRoles(guildId));
|
|
162
159
|
}
|
|
163
160
|
async function addRoleDiscord(payload, opts) {
|
|
164
|
-
|
|
165
|
-
await addGuildMemberRole(rest, payload.guildId, payload.userId, payload.roleId);
|
|
161
|
+
await resolveDiscordRest(opts).put(Routes.guildMemberRole(payload.guildId, payload.userId, payload.roleId));
|
|
166
162
|
return { ok: true };
|
|
167
163
|
}
|
|
168
164
|
async function removeRoleDiscord(payload, opts) {
|
|
169
|
-
|
|
170
|
-
await removeGuildMemberRole(rest, payload.guildId, payload.userId, payload.roleId);
|
|
165
|
+
await resolveDiscordRest(opts).delete(Routes.guildMemberRole(payload.guildId, payload.userId, payload.roleId));
|
|
171
166
|
return { ok: true };
|
|
172
167
|
}
|
|
173
168
|
async function fetchChannelInfoDiscord(channelId, opts) {
|
|
@@ -179,8 +174,7 @@ async function fetchGuildInfoDiscord(guildId, opts) {
|
|
|
179
174
|
return await getGuild(rest, guildId);
|
|
180
175
|
}
|
|
181
176
|
async function listGuildChannelsDiscord(guildId, opts) {
|
|
182
|
-
|
|
183
|
-
return await listGuildChannels(rest, guildId);
|
|
177
|
+
return await resolveDiscordRest(opts).get(Routes.guildChannels(guildId));
|
|
184
178
|
}
|
|
185
179
|
async function fetchVoiceStatusDiscord(guildId, userId, opts) {
|
|
186
180
|
const rest = resolveDiscordRest(opts);
|
|
@@ -199,8 +193,7 @@ async function fetchVoiceStatusDiscord(guildId, userId, opts) {
|
|
|
199
193
|
}
|
|
200
194
|
}
|
|
201
195
|
async function listScheduledEventsDiscord(guildId, opts) {
|
|
202
|
-
|
|
203
|
-
return await listGuildScheduledEvents(rest, guildId);
|
|
196
|
+
return await resolveDiscordRest(opts).get(Routes.guildScheduledEvents(guildId));
|
|
204
197
|
}
|
|
205
198
|
const ALLOWED_EVENT_COVER_TYPES = /* @__PURE__ */ new Set([
|
|
206
199
|
"image/png",
|
|
@@ -220,8 +213,7 @@ async function resolveEventCoverImage(imageUrl, opts) {
|
|
|
220
213
|
return `data:${contentType};base64,${media.buffer.toString("base64")}`;
|
|
221
214
|
}
|
|
222
215
|
async function createScheduledEventDiscord(guildId, payload, opts) {
|
|
223
|
-
|
|
224
|
-
return await createGuildScheduledEvent(rest, guildId, payload);
|
|
216
|
+
return await resolveDiscordRest(opts).post(Routes.guildScheduledEvents(guildId), { body: payload });
|
|
225
217
|
}
|
|
226
218
|
async function timeoutMemberDiscord(payload, opts) {
|
|
227
219
|
const rest = resolveDiscordRest(opts);
|
|
@@ -231,20 +223,19 @@ async function timeoutMemberDiscord(payload, opts) {
|
|
|
231
223
|
until = timestampMsToIsoString(resolveExpiresAtMsFromDurationMs(ms));
|
|
232
224
|
if (!until) throw new Error("Discord timeout duration is outside the supported Date range");
|
|
233
225
|
}
|
|
234
|
-
return await
|
|
226
|
+
return await rest.patch(Routes.guildMember(payload.guildId, payload.userId), {
|
|
235
227
|
body: { communication_disabled_until: until ?? null },
|
|
236
228
|
headers: payload.reason ? { "X-Audit-Log-Reason": encodeURIComponent(payload.reason) } : void 0
|
|
237
229
|
});
|
|
238
230
|
}
|
|
239
231
|
async function kickMemberDiscord(payload, opts) {
|
|
240
|
-
|
|
241
|
-
await removeGuildMember(rest, payload.guildId, payload.userId, { headers: payload.reason ? { "X-Audit-Log-Reason": encodeURIComponent(payload.reason) } : void 0 });
|
|
232
|
+
await resolveDiscordRest(opts).delete(Routes.guildMember(payload.guildId, payload.userId), { headers: payload.reason ? { "X-Audit-Log-Reason": encodeURIComponent(payload.reason) } : void 0 });
|
|
242
233
|
return { ok: true };
|
|
243
234
|
}
|
|
244
235
|
async function banMemberDiscord(payload, opts) {
|
|
245
236
|
const rest = resolveDiscordRest(opts);
|
|
246
237
|
const deleteMessageDays = typeof payload.deleteMessageDays === "number" && Number.isFinite(payload.deleteMessageDays) ? Math.min(Math.max(Math.floor(payload.deleteMessageDays), 0), 7) : void 0;
|
|
247
|
-
await
|
|
238
|
+
await rest.put(Routes.guildBan(payload.guildId, payload.userId), {
|
|
248
239
|
body: deleteMessageDays !== void 0 ? { delete_message_days: deleteMessageDays } : void 0,
|
|
249
240
|
headers: payload.reason ? { "X-Audit-Log-Reason": encodeURIComponent(payload.reason) } : void 0
|
|
250
241
|
});
|
|
@@ -298,7 +289,7 @@ async function readMessagesDiscord(channelId, query, opts) {
|
|
|
298
289
|
if (messageQuery.before) params.before = messageQuery.before;
|
|
299
290
|
if (messageQuery.after) params.after = messageQuery.after;
|
|
300
291
|
if (messageQuery.around) params.around = messageQuery.around;
|
|
301
|
-
return assertDiscordResponseArray(await
|
|
292
|
+
return assertDiscordResponseArray(await rest.get(Routes.channelMessages(channelId), params), "message read");
|
|
302
293
|
}
|
|
303
294
|
async function fetchMessageDiscord(channelId, messageId, opts) {
|
|
304
295
|
const rest = resolveDiscordRest(opts);
|
|
@@ -328,8 +319,7 @@ async function unpinMessageDiscord(channelId, messageId, opts) {
|
|
|
328
319
|
return { ok: true };
|
|
329
320
|
}
|
|
330
321
|
async function listPinsDiscord(channelId, opts) {
|
|
331
|
-
|
|
332
|
-
return await listChannelPins(rest, channelId);
|
|
322
|
+
return await resolveDiscordRest(opts).get(Routes.channelPins(channelId));
|
|
333
323
|
}
|
|
334
324
|
async function createThreadDiscord(channelId, payload, opts) {
|
|
335
325
|
const assertCreateAllowed = opts.assertCreateAllowed;
|
|
@@ -343,7 +333,7 @@ async function createThreadDiscord(channelId, payload, opts) {
|
|
|
343
333
|
const archiveDuration = payload.autoArchiveMinutes ?? resolveDefaultThreadAutoArchiveDuration(channel);
|
|
344
334
|
if (archiveDuration !== void 0) body.auto_archive_duration = archiveDuration;
|
|
345
335
|
const isForumLike = channel?.type === ChannelType.GuildForum || channel?.type === ChannelType.GuildMedia;
|
|
346
|
-
const initialMessageContent =
|
|
336
|
+
const initialMessageContent = payload.content?.trim() ? payload.content : isForumLike ? payload.name : "";
|
|
347
337
|
const initialMessageChunks = buildDiscordTextChunks(initialMessageContent, { maxLinesPerMessage: DISCORD_THREAD_TRANSPORT_ONLY_MAX_LINES });
|
|
348
338
|
if (isForumLike) {
|
|
349
339
|
body.message = { content: initialMessageChunks[0] ?? payload.name };
|
|
@@ -412,21 +402,21 @@ async function listThreadsDiscord(payload, opts) {
|
|
|
412
402
|
const params = {};
|
|
413
403
|
if (payload.before) params.before = payload.before;
|
|
414
404
|
if (payload.limit) params.limit = payload.limit;
|
|
415
|
-
return await
|
|
405
|
+
return await rest.get(Routes.channelThreads(payload.channelId, "public"), params);
|
|
416
406
|
}
|
|
417
|
-
return await
|
|
407
|
+
return await rest.get(Routes.guildActiveThreads(payload.guildId));
|
|
418
408
|
}
|
|
419
409
|
async function searchMessagesDiscord(query, opts) {
|
|
420
410
|
const rest = resolveDiscordRest(opts);
|
|
421
411
|
const params = new URLSearchParams();
|
|
422
412
|
params.set("content", query.content);
|
|
423
|
-
|
|
424
|
-
|
|
413
|
+
for (const channelId of query.channelIds ?? []) params.append("channel_id", channelId);
|
|
414
|
+
for (const authorId of query.authorIds ?? []) params.append("author_id", authorId);
|
|
425
415
|
if (query.limit) {
|
|
426
416
|
const limit = Math.min(Math.max(Math.floor(query.limit), 1), 25);
|
|
427
417
|
params.set("limit", String(limit));
|
|
428
418
|
}
|
|
429
|
-
const result = assertDiscordResponseObject(await
|
|
419
|
+
const result = assertDiscordResponseObject(await rest.get(`/guilds/${query.guildId}/messages/search?${params.toString()}`), "message search");
|
|
430
420
|
if (result.code === 11e4) {
|
|
431
421
|
const message = typeof result.message === "string" && result.message.trim() ? result.message.trim() : "Discord search index is not yet available";
|
|
432
422
|
const retryAfter = parseDiscordRetryAfterBodySeconds(result.retry_after);
|
|
@@ -638,7 +628,7 @@ async function generateWaveformFromPcm(filePath) {
|
|
|
638
628
|
const pcmData = await fs.readFile(tempPcm);
|
|
639
629
|
const samples = new Int16Array(pcmData.buffer, pcmData.byteOffset, pcmData.byteLength / 2);
|
|
640
630
|
const step = Math.max(1, Math.floor(samples.length / WAVEFORM_SAMPLES));
|
|
641
|
-
const waveform =
|
|
631
|
+
const waveform = Buffer.alloc(WAVEFORM_SAMPLES);
|
|
642
632
|
for (let i = 0; i < WAVEFORM_SAMPLES && i * step < samples.length; i++) {
|
|
643
633
|
let sum = 0;
|
|
644
634
|
let count = 0;
|
|
@@ -648,10 +638,9 @@ async function generateWaveformFromPcm(filePath) {
|
|
|
648
638
|
}
|
|
649
639
|
const avg = count > 0 ? sum / count : 0;
|
|
650
640
|
const normalized = Math.min(255, Math.round(avg / 32767 * 255));
|
|
651
|
-
waveform
|
|
641
|
+
waveform[i] = normalized;
|
|
652
642
|
}
|
|
653
|
-
|
|
654
|
-
return Buffer.from(waveform).toString("base64");
|
|
643
|
+
return waveform.toString("base64");
|
|
655
644
|
} finally {
|
|
656
645
|
await unlinkIfExists(tempPcm);
|
|
657
646
|
}
|
|
@@ -835,11 +824,11 @@ async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, r
|
|
|
835
824
|
uploaded_filename: upload_filename,
|
|
836
825
|
duration_secs: metadata.durationSecs,
|
|
837
826
|
waveform: metadata.waveform
|
|
838
|
-
}]
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
827
|
+
}],
|
|
828
|
+
...replyTo ? { message_reference: {
|
|
829
|
+
message_id: replyTo,
|
|
830
|
+
fail_if_not_exists: false
|
|
831
|
+
} } : {}
|
|
843
832
|
};
|
|
844
833
|
let messageCreateMayHaveCommitted = false;
|
|
845
834
|
try {
|
|
@@ -932,8 +921,7 @@ async function sendVoiceMessageDiscordInternal(to, audioPath, opts) {
|
|
|
932
921
|
//#endregion
|
|
933
922
|
//#region extensions/discord/src/send.typing.ts
|
|
934
923
|
async function sendTypingDiscord(channelId, opts) {
|
|
935
|
-
|
|
936
|
-
await sendChannelTyping(rest, channelId);
|
|
924
|
+
await resolveDiscordRest(opts).post(Routes.channelTyping(channelId));
|
|
937
925
|
return {
|
|
938
926
|
ok: true,
|
|
939
927
|
channelId
|
|
@@ -943,7 +931,6 @@ async function sendTypingDiscord(channelId, opts) {
|
|
|
943
931
|
//#region extensions/discord/src/send.reactions.ts
|
|
944
932
|
function resolveDiscordReactionClient(opts) {
|
|
945
933
|
if (opts.rest && opts.cfg && opts.accountId) return createDiscordClient(opts);
|
|
946
|
-
if (!opts.cfg) throw new Error("Discord reactions requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
|
|
947
934
|
const cfg = requireRuntimeConfig(opts.cfg, "Discord reactions");
|
|
948
935
|
return createDiscordClient({
|
|
949
936
|
...opts,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
|
|
2
|
-
import { d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as resolveDiscordComponentAttachmentName } from "./components-
|
|
3
|
-
import { A as serializePayload, C as withDiscordRequestAuthority,
|
|
2
|
+
import { d as buildDiscordComponentMessage, f as buildDiscordComponentMessageFlags, g as resolveDiscordComponentAttachmentName } from "./components-CzXLR3QH.mjs";
|
|
3
|
+
import { A as serializePayload, C as withDiscordRequestAuthority, ut as editChannelMessage } from "./discord-J7aRzq2Q.mjs";
|
|
4
4
|
import { n as getOptionalDiscordRuntime } from "./runtime-DgnVQ7zW.mjs";
|
|
5
|
-
import { u as createDiscordSendResult } from "./retry-
|
|
6
|
-
import { D as createDiscordMessageNonce, G as parseAndResolveChannelRecipient, M as createDiscordClient, T as SUPPRESS_NOTIFICATIONS_FLAG, c as resolveChannelId, l as resolveDiscordChannel, t as buildDiscordSendError } from "./send.shared-
|
|
7
|
-
import { t as sendMessageDiscord } from "./send.outbound-
|
|
8
|
-
import {
|
|
5
|
+
import { u as createDiscordSendResult } from "./retry-BKzO25k4.mjs";
|
|
6
|
+
import { D as createDiscordMessageNonce, G as parseAndResolveChannelRecipient, M as createDiscordClient, T as SUPPRESS_NOTIFICATIONS_FLAG, c as resolveChannelId, l as resolveDiscordChannel, t as buildDiscordSendError } from "./send.shared-BQIUh6Vn.mjs";
|
|
7
|
+
import { t as sendMessageDiscord } from "./send.outbound-B4QHSEzm.mjs";
|
|
8
|
+
import { hasNonEmptyString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
|
+
import { ChannelType, Routes } from "discord-api-types/v10";
|
|
9
10
|
import { asDateTimestampMs, isFutureDateTimestampMs, resolveDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
10
11
|
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
|
|
11
|
-
import { hasNonEmptyString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
12
|
import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
|
|
13
13
|
import { extensionForMime } from "openclaw/plugin-sdk/media-mime";
|
|
14
14
|
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
@@ -35,8 +35,7 @@ const discordComponentRegistryState = resolveGlobalSingleton(Symbol.for("opencla
|
|
|
35
35
|
const DEFAULT_COMPONENT_TTL_MS = 18e5;
|
|
36
36
|
const PERSISTENT_COMPONENT_NAMESPACE = "discord.components";
|
|
37
37
|
const PERSISTENT_MODAL_NAMESPACE = "discord.modals";
|
|
38
|
-
const
|
|
39
|
-
const PERSISTENT_MODAL_MAX_ENTRIES = 500;
|
|
38
|
+
const PERSISTENT_REGISTRY_MAX_ENTRIES = 500;
|
|
40
39
|
function formatRegistryError(error) {
|
|
41
40
|
if (!(error instanceof Error)) return { error: formatRegistryErrorValue(error) };
|
|
42
41
|
const details = {
|
|
@@ -58,7 +57,6 @@ const reportPersistentComponentRegistryError = createPluginStateErrorReporter(ge
|
|
|
58
57
|
function formatRegistryErrorValue(value) {
|
|
59
58
|
if (typeof value === "string") return value;
|
|
60
59
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol") return String(value);
|
|
61
|
-
if (value === null) return "null";
|
|
62
60
|
try {
|
|
63
61
|
return JSON.stringify(value) ?? Object.prototype.toString.call(value);
|
|
64
62
|
} catch {
|
|
@@ -71,52 +69,31 @@ function disablePersistentComponentRegistry(error) {
|
|
|
71
69
|
discordComponentRegistryState.persistentModalStore = void 0;
|
|
72
70
|
reportPersistentComponentRegistryError(error);
|
|
73
71
|
}
|
|
74
|
-
function
|
|
72
|
+
function openPersistentRegistryStore(cached, namespace) {
|
|
75
73
|
if (discordComponentRegistryState.persistentRegistryDisabled) return;
|
|
76
|
-
if (
|
|
74
|
+
if (cached) return cached;
|
|
77
75
|
const runtime = getOptionalDiscordRuntime();
|
|
78
76
|
if (!runtime) return;
|
|
79
77
|
try {
|
|
80
|
-
|
|
81
|
-
namespace
|
|
82
|
-
maxEntries:
|
|
78
|
+
return runtime.state.openKeyedStore({
|
|
79
|
+
namespace,
|
|
80
|
+
maxEntries: PERSISTENT_REGISTRY_MAX_ENTRIES,
|
|
83
81
|
defaultTtlMs: DEFAULT_COMPONENT_TTL_MS
|
|
84
82
|
});
|
|
85
|
-
return discordComponentRegistryState.persistentComponentStore;
|
|
86
83
|
} catch (error) {
|
|
87
84
|
disablePersistentComponentRegistry(error);
|
|
88
85
|
return;
|
|
89
86
|
}
|
|
90
87
|
}
|
|
88
|
+
function getPersistentComponentStore() {
|
|
89
|
+
return discordComponentRegistryState.persistentComponentStore = openPersistentRegistryStore(discordComponentRegistryState.persistentComponentStore, PERSISTENT_COMPONENT_NAMESPACE);
|
|
90
|
+
}
|
|
91
91
|
function getPersistentModalStore() {
|
|
92
|
-
|
|
93
|
-
if (discordComponentRegistryState.persistentModalStore) return discordComponentRegistryState.persistentModalStore;
|
|
94
|
-
const runtime = getOptionalDiscordRuntime();
|
|
95
|
-
if (!runtime) return;
|
|
96
|
-
try {
|
|
97
|
-
discordComponentRegistryState.persistentModalStore = runtime.state.openKeyedStore({
|
|
98
|
-
namespace: PERSISTENT_MODAL_NAMESPACE,
|
|
99
|
-
maxEntries: PERSISTENT_MODAL_MAX_ENTRIES,
|
|
100
|
-
defaultTtlMs: DEFAULT_COMPONENT_TTL_MS
|
|
101
|
-
});
|
|
102
|
-
return discordComponentRegistryState.persistentModalStore;
|
|
103
|
-
} catch (error) {
|
|
104
|
-
disablePersistentComponentRegistry(error);
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
92
|
+
return discordComponentRegistryState.persistentModalStore = openPersistentRegistryStore(discordComponentRegistryState.persistentModalStore, PERSISTENT_MODAL_NAMESPACE);
|
|
107
93
|
}
|
|
108
94
|
function isExpired(entry, now) {
|
|
109
95
|
return entry.expiresAt !== void 0 && !isFutureDateTimestampMs(entry.expiresAt, { nowMs: now });
|
|
110
96
|
}
|
|
111
|
-
function normalizeEntryTimestamps(entry, now, ttlMs) {
|
|
112
|
-
const createdAt = resolveDateTimestampMs(entry.createdAt, now);
|
|
113
|
-
const expiresAt = asDateTimestampMs(entry.expiresAt) ?? resolveExpiresAtMsFromDurationMs(ttlMs, { nowMs: createdAt }) ?? 0;
|
|
114
|
-
return {
|
|
115
|
-
...entry,
|
|
116
|
-
createdAt,
|
|
117
|
-
expiresAt
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
97
|
function pruneUndefinedRegistryValues(value) {
|
|
121
98
|
if (Array.isArray(value)) return value.filter((entry) => entry !== void 0).map((entry) => pruneUndefinedRegistryValues(entry));
|
|
122
99
|
if (!value || typeof value !== "object") return value;
|
|
@@ -128,10 +105,16 @@ function pruneUndefinedRegistryValues(value) {
|
|
|
128
105
|
return result;
|
|
129
106
|
}
|
|
130
107
|
function normalizeRegistryEntries(entries, params) {
|
|
131
|
-
return entries.map((entry) =>
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
108
|
+
return entries.map((entry) => {
|
|
109
|
+
const createdAt = resolveDateTimestampMs(entry.createdAt, params.now);
|
|
110
|
+
const expiresAt = asDateTimestampMs(entry.expiresAt) ?? resolveExpiresAtMsFromDurationMs(params.ttlMs, { nowMs: createdAt }) ?? 0;
|
|
111
|
+
return {
|
|
112
|
+
...entry,
|
|
113
|
+
messageId: params.messageId ?? entry.messageId,
|
|
114
|
+
createdAt,
|
|
115
|
+
expiresAt
|
|
116
|
+
};
|
|
117
|
+
});
|
|
135
118
|
}
|
|
136
119
|
function resolveEntry(store, params) {
|
|
137
120
|
const entry = store.get(params.id);
|
|
@@ -163,17 +146,6 @@ async function registerPersistentRegistryEntries(params) {
|
|
|
163
146
|
}
|
|
164
147
|
}));
|
|
165
148
|
}
|
|
166
|
-
async function registerPersistentEntries(params) {
|
|
167
|
-
await Promise.all([registerPersistentRegistryEntries({
|
|
168
|
-
entries: params.entries,
|
|
169
|
-
ttlMs: params.ttlMs,
|
|
170
|
-
openStore: getPersistentComponentStore
|
|
171
|
-
}), registerPersistentRegistryEntries({
|
|
172
|
-
entries: params.modals,
|
|
173
|
-
ttlMs: params.ttlMs,
|
|
174
|
-
openStore: getPersistentModalStore
|
|
175
|
-
})]);
|
|
176
|
-
}
|
|
177
149
|
async function deletePersistentEntry(params) {
|
|
178
150
|
const store = params.openStore();
|
|
179
151
|
if (!store) return;
|
|
@@ -188,10 +160,6 @@ function resolveComponentConsumptionIds(entry) {
|
|
|
188
160
|
const ids = entry.consumptionGroupEntryIds?.filter((id) => typeof id === "string" && id) ?? [];
|
|
189
161
|
return ids.length > 0 ? uniqueStrings(ids) : [entry.id];
|
|
190
162
|
}
|
|
191
|
-
function deleteComponentConsumptionGroup(entry) {
|
|
192
|
-
const store = discordComponentRegistryState.componentEntries;
|
|
193
|
-
for (const id of resolveComponentConsumptionIds(entry)) store.delete(id);
|
|
194
|
-
}
|
|
195
163
|
async function deletePersistentComponentConsumptionGroup(entry) {
|
|
196
164
|
await Promise.all(resolveComponentConsumptionIds(entry).map((id) => deletePersistentEntry({
|
|
197
165
|
id,
|
|
@@ -224,23 +192,26 @@ function registerDiscordComponentEntries(params) {
|
|
|
224
192
|
return discordComponentRegistryState.withRegistryLock(async () => {
|
|
225
193
|
for (const entry of normalizedEntries) discordComponentRegistryState.componentEntries.set(entry.id, entry);
|
|
226
194
|
for (const entry of normalizedModals) discordComponentRegistryState.modalEntries.set(entry.id, entry);
|
|
227
|
-
await
|
|
195
|
+
await Promise.all([registerPersistentRegistryEntries({
|
|
228
196
|
entries: normalizedEntries,
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
})
|
|
197
|
+
ttlMs,
|
|
198
|
+
openStore: getPersistentComponentStore
|
|
199
|
+
}), registerPersistentRegistryEntries({
|
|
200
|
+
entries: normalizedModals,
|
|
201
|
+
ttlMs,
|
|
202
|
+
openStore: getPersistentModalStore
|
|
203
|
+
})]);
|
|
232
204
|
});
|
|
233
205
|
}
|
|
234
|
-
function resolveDiscordComponentEntry(params) {
|
|
235
|
-
const entry = resolveEntry(discordComponentRegistryState.componentEntries, params);
|
|
236
|
-
if (entry && params.consume !== false) deleteComponentConsumptionGroup(entry);
|
|
237
|
-
return entry;
|
|
238
|
-
}
|
|
239
206
|
async function resolveDiscordComponentEntryWithPersistence(params) {
|
|
240
207
|
return discordComponentRegistryState.withRegistryLock(async () => {
|
|
241
|
-
const
|
|
208
|
+
const store = discordComponentRegistryState.componentEntries;
|
|
209
|
+
const inMemory = resolveEntry(store, params);
|
|
242
210
|
if (inMemory) {
|
|
243
|
-
if (params.consume !== false)
|
|
211
|
+
if (params.consume !== false) {
|
|
212
|
+
for (const id of resolveComponentConsumptionIds(inMemory)) store.delete(id);
|
|
213
|
+
await deletePersistentComponentConsumptionGroup(inMemory);
|
|
214
|
+
}
|
|
244
215
|
return inMemory;
|
|
245
216
|
}
|
|
246
217
|
const persisted = await resolvePersistentRegistryEntry({
|
|
@@ -377,25 +348,8 @@ async function sendDiscordComponentMessage(to, spec, opts) {
|
|
|
377
348
|
return await withDiscordRequestAuthority(opts.assertPlatformSendAuthorized, async () => {
|
|
378
349
|
const classicMessage = opts.mediaUrl ? resolveClassicDiscordMessage(spec) : void 0;
|
|
379
350
|
if (classicMessage) return await sendMessageDiscord(to, classicMessage.text, {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
token: opts.token,
|
|
383
|
-
rest: opts.rest,
|
|
384
|
-
mediaUrl: opts.mediaUrl,
|
|
385
|
-
filename: opts.filename?.trim() || classicMessage.filename,
|
|
386
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
387
|
-
mediaReadFile: opts.mediaReadFile,
|
|
388
|
-
mediaAccess: opts.mediaAccess,
|
|
389
|
-
reply: opts.reply,
|
|
390
|
-
silent: opts.silent,
|
|
391
|
-
textLimit: opts.textLimit,
|
|
392
|
-
maxLinesPerMessage: opts.maxLinesPerMessage,
|
|
393
|
-
tableMode: opts.tableMode,
|
|
394
|
-
chunkMode: opts.chunkMode,
|
|
395
|
-
onDeliveryResult: opts.onDeliveryResult,
|
|
396
|
-
onPlatformSendDispatch: opts.onPlatformSendDispatch,
|
|
397
|
-
assertPlatformSendAuthorized: opts.assertPlatformSendAuthorized,
|
|
398
|
-
...opts.suppressEmbeds === void 0 ? {} : { suppressEmbeds: opts.suppressEmbeds }
|
|
351
|
+
...opts,
|
|
352
|
+
filename: opts.filename?.trim() || classicMessage.filename
|
|
399
353
|
});
|
|
400
354
|
return await writeDiscordComponentMessage(to, spec, opts);
|
|
401
355
|
});
|
|
@@ -432,7 +386,7 @@ async function writeDiscordComponentMessage(to, spec, opts, messageId) {
|
|
|
432
386
|
if (messageId !== void 0) return editChannelMessage(rest, channelId, messageId, { body });
|
|
433
387
|
await opts.onPlatformSendDispatch?.();
|
|
434
388
|
opts.assertPlatformSendAuthorized?.();
|
|
435
|
-
return
|
|
389
|
+
return await rest.post(Routes.channelMessages(channelId), { body });
|
|
436
390
|
}, "components", creating ? { safety: "nonce-protected-create" } : void 0);
|
|
437
391
|
} catch (err) {
|
|
438
392
|
throw await buildDiscordSendError(err, {
|