@openclaw/discord 2026.5.2 → 2026.5.3-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/access-B9ujuUtS.js +89 -0
- package/dist/account-inspect-C2UEUhbG.js +81 -0
- package/dist/account-inspect-api.js +10 -0
- package/dist/accounts-BKnkNaoA.js +128 -0
- package/dist/action-runtime-api.js +2 -0
- package/dist/agent-components.runtime-DUhLr9hy.js +4 -0
- package/dist/allow-list-ek-1hMKN.js +336 -0
- package/dist/api-DzNBVTto.js +130 -0
- package/dist/api.js +24 -0
- package/dist/approval-handler.runtime-v8nzQHlT.js +426 -0
- package/dist/approval-native-DqWGp0bM.js +153 -0
- package/dist/approval-shared-DKnwwjZM.js +93 -0
- package/dist/audit-CJ92YD6J.js +102 -0
- package/dist/channel-B3aTtBj1.js +745 -0
- package/dist/channel-access-ewDxhd9q.js +62 -0
- package/dist/channel-actions-TNih7k3w.js +140 -0
- package/dist/channel-actions.runtime-CaPytiY4.js +236 -0
- package/dist/channel-api-CTSWMrnD.js +21 -0
- package/dist/channel-config-api.js +2 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.setup-Dt4tIDrl.js +336 -0
- package/dist/components-BapWDmDM.js +760 -0
- package/dist/config-api-CFZtoMaS.js +2 -0
- package/dist/config-schema-DwFkL904.js +252 -0
- package/dist/configured-state.js +6 -0
- package/dist/contract-api.js +8 -0
- package/dist/conversation-identity-BN9wSmxJ.js +31 -0
- package/dist/directory-cache-D93eSrpB.js +62 -0
- package/dist/directory-config-LyMP0sdv.js +49 -0
- package/dist/directory-contract-api.js +2 -0
- package/dist/directory-live-BQapdpkZ.js +101 -0
- package/dist/discord-D1kDh0X_.js +2751 -0
- package/dist/doctor-B2G7WqO0.js +244 -0
- package/dist/doctor-contract-D3pSutkb.js +383 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/doctor-shared-DU8RcnF5.js +4 -0
- package/dist/format-D8TsaXxW.js +24 -0
- package/dist/gateway-registry-BKG4KIVC.js +74 -0
- package/dist/handle-action.guild-admin-BuqsSVXu.js +283 -0
- package/dist/inbound-context-e_oBBJtF.js +51 -0
- package/dist/index.js +26 -0
- package/dist/manager.runtime-M2aAa7qA.js +1019 -0
- package/dist/mentions-BPZUaFk7.js +88 -0
- package/dist/message-handler-D6JfFV3P.js +381 -0
- package/dist/message-handler.preflight-DqaF3vHm.js +1022 -0
- package/dist/message-handler.process-tl3Nwnhr.js +1124 -0
- package/dist/message-utils-Dmgu-7fC.js +512 -0
- package/dist/normalize-B-ktw-T_.js +275 -0
- package/dist/outbound-adapter-DJf9_sfH.js +451 -0
- package/dist/outbound-session-route-uHGLDP-Y.js +43 -0
- package/dist/pluralkit-voQvSN3g.js +22 -0
- package/dist/preflight-audio-BpYtUAT6.js +72 -0
- package/dist/preflight-audio.runtime-BAGmU6uO.js +7 -0
- package/dist/preview-streaming-C0O92Qqz.js +14 -0
- package/dist/probe-DcNEodPI.js +139 -0
- package/dist/probe.runtime-P-e4r1Hl.js +2 -0
- package/dist/provider-CMvXOp-3.js +8440 -0
- package/dist/provider-session.runtime-JFemrDZT.js +6 -0
- package/dist/provider.runtime-BO007oR2.js +2 -0
- package/dist/reply-delivery-D9So77a6.js +131 -0
- package/dist/resolve-allowlist-common-DqqFY_qa.js +34 -0
- package/dist/resolve-channels-CGPntufJ.js +265 -0
- package/dist/resolve-users-CDvSlW0V.js +120 -0
- package/dist/rolldown-runtime-C3SqQTfK.js +28 -0
- package/dist/route-resolution-BYiC-6Cc.js +236 -0
- package/dist/runtime-K9RT6Egn.js +8 -0
- package/dist/runtime-api.actions.js +3 -0
- package/dist/runtime-api.js +31 -0
- package/dist/runtime-api.lookup.js +7 -0
- package/dist/runtime-api.monitor-BC-XN0tY.js +6 -0
- package/dist/runtime-api.monitor.js +9 -0
- package/dist/runtime-api.send.js +6 -0
- package/dist/runtime-api.threads.js +6 -0
- package/dist/runtime-n5xZHW55.js +1001 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/secret-config-contract-CoGryS5c.js +115 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-Cdz2iq3m.js +120 -0
- package/dist/security-audit-contract-api.js +2 -0
- package/dist/security-audit.runtime-DBV1T1_N.js +2 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/security-contract-ei3Mz8Sa.js +26 -0
- package/dist/security-doctor-CzTzpXV8.js +18 -0
- package/dist/send-B_frVn_Q.js +845 -0
- package/dist/send.components-B1EgHAds.js +468 -0
- package/dist/send.outbound-DlBAuW7y.js +211 -0
- package/dist/send.shared-Db0opnak.js +708 -0
- package/dist/sender-identity-BiSDAk2P.js +43 -0
- package/dist/session-contract-goJZckp2.js +6 -0
- package/dist/session-key-api.js +2 -0
- package/dist/session-key-normalization-Daag9II6.js +23 -0
- package/dist/setup-entry.js +11 -0
- package/dist/setup-plugin-api.js +2 -0
- package/dist/shared-CqlrJmSs.js +166 -0
- package/dist/shared-interactive-KgJjCqnB.js +79 -0
- package/dist/subagent-hooks-api.js +22 -0
- package/dist/subagent-hooks-mEK5ARfP.js +113 -0
- package/dist/system-events-Bu9jmO4W.js +34 -0
- package/dist/targets-kKlbZ4ai.js +3 -0
- package/dist/test-api.js +45 -0
- package/dist/thread-binding-api.js +4 -0
- package/dist/thread-bindings-Bj1R-6QH.js +256 -0
- package/dist/thread-bindings.discord-api-ClPMuIr8.js +184 -0
- package/dist/thread-bindings.manager-BaN0l4y8.js +535 -0
- package/dist/thread-bindings.session-updates-TTP020qQ.js +54 -0
- package/dist/thread-bindings.state-Dzu1gCE7.js +318 -0
- package/dist/threading-CWhdYHVx.js +475 -0
- package/dist/timeouts-C7jeTtGs.js +52 -0
- package/dist/timeouts.js +2 -0
- package/dist/token-D-w3Rigl.js +42 -0
- package/dist/typing-CJiowRTZ.js +15 -0
- package/package.json +14 -6
- package/account-inspect-api.ts +0 -6
- package/action-runtime-api.ts +0 -1
- package/api.ts +0 -132
- package/channel-config-api.ts +0 -1
- package/channel-plugin-api.ts +0 -3
- package/config-api.ts +0 -4
- package/configured-state.ts +0 -6
- package/contract-api.ts +0 -21
- package/directory-contract-api.ts +0 -4
- package/doctor-contract-api.ts +0 -1
- package/index.test.ts +0 -13
- package/index.ts +0 -24
- package/runtime-api.actions.ts +0 -15
- package/runtime-api.lookup.ts +0 -22
- package/runtime-api.monitor.ts +0 -50
- package/runtime-api.send.ts +0 -79
- package/runtime-api.threads.ts +0 -30
- package/runtime-api.ts +0 -180
- package/runtime-setter-api.ts +0 -3
- package/secret-contract-api.ts +0 -4
- package/security-audit-contract-api.ts +0 -1
- package/security-contract-api.ts +0 -4
- package/session-key-api.ts +0 -1
- package/setup-entry.ts +0 -9
- package/setup-plugin-api.ts +0 -3
- package/src/account-inspect.test.ts +0 -126
- package/src/account-inspect.ts +0 -132
- package/src/accounts.test.ts +0 -247
- package/src/accounts.ts +0 -196
- package/src/actions/handle-action.guild-admin.ts +0 -411
- package/src/actions/handle-action.test.ts +0 -306
- package/src/actions/handle-action.ts +0 -372
- package/src/actions/runtime.guild.ts +0 -446
- package/src/actions/runtime.messaging.messages.ts +0 -205
- package/src/actions/runtime.messaging.reactions.ts +0 -67
- package/src/actions/runtime.messaging.runtime.ts +0 -69
- package/src/actions/runtime.messaging.send.ts +0 -248
- package/src/actions/runtime.messaging.shared.ts +0 -97
- package/src/actions/runtime.messaging.ts +0 -37
- package/src/actions/runtime.moderation-shared.ts +0 -48
- package/src/actions/runtime.moderation.authz.test.ts +0 -151
- package/src/actions/runtime.moderation.ts +0 -116
- package/src/actions/runtime.presence.test.ts +0 -160
- package/src/actions/runtime.presence.ts +0 -117
- package/src/actions/runtime.shared.ts +0 -83
- package/src/actions/runtime.test.ts +0 -1087
- package/src/actions/runtime.ts +0 -87
- package/src/api-barrel.test.ts +0 -80
- package/src/api.test.ts +0 -130
- package/src/api.ts +0 -169
- package/src/approval-handler.runtime.test.ts +0 -41
- package/src/approval-handler.runtime.ts +0 -632
- package/src/approval-native.test.ts +0 -330
- package/src/approval-native.ts +0 -219
- package/src/approval-runtime.ts +0 -14
- package/src/approval-shared.ts +0 -53
- package/src/audit-core.ts +0 -141
- package/src/audit.test.ts +0 -145
- package/src/audit.ts +0 -32
- package/src/channel-actions.contract.test.ts +0 -45
- package/src/channel-actions.runtime.ts +0 -1
- package/src/channel-actions.test.ts +0 -275
- package/src/channel-actions.ts +0 -203
- package/src/channel-api.ts +0 -29
- package/src/channel.conversation.ts +0 -159
- package/src/channel.loaders.ts +0 -47
- package/src/channel.runtime.ts +0 -1
- package/src/channel.setup.ts +0 -12
- package/src/channel.test.ts +0 -571
- package/src/channel.ts +0 -629
- package/src/chunk.test.ts +0 -157
- package/src/chunk.ts +0 -321
- package/src/client.proxy.test.ts +0 -176
- package/src/client.test.ts +0 -76
- package/src/client.ts +0 -132
- package/src/component-custom-id.ts +0 -72
- package/src/components-registry.ts +0 -356
- package/src/components.builders.ts +0 -409
- package/src/components.modal.ts +0 -124
- package/src/components.parse.ts +0 -407
- package/src/components.test.ts +0 -312
- package/src/components.ts +0 -54
- package/src/components.types.ts +0 -187
- package/src/config-schema.test.ts +0 -325
- package/src/config-schema.ts +0 -6
- package/src/config-ui-hints.ts +0 -249
- package/src/conversation-identity.ts +0 -58
- package/src/delivery-retry.ts +0 -56
- package/src/directory-cache.ts +0 -116
- package/src/directory-config.ts +0 -58
- package/src/directory-contract.test.ts +0 -129
- package/src/directory-live.test.ts +0 -126
- package/src/directory-live.ts +0 -135
- package/src/doctor-contract.ts +0 -477
- package/src/doctor-shared.ts +0 -5
- package/src/doctor.test.ts +0 -405
- package/src/doctor.ts +0 -340
- package/src/draft-chunking.test.ts +0 -64
- package/src/draft-chunking.ts +0 -43
- package/src/draft-stream.test.ts +0 -159
- package/src/draft-stream.ts +0 -154
- package/src/error-body.ts +0 -38
- package/src/exec-approvals.test.ts +0 -88
- package/src/exec-approvals.ts +0 -110
- package/src/gateway-logging.test.ts +0 -98
- package/src/gateway-logging.ts +0 -67
- package/src/group-policy.ts +0 -113
- package/src/guilds.ts +0 -29
- package/src/inbound-context.contract.test.ts +0 -11
- package/src/interactive-dispatch.ts +0 -104
- package/src/internal/api.commands.ts +0 -51
- package/src/internal/api.guild.ts +0 -164
- package/src/internal/api.interactions.ts +0 -53
- package/src/internal/api.messages.ts +0 -113
- package/src/internal/api.reactions.ts +0 -38
- package/src/internal/api.test.ts +0 -262
- package/src/internal/api.ts +0 -61
- package/src/internal/api.users.ts +0 -19
- package/src/internal/api.webhooks.ts +0 -13
- package/src/internal/client.test.ts +0 -440
- package/src/internal/client.ts +0 -310
- package/src/internal/command-deploy.ts +0 -297
- package/src/internal/commands.ts +0 -188
- package/src/internal/components.base.ts +0 -65
- package/src/internal/components.message.ts +0 -279
- package/src/internal/components.modal.ts +0 -95
- package/src/internal/components.ts +0 -31
- package/src/internal/discord.ts +0 -11
- package/src/internal/embeds.ts +0 -35
- package/src/internal/entity-cache.ts +0 -98
- package/src/internal/event-queue.ts +0 -162
- package/src/internal/gateway-close-codes.ts +0 -25
- package/src/internal/gateway-dispatch.ts +0 -96
- package/src/internal/gateway-identify-limiter.ts +0 -26
- package/src/internal/gateway-lifecycle.ts +0 -61
- package/src/internal/gateway-rate-limit.ts +0 -104
- package/src/internal/gateway.test.ts +0 -603
- package/src/internal/gateway.ts +0 -476
- package/src/internal/interaction-dispatch.test.ts +0 -148
- package/src/internal/interaction-dispatch.ts +0 -162
- package/src/internal/interaction-options.ts +0 -98
- package/src/internal/interaction-response.ts +0 -53
- package/src/internal/interactions.test.ts +0 -325
- package/src/internal/interactions.ts +0 -378
- package/src/internal/listeners.ts +0 -85
- package/src/internal/live-smoke.live.test.ts +0 -26
- package/src/internal/modal-fields.ts +0 -95
- package/src/internal/payload.ts +0 -69
- package/src/internal/rest-body.ts +0 -115
- package/src/internal/rest-errors.ts +0 -88
- package/src/internal/rest-routes.ts +0 -50
- package/src/internal/rest-scheduler.ts +0 -557
- package/src/internal/rest.test.ts +0 -673
- package/src/internal/rest.ts +0 -322
- package/src/internal/schemas.ts +0 -36
- package/src/internal/structures.test.ts +0 -43
- package/src/internal/structures.ts +0 -280
- package/src/internal/test-builders.test-support.ts +0 -167
- package/src/internal/voice.ts +0 -49
- package/src/media-detection.ts +0 -28
- package/src/mentions.test.ts +0 -111
- package/src/mentions.ts +0 -147
- package/src/monitor/access-groups.ts +0 -55
- package/src/monitor/ack-reactions.ts +0 -70
- package/src/monitor/acp-bind-here.integration.test.ts +0 -211
- package/src/monitor/agent-components-auth.ts +0 -7
- package/src/monitor/agent-components-context.ts +0 -154
- package/src/monitor/agent-components-data.ts +0 -224
- package/src/monitor/agent-components-dm-auth.ts +0 -221
- package/src/monitor/agent-components-guild-auth.ts +0 -322
- package/src/monitor/agent-components-helpers.runtime.ts +0 -5
- package/src/monitor/agent-components-helpers.ts +0 -34
- package/src/monitor/agent-components-reply.ts +0 -10
- package/src/monitor/agent-components.deps.runtime.ts +0 -2
- package/src/monitor/agent-components.dispatch.ts +0 -366
- package/src/monitor/agent-components.handlers.ts +0 -303
- package/src/monitor/agent-components.modal.ts +0 -160
- package/src/monitor/agent-components.plugin-interactive.ts +0 -187
- package/src/monitor/agent-components.runtime.ts +0 -14
- package/src/monitor/agent-components.system-controls.ts +0 -211
- package/src/monitor/agent-components.ts +0 -70
- package/src/monitor/agent-components.types.ts +0 -58
- package/src/monitor/agent-components.wildcard-controls.ts +0 -168
- package/src/monitor/agent-components.wildcard.test.ts +0 -71
- package/src/monitor/allow-list.test.ts +0 -14
- package/src/monitor/allow-list.ts +0 -633
- package/src/monitor/auto-presence.test.ts +0 -156
- package/src/monitor/auto-presence.ts +0 -356
- package/src/monitor/channel-access.test.ts +0 -99
- package/src/monitor/channel-access.ts +0 -102
- package/src/monitor/commands.test.ts +0 -24
- package/src/monitor/commands.ts +0 -9
- package/src/monitor/dm-command-auth.test.ts +0 -197
- package/src/monitor/dm-command-auth.ts +0 -158
- package/src/monitor/dm-command-decision.test.ts +0 -113
- package/src/monitor/dm-command-decision.ts +0 -49
- package/src/monitor/exec-approvals.test.ts +0 -226
- package/src/monitor/exec-approvals.ts +0 -158
- package/src/monitor/format.ts +0 -45
- package/src/monitor/gateway-handle.ts +0 -34
- package/src/monitor/gateway-metadata.test.ts +0 -29
- package/src/monitor/gateway-metadata.ts +0 -298
- package/src/monitor/gateway-plugin.test.ts +0 -297
- package/src/monitor/gateway-plugin.ts +0 -294
- package/src/monitor/gateway-registry.ts +0 -37
- package/src/monitor/gateway-supervisor.test.ts +0 -150
- package/src/monitor/gateway-supervisor.ts +0 -206
- package/src/monitor/inbound-context.test-helpers.ts +0 -37
- package/src/monitor/inbound-context.test.ts +0 -106
- package/src/monitor/inbound-context.ts +0 -103
- package/src/monitor/inbound-dedupe.ts +0 -79
- package/src/monitor/inbound-job.test.ts +0 -203
- package/src/monitor/inbound-job.ts +0 -118
- package/src/monitor/listeners.queue.ts +0 -91
- package/src/monitor/listeners.reactions.ts +0 -610
- package/src/monitor/listeners.test.ts +0 -200
- package/src/monitor/listeners.ts +0 -150
- package/src/monitor/message-channel-info.ts +0 -96
- package/src/monitor/message-forwarded.ts +0 -107
- package/src/monitor/message-handler.batch-gate.test.ts +0 -22
- package/src/monitor/message-handler.batch-gate.ts +0 -19
- package/src/monitor/message-handler.bot-self-filter.test.ts +0 -68
- package/src/monitor/message-handler.context.ts +0 -406
- package/src/monitor/message-handler.dm-preflight.ts +0 -123
- package/src/monitor/message-handler.draft-preview.ts +0 -246
- package/src/monitor/message-handler.hydration.test.ts +0 -80
- package/src/monitor/message-handler.hydration.ts +0 -198
- package/src/monitor/message-handler.inbound-context.test.ts +0 -59
- package/src/monitor/message-handler.module-test-helpers.ts +0 -31
- package/src/monitor/message-handler.preflight-channel-access.ts +0 -86
- package/src/monitor/message-handler.preflight-channel-context.test.ts +0 -18
- package/src/monitor/message-handler.preflight-channel-context.ts +0 -58
- package/src/monitor/message-handler.preflight-context.ts +0 -54
- package/src/monitor/message-handler.preflight-helpers.ts +0 -164
- package/src/monitor/message-handler.preflight-history.ts +0 -23
- package/src/monitor/message-handler.preflight-logging.ts +0 -36
- package/src/monitor/message-handler.preflight-pluralkit.ts +0 -26
- package/src/monitor/message-handler.preflight-runtime.ts +0 -28
- package/src/monitor/message-handler.preflight-thread.ts +0 -49
- package/src/monitor/message-handler.preflight.acp-bindings.test.ts +0 -369
- package/src/monitor/message-handler.preflight.test-helpers.ts +0 -111
- package/src/monitor/message-handler.preflight.test.ts +0 -1623
- package/src/monitor/message-handler.preflight.ts +0 -679
- package/src/monitor/message-handler.preflight.types.ts +0 -110
- package/src/monitor/message-handler.process.test.ts +0 -1369
- package/src/monitor/message-handler.process.ts +0 -686
- package/src/monitor/message-handler.queue.test.ts +0 -496
- package/src/monitor/message-handler.routing-preflight.ts +0 -112
- package/src/monitor/message-handler.test-harness.ts +0 -99
- package/src/monitor/message-handler.test-helpers.ts +0 -75
- package/src/monitor/message-handler.ts +0 -274
- package/src/monitor/message-media.ts +0 -509
- package/src/monitor/message-run-queue.ts +0 -101
- package/src/monitor/message-text.ts +0 -171
- package/src/monitor/message-utils.test.ts +0 -1157
- package/src/monitor/message-utils.ts +0 -32
- package/src/monitor/model-picker-preferences.test.ts +0 -67
- package/src/monitor/model-picker-preferences.ts +0 -184
- package/src/monitor/model-picker.state.ts +0 -364
- package/src/monitor/model-picker.test-utils.ts +0 -26
- package/src/monitor/model-picker.test.ts +0 -794
- package/src/monitor/model-picker.ts +0 -38
- package/src/monitor/model-picker.view.ts +0 -695
- package/src/monitor/monitor.agent-components.test.ts +0 -375
- package/src/monitor/monitor.test.ts +0 -849
- package/src/monitor/monitor.threading-utils.test.ts +0 -598
- package/src/monitor/native-command-agent-reply.ts +0 -125
- package/src/monitor/native-command-arg-ui.ts +0 -233
- package/src/monitor/native-command-auth.ts +0 -308
- package/src/monitor/native-command-bypass.ts +0 -13
- package/src/monitor/native-command-context.test.ts +0 -98
- package/src/monitor/native-command-context.ts +0 -103
- package/src/monitor/native-command-dispatch.ts +0 -35
- package/src/monitor/native-command-model-picker-apply.ts +0 -177
- package/src/monitor/native-command-model-picker-interaction.ts +0 -461
- package/src/monitor/native-command-model-picker-ui.ts +0 -368
- package/src/monitor/native-command-reply.test.ts +0 -68
- package/src/monitor/native-command-reply.ts +0 -185
- package/src/monitor/native-command-route.ts +0 -91
- package/src/monitor/native-command-status.ts +0 -76
- package/src/monitor/native-command-ui.ts +0 -26
- package/src/monitor/native-command-ui.types.ts +0 -20
- package/src/monitor/native-command.args.ts +0 -45
- package/src/monitor/native-command.command-arg.test.ts +0 -99
- package/src/monitor/native-command.commands-allowfrom.test.ts +0 -490
- package/src/monitor/native-command.model-picker.test.ts +0 -767
- package/src/monitor/native-command.options.test.ts +0 -369
- package/src/monitor/native-command.options.ts +0 -153
- package/src/monitor/native-command.plugin-dispatch.test.ts +0 -961
- package/src/monitor/native-command.runtime.ts +0 -50
- package/src/monitor/native-command.status-direct.test.ts +0 -272
- package/src/monitor/native-command.test-helpers.ts +0 -64
- package/src/monitor/native-command.think-autocomplete.test.ts +0 -416
- package/src/monitor/native-command.ts +0 -700
- package/src/monitor/native-command.types.ts +0 -9
- package/src/monitor/native-interaction-channel-context.ts +0 -50
- package/src/monitor/preflight-audio.runtime.ts +0 -9
- package/src/monitor/preflight-audio.test.ts +0 -157
- package/src/monitor/preflight-audio.ts +0 -130
- package/src/monitor/presence-cache.ts +0 -61
- package/src/monitor/presence.test.ts +0 -44
- package/src/monitor/presence.ts +0 -50
- package/src/monitor/provider-session.runtime.ts +0 -12
- package/src/monitor/provider.acp.ts +0 -89
- package/src/monitor/provider.allowlist.test.ts +0 -149
- package/src/monitor/provider.allowlist.ts +0 -394
- package/src/monitor/provider.cleanup.ts +0 -41
- package/src/monitor/provider.commands.ts +0 -129
- package/src/monitor/provider.config-log.ts +0 -45
- package/src/monitor/provider.deploy-errors.ts +0 -362
- package/src/monitor/provider.deploy.ts +0 -221
- package/src/monitor/provider.interactions.ts +0 -160
- package/src/monitor/provider.lifecycle.test.ts +0 -713
- package/src/monitor/provider.lifecycle.ts +0 -552
- package/src/monitor/provider.proxy.test.ts +0 -745
- package/src/monitor/provider.rest-proxy.test.ts +0 -121
- package/src/monitor/provider.runtime.ts +0 -1
- package/src/monitor/provider.skill-dedupe.test.ts +0 -42
- package/src/monitor/provider.startup-log.ts +0 -32
- package/src/monitor/provider.startup.test.ts +0 -426
- package/src/monitor/provider.startup.ts +0 -330
- package/src/monitor/provider.test.ts +0 -1111
- package/src/monitor/provider.ts +0 -713
- package/src/monitor/reply-context.ts +0 -64
- package/src/monitor/reply-delivery.test.ts +0 -244
- package/src/monitor/reply-delivery.ts +0 -203
- package/src/monitor/rest-fetch.ts +0 -43
- package/src/monitor/route-resolution.test.ts +0 -204
- package/src/monitor/route-resolution.ts +0 -140
- package/src/monitor/sender-identity.ts +0 -81
- package/src/monitor/startup-status.test.ts +0 -30
- package/src/monitor/startup-status.ts +0 -10
- package/src/monitor/status.ts +0 -22
- package/src/monitor/system-events.ts +0 -55
- package/src/monitor/thread-bindings.config.ts +0 -35
- package/src/monitor/thread-bindings.discord-api.test.ts +0 -229
- package/src/monitor/thread-bindings.discord-api.ts +0 -310
- package/src/monitor/thread-bindings.lifecycle.test.ts +0 -1871
- package/src/monitor/thread-bindings.lifecycle.ts +0 -354
- package/src/monitor/thread-bindings.manager.ts +0 -553
- package/src/monitor/thread-bindings.messages.ts +0 -6
- package/src/monitor/thread-bindings.persona.test.ts +0 -34
- package/src/monitor/thread-bindings.persona.ts +0 -25
- package/src/monitor/thread-bindings.session-adapter.ts +0 -229
- package/src/monitor/thread-bindings.session-shared.ts +0 -59
- package/src/monitor/thread-bindings.session-updates.ts +0 -35
- package/src/monitor/thread-bindings.shared-state.test.ts +0 -36
- package/src/monitor/thread-bindings.state.ts +0 -540
- package/src/monitor/thread-bindings.ts +0 -48
- package/src/monitor/thread-bindings.types.ts +0 -83
- package/src/monitor/thread-channel-context.ts +0 -112
- package/src/monitor/thread-session-close.test.ts +0 -180
- package/src/monitor/thread-session-close.ts +0 -63
- package/src/monitor/thread-title.generate.test.ts +0 -197
- package/src/monitor/thread-title.test.ts +0 -31
- package/src/monitor/thread-title.ts +0 -181
- package/src/monitor/threading.auto-thread.test.ts +0 -327
- package/src/monitor/threading.auto-thread.ts +0 -287
- package/src/monitor/threading.cache.ts +0 -45
- package/src/monitor/threading.parent-info.test.ts +0 -156
- package/src/monitor/threading.starter.test.ts +0 -260
- package/src/monitor/threading.starter.ts +0 -287
- package/src/monitor/threading.ts +0 -20
- package/src/monitor/threading.types.ts +0 -102
- package/src/monitor/timeouts.ts +0 -84
- package/src/monitor/typing.test.ts +0 -42
- package/src/monitor/typing.ts +0 -17
- package/src/monitor.gateway.test.ts +0 -187
- package/src/monitor.gateway.ts +0 -75
- package/src/monitor.test.ts +0 -1397
- package/src/monitor.ts +0 -28
- package/src/normalize.test.ts +0 -56
- package/src/normalize.ts +0 -86
- package/src/outbound-adapter.interactive-order.test.ts +0 -64
- package/src/outbound-adapter.test-harness.ts +0 -207
- package/src/outbound-adapter.test.ts +0 -696
- package/src/outbound-adapter.ts +0 -291
- package/src/outbound-approval.ts +0 -29
- package/src/outbound-components.ts +0 -81
- package/src/outbound-payload.contract.test.ts +0 -38
- package/src/outbound-payload.ts +0 -134
- package/src/outbound-send-context.ts +0 -92
- package/src/outbound-session-route.test.ts +0 -34
- package/src/outbound-session-route.ts +0 -72
- package/src/pluralkit.test.ts +0 -67
- package/src/pluralkit.ts +0 -58
- package/src/preview-streaming.ts +0 -32
- package/src/probe.intents.test.ts +0 -94
- package/src/probe.parse-token.test.ts +0 -43
- package/src/probe.runtime.ts +0 -1
- package/src/probe.ts +0 -237
- package/src/proxy-fetch.ts +0 -92
- package/src/proxy-request-client.test.ts +0 -78
- package/src/proxy-request-client.ts +0 -21
- package/src/recipient-resolution.ts +0 -39
- package/src/resolve-allowlist-common.test.ts +0 -36
- package/src/resolve-allowlist-common.ts +0 -39
- package/src/resolve-channels.test.ts +0 -340
- package/src/resolve-channels.ts +0 -369
- package/src/resolve-users.test.ts +0 -222
- package/src/resolve-users.ts +0 -184
- package/src/retry.test.ts +0 -83
- package/src/retry.ts +0 -98
- package/src/runtime-api.ts +0 -64
- package/src/runtime.ts +0 -23
- package/src/secret-config-contract.ts +0 -140
- package/src/security-audit.runtime.ts +0 -1
- package/src/security-audit.test.ts +0 -246
- package/src/security-audit.ts +0 -208
- package/src/security-contract.ts +0 -47
- package/src/security-doctor.test.ts +0 -25
- package/src/security-doctor.ts +0 -20
- package/src/security.ts +0 -60
- package/src/send-target-parsing.ts +0 -14
- package/src/send.channels.ts +0 -139
- package/src/send.components.test.ts +0 -275
- package/src/send.components.ts +0 -381
- package/src/send.creates-thread.test.ts +0 -643
- package/src/send.emojis-stickers.ts +0 -57
- package/src/send.guild.ts +0 -170
- package/src/send.message-request.ts +0 -97
- package/src/send.messages.test.ts +0 -53
- package/src/send.messages.ts +0 -225
- package/src/send.outbound.ts +0 -413
- package/src/send.permissions.authz.test.ts +0 -188
- package/src/send.permissions.ts +0 -283
- package/src/send.reactions.ts +0 -155
- package/src/send.sends-basic-channel-messages.test.ts +0 -941
- package/src/send.shared.ts +0 -447
- package/src/send.test-harness.ts +0 -56
- package/src/send.ts +0 -82
- package/src/send.types.ts +0 -188
- package/src/send.typing.test.ts +0 -41
- package/src/send.typing.ts +0 -9
- package/src/send.voice.ts +0 -134
- package/src/send.webhook-activity.test.ts +0 -105
- package/src/send.webhook.proxy.test.ts +0 -191
- package/src/send.webhook.ts +0 -133
- package/src/session-contract.ts +0 -3
- package/src/session-key-normalization.test.ts +0 -44
- package/src/session-key-normalization.ts +0 -47
- package/src/setup-account-state.test.ts +0 -91
- package/src/setup-account-state.ts +0 -144
- package/src/setup-adapter.ts +0 -12
- package/src/setup-core.ts +0 -212
- package/src/setup-runtime-helpers.ts +0 -10
- package/src/setup-surface.test.ts +0 -137
- package/src/setup-surface.ts +0 -129
- package/src/shared-interactive.test.ts +0 -153
- package/src/shared-interactive.ts +0 -124
- package/src/shared.test.ts +0 -165
- package/src/shared.ts +0 -190
- package/src/status-issues.test.ts +0 -70
- package/src/status-issues.ts +0 -169
- package/src/subagent-hooks.test.ts +0 -432
- package/src/subagent-hooks.ts +0 -214
- package/src/target-parsing.ts +0 -53
- package/src/target-resolver.ts +0 -129
- package/src/targets.test.ts +0 -367
- package/src/targets.ts +0 -12
- package/src/test-http-helpers.ts +0 -10
- package/src/test-support/component-runtime.ts +0 -190
- package/src/test-support/config.ts +0 -7
- package/src/test-support/configured-binding-runtime.ts +0 -29
- package/src/test-support/partial-channel.ts +0 -26
- package/src/test-support/provider.test-support.ts +0 -545
- package/src/token.test.ts +0 -107
- package/src/token.ts +0 -60
- package/src/ui-colors.ts +0 -27
- package/src/ui.ts +0 -20
- package/src/voice/access.test.ts +0 -217
- package/src/voice/access.ts +0 -124
- package/src/voice/audio.ts +0 -173
- package/src/voice/capture-state.test.ts +0 -48
- package/src/voice/capture-state.ts +0 -120
- package/src/voice/command.test.ts +0 -164
- package/src/voice/command.ts +0 -283
- package/src/voice/config.ts +0 -8
- package/src/voice/manager.e2e.test.ts +0 -928
- package/src/voice/manager.ready-listener.test.ts +0 -37
- package/src/voice/manager.runtime.ts +0 -11
- package/src/voice/manager.ts +0 -691
- package/src/voice/prompt.test.ts +0 -16
- package/src/voice/prompt.ts +0 -17
- package/src/voice/receive-recovery.test.ts +0 -79
- package/src/voice/receive-recovery.ts +0 -159
- package/src/voice/sanitize.test.ts +0 -34
- package/src/voice/sanitize.ts +0 -32
- package/src/voice/sdk-runtime.ts +0 -14
- package/src/voice/segment.ts +0 -156
- package/src/voice/session.ts +0 -50
- package/src/voice/speaker-context.ts +0 -127
- package/src/voice/tts.ts +0 -125
- package/src/voice-message.test.ts +0 -234
- package/src/voice-message.ts +0 -444
- package/subagent-hooks-api.ts +0 -27
- package/test-api.ts +0 -4
- package/thread-binding-api.ts +0 -1
- package/timeouts.ts +0 -6
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
import { t as normalizeDiscordToken } from "./token-D-w3Rigl.js";
|
|
2
|
+
import { a as mergeDiscordAccountConfig, c as resolveDiscordAccountAllowFrom, s as resolveDiscordAccount } from "./accounts-BKnkNaoA.js";
|
|
3
|
+
import { a as chunkDiscordTextWithMode, o as parseDiscordTarget, t as allowFromContainsDiscordUserId } from "./normalize-B-ktw-T_.js";
|
|
4
|
+
import { $ as createChannelMessage, J as createUserDmChannel, St as getGuildMember, Y as getCurrentUser, at as getChannel, h as RateLimitError, p as RequestClient, u as Embed, w as serializePayload, xt as getGuild } from "./discord-D1kDh0X_.js";
|
|
5
|
+
import { t as rememberDiscordDirectoryUser } from "./directory-cache-D93eSrpB.js";
|
|
6
|
+
import { r as listDiscordDirectoryPeersLive } from "./directory-live-BQapdpkZ.js";
|
|
7
|
+
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
8
|
+
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
|
9
|
+
import { buildMessagingTarget } from "openclaw/plugin-sdk/messaging-targets";
|
|
10
|
+
import { ChannelType, PermissionFlagsBits } from "discord-api-types/v10";
|
|
11
|
+
import { PollLayoutType } from "discord-api-types/payloads/v10";
|
|
12
|
+
import { buildOutboundMediaLoadOptions, extensionForMime, normalizePollDurationHours, normalizePollInput } from "openclaw/plugin-sdk/media-runtime";
|
|
13
|
+
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
14
|
+
import { resolveTextChunksWithFallback } from "openclaw/plugin-sdk/reply-payload";
|
|
15
|
+
import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
|
|
16
|
+
import { isIP } from "node:net";
|
|
17
|
+
import { makeProxyFetch } from "openclaw/plugin-sdk/fetch-runtime";
|
|
18
|
+
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
|
19
|
+
import { collectErrorGraphCandidates, extractErrorCode, formatErrorMessage, readErrorName } from "openclaw/plugin-sdk/error-runtime";
|
|
20
|
+
import { createRateLimitRetryRunner } from "openclaw/plugin-sdk/retry-runtime";
|
|
21
|
+
//#region extensions/discord/src/proxy-fetch.ts
|
|
22
|
+
function resolveDiscordProxyUrl(account, cfg) {
|
|
23
|
+
const accountProxy = account.config.proxy?.trim();
|
|
24
|
+
if (accountProxy) return accountProxy;
|
|
25
|
+
const channelProxy = cfg?.channels?.discord?.proxy;
|
|
26
|
+
if (typeof channelProxy !== "string") return;
|
|
27
|
+
return channelProxy.trim() || void 0;
|
|
28
|
+
}
|
|
29
|
+
function resolveDiscordProxyFetchByUrl(proxyUrl, runtime) {
|
|
30
|
+
return withValidatedDiscordProxy(proxyUrl, runtime, (proxy) => makeProxyFetch(proxy));
|
|
31
|
+
}
|
|
32
|
+
function resolveDiscordProxyFetchForAccount(account, cfg, runtime) {
|
|
33
|
+
return resolveDiscordProxyFetchByUrl(resolveDiscordProxyUrl(account, cfg), runtime);
|
|
34
|
+
}
|
|
35
|
+
function withValidatedDiscordProxy(proxyUrl, runtime, createValue) {
|
|
36
|
+
const proxy = proxyUrl?.trim();
|
|
37
|
+
if (!proxy) return;
|
|
38
|
+
try {
|
|
39
|
+
validateDiscordProxyUrl(proxy);
|
|
40
|
+
return createValue(proxy);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
runtime?.error?.(danger(`discord: invalid rest proxy: ${String(err)}`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function validateDiscordProxyUrl(proxyUrl) {
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = new URL(proxyUrl);
|
|
50
|
+
} catch {
|
|
51
|
+
throw new Error("Proxy URL must be a valid http or https URL");
|
|
52
|
+
}
|
|
53
|
+
if (!["http:", "https:"].includes(parsed.protocol)) throw new Error("Proxy URL must use http or https");
|
|
54
|
+
if (!isLoopbackProxyHostname(parsed.hostname)) throw new Error("Proxy URL must target a loopback host");
|
|
55
|
+
return proxyUrl;
|
|
56
|
+
}
|
|
57
|
+
function isLoopbackProxyHostname(hostname) {
|
|
58
|
+
const normalized = normalizeLowercaseStringOrEmpty(hostname);
|
|
59
|
+
if (!normalized) return false;
|
|
60
|
+
const bracketless = normalized.startsWith("[") && normalized.endsWith("]") ? normalized.slice(1, -1) : normalized;
|
|
61
|
+
if (bracketless === "localhost") return true;
|
|
62
|
+
const ipFamily = isIP(bracketless);
|
|
63
|
+
if (ipFamily === 4) return bracketless.startsWith("127.");
|
|
64
|
+
if (ipFamily === 6) return bracketless === "::1" || bracketless === "0:0:0:0:0:0:0:1";
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region extensions/discord/src/proxy-request-client.ts
|
|
69
|
+
const DISCORD_REST_TIMEOUT_MS = 15e3;
|
|
70
|
+
function createDiscordRequestClient(token, options) {
|
|
71
|
+
if (!options?.fetch) return new RequestClient(token, options);
|
|
72
|
+
return new RequestClient(token, {
|
|
73
|
+
runtimeProfile: "persistent",
|
|
74
|
+
maxQueueSize: 1e3,
|
|
75
|
+
timeout: DISCORD_REST_TIMEOUT_MS,
|
|
76
|
+
...options,
|
|
77
|
+
fetch: options.fetch
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region extensions/discord/src/retry.ts
|
|
82
|
+
const DISCORD_RETRY_DEFAULTS = {
|
|
83
|
+
attempts: 3,
|
|
84
|
+
minDelayMs: 500,
|
|
85
|
+
maxDelayMs: 3e4,
|
|
86
|
+
jitter: .1
|
|
87
|
+
};
|
|
88
|
+
const DISCORD_RETRYABLE_STATUS_CODES = new Set([408, 429]);
|
|
89
|
+
const DISCORD_RETRYABLE_ERROR_CODES = new Set([
|
|
90
|
+
"EAI_AGAIN",
|
|
91
|
+
"ECONNREFUSED",
|
|
92
|
+
"ECONNRESET",
|
|
93
|
+
"ENETUNREACH",
|
|
94
|
+
"ENOTFOUND",
|
|
95
|
+
"EPIPE",
|
|
96
|
+
"ETIMEDOUT",
|
|
97
|
+
"UND_ERR_BODY_TIMEOUT",
|
|
98
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
99
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
100
|
+
"UND_ERR_SOCKET"
|
|
101
|
+
]);
|
|
102
|
+
const DISCORD_TRANSIENT_MESSAGE_RE = /\b(?:bad gateway|fetch failed|network error|networkerror|service unavailable|socket hang up|temporarily unavailable|timed out|timeout)\b|connection (?:closed|reset|refused)/i;
|
|
103
|
+
function readDiscordErrorStatus(err) {
|
|
104
|
+
if (!err || typeof err !== "object") return;
|
|
105
|
+
const raw = "status" in err && err.status !== void 0 ? err.status : "statusCode" in err && err.statusCode !== void 0 ? err.statusCode : void 0;
|
|
106
|
+
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
107
|
+
if (typeof raw === "string" && /^\d+$/.test(raw)) return Number(raw);
|
|
108
|
+
}
|
|
109
|
+
function isRetryableDiscordTransientError(err) {
|
|
110
|
+
if (err instanceof RateLimitError) return true;
|
|
111
|
+
for (const candidate of collectErrorGraphCandidates(err, (current) => [current.cause, current.error])) {
|
|
112
|
+
const status = readDiscordErrorStatus(candidate);
|
|
113
|
+
if (status !== void 0 && (DISCORD_RETRYABLE_STATUS_CODES.has(status) || status >= 500)) return true;
|
|
114
|
+
const code = extractErrorCode(candidate);
|
|
115
|
+
if (code && DISCORD_RETRYABLE_ERROR_CODES.has(code.toUpperCase())) return true;
|
|
116
|
+
if (readErrorName(candidate) === "AbortError") return true;
|
|
117
|
+
if ((candidate instanceof Error || candidate !== null && typeof candidate === "object") && DISCORD_TRANSIENT_MESSAGE_RE.test(formatErrorMessage(candidate))) return true;
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
function createDiscordRetryRunner(params) {
|
|
122
|
+
return createRateLimitRetryRunner({
|
|
123
|
+
...params,
|
|
124
|
+
defaults: DISCORD_RETRY_DEFAULTS,
|
|
125
|
+
logLabel: "discord",
|
|
126
|
+
shouldRetry: isRetryableDiscordTransientError,
|
|
127
|
+
retryAfterMs: (err) => err instanceof RateLimitError ? err.retryAfter * 1e3 : void 0
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region extensions/discord/src/client.ts
|
|
132
|
+
function createDiscordRuntimeAccountContext(params) {
|
|
133
|
+
return {
|
|
134
|
+
cfg: params.cfg,
|
|
135
|
+
accountId: normalizeAccountId(params.accountId)
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function resolveDiscordClientAccountContext(opts, runtime) {
|
|
139
|
+
const resolvedCfg = requireRuntimeConfig(opts.cfg, "Discord client");
|
|
140
|
+
const account = resolveAccountWithoutToken({
|
|
141
|
+
cfg: resolvedCfg,
|
|
142
|
+
accountId: opts.accountId
|
|
143
|
+
});
|
|
144
|
+
return {
|
|
145
|
+
cfg: resolvedCfg,
|
|
146
|
+
account,
|
|
147
|
+
proxyFetch: resolveDiscordProxyFetchForAccount(account, resolvedCfg, runtime)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function resolveToken(params) {
|
|
151
|
+
const fallback = normalizeDiscordToken(params.fallbackToken, "channels.discord.token");
|
|
152
|
+
if (!fallback) throw new Error(`Discord bot token missing for account "${params.accountId}" (set discord.accounts.${params.accountId}.token or DISCORD_BOT_TOKEN for default).`);
|
|
153
|
+
return fallback;
|
|
154
|
+
}
|
|
155
|
+
function resolveRest(token, account, cfg, rest, proxyFetch) {
|
|
156
|
+
if (rest) return rest;
|
|
157
|
+
const resolvedProxyFetch = proxyFetch ?? resolveDiscordProxyFetchForAccount(account, cfg);
|
|
158
|
+
return createDiscordRequestClient(token, resolvedProxyFetch ? { fetch: resolvedProxyFetch } : void 0);
|
|
159
|
+
}
|
|
160
|
+
function resolveAccountWithoutToken(params) {
|
|
161
|
+
const accountId = normalizeAccountId(params.accountId);
|
|
162
|
+
const merged = mergeDiscordAccountConfig(params.cfg, accountId);
|
|
163
|
+
const baseEnabled = params.cfg.channels?.discord?.enabled !== false;
|
|
164
|
+
const accountEnabled = merged.enabled !== false;
|
|
165
|
+
return {
|
|
166
|
+
accountId,
|
|
167
|
+
enabled: baseEnabled && accountEnabled,
|
|
168
|
+
name: normalizeOptionalString(merged.name),
|
|
169
|
+
token: "",
|
|
170
|
+
tokenSource: "none",
|
|
171
|
+
config: merged
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function createDiscordRestClient(opts) {
|
|
175
|
+
const explicitToken = normalizeDiscordToken(opts.token, "channels.discord.token");
|
|
176
|
+
const proxyContext = resolveDiscordClientAccountContext(opts);
|
|
177
|
+
const resolvedCfg = proxyContext.cfg;
|
|
178
|
+
const account = explicitToken ? proxyContext.account : resolveDiscordAccount({
|
|
179
|
+
cfg: resolvedCfg,
|
|
180
|
+
accountId: opts.accountId
|
|
181
|
+
});
|
|
182
|
+
const token = explicitToken ?? resolveToken({
|
|
183
|
+
accountId: account.accountId,
|
|
184
|
+
fallbackToken: account.token
|
|
185
|
+
});
|
|
186
|
+
return {
|
|
187
|
+
token,
|
|
188
|
+
rest: resolveRest(token, account, resolvedCfg, opts.rest, proxyContext.proxyFetch),
|
|
189
|
+
account
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function createDiscordClient(opts) {
|
|
193
|
+
const { token, rest, account } = createDiscordRestClient(opts);
|
|
194
|
+
return {
|
|
195
|
+
token,
|
|
196
|
+
rest,
|
|
197
|
+
request: createDiscordRetryRunner({
|
|
198
|
+
retry: opts.retry,
|
|
199
|
+
configRetry: account.config.retry,
|
|
200
|
+
verbose: opts.verbose
|
|
201
|
+
})
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function resolveDiscordRest(opts) {
|
|
205
|
+
return createDiscordRestClient(opts).rest;
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region extensions/discord/src/send-target-parsing.ts
|
|
209
|
+
const parseDiscordSendTarget = (raw, options = {}) => parseDiscordTarget(raw, options);
|
|
210
|
+
//#endregion
|
|
211
|
+
//#region extensions/discord/src/target-resolver.ts
|
|
212
|
+
/**
|
|
213
|
+
* Resolve a Discord username to user ID using the directory lookup.
|
|
214
|
+
* This enables sending DMs by username instead of requiring explicit user IDs.
|
|
215
|
+
*/
|
|
216
|
+
async function resolveDiscordTarget(raw, options, parseOptions = {}) {
|
|
217
|
+
const trimmed = raw.trim();
|
|
218
|
+
if (!trimmed) return;
|
|
219
|
+
const likelyUsername = isLikelyUsername(trimmed);
|
|
220
|
+
const shouldLookup = isExplicitUserLookup(trimmed, parseOptions) || likelyUsername;
|
|
221
|
+
if (/^\d+$/.test(trimmed) && parseOptions.defaultKind !== "user" && isConfiguredAllowedDiscordDmUser(trimmed, options)) return buildMessagingTarget("user", trimmed, trimmed);
|
|
222
|
+
const directParse = safeParseDiscordTarget(trimmed, parseOptions);
|
|
223
|
+
if (directParse && directParse.kind !== "channel" && !likelyUsername) return directParse;
|
|
224
|
+
if (!shouldLookup) return directParse ?? parseDiscordSendTarget(trimmed, parseOptions);
|
|
225
|
+
try {
|
|
226
|
+
const match = (await listDiscordDirectoryPeersLive({
|
|
227
|
+
...options,
|
|
228
|
+
query: trimmed,
|
|
229
|
+
limit: 1
|
|
230
|
+
}))[0];
|
|
231
|
+
if (match && match.kind === "user") {
|
|
232
|
+
const userId = match.id.replace(/^user:/, "");
|
|
233
|
+
const resolvedAccountId = resolveDiscordAccount({
|
|
234
|
+
cfg: options.cfg,
|
|
235
|
+
accountId: options.accountId
|
|
236
|
+
}).accountId;
|
|
237
|
+
rememberDiscordDirectoryUser({
|
|
238
|
+
accountId: resolvedAccountId,
|
|
239
|
+
userId,
|
|
240
|
+
handles: [
|
|
241
|
+
trimmed,
|
|
242
|
+
match.name,
|
|
243
|
+
match.handle
|
|
244
|
+
]
|
|
245
|
+
});
|
|
246
|
+
return buildMessagingTarget("user", userId, trimmed);
|
|
247
|
+
}
|
|
248
|
+
} catch {}
|
|
249
|
+
return parseDiscordSendTarget(trimmed, parseOptions);
|
|
250
|
+
}
|
|
251
|
+
async function parseAndResolveDiscordTarget(raw, options, parseOptions = {}) {
|
|
252
|
+
const resolved = await resolveDiscordTarget(raw, options, parseOptions) ?? parseDiscordSendTarget(raw, parseOptions);
|
|
253
|
+
if (!resolved) throw new Error("Recipient is required for Discord sends");
|
|
254
|
+
return resolved;
|
|
255
|
+
}
|
|
256
|
+
function safeParseDiscordTarget(input, options) {
|
|
257
|
+
try {
|
|
258
|
+
return parseDiscordSendTarget(input, options);
|
|
259
|
+
} catch {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function isConfiguredAllowedDiscordDmUser(input, options) {
|
|
264
|
+
return allowFromContainsDiscordUserId(resolveDiscordAccountAllowFrom({
|
|
265
|
+
cfg: options.cfg,
|
|
266
|
+
accountId: options.accountId
|
|
267
|
+
}) ?? [], input);
|
|
268
|
+
}
|
|
269
|
+
function isExplicitUserLookup(input, options) {
|
|
270
|
+
if (/^<@!?(\d+)>$/.test(input)) return true;
|
|
271
|
+
if (/^(user:|discord:)/.test(input)) return true;
|
|
272
|
+
if (input.startsWith("@")) return true;
|
|
273
|
+
if (/^\d+$/.test(input)) return options.defaultKind === "user";
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
function isLikelyUsername(input) {
|
|
277
|
+
if (/^(user:|channel:|discord:|@|<@!?)|[\d]+$/.test(input)) return false;
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
//#endregion
|
|
281
|
+
//#region extensions/discord/src/recipient-resolution.ts
|
|
282
|
+
async function parseAndResolveRecipient(raw, cfg, accountId, parseOptions = {}) {
|
|
283
|
+
if (!cfg) throw new Error("Discord recipient resolution requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
|
|
284
|
+
const resolvedCfg = requireRuntimeConfig(cfg, "Discord recipient resolution");
|
|
285
|
+
const resolved = await parseAndResolveDiscordTarget(raw, {
|
|
286
|
+
cfg: resolvedCfg,
|
|
287
|
+
accountId: resolveDiscordAccount({
|
|
288
|
+
cfg: resolvedCfg,
|
|
289
|
+
accountId
|
|
290
|
+
}).accountId
|
|
291
|
+
}, parseOptions);
|
|
292
|
+
return {
|
|
293
|
+
kind: resolved.kind,
|
|
294
|
+
id: resolved.id
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region extensions/discord/src/send.permissions.ts
|
|
299
|
+
const PERMISSION_ENTRIES = Object.entries(PermissionFlagsBits).filter(([, value]) => typeof value === "bigint");
|
|
300
|
+
const ALL_PERMISSIONS = PERMISSION_ENTRIES.reduce((acc, [, value]) => acc | value, 0n);
|
|
301
|
+
const ADMINISTRATOR_BIT = PermissionFlagsBits.Administrator;
|
|
302
|
+
function addPermissionBits(base, add) {
|
|
303
|
+
if (!add) return base;
|
|
304
|
+
return base | BigInt(add);
|
|
305
|
+
}
|
|
306
|
+
function removePermissionBits(base, deny) {
|
|
307
|
+
if (!deny) return base;
|
|
308
|
+
return base & ~BigInt(deny);
|
|
309
|
+
}
|
|
310
|
+
function bitfieldToPermissions(bitfield) {
|
|
311
|
+
return PERMISSION_ENTRIES.filter(([, value]) => (bitfield & value) === value).map(([name]) => name).toSorted();
|
|
312
|
+
}
|
|
313
|
+
function hasAdministrator(bitfield) {
|
|
314
|
+
return (bitfield & ADMINISTRATOR_BIT) === ADMINISTRATOR_BIT;
|
|
315
|
+
}
|
|
316
|
+
function hasPermissionBit(bitfield, permission) {
|
|
317
|
+
return (bitfield & permission) === permission;
|
|
318
|
+
}
|
|
319
|
+
function isThreadChannelType(channelType) {
|
|
320
|
+
return channelType === ChannelType.GuildNewsThread || channelType === ChannelType.GuildPublicThread || channelType === ChannelType.GuildPrivateThread;
|
|
321
|
+
}
|
|
322
|
+
async function fetchBotUserId(rest) {
|
|
323
|
+
const me = await getCurrentUser(rest);
|
|
324
|
+
if (!me?.id) throw new Error("Failed to resolve bot user id");
|
|
325
|
+
return me.id;
|
|
326
|
+
}
|
|
327
|
+
function resolveMemberGuildPermissionBits(params) {
|
|
328
|
+
const rolesById = new Map((params.guild.roles ?? []).map((role) => [role.id, role]));
|
|
329
|
+
const everyoneRole = rolesById.get(params.guild.id);
|
|
330
|
+
let permissions = 0n;
|
|
331
|
+
if (everyoneRole?.permissions) permissions = addPermissionBits(permissions, everyoneRole.permissions);
|
|
332
|
+
for (const roleId of params.member.roles ?? []) {
|
|
333
|
+
const role = rolesById.get(roleId);
|
|
334
|
+
if (role?.permissions) permissions = addPermissionBits(permissions, role.permissions);
|
|
335
|
+
}
|
|
336
|
+
return permissions;
|
|
337
|
+
}
|
|
338
|
+
function resolveMemberChannelPermissionBits(params) {
|
|
339
|
+
let permissions = resolveMemberGuildPermissionBits({
|
|
340
|
+
guild: params.guild,
|
|
341
|
+
member: params.member
|
|
342
|
+
});
|
|
343
|
+
if (hasAdministrator(permissions)) return ALL_PERMISSIONS;
|
|
344
|
+
const overwrites = "permission_overwrites" in params.channel ? params.channel.permission_overwrites ?? [] : [];
|
|
345
|
+
for (const overwrite of overwrites) if (overwrite.id === params.guildId) {
|
|
346
|
+
permissions = removePermissionBits(permissions, overwrite.deny ?? "0");
|
|
347
|
+
permissions = addPermissionBits(permissions, overwrite.allow ?? "0");
|
|
348
|
+
}
|
|
349
|
+
let roleDeny = 0n;
|
|
350
|
+
let roleAllow = 0n;
|
|
351
|
+
for (const overwrite of overwrites) if (params.member.roles?.includes(overwrite.id)) {
|
|
352
|
+
roleDeny = addPermissionBits(roleDeny, overwrite.deny ?? "0");
|
|
353
|
+
roleAllow = addPermissionBits(roleAllow, overwrite.allow ?? "0");
|
|
354
|
+
}
|
|
355
|
+
permissions = permissions & ~roleDeny;
|
|
356
|
+
permissions = permissions | roleAllow;
|
|
357
|
+
for (const overwrite of overwrites) if (overwrite.id === params.userId) {
|
|
358
|
+
permissions = removePermissionBits(permissions, overwrite.deny ?? "0");
|
|
359
|
+
permissions = addPermissionBits(permissions, overwrite.allow ?? "0");
|
|
360
|
+
}
|
|
361
|
+
return permissions;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Fetch guild-level permissions for a user. This does not include channel-specific overwrites.
|
|
365
|
+
*/
|
|
366
|
+
async function fetchMemberGuildPermissionsDiscord(guildId, userId, opts) {
|
|
367
|
+
const rest = resolveDiscordRest(opts);
|
|
368
|
+
try {
|
|
369
|
+
const [guild, member] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, userId)]);
|
|
370
|
+
return resolveMemberGuildPermissionBits({
|
|
371
|
+
guild,
|
|
372
|
+
member
|
|
373
|
+
});
|
|
374
|
+
} catch {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
async function canViewDiscordGuildChannel(guildId, channelId, userId, opts) {
|
|
379
|
+
const rest = resolveDiscordRest(opts);
|
|
380
|
+
try {
|
|
381
|
+
const channel = await getChannel(rest, channelId);
|
|
382
|
+
if (("guild_id" in channel ? channel.guild_id : void 0) !== guildId) return false;
|
|
383
|
+
const [guild, member] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, userId)]);
|
|
384
|
+
return hasPermissionBit(resolveMemberChannelPermissionBits({
|
|
385
|
+
guildId,
|
|
386
|
+
userId,
|
|
387
|
+
guild,
|
|
388
|
+
member,
|
|
389
|
+
channel
|
|
390
|
+
}), PermissionFlagsBits.ViewChannel);
|
|
391
|
+
} catch {
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Returns true when the user has ADMINISTRATOR or required permission bits
|
|
397
|
+
* matching the provided predicate.
|
|
398
|
+
*/
|
|
399
|
+
async function hasGuildPermissionsDiscord(guildId, userId, requiredPermissions, check, opts) {
|
|
400
|
+
const permissions = await fetchMemberGuildPermissionsDiscord(guildId, userId, opts);
|
|
401
|
+
if (permissions === null) return false;
|
|
402
|
+
if (hasAdministrator(permissions)) return true;
|
|
403
|
+
return check(permissions, requiredPermissions);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Returns true when the user has ADMINISTRATOR or any required permission bit.
|
|
407
|
+
*/
|
|
408
|
+
async function hasAnyGuildPermissionDiscord(guildId, userId, requiredPermissions, opts) {
|
|
409
|
+
return await hasGuildPermissionsDiscord(guildId, userId, requiredPermissions, (permissions, required) => required.some((permission) => hasPermissionBit(permissions, permission)), opts);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Returns true when the user has ADMINISTRATOR or all required permission bits.
|
|
413
|
+
*/
|
|
414
|
+
async function hasAllGuildPermissionsDiscord(guildId, userId, requiredPermissions, opts) {
|
|
415
|
+
return await hasGuildPermissionsDiscord(guildId, userId, requiredPermissions, (permissions, required) => required.every((permission) => hasPermissionBit(permissions, permission)), opts);
|
|
416
|
+
}
|
|
417
|
+
async function fetchChannelPermissionsDiscord(channelId, opts) {
|
|
418
|
+
const rest = resolveDiscordRest(opts);
|
|
419
|
+
const channel = await getChannel(rest, channelId);
|
|
420
|
+
const channelType = "type" in channel ? channel.type : void 0;
|
|
421
|
+
const guildId = "guild_id" in channel ? channel.guild_id : void 0;
|
|
422
|
+
if (!guildId) return {
|
|
423
|
+
channelId,
|
|
424
|
+
permissions: [],
|
|
425
|
+
raw: "0",
|
|
426
|
+
isDm: true,
|
|
427
|
+
channelType
|
|
428
|
+
};
|
|
429
|
+
const botId = await fetchBotUserId(rest);
|
|
430
|
+
const [guild, member] = await Promise.all([getGuild(rest, guildId), getGuildMember(rest, guildId, botId)]);
|
|
431
|
+
const permissions = resolveMemberChannelPermissionBits({
|
|
432
|
+
guildId,
|
|
433
|
+
userId: botId,
|
|
434
|
+
guild,
|
|
435
|
+
member,
|
|
436
|
+
channel
|
|
437
|
+
});
|
|
438
|
+
return {
|
|
439
|
+
channelId,
|
|
440
|
+
guildId,
|
|
441
|
+
permissions: bitfieldToPermissions(permissions),
|
|
442
|
+
raw: permissions.toString(),
|
|
443
|
+
isDm: false,
|
|
444
|
+
channelType
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region extensions/discord/src/send.types.ts
|
|
449
|
+
var DiscordSendError = class extends Error {
|
|
450
|
+
constructor(message, opts) {
|
|
451
|
+
super(message);
|
|
452
|
+
this.name = "DiscordSendError";
|
|
453
|
+
if (opts) Object.assign(this, opts);
|
|
454
|
+
}
|
|
455
|
+
toString() {
|
|
456
|
+
return this.message;
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
const DISCORD_MAX_EMOJI_BYTES = 256 * 1024;
|
|
460
|
+
const DISCORD_MAX_STICKER_BYTES = 512 * 1024;
|
|
461
|
+
const DISCORD_MAX_EVENT_COVER_BYTES = 8 * 1024 * 1024;
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region extensions/discord/src/send.message-request.ts
|
|
464
|
+
const SUPPRESS_NOTIFICATIONS_FLAG = 4096;
|
|
465
|
+
function resolveDiscordSendComponents(params) {
|
|
466
|
+
if (!params.components || !params.isFirst) return;
|
|
467
|
+
return typeof params.components === "function" ? params.components(params.text) : params.components;
|
|
468
|
+
}
|
|
469
|
+
function normalizeDiscordEmbeds(embeds) {
|
|
470
|
+
if (!embeds?.length) return;
|
|
471
|
+
return embeds.map((embed) => embed instanceof Embed ? embed : new Embed(embed));
|
|
472
|
+
}
|
|
473
|
+
function resolveDiscordSendEmbeds(params) {
|
|
474
|
+
if (!params.embeds || !params.isFirst) return;
|
|
475
|
+
return normalizeDiscordEmbeds(params.embeds);
|
|
476
|
+
}
|
|
477
|
+
function buildDiscordMessagePayload(params) {
|
|
478
|
+
const payload = {};
|
|
479
|
+
const hasV2 = hasV2Components(params.components);
|
|
480
|
+
const trimmed = params.text.trim();
|
|
481
|
+
if (!hasV2 && trimmed) payload.content = params.text;
|
|
482
|
+
if (params.components?.length) payload.components = params.components;
|
|
483
|
+
if (!hasV2 && params.embeds?.length) payload.embeds = params.embeds;
|
|
484
|
+
if (params.flags !== void 0) payload.flags = params.flags;
|
|
485
|
+
if (params.files?.length) payload.files = params.files;
|
|
486
|
+
return payload;
|
|
487
|
+
}
|
|
488
|
+
function buildDiscordMessageRequest(params) {
|
|
489
|
+
return stripUndefinedFields({
|
|
490
|
+
...serializePayload(buildDiscordMessagePayload(params)),
|
|
491
|
+
...params.replyTo ? { message_reference: {
|
|
492
|
+
message_id: params.replyTo,
|
|
493
|
+
fail_if_not_exists: false
|
|
494
|
+
} } : {}
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
function stripUndefinedFields(value) {
|
|
498
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
499
|
+
}
|
|
500
|
+
function hasV2Components(components) {
|
|
501
|
+
return Boolean(components?.some((component) => "isV2" in component && component.isV2));
|
|
502
|
+
}
|
|
503
|
+
//#endregion
|
|
504
|
+
//#region extensions/discord/src/send.shared.ts
|
|
505
|
+
const DISCORD_TEXT_LIMIT = 2e3;
|
|
506
|
+
const DISCORD_MAX_STICKERS = 3;
|
|
507
|
+
const DISCORD_POLL_MAX_ANSWERS = 10;
|
|
508
|
+
const DISCORD_POLL_MAX_DURATION_HOURS = 768;
|
|
509
|
+
const DISCORD_MISSING_PERMISSIONS = 50013;
|
|
510
|
+
const DISCORD_CANNOT_DM = 50007;
|
|
511
|
+
function normalizeReactionEmoji(raw) {
|
|
512
|
+
const trimmed = raw.trim();
|
|
513
|
+
if (!trimmed) throw new Error("emoji required");
|
|
514
|
+
const customMatch = trimmed.match(/^<a?:([^:>]+):(\d+)>$/);
|
|
515
|
+
const identifier = customMatch ? `${customMatch[1]}:${customMatch[2]}` : trimmed.replace(/[\uFE0E\uFE0F]/g, "");
|
|
516
|
+
return encodeURIComponent(identifier);
|
|
517
|
+
}
|
|
518
|
+
function normalizeStickerIds(raw) {
|
|
519
|
+
const ids = raw.map((entry) => entry.trim()).filter(Boolean);
|
|
520
|
+
if (ids.length === 0) throw new Error("At least one sticker id is required");
|
|
521
|
+
if (ids.length > DISCORD_MAX_STICKERS) throw new Error("Discord supports up to 3 stickers per message");
|
|
522
|
+
return ids;
|
|
523
|
+
}
|
|
524
|
+
function normalizeEmojiName(raw, label) {
|
|
525
|
+
const name = raw.trim();
|
|
526
|
+
if (!name) throw new Error(`${label} is required`);
|
|
527
|
+
return name;
|
|
528
|
+
}
|
|
529
|
+
function normalizeDiscordPollInput(input) {
|
|
530
|
+
const poll = normalizePollInput(input, { maxOptions: DISCORD_POLL_MAX_ANSWERS });
|
|
531
|
+
const duration = normalizePollDurationHours(poll.durationHours, {
|
|
532
|
+
defaultHours: 24,
|
|
533
|
+
maxHours: DISCORD_POLL_MAX_DURATION_HOURS
|
|
534
|
+
});
|
|
535
|
+
return {
|
|
536
|
+
question: { text: poll.question },
|
|
537
|
+
answers: poll.options.map((answer) => ({ poll_media: { text: answer } })),
|
|
538
|
+
duration,
|
|
539
|
+
allow_multiselect: poll.maxSelections > 1,
|
|
540
|
+
layout_type: PollLayoutType.Default
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function getDiscordErrorCode(err) {
|
|
544
|
+
if (!err || typeof err !== "object") return;
|
|
545
|
+
const candidate = "code" in err && err.code !== void 0 ? err.code : "rawError" in err && err.rawError && typeof err.rawError === "object" ? err.rawError.code : void 0;
|
|
546
|
+
if (typeof candidate === "number") return candidate;
|
|
547
|
+
if (typeof candidate === "string" && /^\d+$/.test(candidate)) return Number(candidate);
|
|
548
|
+
}
|
|
549
|
+
function getDiscordErrorStatus(err) {
|
|
550
|
+
if (!err || typeof err !== "object") return;
|
|
551
|
+
const candidate = "status" in err && err.status !== void 0 ? err.status : "statusCode" in err && err.statusCode !== void 0 ? err.statusCode : void 0;
|
|
552
|
+
if (typeof candidate === "number" && Number.isFinite(candidate)) return candidate;
|
|
553
|
+
if (typeof candidate === "string" && /^\d+$/.test(candidate)) return Number(candidate);
|
|
554
|
+
}
|
|
555
|
+
async function buildDiscordSendError(err, ctx) {
|
|
556
|
+
if (err instanceof DiscordSendError) return err;
|
|
557
|
+
const code = getDiscordErrorCode(err);
|
|
558
|
+
if (code === DISCORD_CANNOT_DM) return new DiscordSendError(`discord dm failed: user blocks dms or privacy settings disallow it (code=${code})`, {
|
|
559
|
+
kind: "dm-blocked",
|
|
560
|
+
discordCode: code,
|
|
561
|
+
status: getDiscordErrorStatus(err)
|
|
562
|
+
});
|
|
563
|
+
if (code !== DISCORD_MISSING_PERMISSIONS) return err;
|
|
564
|
+
let missing = [];
|
|
565
|
+
let probedChannelType;
|
|
566
|
+
try {
|
|
567
|
+
const permissions = await fetchChannelPermissionsDiscord(ctx.channelId, {
|
|
568
|
+
rest: ctx.rest,
|
|
569
|
+
token: ctx.token,
|
|
570
|
+
cfg: ctx.cfg
|
|
571
|
+
});
|
|
572
|
+
probedChannelType = permissions.channelType;
|
|
573
|
+
const current = new Set(permissions.permissions);
|
|
574
|
+
const required = ["ViewChannel", "SendMessages"];
|
|
575
|
+
if (isThreadChannelType(probedChannelType)) required.push("SendMessagesInThreads");
|
|
576
|
+
if (ctx.hasMedia) required.push("AttachFiles");
|
|
577
|
+
missing = required.filter((permission) => !current.has(permission));
|
|
578
|
+
} catch {}
|
|
579
|
+
const status = getDiscordErrorStatus(err);
|
|
580
|
+
const apiDetails = [`code=${code}`, status != null ? `status=${status}` : void 0].filter(Boolean).join(" ");
|
|
581
|
+
const probedPermissions = ["ViewChannel", "SendMessages"];
|
|
582
|
+
if (isThreadChannelType(probedChannelType)) probedPermissions.push("SendMessagesInThreads");
|
|
583
|
+
if (ctx.hasMedia) probedPermissions.push("AttachFiles");
|
|
584
|
+
const probeSummary = probedPermissions.join("/");
|
|
585
|
+
return new DiscordSendError(`${missing.length ? `discord missing permissions in channel ${ctx.channelId}: ${missing.join(", ")}` : `discord missing permissions in channel ${ctx.channelId}; permission probe did not identify missing ${probeSummary}`} (${apiDetails}). bot might be blocked by channel/thread overrides, archived thread state, reply target visibility, or app-role position`, {
|
|
586
|
+
kind: "missing-permissions",
|
|
587
|
+
channelId: ctx.channelId,
|
|
588
|
+
missingPermissions: missing,
|
|
589
|
+
discordCode: code,
|
|
590
|
+
status
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
async function resolveChannelId(rest, recipient, request) {
|
|
594
|
+
if (recipient.kind === "channel") return { channelId: recipient.id };
|
|
595
|
+
const dmChannel = await request(() => createUserDmChannel(rest, recipient.id), "dm-channel");
|
|
596
|
+
if (!dmChannel?.id) throw new Error("Failed to create Discord DM channel");
|
|
597
|
+
return {
|
|
598
|
+
channelId: dmChannel.id,
|
|
599
|
+
dm: true
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
async function resolveDiscordTargetChannelId(raw, opts) {
|
|
603
|
+
const recipient = await parseAndResolveRecipient(raw, requireRuntimeConfig(opts.cfg, "Discord target channel resolution"), opts.accountId, { defaultKind: "channel" });
|
|
604
|
+
const { rest, request } = createDiscordClient(opts);
|
|
605
|
+
return await resolveChannelId(rest, recipient, request);
|
|
606
|
+
}
|
|
607
|
+
async function resolveDiscordChannelType(rest, channelId) {
|
|
608
|
+
try {
|
|
609
|
+
return (await getChannel(rest, channelId))?.type;
|
|
610
|
+
} catch {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
function buildDiscordTextChunks(text, opts = {}) {
|
|
615
|
+
if (!text) return [];
|
|
616
|
+
return resolveTextChunksWithFallback(text, chunkDiscordTextWithMode(text, {
|
|
617
|
+
maxChars: opts.maxChars ?? DISCORD_TEXT_LIMIT,
|
|
618
|
+
maxLines: opts.maxLinesPerMessage,
|
|
619
|
+
chunkMode: opts.chunkMode
|
|
620
|
+
}));
|
|
621
|
+
}
|
|
622
|
+
function toDiscordFileBlob(data) {
|
|
623
|
+
if (data instanceof Blob) return data;
|
|
624
|
+
const arrayBuffer = new ArrayBuffer(data.byteLength);
|
|
625
|
+
new Uint8Array(arrayBuffer).set(data);
|
|
626
|
+
return new Blob([arrayBuffer]);
|
|
627
|
+
}
|
|
628
|
+
async function sendDiscordText(rest, channelId, text, replyTo, request, maxLinesPerMessage, components, embeds, chunkMode, silent, maxChars) {
|
|
629
|
+
if (!text.trim()) throw new Error("Message must be non-empty for Discord sends");
|
|
630
|
+
const flags = silent ? SUPPRESS_NOTIFICATIONS_FLAG : void 0;
|
|
631
|
+
const chunks = buildDiscordTextChunks(text, {
|
|
632
|
+
maxLinesPerMessage,
|
|
633
|
+
chunkMode,
|
|
634
|
+
maxChars
|
|
635
|
+
});
|
|
636
|
+
const sendChunk = async (chunk, isFirst) => {
|
|
637
|
+
const body = buildDiscordMessageRequest({
|
|
638
|
+
text: chunk,
|
|
639
|
+
components: resolveDiscordSendComponents({
|
|
640
|
+
components,
|
|
641
|
+
text: chunk,
|
|
642
|
+
isFirst
|
|
643
|
+
}),
|
|
644
|
+
embeds: resolveDiscordSendEmbeds({
|
|
645
|
+
embeds,
|
|
646
|
+
isFirst
|
|
647
|
+
}),
|
|
648
|
+
flags,
|
|
649
|
+
replyTo
|
|
650
|
+
});
|
|
651
|
+
return await request(() => createChannelMessage(rest, channelId, { body }), "text");
|
|
652
|
+
};
|
|
653
|
+
if (chunks.length === 1) return await sendChunk(chunks[0], true);
|
|
654
|
+
let last = null;
|
|
655
|
+
for (const [index, chunk] of chunks.entries()) last = await sendChunk(chunk, index === 0);
|
|
656
|
+
if (!last) throw new Error("Discord send failed (empty chunk result)");
|
|
657
|
+
return last;
|
|
658
|
+
}
|
|
659
|
+
async function sendDiscordMedia(rest, channelId, text, mediaUrl, filename, mediaAccess, mediaLocalRoots, mediaReadFile, maxBytes, replyTo, request, maxLinesPerMessage, components, embeds, chunkMode, silent, maxChars) {
|
|
660
|
+
const media = await loadWebMedia(mediaUrl, buildOutboundMediaLoadOptions({
|
|
661
|
+
maxBytes,
|
|
662
|
+
mediaAccess,
|
|
663
|
+
mediaLocalRoots,
|
|
664
|
+
mediaReadFile
|
|
665
|
+
}));
|
|
666
|
+
const resolvedFileName = filename?.trim() || media.fileName || (media.contentType ? `upload${extensionForMime(media.contentType) ?? ""}` : "") || "upload";
|
|
667
|
+
const chunks = text ? buildDiscordTextChunks(text, {
|
|
668
|
+
maxLinesPerMessage,
|
|
669
|
+
chunkMode,
|
|
670
|
+
maxChars
|
|
671
|
+
}) : [];
|
|
672
|
+
const caption = chunks[0] ?? "";
|
|
673
|
+
const flags = silent ? SUPPRESS_NOTIFICATIONS_FLAG : void 0;
|
|
674
|
+
const fileData = toDiscordFileBlob(media.buffer);
|
|
675
|
+
const body = buildDiscordMessageRequest({
|
|
676
|
+
text: caption,
|
|
677
|
+
components: resolveDiscordSendComponents({
|
|
678
|
+
components,
|
|
679
|
+
text: caption,
|
|
680
|
+
isFirst: true
|
|
681
|
+
}),
|
|
682
|
+
embeds: resolveDiscordSendEmbeds({
|
|
683
|
+
embeds,
|
|
684
|
+
isFirst: true
|
|
685
|
+
}),
|
|
686
|
+
flags,
|
|
687
|
+
replyTo,
|
|
688
|
+
files: [{
|
|
689
|
+
data: fileData,
|
|
690
|
+
name: resolvedFileName
|
|
691
|
+
}]
|
|
692
|
+
});
|
|
693
|
+
const res = await request(() => createChannelMessage(rest, channelId, { body }), "media");
|
|
694
|
+
for (const chunk of chunks.slice(1)) {
|
|
695
|
+
if (!chunk.trim()) continue;
|
|
696
|
+
await sendDiscordText(rest, channelId, chunk, replyTo, request, maxLinesPerMessage, void 0, void 0, chunkMode, silent, maxChars);
|
|
697
|
+
}
|
|
698
|
+
return res;
|
|
699
|
+
}
|
|
700
|
+
function buildReactionIdentifier(emoji) {
|
|
701
|
+
if (emoji.id && emoji.name) return `${emoji.name}:${emoji.id}`;
|
|
702
|
+
return emoji.name ?? "";
|
|
703
|
+
}
|
|
704
|
+
function formatReactionEmoji(emoji) {
|
|
705
|
+
return buildReactionIdentifier(emoji);
|
|
706
|
+
}
|
|
707
|
+
//#endregion
|
|
708
|
+
export { resolveDiscordTarget as A, validateDiscordProxyUrl as B, DiscordSendError as C, hasAllGuildPermissionsDiscord as D, fetchMemberGuildPermissionsDiscord as E, resolveDiscordClientAccountContext as F, resolveDiscordRest as I, DISCORD_REST_TIMEOUT_MS as L, createDiscordClient as M, createDiscordRestClient as N, hasAnyGuildPermissionDiscord as O, createDiscordRuntimeAccountContext as P, createDiscordRequestClient as R, DISCORD_MAX_STICKER_BYTES as S, fetchChannelPermissionsDiscord as T, withValidatedDiscordProxy as V, resolveDiscordSendComponents as _, normalizeDiscordPollInput as a, DISCORD_MAX_EMOJI_BYTES as b, normalizeStickerIds as c, resolveDiscordTargetChannelId as d, sendDiscordMedia as f, buildDiscordMessageRequest as g, SUPPRESS_NOTIFICATIONS_FLAG as h, formatReactionEmoji as i, parseDiscordSendTarget as j, parseAndResolveRecipient as k, resolveChannelId as l, toDiscordFileBlob as m, buildDiscordTextChunks as n, normalizeEmojiName as o, sendDiscordText as p, buildReactionIdentifier as r, normalizeReactionEmoji as s, buildDiscordSendError as t, resolveDiscordChannelType as u, resolveDiscordSendEmbeds as v, canViewDiscordGuildChannel as w, DISCORD_MAX_EVENT_COVER_BYTES as x, stripUndefinedFields as y, resolveDiscordProxyFetchForAccount as z };
|