@openclaw/discord 2026.9.1-beta.1 → 2026.9.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/dist/account-inspect-BY-ve3yH.js +45 -0
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-CfQ-vSyf.js → accounts-CwJQoLjM.js} +89 -45
- package/dist/action-runtime-api.js +1 -1
- package/dist/{activities-api-q-9PaaHH.js → activities-api-CTcGq3Hf.js} +30 -17
- package/dist/activities-api.js +1 -1
- package/dist/{allow-list-BDMimASD.js → allow-list-DBTtR2dz.js} +13 -35
- package/dist/{api-DNVbJyEy.js → api-BfmEP6wp.js} +6 -5
- package/dist/api.js +18 -18
- package/dist/{approval-handler.runtime-B7qhK3fR.js → approval-handler.runtime-DUSe5fyH.js} +19 -12
- package/dist/{audit-CBEv_ERu.js → audit-DpPfwoJM.js} +8 -7
- package/dist/{channel-Dx1tMTfx.js → channel-BHajPgwR.js} +29 -23
- package/dist/{channel-actions.runtime-CLWWu9nC.js → channel-actions.runtime-DS8pXo0S.js} +38 -38
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-DOzXS2Pk.js → channel.setup-BWmMe1tT.js} +18 -18
- package/dist/command-owners-D78sAoOz.js +10 -0
- package/dist/{components-B9V5o361.js → components-BimX47Mq.js} +111 -149
- package/dist/{config-schema-BR13IAx6.js → config-schema-B797-Spt.js} +19 -12
- package/dist/{conversation-binding-route-DJYrY2TQ.js → conversation-binding-route-DuR5NGIx.js} +1 -1
- package/dist/{directory-config-BK6eqekJ.js → directory-config-CD2v2Szs.js} +2 -2
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DSAJSrJk.js → directory-live-DaJzWJ2N.js} +4 -4
- package/dist/{doctor-Cm7Y1pJ2.js → doctor-D4HH1inA.js} +9 -6
- package/dist/{doctor-contract-DsWvKIXF.js → doctor-contract-Co5vRCZ6.js} +9 -6
- package/dist/doctor-contract-api.js +31 -28
- package/dist/{handle-action.guild-admin-BdwCRHmm.js → handle-action.guild-admin-4We6wWQU.js} +6 -3
- package/dist/index.js +1 -1
- package/dist/ingress-identity-XNmW-mZS.js +60 -0
- package/dist/{message-handler-BXpWZyni.js → message-handler-DhgBabyU.js} +61 -70
- package/dist/{message-handler.preflight-Ba5LAY_X.js → message-handler.preflight-oZ7dQCd0.js} +41 -101
- package/dist/{message-handler.process-3HEzmemS.js → message-handler.process-BzCYf1pa.js} +82 -108
- package/dist/{message-text-aiwO5R2F.js → message-text-DK4NnBg-.js} +11 -6
- package/dist/{outbound-adapter-BE4jSq2d.js → outbound-adapter-CtggmGh9.js} +52 -67
- package/dist/{outbound-components-oLpg8Qzb.js → outbound-components-Dn8SJWMS.js} +5 -4
- package/dist/{outbound-session-route-Cg15ZFJd.js → outbound-session-route-Q_HEusBQ.js} +57 -15
- package/dist/{owner-access-UlYi9t0M.js → owner-access-Cp8r6Ipf.js} +9 -7
- package/dist/{pluralkit-Tiyl70dx.js → pluralkit-BY75YcK0.js} +2 -2
- package/dist/{probe-n6ZXxK8V.js → probe-3ovFAp3b.js} +3 -3
- package/dist/{probe.runtime-CN4bdPfZ.js → probe.runtime-BckHn3cJ.js} +1 -1
- package/dist/{provider-session.runtime-B9xe-Qaf.js → provider-session.runtime-BL2lHBH7.js} +3 -3
- package/dist/{provider-B11xwilq.js → provider-uKmmrDM4.js} +299 -136
- package/dist/provider.runtime-C-IkWF2w.js +2 -0
- package/dist/{realtime-session.runtime-CU8IQUS-.js → realtime-session.runtime-CGYm1t_0.js} +798 -448
- package/dist/{resolve-allowlist-common-BLoYaxEG.js → resolve-allowlist-common-sKIKy-cF.js} +3 -3
- package/dist/{resolve-channels-C2sT_n67.js → resolve-channels-CoiMlWy0.js} +4 -4
- package/dist/{resolve-users-CzpjLwjy.js → resolve-users-DJpiokfW.js} +5 -4
- package/dist/{retry-Cv4jCU5Z.js → retry-DQt1zDgH.js} +356 -214
- package/dist/{retry-after-DdLPmPoa.js → retry-after-BrLjLUJi.js} +2 -1
- package/dist/{runtime-CY4PRMF-.js → runtime-BHsdEdr5.js} +2 -2
- package/dist/{runtime-BHrTlFkf.js → runtime-Ghtfh5ZA.js} +151 -109
- package/dist/runtime-api.js +20 -20
- package/dist/{secret-config-contract-B3i6WxV5.js → secret-config-contract-DFu9hfU8.js} +14 -6
- package/dist/secret-contract-api.js +1 -1
- package/dist/{security-audit-BfJhAXZp.js → security-audit-DKfK-iPY.js} +10 -11
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/{security-audit.runtime-BVKF9VtY.js → security-audit.runtime-sKZyKgpx.js} +1 -1
- package/dist/{send-C49MFF9j.js → send-CZeWKUiA.js} +132 -100
- package/dist/{send.components-DKKAw5VX.js → send.components-BG5IDABj.js} +21 -15
- package/dist/{send.outbound-zam0TrZx.js → send.outbound-DHuFUL6W.js} +42 -63
- package/dist/{send.shared-JjljcV4O.js → send.shared-B0n_fWzu.js} +77 -149
- package/dist/{sender-identity-BJtfyise.js → sender-identity-B8Ncfi63.js} +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-_5EcP4jW.js → shared-C3dKun_X.js} +24 -15
- package/dist/{subagent-hooks-DQzvOptn.js → subagent-hooks-ZoQXEI1E.js} +2 -2
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{system-events-C7yxaHWP.js → system-events-DFF_awl7.js} +2 -2
- package/dist/{target-resolver-vxIh6O3-.js → target-resolver-DLtHDwMK.js} +6 -5
- package/dist/targets-BObRyaKX.js +3 -0
- package/dist/{thread-bindings-DW5F9vat.js → thread-bindings-DKvsNjQR.js} +7 -6
- package/dist/{thread-bindings.manager-ByOtwjo_.js → thread-bindings.manager-pbbRT5gb.js} +38 -29
- package/dist/{thread-bindings.session-updates-CJb-BpPL.js → thread-bindings.session-updates-t6jeFB1-.js} +3 -2
- package/dist/{thread-bindings.state-D8OMdk4O.js → thread-bindings.state-DtgOqsbX.js} +34 -1
- package/dist/{threading-agH1T_6s.js → threading-BCx49X-6.js} +8 -6
- package/dist/{timeouts-B9cy6RvQ.js → timeouts-D86uWLt_.js} +1 -1
- package/dist/{transcripts-source-BR11iHA4.js → transcripts-source-Dc6Nnli5.js} +55 -7
- package/dist/transcripts-source-api.js +1 -1
- package/dist/{typing-Dc_YMY2e.js → typing-CuopV-Hi.js} +2 -2
- package/dist/{voice-runtime-DIeaa8fJ.js → voice-runtime-BQnILUbG.js} +492 -105
- package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/README.md +1 -1
- package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/conforms.d.ts +2 -0
- package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/package.json +3 -3
- package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubArray.d.ts +2 -0
- package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubObject.d.ts +2 -0
- package/node_modules/@discord/embedded-app-sdk/node_modules/@types/lodash/stubString.d.ts +2 -0
- package/node_modules/@discordjs/voice/node_modules/@types/node/README.md +1 -1
- package/node_modules/@discordjs/voice/node_modules/@types/node/buffer.buffer.d.ts +5 -5
- package/node_modules/@discordjs/voice/node_modules/@types/node/crypto.d.ts +2 -2
- package/node_modules/@discordjs/voice/node_modules/@types/node/http.d.ts +16 -0
- package/node_modules/@discordjs/voice/node_modules/@types/node/http2.d.ts +10 -2
- package/node_modules/@discordjs/voice/node_modules/@types/node/package.json +2 -2
- package/node_modules/@discordjs/voice/node_modules/@types/node/process.d.ts +52 -0
- package/node_modules/@discordjs/voice/node_modules/@types/node/quic.d.ts +210 -28
- package/node_modules/@discordjs/voice/node_modules/@types/node/sqlite.d.ts +6 -2
- package/node_modules/@discordjs/voice/node_modules/@types/node/test.d.ts +36 -0
- package/node_modules/typebox/build/format/email.mjs +1 -1
- package/node_modules/typebox/build/format/idna/idn-hostname.mjs +19 -1
- package/node_modules/typebox/build/format/json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer.mjs +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.d.mts +2 -2
- package/node_modules/typebox/build/format/json_pointer_uri_fragment.mjs +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.d.mts +2 -2
- package/node_modules/typebox/build/format/relative_json_pointer.mjs +2 -2
- package/node_modules/typebox/build/system/memory/assign.mjs +2 -1
- package/node_modules/typebox/build/system/memory/create.mjs +3 -4
- package/node_modules/typebox/build/system/memory/discard.mjs +2 -2
- package/node_modules/typebox/build/system/memory/freeze.d.mts +4 -0
- package/node_modules/typebox/build/system/memory/freeze.mjs +6 -0
- package/node_modules/typebox/build/system/memory/update.mjs +3 -2
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/undici/docs/docs/api/Client.md +4 -0
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +3 -2
- package/node_modules/undici/docs/docs/api/EventSource.md +4 -0
- package/node_modules/undici/docs/docs/api/Interceptors.md +7 -3
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +7 -1
- package/node_modules/undici/lib/cache/memory-cache-store.js +2 -2
- package/node_modules/undici/lib/core/symbols.js +2 -0
- package/node_modules/undici/lib/dispatcher/agent.js +7 -2
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +7 -4
- package/node_modules/undici/lib/dispatcher/client-h1.js +12 -4
- package/node_modules/undici/lib/dispatcher/client-h2.js +43 -3
- package/node_modules/undici/lib/dispatcher/client.js +3 -2
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +13 -1
- package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -1
- package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +3 -0
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +10 -3
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +18 -1
- package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
- package/node_modules/undici/lib/dispatcher/round-robin-pool.js +1 -1
- package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +91 -21
- package/node_modules/undici/lib/handler/cache-handler.js +29 -5
- package/node_modules/undici/lib/handler/decorator-handler.js +7 -1
- package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
- package/node_modules/undici/lib/handler/redirect-handler.js +21 -4
- package/node_modules/undici/lib/handler/retry-handler.js +148 -30
- package/node_modules/undici/lib/interceptor/cache.js +65 -12
- package/node_modules/undici/lib/interceptor/decompress.js +115 -13
- package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
- package/node_modules/undici/lib/interceptor/dns.js +7 -0
- package/node_modules/undici/lib/interceptor/dump.js +10 -23
- package/node_modules/undici/lib/mock/mock-agent.js +13 -1
- package/node_modules/undici/lib/mock/mock-utils.js +11 -10
- package/node_modules/undici/lib/util/cache.js +45 -3
- package/node_modules/undici/lib/web/cookies/parse.js +150 -147
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
- package/node_modules/undici/lib/web/eventsource/eventsource.js +13 -3
- package/node_modules/undici/lib/web/fetch/index.js +6 -0
- package/node_modules/undici/lib/web/fetch/request.js +2 -3
- package/node_modules/undici/lib/web/fetch/util.js +6 -1
- package/node_modules/undici/lib/web/webidl/index.js +3 -3
- package/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
- package/node_modules/undici/package.json +3 -3
- package/node_modules/undici/types/client.d.ts +10 -0
- package/node_modules/undici/types/interceptors.d.ts +2 -0
- package/node_modules/undici/types/mock-agent.d.ts +11 -10
- package/node_modules/undici/types/socks5-proxy-agent.d.ts +2 -0
- package/openclaw.plugin.json +15 -8
- package/package.json +7 -6
- package/skills/discord/SKILL.md +1 -1
- package/dist/account-inspect-BDfKyuvL.js +0 -89
- package/dist/provider.runtime-DiYaHvOz.js +0 -2
- package/dist/sdk-runtime-4geQHtXc.js +0 -338
- package/dist/targets-CtTKvntJ.js +0 -3
|
@@ -3,7 +3,7 @@ import { collectNestedChannelFieldAssignments, collectSimpleChannelFieldAssignme
|
|
|
3
3
|
import { collectNestedChannelTtsAssignments } from "openclaw/plugin-sdk/channel-secret-tts-runtime";
|
|
4
4
|
//#region extensions/discord/src/secret-config-contract.ts
|
|
5
5
|
function createVoiceProviderSecretTarget(params) {
|
|
6
|
-
const path = `${params.scope === "account" ? "channels.discord.accounts.*" : "channels.discord"}.voice.${params.
|
|
6
|
+
const path = `${params.scope === "account" ? "channels.discord.accounts.*" : "channels.discord"}.voice.${params.providerPath}.providers.*.apiKey`;
|
|
7
7
|
return {
|
|
8
8
|
id: path,
|
|
9
9
|
targetType: path,
|
|
@@ -14,7 +14,7 @@ function createVoiceProviderSecretTarget(params) {
|
|
|
14
14
|
includeInPlan: true,
|
|
15
15
|
includeInConfigure: true,
|
|
16
16
|
includeInAudit: true,
|
|
17
|
-
providerIdPathSegmentIndex:
|
|
17
|
+
providerIdPathSegmentIndex: path.split(".").length - 2
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
function discordRealtimeVoiceSecretOwnerId(accountId, providerId) {
|
|
@@ -47,11 +47,15 @@ const secretTargetRegistryEntries = [
|
|
|
47
47
|
includeInAudit: true
|
|
48
48
|
},
|
|
49
49
|
createVoiceProviderSecretTarget({
|
|
50
|
-
|
|
50
|
+
providerPath: "realtime",
|
|
51
51
|
scope: "account"
|
|
52
52
|
}),
|
|
53
53
|
createVoiceProviderSecretTarget({
|
|
54
|
-
|
|
54
|
+
providerPath: "tts",
|
|
55
|
+
scope: "account"
|
|
56
|
+
}),
|
|
57
|
+
createVoiceProviderSecretTarget({
|
|
58
|
+
providerPath: "tts.personas.*",
|
|
55
59
|
scope: "account"
|
|
56
60
|
}),
|
|
57
61
|
{
|
|
@@ -77,11 +81,15 @@ const secretTargetRegistryEntries = [
|
|
|
77
81
|
includeInAudit: true
|
|
78
82
|
},
|
|
79
83
|
createVoiceProviderSecretTarget({
|
|
80
|
-
|
|
84
|
+
providerPath: "realtime",
|
|
85
|
+
scope: "channel"
|
|
86
|
+
}),
|
|
87
|
+
createVoiceProviderSecretTarget({
|
|
88
|
+
providerPath: "tts",
|
|
81
89
|
scope: "channel"
|
|
82
90
|
}),
|
|
83
91
|
createVoiceProviderSecretTarget({
|
|
84
|
-
|
|
92
|
+
providerPath: "tts.personas.*",
|
|
85
93
|
scope: "channel"
|
|
86
94
|
})
|
|
87
95
|
];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { r as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-
|
|
1
|
+
import { r as secretTargetRegistryEntries, t as collectRuntimeConfigAssignments } from "./secret-config-contract-DFu9hfU8.js";
|
|
2
2
|
export { collectRuntimeConfigAssignments, secretTargetRegistryEntries };
|
|
@@ -32,12 +32,8 @@ function listBroadMemberTargetPaths(params) {
|
|
|
32
32
|
}
|
|
33
33
|
function addDiscordNameBasedEntries(params) {
|
|
34
34
|
if (!Array.isArray(params.values)) return;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const text = normalizeOptionalString(String(value)) ?? "";
|
|
38
|
-
if (!text) continue;
|
|
39
|
-
params.target.add(`${params.source}:${text}`);
|
|
40
|
-
}
|
|
35
|
+
const entries = new Set(params.values.map((value) => String(value).trim()).filter(isDiscordMutableAllowEntry));
|
|
36
|
+
if (entries.size > 0) params.target.set(params.source, entries.size);
|
|
41
37
|
}
|
|
42
38
|
async function collectDiscordSecurityAuditFindings(params) {
|
|
43
39
|
const findings = [];
|
|
@@ -45,7 +41,7 @@ async function collectDiscordSecurityAuditFindings(params) {
|
|
|
45
41
|
const accountId = normalizeOptionalString(params.accountId) ?? params.account.accountId ?? "default";
|
|
46
42
|
const dangerousNameMatchingEnabled = isDangerousNameMatchingEnabled(discordCfg);
|
|
47
43
|
const storeAllowFrom = await readChannelAllowFromStore("discord", process.env, accountId).catch(() => []);
|
|
48
|
-
const discordNameBasedAllowEntries = /* @__PURE__ */ new
|
|
44
|
+
const discordNameBasedAllowEntries = /* @__PURE__ */ new Map();
|
|
49
45
|
const discordPathPrefix = params.orderedAccountIds.length > 1 || params.hasExplicitAccountPath ? `channels.discord.accounts.${accountId}` : "channels.discord";
|
|
50
46
|
if ((discordCfg.groupPolicy ?? params.cfg.channels?.defaults?.groupPolicy ?? "allowlist") === "allowlist") {
|
|
51
47
|
const broadMemberPaths = listBroadMemberTargetPaths({
|
|
@@ -73,7 +69,7 @@ async function collectDiscordSecurityAuditFindings(params) {
|
|
|
73
69
|
addDiscordNameBasedEntries({
|
|
74
70
|
target: discordNameBasedAllowEntries,
|
|
75
71
|
values: storeAllowFrom,
|
|
76
|
-
source: "
|
|
72
|
+
source: "Discord pairing store"
|
|
77
73
|
});
|
|
78
74
|
const guildEntries = discordCfg.guilds ?? {};
|
|
79
75
|
for (const [guildKey, guildValue] of Object.entries(guildEntries)) {
|
|
@@ -96,13 +92,16 @@ async function collectDiscordSecurityAuditFindings(params) {
|
|
|
96
92
|
}
|
|
97
93
|
}
|
|
98
94
|
if (discordNameBasedAllowEntries.size > 0) {
|
|
99
|
-
const
|
|
100
|
-
const
|
|
95
|
+
const counts = Array.from(discordNameBasedAllowEntries);
|
|
96
|
+
const entryCount = counts.reduce((total, [, count]) => total + count, 0);
|
|
97
|
+
const sources = counts.slice(0, 5).map(([source, count]) => `${source} (${count})`);
|
|
98
|
+
const more = counts.length > sources.length ? ` (+${counts.length - sources.length} more sources)` : "";
|
|
99
|
+
const summary = `Found ${entryCount} name/tag entries: ${sources.join(", ")}${more}.`;
|
|
101
100
|
findings.push({
|
|
102
101
|
checkId: "channels.discord.allowFrom.name_based_entries",
|
|
103
102
|
severity: dangerousNameMatchingEnabled ? "info" : "warn",
|
|
104
103
|
title: dangerousNameMatchingEnabled ? "Discord allowlist uses break-glass name/tag matching" : "Discord allowlist contains name or tag entries",
|
|
105
|
-
detail: dangerousNameMatchingEnabled ?
|
|
104
|
+
detail: dangerousNameMatchingEnabled ? "Discord name/tag allowlist matching is explicitly enabled via dangerouslyAllowNameMatching. This mutable-identity mode is operator-selected break-glass behavior and out-of-scope for vulnerability reports by itself. " + summary : "Discord name/tag allowlist matching uses normalized slugs and can collide across users. " + summary,
|
|
106
105
|
remediation: dangerousNameMatchingEnabled ? "Prefer stable Discord IDs (or <@id>/user:<id>/pk:<id>), then disable dangerouslyAllowNameMatching." : "Prefer stable Discord IDs (or <@id>/user:<id>/pk:<id>) in channels.discord.allowFrom and channels.discord.guilds.*.users, or explicitly opt in with dangerouslyAllowNameMatching=true if you accept the risk."
|
|
107
106
|
});
|
|
108
107
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as collectDiscordSecurityAuditFindings } from "./security-audit-
|
|
1
|
+
import { t as collectDiscordSecurityAuditFindings } from "./security-audit-DKfK-iPY.js";
|
|
2
2
|
export { collectDiscordSecurityAuditFindings };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as collectDiscordSecurityAuditFindings } from "./security-audit-
|
|
1
|
+
import { t as collectDiscordSecurityAuditFindings } from "./security-audit-DKfK-iPY.js";
|
|
2
2
|
export { collectDiscordSecurityAuditFindings };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { $t as
|
|
2
|
-
import { t as parseDiscordRetryAfterBodySeconds } from "./retry-after-
|
|
3
|
-
import { C as hasAllGuildPermissionsDiscord, I as resolveDiscordClientAccountContext, K as parseAndResolveChannelRecipient, L as resolveDiscordRest, M as resolveDiscordSuppressEmbeds, N as createDiscordClient, O as createDiscordMessageNonce, R as DISCORD_REST_TIMEOUT_MS, S as fetchMemberGuildPermissionsDiscord, T as hasAnyGuildPermissionDiscord, _ as DiscordSendError, b as canViewDiscordGuildChannel, g as DISCORD_MAX_STICKER_BYTES, h as DISCORD_MAX_EVENT_COVER_BYTES, i as formatReactionEmoji, k as resolveDiscordMessageFlags, l as resolveChannelId, m as DISCORD_MAX_EMOJI_BYTES, n as buildDiscordTextChunks, o as normalizeEmojiName, p as sendDiscordText, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, v as canManageGuildMemberRoleDiscord, w as hasAnyChannelPermissionDiscord, x as fetchChannelPermissionsDiscord, y as canManageGuildRoleDiscord } from "./send.shared-
|
|
4
|
-
import { n as sendPollDiscord, o as rewriteDiscordKnownMentions, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-
|
|
5
|
-
import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS } from "./timeouts-
|
|
1
|
+
import { $t as listGuildEmojis, At as editChannelMessage, B as readDiscordMessage, Bt as unpinChannelMessage, Ct as deleteOwnMessageReaction, Dt as deleteChannel, Et as createThread, Ft as listChannelMessages, Gt as createGuildScheduledEvent, Ht as createGuildBan, I as DiscordError, It as listChannelPins, Jt as getGuild, Kt as createGuildSticker, L as RateLimitError, Lt as pinChannelMessage, Mt as getChannelMessage, Ot as deleteChannelMessage, Pt as listChannelArchivedThreads, Qt as listGuildChannels, R as isUnknownDiscordVoiceStateError, Rt as searchGuildMessages, St as createOwnMessageReaction, Ut as createGuildChannel, V as readRetryAfter, Vt as addGuildMemberRole, Wt as createGuildEmoji, Xt as getGuildVoiceState, Yt as getGuildMember, Zt as listGuildActiveThreads, a as recordDiscordMessageCreateAmbiguity, an as removeGuildMemberRole, c as createDiscordSendReceiptFromResults, en as listGuildRoles, in as removeGuildMember, jt as getChannel, kt as editChannel, l as createDiscordSendResult, n as classifyDiscordDeliveryFailure, nn as moveGuildChannels, o as chunkDiscordTextWithMode, on as timeoutGuildMember, qt as deleteChannelPermission, r as createDiscordRetryRunner, rn as putChannelPermission, sn as __exportAll, tn as listGuildScheduledEvents, wt as listMessageReactionUsers, z as readDiscordCode, zt as sendChannelTyping } from "./retry-DQt1zDgH.js";
|
|
2
|
+
import { t as parseDiscordRetryAfterBodySeconds } from "./retry-after-BrLjLUJi.js";
|
|
3
|
+
import { C as hasAllGuildPermissionsDiscord, I as resolveDiscordClientAccountContext, K as parseAndResolveChannelRecipient, L as resolveDiscordRest, M as resolveDiscordSuppressEmbeds, N as createDiscordClient, O as createDiscordMessageNonce, R as DISCORD_REST_TIMEOUT_MS, S as fetchMemberGuildPermissionsDiscord, T as hasAnyGuildPermissionDiscord, _ as DiscordSendError, b as canViewDiscordGuildChannel, g as DISCORD_MAX_STICKER_BYTES, h as DISCORD_MAX_EVENT_COVER_BYTES, i as formatReactionEmoji, k as resolveDiscordMessageFlags, l as resolveChannelId, m as DISCORD_MAX_EMOJI_BYTES, n as buildDiscordTextChunks, o as normalizeEmojiName, p as sendDiscordText, r as buildReactionIdentifier, s as normalizeReactionEmoji, t as buildDiscordSendError, v as canManageGuildMemberRoleDiscord, w as hasAnyChannelPermissionDiscord, x as fetchChannelPermissionsDiscord, y as canManageGuildRoleDiscord } from "./send.shared-B0n_fWzu.js";
|
|
4
|
+
import { n as sendPollDiscord, o as rewriteDiscordKnownMentions, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-DHuFUL6W.js";
|
|
5
|
+
import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS } from "./timeouts-D86uWLt_.js";
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
7
|
import { ChannelType } from "discord-api-types/v10";
|
|
8
8
|
import crypto from "node:crypto";
|
|
@@ -55,7 +55,8 @@ async function editChannelDiscord(payload, opts) {
|
|
|
55
55
|
return await editChannel(rest, payload.channelId, { body });
|
|
56
56
|
}
|
|
57
57
|
async function deleteChannelDiscord(channelId, opts) {
|
|
58
|
-
|
|
58
|
+
const rest = resolveDiscordRest(opts);
|
|
59
|
+
await deleteChannel(rest, channelId);
|
|
59
60
|
return {
|
|
60
61
|
ok: true,
|
|
61
62
|
channelId
|
|
@@ -80,13 +81,15 @@ async function setChannelPermissionDiscord(payload, opts) {
|
|
|
80
81
|
return { ok: true };
|
|
81
82
|
}
|
|
82
83
|
async function removeChannelPermissionDiscord(channelId, targetId, opts) {
|
|
83
|
-
|
|
84
|
+
const rest = resolveDiscordRest(opts);
|
|
85
|
+
await deleteChannelPermission(rest, channelId, targetId);
|
|
84
86
|
return { ok: true };
|
|
85
87
|
}
|
|
86
88
|
//#endregion
|
|
87
89
|
//#region extensions/discord/src/send.emojis-stickers.ts
|
|
88
90
|
async function listGuildEmojisDiscord(guildId, opts) {
|
|
89
|
-
|
|
91
|
+
const rest = resolveDiscordRest(opts);
|
|
92
|
+
return await listGuildEmojis(rest, guildId);
|
|
90
93
|
}
|
|
91
94
|
async function uploadEmojiDiscord(payload, opts) {
|
|
92
95
|
const rest = resolveDiscordRest(opts);
|
|
@@ -133,27 +136,34 @@ async function uploadStickerDiscord(payload, opts) {
|
|
|
133
136
|
//#endregion
|
|
134
137
|
//#region extensions/discord/src/send.guild.ts
|
|
135
138
|
async function fetchMemberInfoDiscord(guildId, userId, opts) {
|
|
136
|
-
|
|
139
|
+
const rest = resolveDiscordRest(opts);
|
|
140
|
+
return await getGuildMember(rest, guildId, userId);
|
|
137
141
|
}
|
|
138
142
|
async function fetchRoleInfoDiscord(guildId, opts) {
|
|
139
|
-
|
|
143
|
+
const rest = resolveDiscordRest(opts);
|
|
144
|
+
return await listGuildRoles(rest, guildId);
|
|
140
145
|
}
|
|
141
146
|
async function addRoleDiscord(payload, opts) {
|
|
142
|
-
|
|
147
|
+
const rest = resolveDiscordRest(opts);
|
|
148
|
+
await addGuildMemberRole(rest, payload.guildId, payload.userId, payload.roleId);
|
|
143
149
|
return { ok: true };
|
|
144
150
|
}
|
|
145
151
|
async function removeRoleDiscord(payload, opts) {
|
|
146
|
-
|
|
152
|
+
const rest = resolveDiscordRest(opts);
|
|
153
|
+
await removeGuildMemberRole(rest, payload.guildId, payload.userId, payload.roleId);
|
|
147
154
|
return { ok: true };
|
|
148
155
|
}
|
|
149
156
|
async function fetchChannelInfoDiscord(channelId, opts) {
|
|
150
|
-
|
|
157
|
+
const rest = resolveDiscordRest(opts);
|
|
158
|
+
return await getChannel(rest, channelId);
|
|
151
159
|
}
|
|
152
160
|
async function fetchGuildInfoDiscord(guildId, opts) {
|
|
153
|
-
|
|
161
|
+
const rest = resolveDiscordRest(opts);
|
|
162
|
+
return await getGuild(rest, guildId);
|
|
154
163
|
}
|
|
155
164
|
async function listGuildChannelsDiscord(guildId, opts) {
|
|
156
|
-
|
|
165
|
+
const rest = resolveDiscordRest(opts);
|
|
166
|
+
return await listGuildChannels(rest, guildId);
|
|
157
167
|
}
|
|
158
168
|
async function fetchVoiceStatusDiscord(guildId, userId, opts) {
|
|
159
169
|
const rest = resolveDiscordRest(opts);
|
|
@@ -172,7 +182,8 @@ async function fetchVoiceStatusDiscord(guildId, userId, opts) {
|
|
|
172
182
|
}
|
|
173
183
|
}
|
|
174
184
|
async function listScheduledEventsDiscord(guildId, opts) {
|
|
175
|
-
|
|
185
|
+
const rest = resolveDiscordRest(opts);
|
|
186
|
+
return await listGuildScheduledEvents(rest, guildId);
|
|
176
187
|
}
|
|
177
188
|
const ALLOWED_EVENT_COVER_TYPES = /* @__PURE__ */ new Set([
|
|
178
189
|
"image/png",
|
|
@@ -187,13 +198,15 @@ async function resolveEventCoverImage(imageUrl, opts) {
|
|
|
187
198
|
return `data:${contentType};base64,${media.buffer.toString("base64")}`;
|
|
188
199
|
}
|
|
189
200
|
async function createScheduledEventDiscord(guildId, payload, opts) {
|
|
190
|
-
|
|
201
|
+
const rest = resolveDiscordRest(opts);
|
|
202
|
+
return await createGuildScheduledEvent(rest, guildId, payload);
|
|
191
203
|
}
|
|
192
204
|
async function timeoutMemberDiscord(payload, opts) {
|
|
193
205
|
const rest = resolveDiscordRest(opts);
|
|
194
206
|
let until = payload.until;
|
|
195
207
|
if (!until && payload.durationMinutes) {
|
|
196
|
-
|
|
208
|
+
const ms = payload.durationMinutes * 60 * 1e3;
|
|
209
|
+
until = timestampMsToIsoString(resolveExpiresAtMsFromDurationMs(ms));
|
|
197
210
|
if (!until) throw new Error("Discord timeout duration is outside the supported Date range");
|
|
198
211
|
}
|
|
199
212
|
return await timeoutGuildMember(rest, payload.guildId, payload.userId, {
|
|
@@ -202,7 +215,8 @@ async function timeoutMemberDiscord(payload, opts) {
|
|
|
202
215
|
});
|
|
203
216
|
}
|
|
204
217
|
async function kickMemberDiscord(payload, opts) {
|
|
205
|
-
|
|
218
|
+
const rest = resolveDiscordRest(opts);
|
|
219
|
+
await removeGuildMember(rest, payload.guildId, payload.userId, { headers: payload.reason ? { "X-Audit-Log-Reason": encodeURIComponent(payload.reason) } : void 0 });
|
|
206
220
|
return { ok: true };
|
|
207
221
|
}
|
|
208
222
|
async function banMemberDiscord(payload, opts) {
|
|
@@ -265,28 +279,34 @@ async function readMessagesDiscord(channelId, query, opts) {
|
|
|
265
279
|
return assertDiscordResponseArray(await listChannelMessages(rest, channelId, params), "message read");
|
|
266
280
|
}
|
|
267
281
|
async function fetchMessageDiscord(channelId, messageId, opts) {
|
|
268
|
-
|
|
282
|
+
const rest = resolveDiscordRest(opts);
|
|
283
|
+
return await getChannelMessage(rest, channelId, messageId);
|
|
269
284
|
}
|
|
270
285
|
async function editMessageDiscord(channelId, messageId, payload, opts) {
|
|
271
|
-
|
|
286
|
+
const rest = resolveDiscordRest(opts);
|
|
287
|
+
return await editChannelMessage(rest, channelId, messageId, { body: {
|
|
272
288
|
content: payload.content,
|
|
273
289
|
...payload.flags !== void 0 ? { flags: payload.flags } : {}
|
|
274
290
|
} });
|
|
275
291
|
}
|
|
276
292
|
async function deleteMessageDiscord(channelId, messageId, opts) {
|
|
277
|
-
|
|
293
|
+
const rest = resolveDiscordRest(opts);
|
|
294
|
+
await deleteChannelMessage(rest, channelId, messageId);
|
|
278
295
|
return { ok: true };
|
|
279
296
|
}
|
|
280
297
|
async function pinMessageDiscord(channelId, messageId, opts) {
|
|
281
|
-
|
|
298
|
+
const rest = resolveDiscordRest(opts);
|
|
299
|
+
await pinChannelMessage(rest, channelId, messageId);
|
|
282
300
|
return { ok: true };
|
|
283
301
|
}
|
|
284
302
|
async function unpinMessageDiscord(channelId, messageId, opts) {
|
|
285
|
-
|
|
303
|
+
const rest = resolveDiscordRest(opts);
|
|
304
|
+
await unpinChannelMessage(rest, channelId, messageId);
|
|
286
305
|
return { ok: true };
|
|
287
306
|
}
|
|
288
307
|
async function listPinsDiscord(channelId, opts) {
|
|
289
|
-
|
|
308
|
+
const rest = resolveDiscordRest(opts);
|
|
309
|
+
return await listChannelPins(rest, channelId);
|
|
290
310
|
}
|
|
291
311
|
async function createThreadDiscord(channelId, payload, opts) {
|
|
292
312
|
const { rest, request } = createDiscordClient(opts);
|
|
@@ -299,7 +319,8 @@ async function createThreadDiscord(channelId, payload, opts) {
|
|
|
299
319
|
const archiveDuration = payload.autoArchiveMinutes ?? resolveDefaultThreadAutoArchiveDuration(channel);
|
|
300
320
|
if (archiveDuration !== void 0) body.auto_archive_duration = archiveDuration;
|
|
301
321
|
const isForumLike = channel?.type === ChannelType.GuildForum || channel?.type === ChannelType.GuildMedia;
|
|
302
|
-
const
|
|
322
|
+
const initialMessageContent = isForumLike ? payload.content?.trim() ? payload.content : payload.name : payload.content?.trim() ? payload.content : "";
|
|
323
|
+
const initialMessageChunks = buildDiscordTextChunks(initialMessageContent, { maxLinesPerMessage: DISCORD_THREAD_TRANSPORT_ONLY_MAX_LINES });
|
|
303
324
|
if (isForumLike) {
|
|
304
325
|
body.message = { content: initialMessageChunks[0] ?? payload.name };
|
|
305
326
|
if (payload.appliedTags?.length) body.applied_tags = payload.appliedTags;
|
|
@@ -381,14 +402,8 @@ async function searchMessagesDiscord(query, opts) {
|
|
|
381
402
|
}
|
|
382
403
|
//#endregion
|
|
383
404
|
//#region extensions/discord/src/send.webhook.ts
|
|
384
|
-
const DISCORD_WEBHOOK_ERROR_BODY_LIMIT_BYTES =
|
|
405
|
+
const DISCORD_WEBHOOK_ERROR_BODY_LIMIT_BYTES = 8192;
|
|
385
406
|
const DISCORD_WEBHOOK_TIMEOUT_MS = DISCORD_REST_TIMEOUT_MS;
|
|
386
|
-
function resolveWebhookExecutionUrl(params) {
|
|
387
|
-
const baseUrl = new URL(`https://discord.com/api/v10/webhooks/${encodeURIComponent(params.webhookId)}/${encodeURIComponent(params.webhookToken)}`);
|
|
388
|
-
baseUrl.searchParams.set("wait", params.wait === false ? "false" : "true");
|
|
389
|
-
if (params.threadId !== void 0 && params.threadId !== null && params.threadId !== "") baseUrl.searchParams.set("thread_id", String(params.threadId));
|
|
390
|
-
return baseUrl.toString();
|
|
391
|
-
}
|
|
392
407
|
function coerceWebhookErrorBody(raw) {
|
|
393
408
|
if (!raw) return;
|
|
394
409
|
try {
|
|
@@ -439,62 +454,73 @@ async function sendWebhookMessageDiscord(text, opts) {
|
|
|
439
454
|
conversationId: threadConversationId,
|
|
440
455
|
sourceId: webhookId
|
|
441
456
|
});
|
|
442
|
-
const url =
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
threadId: opts.threadId,
|
|
446
|
-
wait: opts.wait
|
|
447
|
-
});
|
|
457
|
+
const url = new URL(`https://discord.com/api/v10/webhooks/${encodeURIComponent(webhookId)}/${encodeURIComponent(webhookToken)}`);
|
|
458
|
+
url.searchParams.set("wait", opts.wait === false ? "false" : "true");
|
|
459
|
+
if (opts.threadId != null && opts.threadId !== "") url.searchParams.set("thread_id", String(opts.threadId));
|
|
448
460
|
const deadline = buildTimeoutAbortSignal({
|
|
449
461
|
timeoutMs: DISCORD_WEBHOOK_TIMEOUT_MS,
|
|
450
462
|
operation: "discord.webhook.send"
|
|
451
463
|
});
|
|
452
464
|
const request = createDiscordRetryRunner({ signal: deadline.signal });
|
|
465
|
+
const chunks = chunkDiscordTextWithMode(rewrittenText, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
466
|
+
const results = [];
|
|
453
467
|
try {
|
|
454
|
-
const
|
|
455
|
-
await
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
content:
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
468
|
+
for (const content of chunks.length ? chunks : [""]) {
|
|
469
|
+
const response = await request(async () => {
|
|
470
|
+
await opts.onPlatformSendDispatch?.();
|
|
471
|
+
opts.assertPlatformSendAuthorized?.();
|
|
472
|
+
const attemptResponse = await (proxyFetch ?? fetch)(url.toString(), {
|
|
473
|
+
method: "POST",
|
|
474
|
+
headers: { "content-type": "application/json" },
|
|
475
|
+
body: JSON.stringify({
|
|
476
|
+
content,
|
|
477
|
+
username: normalizeOptionalString(opts.username),
|
|
478
|
+
avatar_url: normalizeOptionalString(opts.avatarUrl),
|
|
479
|
+
...flags ? { flags } : {},
|
|
480
|
+
...messageReference ? { message_reference: messageReference } : {}
|
|
481
|
+
}),
|
|
482
|
+
signal: deadline.signal
|
|
483
|
+
});
|
|
484
|
+
if (!attemptResponse.ok) await throwWebhookResponseError(attemptResponse, deadline.signal);
|
|
485
|
+
return attemptResponse;
|
|
486
|
+
}, "webhook", { safety: "non-idempotent-create" });
|
|
487
|
+
const payload = response.status === 204 ? {} : await readProviderJsonResponse(response, "Discord webhook send").catch(() => {
|
|
488
|
+
throwIfWebhookDeadlineExpired(deadline.signal);
|
|
489
|
+
return {};
|
|
467
490
|
});
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
491
|
+
try {
|
|
492
|
+
recordChannelActivity({
|
|
493
|
+
channel: "discord",
|
|
494
|
+
accountId: account.accountId,
|
|
495
|
+
direction: "outbound"
|
|
496
|
+
});
|
|
497
|
+
} catch {}
|
|
498
|
+
const result = createDiscordSendResult({
|
|
499
|
+
result: payload,
|
|
500
|
+
fallbackChannelId: opts.threadId ? String(opts.threadId) : "",
|
|
501
|
+
kind: "text",
|
|
502
|
+
...opts.threadId != null ? { threadId: opts.threadId } : {},
|
|
503
|
+
...replyTo ? { replyToId: replyTo } : {}
|
|
504
|
+
});
|
|
505
|
+
const resultConversationId = result.channelId.trim();
|
|
506
|
+
if (result.messageId && resultConversationId) recordOutboundMessageIdentity({
|
|
477
507
|
channel: "discord",
|
|
478
508
|
accountId: account.accountId,
|
|
479
|
-
|
|
509
|
+
conversationId: resultConversationId,
|
|
510
|
+
messageId: result.messageId,
|
|
511
|
+
sourceId: webhookId
|
|
480
512
|
});
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
...
|
|
487
|
-
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
if (
|
|
491
|
-
|
|
492
|
-
accountId: account.accountId,
|
|
493
|
-
conversationId: resultConversationId,
|
|
494
|
-
messageId: result.messageId,
|
|
495
|
-
sourceId: webhookId
|
|
496
|
-
});
|
|
497
|
-
return result;
|
|
513
|
+
results.push(result);
|
|
514
|
+
await opts.onDeliveryResult?.(result);
|
|
515
|
+
}
|
|
516
|
+
const last = expectDefined(results.at(-1), "Discord webhook delivery result");
|
|
517
|
+
return results.length === 1 ? last : {
|
|
518
|
+
...last,
|
|
519
|
+
receipt: createDiscordSendReceiptFromResults({ results })
|
|
520
|
+
};
|
|
521
|
+
} catch (error) {
|
|
522
|
+
if (results.length) recordDiscordMessageCreateAmbiguity(error);
|
|
523
|
+
throw error;
|
|
498
524
|
} finally {
|
|
499
525
|
deadline.cleanup();
|
|
500
526
|
}
|
|
@@ -515,7 +541,7 @@ async function sendWebhookMessageDiscord(text, opts) {
|
|
|
515
541
|
const DISCORD_VOICE_MESSAGE_FLAG = 8192;
|
|
516
542
|
const WAVEFORM_SAMPLES = 256;
|
|
517
543
|
const DISCORD_OPUS_SAMPLE_RATE_HZ = 48e3;
|
|
518
|
-
const DISCORD_VOICE_ERROR_BODY_LIMIT_BYTES =
|
|
544
|
+
const DISCORD_VOICE_ERROR_BODY_LIMIT_BYTES = 8192;
|
|
519
545
|
const DISCORD_VOICE_UPLOAD_SSRF_POLICY = {
|
|
520
546
|
allowRfc2544BenchmarkRange: true,
|
|
521
547
|
allowIpv6UniqueLocalRange: true
|
|
@@ -539,7 +565,7 @@ function createRateLimitError(response, body) {
|
|
|
539
565
|
*/
|
|
540
566
|
async function getAudioDuration(filePath) {
|
|
541
567
|
try {
|
|
542
|
-
const
|
|
568
|
+
const stdout = await runFfprobe([
|
|
543
569
|
"-v",
|
|
544
570
|
"error",
|
|
545
571
|
"-show_entries",
|
|
@@ -547,7 +573,8 @@ async function getAudioDuration(filePath) {
|
|
|
547
573
|
"-of",
|
|
548
574
|
"csv=p=0",
|
|
549
575
|
filePath
|
|
550
|
-
])
|
|
576
|
+
]);
|
|
577
|
+
const duration = parseStrictFiniteNumber(stdout);
|
|
551
578
|
if (duration === void 0) throw new Error("Could not parse duration");
|
|
552
579
|
return Math.round(duration * 100) / 100;
|
|
553
580
|
} catch (err) {
|
|
@@ -635,7 +662,7 @@ async function ensureOggOpus(filePath) {
|
|
|
635
662
|
const trimmed = filePath.trim();
|
|
636
663
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) throw new Error(`Voice message conversion requires a local file path; received a URL/protocol source: ${trimmed}`);
|
|
637
664
|
if (normalizeLowercaseStringOrEmpty(path.extname(filePath)) === ".ogg") try {
|
|
638
|
-
const
|
|
665
|
+
const stdout = await runFfprobe([
|
|
639
666
|
"-v",
|
|
640
667
|
"error",
|
|
641
668
|
"-select_streams",
|
|
@@ -645,7 +672,8 @@ async function ensureOggOpus(filePath) {
|
|
|
645
672
|
"-of",
|
|
646
673
|
"csv=p=0",
|
|
647
674
|
filePath
|
|
648
|
-
])
|
|
675
|
+
]);
|
|
676
|
+
const { codec, sampleRateHz } = parseFfprobeCodecAndSampleRate(stdout);
|
|
649
677
|
if (codec === "opus" && sampleRateHz === DISCORD_OPUS_SAMPLE_RATE_HZ) return {
|
|
650
678
|
path: filePath,
|
|
651
679
|
cleanup: false
|
|
@@ -708,20 +736,22 @@ async function createVoiceRequestError(response, fallbackMessage) {
|
|
|
708
736
|
return new DiscordError(response, parsed ?? { message: fallbackMessage });
|
|
709
737
|
}
|
|
710
738
|
async function requestVoiceUploadUrl(params) {
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
"Content-Type": "application/json"
|
|
718
|
-
},
|
|
719
|
-
body: JSON.stringify({ files: [{
|
|
720
|
-
filename: params.filename,
|
|
721
|
-
file_size: params.fileSize,
|
|
722
|
-
id: "0"
|
|
723
|
-
}] })
|
|
739
|
+
const url = `${params.rest.options?.baseUrl ?? "https://discord.com/api"}/channels/${params.channelId}/attachments`;
|
|
740
|
+
const uploadUrlInit = {
|
|
741
|
+
method: "POST",
|
|
742
|
+
headers: {
|
|
743
|
+
Authorization: `Bot ${params.botToken}`,
|
|
744
|
+
"Content-Type": "application/json"
|
|
724
745
|
},
|
|
746
|
+
body: JSON.stringify({ files: [{
|
|
747
|
+
filename: params.filename,
|
|
748
|
+
file_size: params.fileSize,
|
|
749
|
+
id: "0"
|
|
750
|
+
}] })
|
|
751
|
+
};
|
|
752
|
+
const { response: res, release } = await fetchWithSsrFGuard({
|
|
753
|
+
url,
|
|
754
|
+
init: uploadUrlInit,
|
|
725
755
|
timeoutMs: params.rest.options.timeout,
|
|
726
756
|
policy: DISCORD_VOICE_UPLOAD_SSRF_POLICY,
|
|
727
757
|
auditContext: "discord.voice.upload-url"
|
|
@@ -760,7 +790,7 @@ async function uploadVoiceAttachment(params) {
|
|
|
760
790
|
* 2. Upload the OGG file to the provided URL
|
|
761
791
|
* 3. Send the message with flag 8192 and attachment metadata
|
|
762
792
|
*/
|
|
763
|
-
async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, replyTo, request, silent, token, onPlatformSendDispatch) {
|
|
793
|
+
async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, replyTo, request, silent, token, onPlatformSendDispatch, assertPlatformSendAuthorized) {
|
|
764
794
|
const filename = "voice-message.ogg";
|
|
765
795
|
const fileSize = audioBuffer.byteLength;
|
|
766
796
|
const botToken = token;
|
|
@@ -801,6 +831,7 @@ async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, r
|
|
|
801
831
|
try {
|
|
802
832
|
return await request(async () => {
|
|
803
833
|
await onPlatformSendDispatch?.();
|
|
834
|
+
assertPlatformSendAuthorized?.();
|
|
804
835
|
try {
|
|
805
836
|
return await rest.post(`/channels/${channelId}/messages`, { body: messagePayload });
|
|
806
837
|
} catch (error) {
|
|
@@ -872,7 +903,7 @@ async function sendVoiceMessageDiscord(to, audioPath, opts) {
|
|
|
872
903
|
oggCleanup = ogg.cleanup;
|
|
873
904
|
const metadata = await getVoiceMessageMetadata(oggPath);
|
|
874
905
|
const audioBuffer = await fs.readFile(oggPath);
|
|
875
|
-
const result = await sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, opts.reply?.messageId, request, opts.silent, token, opts.onPlatformSendDispatch);
|
|
906
|
+
const result = await sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, opts.reply?.messageId, request, opts.silent, token, opts.onPlatformSendDispatch, opts.assertPlatformSendAuthorized);
|
|
876
907
|
recordChannelActivity({
|
|
877
908
|
channel: "discord",
|
|
878
909
|
accountId: accountInfo.accountId,
|
|
@@ -896,7 +927,8 @@ async function sendVoiceMessageDiscord(to, audioPath, opts) {
|
|
|
896
927
|
//#endregion
|
|
897
928
|
//#region extensions/discord/src/send.typing.ts
|
|
898
929
|
async function sendTypingDiscord(channelId, opts) {
|
|
899
|
-
|
|
930
|
+
const rest = resolveDiscordRest(opts);
|
|
931
|
+
await sendChannelTyping(rest, channelId);
|
|
900
932
|
return {
|
|
901
933
|
ok: true,
|
|
902
934
|
channelId
|