@openclaw/discord 2026.10.2 → 2026.10.5-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/dist/.setup/account-inspect-8cCu6uPG.mjs +31 -0
- package/dist/.setup/{accounts-HE9-mj1L.mjs → accounts-ljrzXBJi.mjs} +47 -45
- package/dist/.setup/{allow-list-vxkG9_JD.mjs → allow-list-B_ToXtew.mjs} +34 -101
- package/dist/.setup/{api-DlNUkDqj.mjs → api-CtmE1OUN.mjs} +25 -31
- package/dist/.setup/{approval-handler.runtime-DmnEa54W.mjs → approval-handler.runtime-D7FoZSn0.mjs} +30 -53
- package/dist/.setup/{approval-message-updates-B0jdSqOj.mjs → approval-message-updates-CIGByUcE.mjs} +2 -2
- package/dist/.setup/{audit-BpikUwN_.mjs → audit-zSawfbsN.mjs} +5 -8
- package/dist/.setup/{channel-Dr-AUnGt.mjs → channel-DI7DMzu0.mjs} +136 -215
- package/dist/.setup/{channel-access-BRp3Y-rF.mjs → channel-access-DasWY_OV.mjs} +6 -7
- package/dist/.setup/{channel.setup-BmNvkidb.mjs → channel.setup-DdFVN1mr.mjs} +35 -64
- package/dist/.setup/{components-DLJR0xU-.mjs → components-HN9052L1.mjs} +123 -146
- package/dist/.setup/{config-schema-BQWfnSCx.mjs → config-schema-_uBILpQf.mjs} +7 -3
- package/dist/.setup/{conversation-binding-route-DicJC1Lj.mjs → conversation-binding-route-DTjCBx-O.mjs} +1 -1
- package/dist/.setup/{directory-config-gqsdcplU.mjs → directory-config-3iVub-3m.mjs} +1 -1
- package/dist/.setup/{directory-live-Bipr0eUJ.mjs → directory-live-DLygQVtW.mjs} +18 -22
- package/dist/.setup/{discord-9gysrhzp.mjs → discord-BGqgx-yd.mjs} +686 -854
- package/dist/.setup/{doctor-B2bskDcF.mjs → doctor-DSrNJ7m2.mjs} +36 -47
- package/dist/.setup/{doctor-contract-Bg3NPAMw.mjs → doctor-contract-Bwv8EuQ_.mjs} +7 -16
- package/dist/.setup/{handle-action-UmkjXBfo.mjs → handle-action-CXH1h1tq.mjs} +25 -38
- package/dist/.setup/{handle-action.guild-admin-CB4sc9VV.mjs → handle-action.guild-admin-CHKW6PIs.mjs} +25 -31
- package/dist/.setup/{live-policy-config-VxexfRKo.mjs → live-policy-config-BPoB3eQi.mjs} +1 -1
- package/dist/.setup/{message-handler-BK69A-NB.mjs → message-handler-Ii_etru1.mjs} +9 -14
- package/dist/.setup/{message-handler.preflight-DFpsh90H.mjs → message-handler.preflight-C7YuSRl_.mjs} +79 -128
- package/dist/.setup/{message-handler.preflight-pluralkit-BXGGVmpe.mjs → message-handler.preflight-pluralkit-C3iAG--b.mjs} +6 -6
- package/dist/.setup/{message-handler.process-TKoqcqIP.mjs → message-handler.process-ClgWYH6o.mjs} +234 -206
- package/dist/.setup/{outbound-adapter-D4wRAb5S.mjs → outbound-adapter-D8OOIuKn.mjs} +73 -112
- package/dist/.setup/{outbound-session-route-BvBH4LC6.mjs → outbound-session-route-B0Hpwn3Q.mjs} +57 -115
- package/dist/.setup/output-activity-uBpMSX75.mjs +11 -0
- package/dist/.setup/{pluralkit-a6_NLfH9.mjs → pluralkit-B64dfq_j.mjs} +3 -1
- package/dist/.setup/{preflight-audio-DHGIHEpv.mjs → preflight-audio-wWgsZG5F.mjs} +1 -5
- package/dist/.setup/{presence-cache-Dg3_dADn.mjs → presence-cache-DCeTsL73.mjs} +3 -6
- package/dist/.setup/{probe-BwSKpnZf.mjs → probe-D3P1x4aN.mjs} +10 -18
- package/dist/.setup/{provider-YP8gN9_o.mjs → provider-D9EzOfG8.mjs} +2990 -3903
- package/dist/.setup/{provider-session.runtime-D1gkPxHT.mjs → provider-session.runtime-CsnRvddI.mjs} +5 -5
- package/dist/.setup/provider.runtime-BQVcM7Pg.mjs +2 -0
- package/dist/.setup/{realtime-session.runtime-BKUQBy1u.mjs → realtime-session.runtime-CxGBk8H-.mjs} +69 -98
- package/dist/.setup/{receive-recovery-DgkX7Qvi.mjs → receive-recovery-eVmK2_hl.mjs} +2 -12
- package/dist/.setup/resolve-allowlist-common-DNSsUQRF.mjs +66 -0
- package/dist/.setup/resolve-channels-UdT38DzU.mjs +173 -0
- package/dist/.setup/{resolve-users-DNrwvunm.mjs → resolve-users-DnCsrXZ_.mjs} +12 -41
- package/dist/.setup/{runtime-CESTexGn.mjs → runtime-CRTkKU1G.mjs} +202 -313
- package/dist/.setup/{runtime-DPcmPST9.mjs → runtime-DPm3gZXk.mjs} +2 -2
- package/dist/.setup/{secret-config-contract-uOE2J7yM.mjs → secret-config-contract-CIsH7R3B.mjs} +9 -18
- package/dist/.setup/{security-audit-D42cp5N7.mjs → security-audit-BFT84Uny.mjs} +1 -2
- package/dist/.setup/security-contract-DNyyjTZZ.mjs +19 -0
- package/dist/.setup/{send-CJk3VP5q.mjs → send-DbILKgcm.mjs} +184 -241
- package/dist/.setup/{send.components-dPljuV24.mjs → send.components-FxOS3CeP.mjs} +47 -63
- package/dist/.setup/{send.outbound-rOboMO_6.mjs → send.outbound-_jx4Xpd3.mjs} +178 -202
- package/dist/.setup/{send.receipt-DVOg2Oaw.mjs → send.receipt-BAlzXd8e.mjs} +33 -109
- package/dist/.setup/{send.shared-C4CN24D9.mjs → send.shared-CjQ4jbMA.mjs} +97 -153
- package/dist/.setup/{sender-identity-AHpUNr72.mjs → sender-identity-BNBvGt1l.mjs} +1 -1
- package/dist/.setup/setup-plugin-api-xfOFmxHP.mjs +3 -0
- package/dist/.setup/{shared-BoBnM5kM.mjs → shared-CestGDpq.mjs} +30 -20
- package/dist/.setup/{subagent-hooks-HH8Uy9cx.mjs → subagent-hooks-CME7dSGf.mjs} +5 -10
- package/dist/.setup/{system-events-Cwxaww8i.mjs → system-events-BwwSDCw4.mjs} +2 -2
- package/dist/.setup/target-parsing-C-HyNxcE.mjs +48 -0
- package/dist/.setup/{target-resolver-CSFoPQ12.mjs → target-resolver-Bse8fuTi.mjs} +11 -27
- package/dist/.setup/targets-DZJjkzwv.mjs +3 -0
- package/dist/.setup/{thread-bindings-DjQCkmsd.mjs → thread-bindings-0hPTSK14.mjs} +61 -52
- package/dist/.setup/{thread-bindings.manager-D2-GYZ5s.mjs → thread-bindings.manager-CdNa6UIs.mjs} +138 -211
- package/dist/.setup/{thread-bindings.session-updates-Bu_CGr_O.mjs → thread-bindings.session-updates-DGSljVf6.mjs} +60 -99
- package/dist/.setup/threading-BKe3E3tp.mjs +246 -0
- package/dist/.setup/{timeouts-pun7VJ02.mjs → timeouts-CuNARfyw.mjs} +10 -18
- package/dist/.setup/{transcripts-source-CaZQnGRH.mjs → transcripts-source-0qQYVu2H.mjs} +50 -368
- package/dist/.setup/{voice-runtime-DDymtIw8.mjs → voice-runtime-QlZJ4sHv.mjs} +166 -322
- package/dist/account-inspect-api.js +1 -1
- package/dist/action-runtime-api.js +1 -1
- package/dist/activities-api.js +77 -120
- package/dist/api.js +19 -18
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/doctor-contract-api.js +1 -1
- package/dist/runtime-api.js +21 -20
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/setup-entry.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/src/voice/audio-worker.runtime.js +38 -57
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/crypto.d.ts +2 -2
- package/node_modules/@types/node/dgram.d.ts +1 -1
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/@types/node/zlib.d.ts +6 -0
- package/node_modules/@types/ws/README.md +1 -1
- package/node_modules/@types/ws/index.d.mts +4 -0
- package/node_modules/@types/ws/index.d.ts +4 -0
- package/node_modules/@types/ws/package.json +3 -3
- package/node_modules/discord-api-types/_generated_/rest/v10/interfaces.d.ts +21 -0
- package/node_modules/discord-api-types/_generated_/rest/v10/interfaces.d.ts.map +1 -1
- package/node_modules/discord-api-types/_generated_/rest/v9/interfaces.d.ts +21 -0
- package/node_modules/discord-api-types/_generated_/rest/v9/interfaces.d.ts.map +1 -1
- package/node_modules/discord-api-types/globals.d.ts +6 -0
- package/node_modules/discord-api-types/globals.d.ts.map +1 -1
- package/node_modules/discord-api-types/globals.js +6 -0
- package/node_modules/discord-api-types/globals.js.map +1 -1
- package/node_modules/discord-api-types/package.json +3 -3
- package/node_modules/discord-api-types/payloads/index.mjs +1 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.d.ts +207 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.js +25 -0
- package/node_modules/discord-api-types/payloads/v10/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/payloads/v10/autoModeration.d.ts +1 -1
- package/node_modules/discord-api-types/payloads/v10/autoModeration.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/guild.d.ts +27 -23
- package/node_modules/discord-api-types/payloads/v10/guild.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/guild.js +26 -22
- package/node_modules/discord-api-types/payloads/v10/guild.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/index.d.ts +1 -0
- package/node_modules/discord-api-types/payloads/v10/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/index.js +1 -0
- package/node_modules/discord-api-types/payloads/v10/index.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v10/index.mjs +1 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.d.ts +207 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.js +25 -0
- package/node_modules/discord-api-types/payloads/v9/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/payloads/v9/autoModeration.d.ts +1 -1
- package/node_modules/discord-api-types/payloads/v9/autoModeration.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/guild.d.ts +27 -23
- package/node_modules/discord-api-types/payloads/v9/guild.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/guild.js +26 -22
- package/node_modules/discord-api-types/payloads/v9/guild.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/index.d.ts +1 -0
- package/node_modules/discord-api-types/payloads/v9/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/index.js +1 -0
- package/node_modules/discord-api-types/payloads/v9/index.js.map +1 -1
- package/node_modules/discord-api-types/payloads/v9/index.mjs +1 -0
- package/node_modules/discord-api-types/rest/common.d.ts +2 -0
- package/node_modules/discord-api-types/rest/common.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/common.js +2 -0
- package/node_modules/discord-api-types/rest/common.js.map +1 -1
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.d.ts +70 -0
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.js +3 -0
- package/node_modules/discord-api-types/rest/v10/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/rest/v10/index.d.ts +1 -0
- package/node_modules/discord-api-types/rest/v10/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v10/index.js +29 -0
- package/node_modules/discord-api-types/rest/v10/index.js.map +1 -1
- package/node_modules/discord-api-types/rest/v10/interactions.d.ts +4 -2
- package/node_modules/discord-api-types/rest/v10/interactions.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v10/user.d.ts +2 -2
- package/node_modules/discord-api-types/rest/v10/user.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.d.ts +70 -0
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.d.ts.map +1 -0
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.js +3 -0
- package/node_modules/discord-api-types/rest/v9/applicationIdentityProfile.js.map +1 -0
- package/node_modules/discord-api-types/rest/v9/index.d.ts +1 -0
- package/node_modules/discord-api-types/rest/v9/index.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v9/index.js +29 -0
- package/node_modules/discord-api-types/rest/v9/index.js.map +1 -1
- package/node_modules/discord-api-types/rest/v9/interactions.d.ts +4 -2
- package/node_modules/discord-api-types/rest/v9/interactions.d.ts.map +1 -1
- package/node_modules/discord-api-types/rest/v9/user.d.ts +2 -2
- package/node_modules/discord-api-types/rest/v9/user.d.ts.map +1 -1
- package/node_modules/discord-api-types/v10.mjs +1 -0
- package/node_modules/discord-api-types/v9.mjs +1 -0
- package/node_modules/micromark/dev/lib/compile.d.ts.map +1 -1
- package/node_modules/micromark/dev/lib/compile.js +14 -4
- package/node_modules/micromark/dev/lib/create-tokenizer.d.ts.map +1 -1
- package/node_modules/micromark/dev/lib/create-tokenizer.js +7 -6
- package/node_modules/micromark/dev/lib/initialize/document.js +25 -21
- package/node_modules/micromark/dev/lib/initialize/text.d.ts.map +1 -1
- package/node_modules/micromark/dev/lib/initialize/text.js +10 -6
- package/node_modules/micromark/dev/lib/preprocess.d.ts.map +1 -1
- package/node_modules/micromark/dev/lib/preprocess.js +19 -21
- package/node_modules/micromark/lib/compile.d.ts.map +1 -1
- package/node_modules/micromark/lib/compile.js +37 -29
- package/node_modules/micromark/lib/create-tokenizer.d.ts.map +1 -1
- package/node_modules/micromark/lib/create-tokenizer.js +37 -35
- package/node_modules/micromark/lib/initialize/document.js +21 -13
- package/node_modules/micromark/lib/initialize/text.d.ts.map +1 -1
- package/node_modules/micromark/lib/initialize/text.js +7 -3
- package/node_modules/micromark/lib/preprocess.d.ts.map +1 -1
- package/node_modules/micromark/lib/preprocess.js +16 -19
- package/node_modules/micromark/package.json +2 -15
- package/node_modules/micromark-core-commonmark/dev/lib/attention.js +18 -24
- package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.js +1 -43
- package/node_modules/micromark-core-commonmark/dev/lib/code-indented.js +19 -43
- package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.js +2 -6
- package/node_modules/micromark-core-commonmark/dev/lib/html-flow.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/dev/lib/html-flow.js +2 -53
- package/node_modules/micromark-core-commonmark/dev/lib/label-end.js +14 -12
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.js +14 -5
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.js +14 -5
- package/node_modules/micromark-core-commonmark/dev/lib/partial-non-lazy-continuation.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/dev/lib/partial-non-lazy-continuation.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/dev/lib/partial-non-lazy-continuation.js +67 -0
- package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.js +8 -5
- package/node_modules/micromark-core-commonmark/lib/attention.js +14 -24
- package/node_modules/micromark-core-commonmark/lib/code-fenced.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/lib/code-fenced.js +1 -39
- package/node_modules/micromark-core-commonmark/lib/code-indented.js +11 -29
- package/node_modules/micromark-core-commonmark/lib/heading-atx.js +2 -6
- package/node_modules/micromark-core-commonmark/lib/html-flow.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/lib/html-flow.js +2 -51
- package/node_modules/micromark-core-commonmark/lib/label-end.js +11 -10
- package/node_modules/micromark-core-commonmark/lib/label-start-image.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/lib/label-start-image.js +11 -3
- package/node_modules/micromark-core-commonmark/lib/label-start-link.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/lib/label-start-link.js +11 -3
- package/node_modules/micromark-core-commonmark/lib/partial-non-lazy-continuation.d.ts +4 -0
- package/node_modules/micromark-core-commonmark/lib/partial-non-lazy-continuation.d.ts.map +1 -0
- package/node_modules/micromark-core-commonmark/lib/partial-non-lazy-continuation.js +61 -0
- package/node_modules/micromark-core-commonmark/lib/setext-underline.d.ts.map +1 -1
- package/node_modules/micromark-core-commonmark/lib/setext-underline.js +7 -5
- package/node_modules/micromark-core-commonmark/package.json +4 -16
- package/node_modules/micromark-factory-space/dev/index.d.ts +24 -1
- package/node_modules/micromark-factory-space/dev/index.d.ts.map +1 -1
- package/node_modules/micromark-factory-space/dev/index.js +58 -3
- package/node_modules/micromark-factory-space/index.d.ts +24 -1
- package/node_modules/micromark-factory-space/index.d.ts.map +1 -1
- package/node_modules/micromark-factory-space/index.js +55 -3
- package/node_modules/micromark-factory-space/package.json +1 -10
- package/node_modules/micromark-factory-space/readme.md +25 -25
- package/node_modules/micromark-util-edit-map/dev/index.d.ts +78 -0
- package/node_modules/micromark-util-edit-map/dev/index.d.ts.map +1 -0
- package/node_modules/micromark-util-edit-map/dev/index.js +237 -0
- package/node_modules/micromark-util-edit-map/index.d.ts +78 -0
- package/node_modules/micromark-util-edit-map/index.d.ts.map +1 -0
- package/node_modules/micromark-util-edit-map/index.js +225 -0
- package/node_modules/micromark-util-edit-map/license +22 -0
- package/node_modules/micromark-util-edit-map/package.json +48 -0
- package/node_modules/micromark-util-edit-map/readme.md +234 -0
- package/node_modules/micromark-util-types/index.d.ts +6 -3
- package/node_modules/micromark-util-types/package.json +2 -36
- package/node_modules/ws/lib/websocket.js +17 -3
- package/node_modules/ws/package.json +1 -1
- package/openclaw.plugin.json +3 -6
- package/package.json +7 -12
- package/dist/.setup/account-inspect-DsER5ILV.mjs +0 -45
- package/dist/.setup/provider.runtime-CZ51OIgD.mjs +0 -2
- package/dist/.setup/resolve-allowlist-common-BUyU3C-T.mjs +0 -27
- package/dist/.setup/resolve-channels-DA6QlhZN.mjs +0 -246
- package/dist/.setup/security-contract-DSHk7I2w.mjs +0 -26
- package/dist/.setup/setup-plugin-api-BVlCz3fm.mjs +0 -3
- package/dist/.setup/targets-bqXQENmX.mjs +0 -3
- package/dist/control-ui/2afbdab1d3aa65a789d8a3eba666f4b1ec5df07073538fe30d6cf32093a1fb2d/index.js +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.mjs";
|
|
2
|
-
import { D as getDiscordEndpointRuntime, O as resolveDiscordEndpointAttachmentGuard, T as parseDiscordRetryAfterBodySeconds } from "./allow-list-
|
|
3
|
-
import { C as hasAnyChannelPermissionDiscord, D as createDiscordMessageNonce, I as resolveDiscordClientAccountContext, L as resolveDiscordRest, M as parseAndResolveChannelRecipient, N as createDiscordClient, O as resolveDiscordMessageFlags, R as DISCORD_REST_TIMEOUT_MS, S as hasAllGuildPermissionsDiscord, _ as canManageGuildMemberRoleDiscord, a as normalizeEmojiName, b as fetchChannelPermissionsDiscord, c as resolveChannelId,
|
|
4
|
-
import {
|
|
5
|
-
import { _ as
|
|
6
|
-
import { o as parseDiscordHttpErrorBody } from "./api-
|
|
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 { D as getDiscordEndpointRuntime, O as resolveDiscordEndpointAttachmentGuard, T as parseDiscordRetryAfterBodySeconds } from "./allow-list-B_ToXtew.mjs";
|
|
3
|
+
import { C as hasAnyChannelPermissionDiscord, D as createDiscordMessageNonce, I as resolveDiscordClientAccountContext, L as resolveDiscordRest, M as parseAndResolveChannelRecipient, N as createDiscordClient, O as resolveDiscordMessageFlags, R as DISCORD_REST_TIMEOUT_MS, S as hasAllGuildPermissionsDiscord, _ as canManageGuildMemberRoleDiscord, a as normalizeEmojiName, b as fetchChannelPermissionsDiscord, c as resolveChannelId, d as sendDiscordChunks, 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-CjQ4jbMA.mjs";
|
|
4
|
+
import { B as readDiscordCode, H as readRetryAfter, L as DiscordError, R as RateLimitError, V as readDiscordMessage, W as withDiscordRequestAuthority, _t as getGuildMember, at as deleteOwnMessageReaction, bt as stripUndefinedFields, ct as createThread, dt as getChannel, ft as getChannelMessage, gt as getGuild, ht as unpinChannelMessage, it as createOwnMessageReaction, lt as deleteChannelMessage, mt as pinChannelMessage, ot as listMessageReactionUsers, ut as editChannelMessage, vt as getGuildVoiceState, yt as listGuildEmojis, z as isUnknownDiscordVoiceStateError } from "./discord-BGqgx-yd.mjs";
|
|
5
|
+
import { _ as recordDiscordMessageCreateAmbiguity, a as createReusableDiscordReplyReference, h as createDiscordRetryRunner, m as classifyDiscordDeliveryFailure, n as createDiscordSendReceiptFromResults, o as resolveDiscordReplyMessageId, r as createDiscordSendResult, v as chunkDiscordTextWithMode } from "./send.receipt-BAlzXd8e.mjs";
|
|
6
|
+
import { o as parseDiscordHttpErrorBody } from "./api-CtmE1OUN.mjs";
|
|
7
|
+
import { i as prepareDiscordOutboundText, n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-_jx4Xpd3.mjs";
|
|
8
|
+
import { n as DISCORD_ATTACHMENT_TOTAL_TIMEOUT_MS } from "./timeouts-CuNARfyw.mjs";
|
|
9
9
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
10
10
|
import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
11
11
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
|
-
import { ChannelType, Routes } from "discord-api-types/v10";
|
|
12
|
+
import { ChannelType, MessageFlags, Routes } from "discord-api-types/v10";
|
|
13
13
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, buildOutboundMediaLoadOptions, extensionForMime, maxBytesForKind, parseFfprobeCodecAndSampleRate, runFfmpeg, runFfprobe, unlinkIfExists } from "openclaw/plugin-sdk/media-runtime";
|
|
14
14
|
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
15
15
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
@@ -92,25 +92,33 @@ async function removeChannelPermissionDiscord(channelId, targetId, opts) {
|
|
|
92
92
|
}
|
|
93
93
|
//#endregion
|
|
94
94
|
//#region extensions/discord/src/send.emojis-stickers.ts
|
|
95
|
+
const DISCORD_IMAGE_UPLOAD_TYPES = [
|
|
96
|
+
"image/png",
|
|
97
|
+
"image/jpeg",
|
|
98
|
+
"image/jpg",
|
|
99
|
+
"image/gif"
|
|
100
|
+
];
|
|
101
|
+
async function loadDiscordMediaForUpload(mediaUrl, opts, maxBytes, contentTypes, invalidType) {
|
|
102
|
+
const media = await loadWebMediaRaw(mediaUrl, buildOutboundMediaLoadOptions({
|
|
103
|
+
maxBytes,
|
|
104
|
+
mediaAccess: opts?.mediaAccess,
|
|
105
|
+
mediaLocalRoots: opts?.mediaLocalRoots,
|
|
106
|
+
mediaReadFile: opts?.mediaReadFile
|
|
107
|
+
}));
|
|
108
|
+
const contentType = normalizeOptionalLowercaseString(media.contentType);
|
|
109
|
+
if (!contentType || !contentTypes.includes(contentType)) throw new Error(invalidType(contentType));
|
|
110
|
+
return {
|
|
111
|
+
media,
|
|
112
|
+
contentType
|
|
113
|
+
};
|
|
114
|
+
}
|
|
95
115
|
async function listGuildEmojisDiscord(guildId, opts) {
|
|
96
116
|
const rest = resolveDiscordRest(opts);
|
|
97
117
|
return await listGuildEmojis(rest, guildId);
|
|
98
118
|
}
|
|
99
119
|
async function uploadEmojiDiscord(payload, opts) {
|
|
100
120
|
const rest = resolveDiscordRest(opts);
|
|
101
|
-
const media = await
|
|
102
|
-
maxBytes: DISCORD_MAX_EMOJI_BYTES,
|
|
103
|
-
mediaAccess: opts.mediaAccess,
|
|
104
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
105
|
-
mediaReadFile: opts.mediaReadFile
|
|
106
|
-
}));
|
|
107
|
-
const contentType = normalizeOptionalLowercaseString(media.contentType);
|
|
108
|
-
if (!contentType || ![
|
|
109
|
-
"image/png",
|
|
110
|
-
"image/jpeg",
|
|
111
|
-
"image/jpg",
|
|
112
|
-
"image/gif"
|
|
113
|
-
].includes(contentType)) throw new Error("Discord emoji uploads require a PNG, JPG, or GIF image");
|
|
121
|
+
const { media, contentType } = await loadDiscordMediaForUpload(payload.mediaUrl, opts, DISCORD_MAX_EMOJI_BYTES, DISCORD_IMAGE_UPLOAD_TYPES, () => "Discord emoji uploads require a PNG, JPG, or GIF image");
|
|
114
122
|
const image = `data:${contentType};base64,${media.buffer.toString("base64")}`;
|
|
115
123
|
const roleIds = normalizeStringEntries(payload.roleIds ?? []);
|
|
116
124
|
return await rest.post(Routes.guildEmojis(payload.guildId), { body: {
|
|
@@ -121,18 +129,11 @@ async function uploadEmojiDiscord(payload, opts) {
|
|
|
121
129
|
}
|
|
122
130
|
async function uploadStickerDiscord(payload, opts) {
|
|
123
131
|
const rest = resolveDiscordRest(opts);
|
|
124
|
-
const media = await
|
|
125
|
-
maxBytes: DISCORD_MAX_STICKER_BYTES,
|
|
126
|
-
mediaAccess: opts.mediaAccess,
|
|
127
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
128
|
-
mediaReadFile: opts.mediaReadFile
|
|
129
|
-
}));
|
|
130
|
-
const contentType = normalizeOptionalLowercaseString(media.contentType);
|
|
131
|
-
if (!contentType || ![
|
|
132
|
+
const { media, contentType } = await loadDiscordMediaForUpload(payload.mediaUrl, opts, DISCORD_MAX_STICKER_BYTES, [
|
|
132
133
|
"image/png",
|
|
133
134
|
"image/apng",
|
|
134
135
|
"application/json"
|
|
135
|
-
]
|
|
136
|
+
], () => "Discord sticker uploads require a PNG, APNG, or Lottie JSON file");
|
|
136
137
|
return await rest.post(Routes.guildStickers(payload.guildId), {
|
|
137
138
|
multipartStyle: "form",
|
|
138
139
|
body: {
|
|
@@ -150,32 +151,32 @@ async function uploadStickerDiscord(payload, opts) {
|
|
|
150
151
|
}
|
|
151
152
|
//#endregion
|
|
152
153
|
//#region extensions/discord/src/send.guild.ts
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return await getGuildMember(rest, guildId, userId);
|
|
154
|
+
function readDiscordResource(read) {
|
|
155
|
+
return async (id, opts) => await read(resolveDiscordRest(opts), id);
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
return
|
|
159
|
-
}
|
|
160
|
-
async function addRoleDiscord(payload, opts) {
|
|
161
|
-
await resolveDiscordRest(opts).put(Routes.guildMemberRole(payload.guildId, payload.userId, payload.roleId));
|
|
162
|
-
return { ok: true };
|
|
163
|
-
}
|
|
164
|
-
async function removeRoleDiscord(payload, opts) {
|
|
165
|
-
await resolveDiscordRest(opts).delete(Routes.guildMemberRole(payload.guildId, payload.userId, payload.roleId));
|
|
166
|
-
return { ok: true };
|
|
167
|
-
}
|
|
168
|
-
async function fetchChannelInfoDiscord(channelId, opts) {
|
|
169
|
-
const rest = resolveDiscordRest(opts);
|
|
170
|
-
return await getChannel(rest, channelId);
|
|
157
|
+
function auditReasonHeaders(reason) {
|
|
158
|
+
return reason ? { "X-Audit-Log-Reason": encodeURIComponent(reason) } : void 0;
|
|
171
159
|
}
|
|
172
|
-
async function
|
|
160
|
+
async function fetchMemberInfoDiscord(guildId, userId, opts) {
|
|
173
161
|
const rest = resolveDiscordRest(opts);
|
|
174
|
-
return await
|
|
162
|
+
return await getGuildMember(rest, guildId, userId);
|
|
175
163
|
}
|
|
176
|
-
|
|
177
|
-
return await
|
|
164
|
+
const fetchRoleInfoDiscord = readDiscordResource(async (rest, guildId) => {
|
|
165
|
+
return await rest.get(Routes.guildRoles(guildId));
|
|
166
|
+
});
|
|
167
|
+
function roleMutation(method) {
|
|
168
|
+
return async (payload, opts) => {
|
|
169
|
+
await resolveDiscordRest(opts)[method](Routes.guildMemberRole(payload.guildId, payload.userId, payload.roleId));
|
|
170
|
+
return { ok: true };
|
|
171
|
+
};
|
|
178
172
|
}
|
|
173
|
+
const addRoleDiscord = roleMutation("put");
|
|
174
|
+
const removeRoleDiscord = roleMutation("delete");
|
|
175
|
+
const fetchChannelInfoDiscord = readDiscordResource(getChannel);
|
|
176
|
+
const fetchGuildInfoDiscord = readDiscordResource(getGuild);
|
|
177
|
+
const listGuildChannelsDiscord = readDiscordResource(async (rest, guildId) => {
|
|
178
|
+
return await rest.get(Routes.guildChannels(guildId));
|
|
179
|
+
});
|
|
179
180
|
async function fetchVoiceStatusDiscord(guildId, userId, opts) {
|
|
180
181
|
const rest = resolveDiscordRest(opts);
|
|
181
182
|
try {
|
|
@@ -192,24 +193,11 @@ async function fetchVoiceStatusDiscord(guildId, userId, opts) {
|
|
|
192
193
|
};
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
|
-
|
|
196
|
-
return await
|
|
197
|
-
}
|
|
198
|
-
const ALLOWED_EVENT_COVER_TYPES = /* @__PURE__ */ new Set([
|
|
199
|
-
"image/png",
|
|
200
|
-
"image/jpeg",
|
|
201
|
-
"image/jpg",
|
|
202
|
-
"image/gif"
|
|
203
|
-
]);
|
|
196
|
+
const listScheduledEventsDiscord = readDiscordResource(async (rest, guildId) => {
|
|
197
|
+
return await rest.get(Routes.guildScheduledEvents(guildId));
|
|
198
|
+
});
|
|
204
199
|
async function resolveEventCoverImage(imageUrl, opts) {
|
|
205
|
-
const media = await
|
|
206
|
-
maxBytes: DISCORD_MAX_EVENT_COVER_BYTES,
|
|
207
|
-
mediaAccess: opts?.mediaAccess,
|
|
208
|
-
mediaLocalRoots: opts?.mediaLocalRoots,
|
|
209
|
-
mediaReadFile: opts?.mediaReadFile
|
|
210
|
-
}));
|
|
211
|
-
const contentType = normalizeOptionalLowercaseString(media.contentType);
|
|
212
|
-
if (!contentType || !ALLOWED_EVENT_COVER_TYPES.has(contentType)) throw new Error(`Discord event cover images must be PNG, JPG, or GIF (got ${contentType ?? "unknown"})`);
|
|
200
|
+
const { media, contentType } = await loadDiscordMediaForUpload(imageUrl, opts, DISCORD_MAX_EVENT_COVER_BYTES, DISCORD_IMAGE_UPLOAD_TYPES, (actualType) => `Discord event cover images must be PNG, JPG, or GIF (got ${actualType ?? "unknown"})`);
|
|
213
201
|
return `data:${contentType};base64,${media.buffer.toString("base64")}`;
|
|
214
202
|
}
|
|
215
203
|
async function createScheduledEventDiscord(guildId, payload, opts) {
|
|
@@ -225,11 +213,11 @@ async function timeoutMemberDiscord(payload, opts) {
|
|
|
225
213
|
}
|
|
226
214
|
return await rest.patch(Routes.guildMember(payload.guildId, payload.userId), {
|
|
227
215
|
body: { communication_disabled_until: until ?? null },
|
|
228
|
-
headers:
|
|
216
|
+
headers: auditReasonHeaders(payload.reason)
|
|
229
217
|
});
|
|
230
218
|
}
|
|
231
219
|
async function kickMemberDiscord(payload, opts) {
|
|
232
|
-
await resolveDiscordRest(opts).delete(Routes.guildMember(payload.guildId, payload.userId), { headers:
|
|
220
|
+
await resolveDiscordRest(opts).delete(Routes.guildMember(payload.guildId, payload.userId), { headers: auditReasonHeaders(payload.reason) });
|
|
233
221
|
return { ok: true };
|
|
234
222
|
}
|
|
235
223
|
async function banMemberDiscord(payload, opts) {
|
|
@@ -237,7 +225,7 @@ async function banMemberDiscord(payload, opts) {
|
|
|
237
225
|
const deleteMessageDays = typeof payload.deleteMessageDays === "number" && Number.isFinite(payload.deleteMessageDays) ? Math.min(Math.max(Math.floor(payload.deleteMessageDays), 0), 7) : void 0;
|
|
238
226
|
await rest.put(Routes.guildBan(payload.guildId, payload.userId), {
|
|
239
227
|
body: deleteMessageDays !== void 0 ? { delete_message_days: deleteMessageDays } : void 0,
|
|
240
|
-
headers:
|
|
228
|
+
headers: auditReasonHeaders(payload.reason)
|
|
241
229
|
});
|
|
242
230
|
return { ok: true };
|
|
243
231
|
}
|
|
@@ -257,10 +245,6 @@ function assertDiscordResponseObject(value, label) {
|
|
|
257
245
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`Unexpected Discord response for ${label}: expected object.`);
|
|
258
246
|
return value;
|
|
259
247
|
}
|
|
260
|
-
function resolveDefaultThreadAutoArchiveDuration(channel) {
|
|
261
|
-
if (!channel || !("default_auto_archive_duration" in channel)) return;
|
|
262
|
-
return channel.default_auto_archive_duration;
|
|
263
|
-
}
|
|
264
248
|
function describeDiscordThreadInitialMessageFailure(delivery) {
|
|
265
249
|
if (delivery?.failedChunkDelivery === "unknown") return delivery.deliveredChunkCount > 0 ? "Discord thread was created, but delivery of the remaining initial content could not be confirmed" : "Discord thread was created, but initial message delivery could not be confirmed";
|
|
266
250
|
return delivery && delivery.deliveredChunkCount > 0 ? "Discord thread was created, but its initial content was only partially delivered" : "Discord thread was created, but sending the initial message failed";
|
|
@@ -286,9 +270,14 @@ async function readMessagesDiscord(channelId, query, opts) {
|
|
|
286
270
|
const limit = typeof messageQuery.limit === "number" && Number.isFinite(messageQuery.limit) ? Math.min(Math.max(Math.floor(messageQuery.limit), 1), 100) : void 0;
|
|
287
271
|
const params = {};
|
|
288
272
|
if (limit) params.limit = limit;
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
273
|
+
for (const key of [
|
|
274
|
+
"before",
|
|
275
|
+
"after",
|
|
276
|
+
"around"
|
|
277
|
+
]) {
|
|
278
|
+
const value = messageQuery[key];
|
|
279
|
+
if (value) params[key] = value;
|
|
280
|
+
}
|
|
292
281
|
return assertDiscordResponseArray(await rest.get(Routes.channelMessages(channelId), params), "message read");
|
|
293
282
|
}
|
|
294
283
|
async function fetchMessageDiscord(channelId, messageId, opts) {
|
|
@@ -303,21 +292,15 @@ async function editMessageDiscord(channelId, messageId, payload, opts) {
|
|
|
303
292
|
...payload.allowedMentions ? { allowed_mentions: payload.allowedMentions } : {}
|
|
304
293
|
} });
|
|
305
294
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
async function pinMessageDiscord(channelId, messageId, opts) {
|
|
312
|
-
const rest = resolveDiscordRest(opts);
|
|
313
|
-
await pinChannelMessage(rest, channelId, messageId);
|
|
314
|
-
return { ok: true };
|
|
315
|
-
}
|
|
316
|
-
async function unpinMessageDiscord(channelId, messageId, opts) {
|
|
317
|
-
const rest = resolveDiscordRest(opts);
|
|
318
|
-
await unpinChannelMessage(rest, channelId, messageId);
|
|
319
|
-
return { ok: true };
|
|
295
|
+
function messageMutation(operation) {
|
|
296
|
+
return async (channelId, messageId, opts) => {
|
|
297
|
+
await operation(resolveDiscordRest(opts), channelId, messageId);
|
|
298
|
+
return { ok: true };
|
|
299
|
+
};
|
|
320
300
|
}
|
|
301
|
+
const deleteMessageDiscord = messageMutation(deleteChannelMessage);
|
|
302
|
+
const pinMessageDiscord = messageMutation(pinChannelMessage);
|
|
303
|
+
const unpinMessageDiscord = messageMutation(unpinChannelMessage);
|
|
321
304
|
async function listPinsDiscord(channelId, opts) {
|
|
322
305
|
return await resolveDiscordRest(opts).get(Routes.channelPins(channelId));
|
|
323
306
|
}
|
|
@@ -327,10 +310,8 @@ async function createThreadDiscord(channelId, payload, opts) {
|
|
|
327
310
|
const body = { name: payload.name };
|
|
328
311
|
if (!payload.messageId && payload.type !== void 0) body.type = payload.type;
|
|
329
312
|
let channel;
|
|
330
|
-
if (!payload.messageId)
|
|
331
|
-
|
|
332
|
-
} catch {}
|
|
333
|
-
const archiveDuration = payload.autoArchiveMinutes ?? resolveDefaultThreadAutoArchiveDuration(channel);
|
|
313
|
+
if (!payload.messageId) channel = await getChannel(rest, channelId).catch(() => void 0);
|
|
314
|
+
const archiveDuration = payload.autoArchiveMinutes ?? (channel && "default_auto_archive_duration" in channel ? channel.default_auto_archive_duration : void 0);
|
|
334
315
|
if (archiveDuration !== void 0) body.auto_archive_duration = archiveDuration;
|
|
335
316
|
const isForumLike = channel?.type === ChannelType.GuildForum || channel?.type === ChannelType.GuildMedia;
|
|
336
317
|
const initialMessageContent = payload.content?.trim() ? payload.content : isForumLike ? payload.name : "";
|
|
@@ -360,7 +341,7 @@ async function createThreadDiscord(channelId, payload, opts) {
|
|
|
360
341
|
}
|
|
361
342
|
}, label, options);
|
|
362
343
|
try {
|
|
363
|
-
const result = await
|
|
344
|
+
const result = await sendDiscordChunks({
|
|
364
345
|
rest,
|
|
365
346
|
request: trackedRequest,
|
|
366
347
|
channelId: thread.id,
|
|
@@ -554,7 +535,6 @@ async function sendWebhookMessageDiscord(text, opts) {
|
|
|
554
535
|
}
|
|
555
536
|
//#endregion
|
|
556
537
|
//#region extensions/discord/src/voice-message.ts
|
|
557
|
-
const DISCORD_VOICE_MESSAGE_FLAG = 8192;
|
|
558
538
|
const WAVEFORM_SAMPLES = 256;
|
|
559
539
|
const DISCORD_OPUS_SAMPLE_RATE_HZ = 48e3;
|
|
560
540
|
const DISCORD_VOICE_ERROR_BODY_LIMIT_BYTES = 8192;
|
|
@@ -562,14 +542,25 @@ const DISCORD_VOICE_UPLOAD_SSRF_POLICY = {
|
|
|
562
542
|
allowRfc2544BenchmarkRange: true,
|
|
563
543
|
allowIpv6UniqueLocalRange: true
|
|
564
544
|
};
|
|
565
|
-
async function runFfmpegToOutput(
|
|
566
|
-
const rootDir = path.dirname(
|
|
545
|
+
async function runFfmpegToOutput(inputPath, outputPath, outputArgs) {
|
|
546
|
+
const rootDir = path.dirname(outputPath);
|
|
567
547
|
await fs.mkdir(rootDir, { recursive: true });
|
|
568
548
|
await writeExternalFileWithinRoot({
|
|
569
549
|
rootDir,
|
|
570
|
-
path: path.basename(
|
|
550
|
+
path: path.basename(outputPath),
|
|
571
551
|
write: async (tempPath) => {
|
|
572
|
-
await runFfmpeg(
|
|
552
|
+
await runFfmpeg([
|
|
553
|
+
"-y",
|
|
554
|
+
"-i",
|
|
555
|
+
inputPath,
|
|
556
|
+
"-vn",
|
|
557
|
+
"-sn",
|
|
558
|
+
"-dn",
|
|
559
|
+
"-t",
|
|
560
|
+
String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
|
|
561
|
+
...outputArgs,
|
|
562
|
+
tempPath
|
|
563
|
+
]);
|
|
573
564
|
}
|
|
574
565
|
});
|
|
575
566
|
}
|
|
@@ -592,51 +583,29 @@ async function getAudioDuration(filePath) {
|
|
|
592
583
|
throw new Error(`Failed to get audio duration: ${errMessage}`, { cause: err });
|
|
593
584
|
}
|
|
594
585
|
}
|
|
595
|
-
async function generateWaveform(filePath) {
|
|
596
|
-
try {
|
|
597
|
-
return await generateWaveformFromPcm(filePath);
|
|
598
|
-
} catch {
|
|
599
|
-
return generatePlaceholderWaveform();
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
586
|
async function generateWaveformFromPcm(filePath) {
|
|
603
587
|
const tempDir = resolvePreferredOpenClawTmpDir();
|
|
604
588
|
const tempPcm = path.join(tempDir, `waveform-${crypto.randomUUID()}.raw`);
|
|
605
589
|
try {
|
|
606
|
-
await runFfmpegToOutput(
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
|
|
617
|
-
"-f",
|
|
618
|
-
"s16le",
|
|
619
|
-
"-acodec",
|
|
620
|
-
"pcm_s16le",
|
|
621
|
-
"-ac",
|
|
622
|
-
"1",
|
|
623
|
-
"-ar",
|
|
624
|
-
"8000",
|
|
625
|
-
outputPath
|
|
626
|
-
]
|
|
627
|
-
});
|
|
590
|
+
await runFfmpegToOutput(filePath, tempPcm, [
|
|
591
|
+
"-f",
|
|
592
|
+
"s16le",
|
|
593
|
+
"-acodec",
|
|
594
|
+
"pcm_s16le",
|
|
595
|
+
"-ac",
|
|
596
|
+
"1",
|
|
597
|
+
"-ar",
|
|
598
|
+
"8000"
|
|
599
|
+
]);
|
|
628
600
|
const pcmData = await fs.readFile(tempPcm);
|
|
629
601
|
const samples = new Int16Array(pcmData.buffer, pcmData.byteOffset, pcmData.byteLength / 2);
|
|
630
602
|
const step = Math.max(1, Math.floor(samples.length / WAVEFORM_SAMPLES));
|
|
631
603
|
const waveform = Buffer.alloc(WAVEFORM_SAMPLES);
|
|
632
604
|
for (let i = 0; i < WAVEFORM_SAMPLES && i * step < samples.length; i++) {
|
|
633
605
|
let sum = 0;
|
|
634
|
-
|
|
635
|
-
for (let j = 0; j <
|
|
636
|
-
|
|
637
|
-
count++;
|
|
638
|
-
}
|
|
639
|
-
const avg = count > 0 ? sum / count : 0;
|
|
606
|
+
const count = Math.min(step, samples.length - i * step);
|
|
607
|
+
for (let j = 0; j < count; j++) sum += Math.abs(expectDefined(samples.at(i * step + j), "bounded PCM waveform sample"));
|
|
608
|
+
const avg = sum / count;
|
|
640
609
|
const normalized = Math.min(255, Math.round(avg / 32767 * 255));
|
|
641
610
|
waveform[i] = normalized;
|
|
642
611
|
}
|
|
@@ -680,28 +649,16 @@ async function ensureOggOpus(filePath) {
|
|
|
680
649
|
} catch {}
|
|
681
650
|
const tempDir = resolvePreferredOpenClawTmpDir();
|
|
682
651
|
const outputPath = path.join(tempDir, `voice-${crypto.randomUUID()}.ogg`);
|
|
683
|
-
await runFfmpegToOutput(
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
|
|
694
|
-
"-ar",
|
|
695
|
-
String(DISCORD_OPUS_SAMPLE_RATE_HZ),
|
|
696
|
-
"-c:a",
|
|
697
|
-
"libopus",
|
|
698
|
-
"-b:a",
|
|
699
|
-
"64k",
|
|
700
|
-
"-f",
|
|
701
|
-
"ogg",
|
|
702
|
-
tempPath
|
|
703
|
-
]
|
|
704
|
-
});
|
|
652
|
+
await runFfmpegToOutput(filePath, outputPath, [
|
|
653
|
+
"-ar",
|
|
654
|
+
String(DISCORD_OPUS_SAMPLE_RATE_HZ),
|
|
655
|
+
"-c:a",
|
|
656
|
+
"libopus",
|
|
657
|
+
"-b:a",
|
|
658
|
+
"64k",
|
|
659
|
+
"-f",
|
|
660
|
+
"ogg"
|
|
661
|
+
]);
|
|
705
662
|
return {
|
|
706
663
|
path: outputPath,
|
|
707
664
|
cleanup: true
|
|
@@ -711,7 +668,7 @@ async function ensureOggOpus(filePath) {
|
|
|
711
668
|
* Wait for waveform cleanup before callers can release the audio input.
|
|
712
669
|
*/
|
|
713
670
|
async function getVoiceMessageMetadata(filePath) {
|
|
714
|
-
const waveform =
|
|
671
|
+
const waveform = generateWaveformFromPcm(filePath).catch(generatePlaceholderWaveform);
|
|
715
672
|
try {
|
|
716
673
|
return {
|
|
717
674
|
durationSecs: await getAudioDuration(filePath),
|
|
@@ -794,14 +751,13 @@ async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, r
|
|
|
794
751
|
const filename = "voice-message.ogg";
|
|
795
752
|
const fileSize = audioBuffer.byteLength;
|
|
796
753
|
const endpointRuntime = getDiscordEndpointRuntime() ?? null;
|
|
797
|
-
|
|
798
|
-
if (!botToken) throw new Error("Discord bot token is required for voice message upload");
|
|
754
|
+
if (!token) throw new Error("Discord bot token is required for voice message upload");
|
|
799
755
|
const { upload_filename } = await request(async () => {
|
|
800
756
|
const uploadUrlResponse = await requestVoiceUploadUrl({
|
|
801
757
|
rest,
|
|
802
758
|
endpointRuntime,
|
|
803
759
|
channelId,
|
|
804
|
-
botToken,
|
|
760
|
+
botToken: token,
|
|
805
761
|
filename,
|
|
806
762
|
fileSize
|
|
807
763
|
});
|
|
@@ -815,7 +771,7 @@ async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, r
|
|
|
815
771
|
return attachment;
|
|
816
772
|
}, "voice-upload");
|
|
817
773
|
const messagePayload = {
|
|
818
|
-
flags: silent ?
|
|
774
|
+
flags: MessageFlags.IsVoiceMessage | (silent ? MessageFlags.SuppressNotifications : 0),
|
|
819
775
|
nonce: createDiscordMessageNonce(),
|
|
820
776
|
enforce_nonce: true,
|
|
821
777
|
attachments: [{
|
|
@@ -849,73 +805,63 @@ async function sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, r
|
|
|
849
805
|
}
|
|
850
806
|
//#endregion
|
|
851
807
|
//#region extensions/discord/src/send.voice.ts
|
|
852
|
-
async function withMaterializedVoiceMessageInput(mediaUrl, opts, run) {
|
|
853
|
-
const media = await loadWebMediaRaw(mediaUrl, buildOutboundMediaLoadOptions({
|
|
854
|
-
maxBytes: maxBytesForKind("audio"),
|
|
855
|
-
mediaAccess: opts.mediaAccess,
|
|
856
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
857
|
-
mediaReadFile: opts.mediaReadFile
|
|
858
|
-
}));
|
|
859
|
-
const extFromName = media.fileName ? path.extname(media.fileName) : "";
|
|
860
|
-
const extFromMime = media.contentType ? extensionForMime(media.contentType) : "";
|
|
861
|
-
const ext = extFromName || extFromMime || ".bin";
|
|
862
|
-
return await withTempWorkspace({
|
|
863
|
-
rootDir: resolvePreferredOpenClawTmpDir(),
|
|
864
|
-
prefix: "voice-src-"
|
|
865
|
-
}, async (workspace) => await run(await workspace.write(`input${ext}`, media.buffer)));
|
|
866
|
-
}
|
|
867
808
|
/** Discord voice messages require OGG/Opus audio with a waveform and cannot include text. */
|
|
868
809
|
async function sendVoiceMessageDiscord(to, audioPath, opts) {
|
|
869
|
-
return await withDiscordRequestAuthority(opts.assertPlatformSendAuthorized, () =>
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
token,
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
810
|
+
return await withDiscordRequestAuthority(opts.assertPlatformSendAuthorized, async () => {
|
|
811
|
+
const cfg = requireRuntimeConfig(opts.cfg, "Discord voice send");
|
|
812
|
+
const media = await loadWebMediaRaw(audioPath, buildOutboundMediaLoadOptions({
|
|
813
|
+
maxBytes: maxBytesForKind("audio"),
|
|
814
|
+
mediaAccess: opts.mediaAccess,
|
|
815
|
+
mediaLocalRoots: opts.mediaLocalRoots,
|
|
816
|
+
mediaReadFile: opts.mediaReadFile
|
|
817
|
+
}));
|
|
818
|
+
const extFromName = media.fileName ? path.extname(media.fileName) : "";
|
|
819
|
+
const extFromMime = media.contentType ? extensionForMime(media.contentType) : "";
|
|
820
|
+
const ext = extFromName || extFromMime || ".bin";
|
|
821
|
+
return await withTempWorkspace({
|
|
822
|
+
rootDir: resolvePreferredOpenClawTmpDir(),
|
|
823
|
+
prefix: "voice-src-"
|
|
824
|
+
}, async (workspace) => {
|
|
825
|
+
const localInputPath = await workspace.write(`input${ext}`, media.buffer);
|
|
826
|
+
let ogg;
|
|
827
|
+
let client;
|
|
828
|
+
let channelId;
|
|
829
|
+
try {
|
|
830
|
+
client = createDiscordClient({
|
|
831
|
+
...opts,
|
|
832
|
+
cfg
|
|
833
|
+
});
|
|
834
|
+
const { token, rest, request, account: accountInfo } = client;
|
|
835
|
+
const recipient = await parseAndResolveChannelRecipient(to, cfg, accountInfo.accountId);
|
|
836
|
+
channelId = (await resolveChannelId(rest, recipient, request)).channelId;
|
|
837
|
+
ogg = await ensureOggOpus(localInputPath);
|
|
838
|
+
const metadata = await getVoiceMessageMetadata(ogg.path);
|
|
839
|
+
const audioBuffer = await fs.readFile(ogg.path);
|
|
840
|
+
const result = await sendDiscordVoiceMessage(rest, channelId, audioBuffer, metadata, opts.reply?.messageId, request, opts.silent, token, opts.onPlatformSendDispatch, opts.assertPlatformSendAuthorized);
|
|
841
|
+
recordChannelActivity({
|
|
842
|
+
channel: "discord",
|
|
843
|
+
accountId: accountInfo.accountId,
|
|
844
|
+
direction: "outbound"
|
|
845
|
+
});
|
|
846
|
+
return createDiscordSendResult({
|
|
847
|
+
result,
|
|
848
|
+
fallbackChannelId: channelId,
|
|
849
|
+
kind: "voice",
|
|
850
|
+
reply: opts.reply
|
|
851
|
+
});
|
|
852
|
+
} catch (err) {
|
|
853
|
+
if (channelId && client?.rest && client.token) throw await buildDiscordSendError(err, {
|
|
854
|
+
channelId,
|
|
855
|
+
cfg,
|
|
856
|
+
rest: client.rest,
|
|
857
|
+
token: client.token,
|
|
858
|
+
hasMedia: true
|
|
859
|
+
});
|
|
860
|
+
throw err;
|
|
861
|
+
} finally {
|
|
862
|
+
await unlinkIfExists(ogg?.cleanup ? ogg.path : null);
|
|
863
|
+
}
|
|
864
|
+
});
|
|
919
865
|
});
|
|
920
866
|
}
|
|
921
867
|
//#endregion
|
|
@@ -937,18 +883,16 @@ function resolveDiscordReactionClient(opts) {
|
|
|
937
883
|
cfg
|
|
938
884
|
});
|
|
939
885
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
const { rest, request } = resolveDiscordReactionClient(opts);
|
|
948
|
-
const encoded = normalizeReactionEmoji(emoji);
|
|
949
|
-
await request(() => deleteOwnMessageReaction(rest, channelId, messageId, encoded), "reaction-remove");
|
|
950
|
-
return { ok: true };
|
|
886
|
+
function reactionMutation(operation, label) {
|
|
887
|
+
return async (channelId, messageId, emoji, opts) => {
|
|
888
|
+
const { rest, request } = resolveDiscordReactionClient(opts);
|
|
889
|
+
const encoded = normalizeReactionEmoji(emoji);
|
|
890
|
+
await request(() => operation(rest, channelId, messageId, encoded), label);
|
|
891
|
+
return { ok: true };
|
|
892
|
+
};
|
|
951
893
|
}
|
|
894
|
+
const reactMessageDiscord = reactionMutation(createOwnMessageReaction, "react");
|
|
895
|
+
const removeReactionDiscord = reactionMutation(deleteOwnMessageReaction, "reaction-remove");
|
|
952
896
|
async function removeOwnReactionsDiscord(channelId, messageId, opts) {
|
|
953
897
|
const { rest, request } = resolveDiscordReactionClient(opts);
|
|
954
898
|
const message = await request(() => getChannelMessage(rest, channelId, messageId), "reaction-list");
|
|
@@ -971,7 +915,6 @@ async function removeOwnReactionsDiscord(channelId, messageId, opts) {
|
|
|
971
915
|
async function fetchReactionsDiscord(channelId, messageId, opts) {
|
|
972
916
|
const { rest, request } = resolveDiscordReactionClient(opts);
|
|
973
917
|
const reactions = (await request(() => getChannelMessage(rest, channelId, messageId), "reaction-list")).reactions ?? [];
|
|
974
|
-
if (reactions.length === 0) return [];
|
|
975
918
|
const limit = typeof opts.limit === "number" && Number.isFinite(opts.limit) ? Math.min(Math.max(Math.floor(opts.limit), 1), 100) : 100;
|
|
976
919
|
const summaries = [];
|
|
977
920
|
for (const reaction of reactions) {
|