@openclaw/discord 2026.5.12 → 2026.5.14-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/{account-inspect-D7jL5YDH.js → account-inspect-B_N30NV0.js} +1 -1
- package/dist/account-inspect-api.js +1 -1
- package/dist/{accounts-BcwyaFd-.js → accounts-DnNVBDfc.js} +95 -4
- package/dist/action-runtime-api.js +1 -1
- package/dist/{allow-list-n8Ki-Rt3.js → allow-list-CBI-M84K.js} +24 -2
- package/dist/api.js +19 -21
- package/dist/{approval-handler.runtime-S-ircYcz.js → approval-handler.runtime-Uco62pII.js} +4 -4
- package/dist/{audit-BliEqCEc.js → audit-eSlKbMHw.js} +5 -5
- package/dist/{channel-Bliqi-Qi.js → channel-BjBa8nYY.js} +23 -25
- package/dist/{channel-actions-Cn_K00Vy.js → channel-actions-DANVAtKL.js} +4 -4
- package/dist/{channel-actions.runtime-DcsRvPnx.js → channel-actions.runtime-CpIslHS9.js} +7 -5
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-DR-xVYso.js → channel.setup-DBFcGRFD.js} +4 -5
- package/dist/{components-Dxq2mU57.js → components-Cgm7XT8-.js} +120 -3
- package/dist/{config-schema-D2KGskAp.js → config-schema-D7AtCpJa.js} +21 -1
- package/dist/contract-api.js +7 -7
- package/dist/{approval-native-Gtqpyfdj.js → conversation-identity-C3AI-1tz.js} +123 -6
- package/dist/{directory-config-CDl4JTCA.js → directory-config-CW_JusGS.js} +2 -2
- package/dist/directory-contract-api.js +1 -1
- package/dist/directory-live-MrDSKsMf.js +159 -0
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{doctor-contract-BGjjFBdq.js → doctor-contract-ftWAMvBl.js} +1 -1
- package/dist/{doctor-jcX_qXsS.js → doctor-mn2XyjuF.js} +5 -5
- package/dist/{handle-action.guild-admin-C4phin-a.js → handle-action.guild-admin-DriifPwO.js} +1 -1
- package/dist/{inbound-context-jtKcY9on.js → inbound-context-DD7n3Q6U.js} +1 -1
- package/dist/{manager.runtime-DqMGETqp.js → manager.runtime-DauS2xA3.js} +107 -25
- package/dist/{message-handler-DIsnboy2.js → message-handler-CMHwRlxG.js} +7 -7
- package/dist/{message-handler.preflight-BRH-dv1o.js → message-handler.preflight-C0sT-ewp.js} +27 -17
- package/dist/{message-handler.process-Bs5wropA.js → message-handler.process-Cy7_-0H0.js} +46 -37
- package/dist/{message-utils-ByofKwPe.js → message-utils-N5UTOXQ2.js} +16 -12
- package/dist/{outbound-adapter-lWjkSeyP.js → outbound-adapter-Cw9JsRTY.js} +7 -10
- package/dist/{pluralkit-B1HTaBc9.js → pluralkit-B2AqgTHV.js} +1 -1
- package/dist/{preflight-audio-CD97vnac.js → preflight-audio-DFGpAvzi.js} +1 -1
- package/dist/{probe-BZtr8qle.js → probe-CiBYm-vD.js} +2 -2
- package/dist/{probe.runtime-0F0UzBoJ.js → probe.runtime-9hi1GYNU.js} +1 -1
- package/dist/{provider-DABvNRT0.js → provider-nzJg2k5t.js} +1039 -45
- package/dist/{provider-session.runtime-BZyP90-i.js → provider-session.runtime-DMxaLPB3.js} +3 -3
- package/dist/provider.runtime-S-wZdzK5.js +2 -0
- package/dist/{resolve-allowlist-common-CVHYb5Hb.js → resolve-allowlist-common-DybgkAjk.js} +3 -3
- package/dist/{resolve-channels-JNt3Ak6P.js → resolve-channels-u7_agBcm.js} +4 -4
- package/dist/{resolve-users-CrjbUxrL.js → resolve-users-Bc25I6OP.js} +3 -3
- package/dist/{runtime-CdnAT8R5.js → runtime-DL82ijB1.js} +102 -46
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +25 -26
- package/dist/runtime-api.lookup.js +6 -6
- package/dist/runtime-api.monitor-DbLcHuhE.js +5 -0
- package/dist/runtime-api.monitor.js +7 -8
- package/dist/runtime-api.send.js +5 -5
- package/dist/runtime-api.threads.js +5 -5
- package/dist/runtime-setter-api.js +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/{security-audit-BQ_sGK3J.js → security-audit-CLPZKYi4.js} +1 -1
- package/dist/security-audit-contract-api.js +1 -1
- package/dist/{security-audit.runtime-B7Gmz2DX.js → security-audit.runtime-CCm9leFJ.js} +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-DCFuSiBi.js → send-BqzTEkt9.js} +4 -6
- package/dist/{send.components-DxDqPJZQ.js → send.components-D6pXHVrU.js} +8 -10
- package/dist/{send.outbound-PM0J0F60.js → send.outbound-D8o8BW6q.js} +91 -7
- package/dist/{discord-BqYcwxvG.js → send.receipt-nKLxvA1s.js} +319 -1
- package/dist/{send.shared-Dza0jdso.js → send.shared-DSpva7uA.js} +4 -6
- package/dist/{sender-identity-w9rSI-nD.js → sender-identity-BTGL3VbF.js} +1 -1
- package/dist/session-key-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-Yp_M6Cfp.js → shared-0kdaIxXP.js} +16 -14
- package/dist/{subagent-hooks-CtN-hfXy.js → subagent-hooks-DhuBhwRw.js} +3 -3
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{system-events-B04UOvPg.js → system-events-Bnit0zkQ.js} +2 -2
- package/dist/{target-resolver-CgJei-kD.js → target-resolver-BsGT9hI7.js} +3 -6
- package/dist/targets-DwW6OieO.js +3 -0
- package/dist/test-api.js +4 -4
- package/dist/{thread-bindings-B4of4OmR.js → thread-bindings-C1f7Iim4.js} +6 -7
- package/dist/{thread-bindings.discord-api-BAw15EQb.js → thread-bindings.discord-api-DJACBZJ1.js} +67 -8
- package/dist/{thread-bindings.manager-DNFl10CA.js → thread-bindings.manager-DN_q0IW7.js} +4 -5
- package/dist/{thread-bindings.session-updates-D18cCLmN.js → thread-bindings.session-updates-ZnRRzzgf.js} +1 -1
- package/dist/timeouts.js +1 -1
- package/dist/{typing-_jePdFIw.js → typing-C_8U8J7E.js} +2 -2
- package/openclaw.plugin.json +68 -0
- package/package.json +6 -6
- package/dist/access-Dxmzr0ix.js +0 -89
- package/dist/approval-shared-BFnWKSQD.js +0 -93
- package/dist/channel-access-BL-wemES.js +0 -62
- package/dist/chunk-DYl-_5RL.js +0 -179
- package/dist/conversation-identity-CvIx6J7M.js +0 -31
- package/dist/directory-cache-Ddl-Oxue.js +0 -62
- package/dist/directory-live-ApUXOSj0.js +0 -101
- package/dist/doctor-shared-D_QLzu30.js +0 -4
- package/dist/format-D8TsaXxW.js +0 -24
- package/dist/mentions-BZoGn0ul.js +0 -88
- package/dist/normalize-Cu94FOqy.js +0 -58
- package/dist/outbound-session-route-BaJRt05p.js +0 -43
- package/dist/provider.runtime-Cmv1SFtb.js +0 -2
- package/dist/reply-delivery-CUSK6SA_.js +0 -191
- package/dist/route-resolution-BFfF9xmG.js +0 -268
- package/dist/runtime-api.monitor-W_dJ5EQu.js +0 -6
- package/dist/send.receipt-BAZw2Zsz.js +0 -35
- package/dist/shared-interactive-DavY6jYt.js +0 -79
- package/dist/target-parsing-D-H7nnh2.js +0 -51
- package/dist/targets-DToZUkgV.js +0 -3
- package/dist/threading-CLZ3v7-y.js +0 -475
- package/dist/token-BZtonk7d.js +0 -93
- /package/dist/{agent-components.runtime-zT8qPsnM.js → agent-components.runtime-CEMbMQcQ.js} +0 -0
- /package/dist/{api-DzNBVTto.js → api-DgQLz1wq.js} +0 -0
- /package/dist/{audit-core-BgDZSkIR.js → audit-core-DRyoXREU.js} +0 -0
- /package/dist/{channel-api-CTSWMrnD.js → channel-api-JudoSiJv.js} +0 -0
- /package/dist/{config-api-CFZtoMaS.js → config-api-oLS_52S7.js} +0 -0
- /package/dist/{gateway-registry-BKG4KIVC.js → gateway-registry-BKSpa4GB.js} +0 -0
- /package/dist/{preflight-audio.runtime-fXnUxxBa.js → preflight-audio.runtime-Drc-OFcp.js} +0 -0
- /package/dist/{preview-streaming-DCPAe24T.js → preview-streaming-CXTZydhx.js} +0 -0
- /package/dist/{runtime-BqCoo-zp.js → runtime-Tqtvj5GX.js} +0 -0
- /package/dist/{secret-config-contract-BCQNNS7N.js → secret-config-contract-B3347_eU.js} +0 -0
- /package/dist/{security-contract-DkCMKSvb.js → security-contract-DyCRvz_Q.js} +0 -0
- /package/dist/{security-doctor-BJH5YIGL.js → security-doctor-Cp-NqNdS.js} +0 -0
- /package/dist/{session-contract-D871HDFG.js → session-contract-ugfEa9Xc.js} +0 -0
- /package/dist/{session-key-normalization-BV82IME9.js → session-key-normalization-B7h83qD2.js} +0 -0
- /package/dist/{thread-bindings.state-SPlv6mh7.js → thread-bindings.state-BdBeo7Rx.js} +0 -0
- /package/dist/{timeouts-C3FYXWJX.js → timeouts-snXNwR4m.js} +0 -0
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { i as resolveTimestampMs } from "./format-D8TsaXxW.js";
|
|
2
|
-
import { s as sendVoiceMessageDiscord } from "./send-DCFuSiBi.js";
|
|
3
|
-
import { t as sendMessageDiscord } from "./send.outbound-PM0J0F60.js";
|
|
4
|
-
import { t as resolveDiscordSenderIdentity } from "./sender-identity-w9rSI-nD.js";
|
|
5
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
-
import { resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
|
|
7
|
-
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
8
|
-
import { sendDurableMessageBatch } from "openclaw/plugin-sdk/channel-message";
|
|
9
|
-
import { buildOutboundSessionContext } from "openclaw/plugin-sdk/outbound-runtime";
|
|
10
|
-
import { resolveAgentAvatar } from "openclaw/plugin-sdk/agent-runtime";
|
|
11
|
-
//#region extensions/discord/src/monitor/reply-context.ts
|
|
12
|
-
function resolveReplyContext(message, resolveDiscordMessageText) {
|
|
13
|
-
const referenced = message.referencedMessage;
|
|
14
|
-
if (!referenced?.author) return null;
|
|
15
|
-
const referencedText = resolveDiscordMessageText(referenced, { includeForwarded: true });
|
|
16
|
-
if (!referencedText) return null;
|
|
17
|
-
const sender = resolveDiscordSenderIdentity({
|
|
18
|
-
author: referenced.author,
|
|
19
|
-
pluralkitInfo: null
|
|
20
|
-
});
|
|
21
|
-
return {
|
|
22
|
-
id: referenced.id,
|
|
23
|
-
channelId: referenced.channelId,
|
|
24
|
-
sender: sender.tag ?? sender.label ?? "unknown",
|
|
25
|
-
senderId: referenced.author.id,
|
|
26
|
-
senderName: referenced.author.username ?? void 0,
|
|
27
|
-
senderTag: sender.tag ?? void 0,
|
|
28
|
-
memberRoleIds: (() => {
|
|
29
|
-
const roles = referenced.member?.roles;
|
|
30
|
-
return Array.isArray(roles) ? roles.map((roleId) => roleId) : void 0;
|
|
31
|
-
})(),
|
|
32
|
-
body: referencedText,
|
|
33
|
-
timestamp: resolveTimestampMs(referenced.timestamp)
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function buildDirectLabel(author, tagOverride) {
|
|
37
|
-
return `${(tagOverride?.trim() || resolveDiscordSenderIdentity({
|
|
38
|
-
author,
|
|
39
|
-
pluralkitInfo: null
|
|
40
|
-
}).tag) ?? "unknown"} user id:${author.id}`;
|
|
41
|
-
}
|
|
42
|
-
function buildGuildLabel(params) {
|
|
43
|
-
const { guild, channelName, channelId } = params;
|
|
44
|
-
return `${guild?.name ?? "Guild"} #${channelName} channel id:${channelId}`;
|
|
45
|
-
}
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region extensions/discord/src/monitor/reply-safety.ts
|
|
48
|
-
const DISCORD_INTERNAL_TRACE_LINE_RE = /^(?:>\s*)?(?:📊|🛠️|📖|📝|🔍|🔎|⚙️)\s*(?:Session Status|Exec|Read|Edit|Write|Patch|Search|Open|Click|Find|Screenshot|Update Plan|Tool Call|Tool Result|Function Call|Shell|Command)\s*:/i;
|
|
49
|
-
const DISCORD_INTERNAL_COMPACT_COMMAND_TRACE_LINE_RE = /^(?:>\s*)?🛠️\s*(?:(?:(?:elevated|pty)\b\s*(?:·|,)\s*)+)?(?:`{1,2}\s*\S|(?:run|check|fetch|pull|push|view|show|list|switch|create|merge|rebase|stage|restore|reset|stash|search|find|print|copy|move|remove|install|start|cd|git|pnpm|npm|yarn|bun|node|python|python3|bash|sh)\b)/i;
|
|
50
|
-
const DISCORD_INTERNAL_CHANNEL_LINE_RE = /^(?:>\s*)?(?:analysis|commentary|tool[-_ ]?call|tool[-_ ]?result|function[-_ ]?call|thinking|reasoning)\s*[:=]/i;
|
|
51
|
-
function hasNonEmptyRecord(value) {
|
|
52
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length > 0);
|
|
53
|
-
}
|
|
54
|
-
function hasInteractiveOrPresentationBlocks(value) {
|
|
55
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
56
|
-
const record = value;
|
|
57
|
-
if (typeof record.title === "string" && record.title.trim().length > 0) return true;
|
|
58
|
-
return Array.isArray(record.blocks) && record.blocks.length > 0;
|
|
59
|
-
}
|
|
60
|
-
function hasNonTextReplyPayloadContent(payload) {
|
|
61
|
-
return payload.audioAsVoice === true || hasNonEmptyRecord(payload.channelData) || hasInteractiveOrPresentationBlocks(payload.interactive) || hasInteractiveOrPresentationBlocks(payload.presentation);
|
|
62
|
-
}
|
|
63
|
-
function stripDiscordInternalTraceLines(text) {
|
|
64
|
-
let inFence = false;
|
|
65
|
-
const kept = [];
|
|
66
|
-
for (const line of text.split(/\r?\n/)) {
|
|
67
|
-
if (/^\s*```/.test(line)) {
|
|
68
|
-
inFence = !inFence;
|
|
69
|
-
kept.push(line);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (!inFence) {
|
|
73
|
-
const trimmed = line.trim();
|
|
74
|
-
if (DISCORD_INTERNAL_TRACE_LINE_RE.test(trimmed) || DISCORD_INTERNAL_COMPACT_COMMAND_TRACE_LINE_RE.test(trimmed) || DISCORD_INTERNAL_CHANNEL_LINE_RE.test(trimmed)) continue;
|
|
75
|
-
}
|
|
76
|
-
kept.push(line);
|
|
77
|
-
}
|
|
78
|
-
return kept.join("\n");
|
|
79
|
-
}
|
|
80
|
-
function collapseExcessBlankLines(text) {
|
|
81
|
-
return text.replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
82
|
-
}
|
|
83
|
-
function sanitizeDiscordFrontChannelText(text) {
|
|
84
|
-
return collapseExcessBlankLines(stripDiscordInternalTraceLines(sanitizeAssistantVisibleText(text))).trim();
|
|
85
|
-
}
|
|
86
|
-
function sanitizeDiscordFrontChannelReplyPayloads(payloads) {
|
|
87
|
-
const safePayloads = [];
|
|
88
|
-
for (const payload of payloads) {
|
|
89
|
-
const safeText = typeof payload.text === "string" ? sanitizeDiscordFrontChannelText(payload.text) : payload.text;
|
|
90
|
-
const nextPayload = safeText === payload.text ? payload : {
|
|
91
|
-
...payload,
|
|
92
|
-
text: safeText || void 0
|
|
93
|
-
};
|
|
94
|
-
if (!resolveSendableOutboundReplyParts(nextPayload).hasContent && !hasNonTextReplyPayloadContent(nextPayload)) continue;
|
|
95
|
-
safePayloads.push(nextPayload);
|
|
96
|
-
}
|
|
97
|
-
return safePayloads;
|
|
98
|
-
}
|
|
99
|
-
//#endregion
|
|
100
|
-
//#region extensions/discord/src/monitor/reply-delivery.ts
|
|
101
|
-
function resolveTargetChannelId(target) {
|
|
102
|
-
if (!target.startsWith("channel:")) return;
|
|
103
|
-
return target.slice(8).trim() || void 0;
|
|
104
|
-
}
|
|
105
|
-
function resolveBoundThreadBinding(params) {
|
|
106
|
-
const sessionKey = params.sessionKey?.trim();
|
|
107
|
-
if (!params.threadBindings || !sessionKey) return;
|
|
108
|
-
const targetChannelId = resolveTargetChannelId(params.target);
|
|
109
|
-
if (!targetChannelId) return;
|
|
110
|
-
return params.threadBindings.listBySessionKey(sessionKey).find((entry) => entry.threadId === targetChannelId);
|
|
111
|
-
}
|
|
112
|
-
function resolveBindingIdentity(cfg, binding) {
|
|
113
|
-
if (!binding) return;
|
|
114
|
-
const identity = { name: (`🤖 ${binding.label?.trim() || binding.agentId}`.trim() || "🤖 agent").slice(0, 80) };
|
|
115
|
-
try {
|
|
116
|
-
const avatar = resolveAgentAvatar(cfg, binding.agentId);
|
|
117
|
-
if (avatar.kind === "remote") identity.avatarUrl = avatar.url;
|
|
118
|
-
} catch {}
|
|
119
|
-
return identity;
|
|
120
|
-
}
|
|
121
|
-
function createDiscordDeliveryDeps(params) {
|
|
122
|
-
return {
|
|
123
|
-
discord: (to, text, opts) => sendMessageDiscord(to, text, {
|
|
124
|
-
...opts,
|
|
125
|
-
cfg: opts?.cfg ?? params.cfg,
|
|
126
|
-
token: params.token,
|
|
127
|
-
rest: params.rest
|
|
128
|
-
}),
|
|
129
|
-
discordVoice: (to, audioPath, opts) => sendVoiceMessageDiscord(to, audioPath, {
|
|
130
|
-
...opts,
|
|
131
|
-
cfg: opts?.cfg ?? params.cfg,
|
|
132
|
-
token: params.token,
|
|
133
|
-
rest: params.rest
|
|
134
|
-
})
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
function resolveDiscordDeliveryOptions(params) {
|
|
138
|
-
const binding = resolveBoundThreadBinding({
|
|
139
|
-
threadBindings: params.threadBindings,
|
|
140
|
-
sessionKey: params.sessionKey,
|
|
141
|
-
target: params.target
|
|
142
|
-
});
|
|
143
|
-
return {
|
|
144
|
-
to: binding ? `channel:${binding.channelId}` : params.target,
|
|
145
|
-
threadId: binding?.threadId,
|
|
146
|
-
agentId: binding?.agentId,
|
|
147
|
-
identity: resolveBindingIdentity(params.cfg, binding),
|
|
148
|
-
mediaAccess: params.mediaLocalRoots?.length ? { localRoots: params.mediaLocalRoots } : void 0,
|
|
149
|
-
replyToMode: params.replyToMode ?? "all",
|
|
150
|
-
formatting: {
|
|
151
|
-
textLimit: params.textLimit,
|
|
152
|
-
maxLinesPerMessage: params.maxLinesPerMessage,
|
|
153
|
-
tableMode: params.tableMode,
|
|
154
|
-
chunkMode: params.chunkMode
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
async function deliverDiscordReply(params) {
|
|
159
|
-
params.runtime;
|
|
160
|
-
const delivery = resolveDiscordDeliveryOptions(params);
|
|
161
|
-
const payloads = sanitizeDiscordFrontChannelReplyPayloads(params.replies);
|
|
162
|
-
if (payloads.length === 0) return;
|
|
163
|
-
const send = await sendDurableMessageBatch({
|
|
164
|
-
cfg: params.cfg,
|
|
165
|
-
channel: "discord",
|
|
166
|
-
to: delivery.to,
|
|
167
|
-
accountId: params.accountId,
|
|
168
|
-
payloads,
|
|
169
|
-
replyToId: normalizeOptionalString(params.replyToId),
|
|
170
|
-
replyToMode: delivery.replyToMode,
|
|
171
|
-
formatting: delivery.formatting,
|
|
172
|
-
threadId: delivery.threadId,
|
|
173
|
-
identity: delivery.identity,
|
|
174
|
-
deps: createDiscordDeliveryDeps({
|
|
175
|
-
cfg: params.cfg,
|
|
176
|
-
token: params.token,
|
|
177
|
-
rest: params.rest
|
|
178
|
-
}),
|
|
179
|
-
mediaAccess: delivery.mediaAccess,
|
|
180
|
-
session: buildOutboundSessionContext({
|
|
181
|
-
cfg: params.cfg,
|
|
182
|
-
sessionKey: params.sessionKey,
|
|
183
|
-
agentId: delivery.agentId,
|
|
184
|
-
requesterAccountId: params.accountId
|
|
185
|
-
})
|
|
186
|
-
});
|
|
187
|
-
if (send.status === "failed" || send.status === "partial_failed") throw send.error;
|
|
188
|
-
if ((send.status === "sent" ? send.results : []).length === 0) throw new Error(`discord final reply produced no delivered message for ${delivery.to}`);
|
|
189
|
-
}
|
|
190
|
-
//#endregion
|
|
191
|
-
export { resolveReplyContext as i, buildDirectLabel as n, buildGuildLabel as r, deliverDiscordReply as t };
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
import { w as canViewDiscordGuildChannel } from "./send.shared-Dza0jdso.js";
|
|
2
|
-
import { r as normalizeDiscordAllowList } from "./allow-list-n8Ki-Rt3.js";
|
|
3
|
-
import { deriveLastRoutePolicy, isAcpSessionKey, isSubagentSessionKey, parseAgentSessionKey, resolveAgentIdFromSessionKey, resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
|
4
|
-
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
5
|
-
import { createChannelPairingChallengeIssuer } from "openclaw/plugin-sdk/channel-pairing";
|
|
6
|
-
import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
|
|
7
|
-
import { createChannelIngressResolver, defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
8
|
-
//#region extensions/discord/src/monitor/dm-command-auth.ts
|
|
9
|
-
const DISCORD_ALLOW_LIST_PREFIXES = [
|
|
10
|
-
"discord:",
|
|
11
|
-
"user:",
|
|
12
|
-
"pk:"
|
|
13
|
-
];
|
|
14
|
-
const DISCORD_CHANNEL_ID = "discord";
|
|
15
|
-
const DISCORD_USER_ID_KIND = "stable-id";
|
|
16
|
-
const DISCORD_USER_NAME_KIND = "username";
|
|
17
|
-
function normalizeDiscordIdEntry(entry) {
|
|
18
|
-
const text = entry.trim();
|
|
19
|
-
if (!text) return null;
|
|
20
|
-
const maybeId = text.replace(/^<@!?/, "").replace(/>$/, "");
|
|
21
|
-
if (/^\d+$/.test(maybeId)) return maybeId;
|
|
22
|
-
const prefix = DISCORD_ALLOW_LIST_PREFIXES.find((entryPrefix) => text.startsWith(entryPrefix));
|
|
23
|
-
if (prefix) return text.slice(prefix.length).trim() || null;
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
function normalizeDiscordNameEntry(entry) {
|
|
27
|
-
const text = entry.trim();
|
|
28
|
-
if (!text || text === "*" || normalizeDiscordIdEntry(text)) return null;
|
|
29
|
-
const nameSlug = normalizeDiscordAllowList([text], DISCORD_ALLOW_LIST_PREFIXES)?.names.values().next().value;
|
|
30
|
-
return typeof nameSlug === "string" && nameSlug ? nameSlug : null;
|
|
31
|
-
}
|
|
32
|
-
function normalizeDiscordNameSubject(value) {
|
|
33
|
-
const nameSlug = normalizeDiscordAllowList([value], DISCORD_ALLOW_LIST_PREFIXES)?.names.values().next().value;
|
|
34
|
-
return typeof nameSlug === "string" && nameSlug ? nameSlug : null;
|
|
35
|
-
}
|
|
36
|
-
const discordIngressIdentity = defineStableChannelIngressIdentity({
|
|
37
|
-
key: "discordUserId",
|
|
38
|
-
kind: DISCORD_USER_ID_KIND,
|
|
39
|
-
normalizeEntry: normalizeDiscordIdEntry,
|
|
40
|
-
normalizeSubject: (value) => value.trim() || null,
|
|
41
|
-
sensitivity: "pii",
|
|
42
|
-
aliases: [["discordUserName", normalizeDiscordNameEntry], ["discordUserTag", () => null]].map(([key, normalizeEntry]) => ({
|
|
43
|
-
key,
|
|
44
|
-
kind: DISCORD_USER_NAME_KIND,
|
|
45
|
-
normalizeEntry,
|
|
46
|
-
normalizeSubject: normalizeDiscordNameSubject,
|
|
47
|
-
dangerous: true,
|
|
48
|
-
sensitivity: "pii"
|
|
49
|
-
}))
|
|
50
|
-
});
|
|
51
|
-
function createDiscordDmIngressSubject(sender) {
|
|
52
|
-
return {
|
|
53
|
-
stableId: sender.id,
|
|
54
|
-
aliases: {
|
|
55
|
-
discordUserName: sender.name,
|
|
56
|
-
discordUserTag: sender.tag
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
function createDiscordDynamicAccessGroupResolver(params) {
|
|
61
|
-
if (!params.cfg) return;
|
|
62
|
-
const cfg = params.cfg;
|
|
63
|
-
return async ({ name, group, accountId, subject }) => {
|
|
64
|
-
if (group.type !== "discord.channelAudience") return false;
|
|
65
|
-
const senderId = String(subject.stableId ?? "").trim();
|
|
66
|
-
if (!senderId) return false;
|
|
67
|
-
if ((group.membership ?? "canViewChannel") !== "canViewChannel") return false;
|
|
68
|
-
try {
|
|
69
|
-
return await canViewDiscordGuildChannel(group.guildId, group.channelId, senderId, {
|
|
70
|
-
cfg,
|
|
71
|
-
accountId,
|
|
72
|
-
token: params.token,
|
|
73
|
-
rest: params.rest
|
|
74
|
-
});
|
|
75
|
-
} catch (err) {
|
|
76
|
-
logVerbose(`discord: accessGroup:${name} lookup failed for user ${senderId}: ${String(err)}`);
|
|
77
|
-
throw err;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function createDiscordIngressResolver(params) {
|
|
82
|
-
return createChannelIngressResolver({
|
|
83
|
-
channelId: DISCORD_CHANNEL_ID,
|
|
84
|
-
accountId: params.accountId,
|
|
85
|
-
identity: discordIngressIdentity,
|
|
86
|
-
cfg: params.cfg,
|
|
87
|
-
resolveAccessGroupMembership: createDiscordDynamicAccessGroupResolver({
|
|
88
|
-
cfg: params.cfg,
|
|
89
|
-
token: params.token,
|
|
90
|
-
rest: params.rest
|
|
91
|
-
}),
|
|
92
|
-
...params.readStoreAllowFrom ? { readStoreAllowFrom: params.readStoreAllowFrom } : {},
|
|
93
|
-
...params.useDefaultPairingStore !== void 0 ? { useDefaultPairingStore: params.useDefaultPairingStore } : {}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function syntheticAccessGroupMembership(groupName, allowed) {
|
|
97
|
-
return allowed ? {
|
|
98
|
-
kind: "matched",
|
|
99
|
-
groupName,
|
|
100
|
-
source: "dynamic",
|
|
101
|
-
matchedEntryIds: [groupName]
|
|
102
|
-
} : {
|
|
103
|
-
kind: "not-matched",
|
|
104
|
-
groupName,
|
|
105
|
-
source: "dynamic"
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
async function resolveDiscordDmCommandAccess(params) {
|
|
109
|
-
return await createDiscordIngressResolver({
|
|
110
|
-
accountId: params.accountId,
|
|
111
|
-
cfg: params.cfg,
|
|
112
|
-
token: params.token,
|
|
113
|
-
rest: params.rest,
|
|
114
|
-
readStoreAllowFrom: params.readStoreAllowFrom,
|
|
115
|
-
useDefaultPairingStore: params.readStoreAllowFrom == null
|
|
116
|
-
}).message({
|
|
117
|
-
subject: createDiscordDmIngressSubject(params.sender),
|
|
118
|
-
conversation: {
|
|
119
|
-
kind: "direct",
|
|
120
|
-
id: params.sender.id
|
|
121
|
-
},
|
|
122
|
-
event: {
|
|
123
|
-
kind: params.eventKind ?? "native-command",
|
|
124
|
-
authMode: "inbound",
|
|
125
|
-
mayPair: true
|
|
126
|
-
},
|
|
127
|
-
dmPolicy: params.dmPolicy,
|
|
128
|
-
groupPolicy: "disabled",
|
|
129
|
-
policy: { mutableIdentifierMatching: params.allowNameMatching ? "enabled" : "disabled" },
|
|
130
|
-
allowFrom: params.configuredAllowFrom,
|
|
131
|
-
command: {
|
|
132
|
-
hasControlCommand: false,
|
|
133
|
-
modeWhenAccessGroupsOff: "configured"
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
async function resolveDiscordTextCommandAccess(params) {
|
|
138
|
-
const ownerAllowFrom = (params.ownerAllowFrom ?? []).filter((entry) => entry.trim() !== "*");
|
|
139
|
-
const memberAccessGroup = "discord-member-access";
|
|
140
|
-
const commandGroup = params.memberAccessConfigured ? [`accessGroup:${memberAccessGroup}`] : [];
|
|
141
|
-
const accessGroupMembership = params.memberAccessConfigured ? [syntheticAccessGroupMembership(memberAccessGroup, params.memberAllowed)] : [];
|
|
142
|
-
return (await createDiscordIngressResolver({
|
|
143
|
-
accountId: params.accountId,
|
|
144
|
-
cfg: params.cfg,
|
|
145
|
-
token: params.token,
|
|
146
|
-
rest: params.rest
|
|
147
|
-
}).command({
|
|
148
|
-
subject: createDiscordDmIngressSubject(params.sender),
|
|
149
|
-
conversation: {
|
|
150
|
-
kind: "group",
|
|
151
|
-
id: "discord-command"
|
|
152
|
-
},
|
|
153
|
-
accessGroupMembership,
|
|
154
|
-
dmPolicy: "allowlist",
|
|
155
|
-
groupPolicy: "allowlist",
|
|
156
|
-
policy: { mutableIdentifierMatching: params.allowNameMatching ? "enabled" : "disabled" },
|
|
157
|
-
allowFrom: ownerAllowFrom,
|
|
158
|
-
groupAllowFrom: commandGroup,
|
|
159
|
-
command: {
|
|
160
|
-
allowTextCommands: params.allowTextCommands,
|
|
161
|
-
hasControlCommand: params.hasControlCommand,
|
|
162
|
-
modeWhenAccessGroupsOff: "configured"
|
|
163
|
-
}
|
|
164
|
-
})).commandAccess;
|
|
165
|
-
}
|
|
166
|
-
//#endregion
|
|
167
|
-
//#region extensions/discord/src/monitor/dm-command-decision.ts
|
|
168
|
-
async function handleDiscordDmCommandDecision(params) {
|
|
169
|
-
if (params.senderAccess.decision === "allow") return true;
|
|
170
|
-
if (params.senderAccess.decision === "pairing") {
|
|
171
|
-
const upsertPairingRequest = params.upsertPairingRequest ?? upsertChannelPairingRequest;
|
|
172
|
-
const result = await createChannelPairingChallengeIssuer({
|
|
173
|
-
channel: "discord",
|
|
174
|
-
upsertPairingRequest: async ({ id, meta }) => await upsertPairingRequest({
|
|
175
|
-
channel: "discord",
|
|
176
|
-
id,
|
|
177
|
-
accountId: params.accountId,
|
|
178
|
-
meta
|
|
179
|
-
})
|
|
180
|
-
})({
|
|
181
|
-
senderId: params.sender.id,
|
|
182
|
-
senderIdLine: `Your Discord user id: ${params.sender.id}`,
|
|
183
|
-
meta: {
|
|
184
|
-
tag: params.sender.tag,
|
|
185
|
-
name: params.sender.name
|
|
186
|
-
},
|
|
187
|
-
sendPairingReply: async () => {}
|
|
188
|
-
});
|
|
189
|
-
if (result.created && result.code) await params.onPairingCreated(result.code);
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
await params.onUnauthorized();
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
//#endregion
|
|
196
|
-
//#region extensions/discord/src/monitor/route-resolution.ts
|
|
197
|
-
function buildDiscordRoutePeer(params) {
|
|
198
|
-
return {
|
|
199
|
-
kind: params.isDirectMessage ? "direct" : params.isGroupDm ? "group" : "channel",
|
|
200
|
-
id: params.isDirectMessage ? params.directUserId?.trim() || params.conversationId : params.conversationId
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
function resolveDiscordConversationRoute(params) {
|
|
204
|
-
return resolveAgentRoute({
|
|
205
|
-
cfg: params.cfg,
|
|
206
|
-
channel: "discord",
|
|
207
|
-
accountId: params.accountId,
|
|
208
|
-
guildId: params.guildId ?? void 0,
|
|
209
|
-
memberRoleIds: params.memberRoleIds,
|
|
210
|
-
peer: params.peer,
|
|
211
|
-
parentPeer: params.parentConversationId ? {
|
|
212
|
-
kind: "channel",
|
|
213
|
-
id: params.parentConversationId
|
|
214
|
-
} : void 0
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
function resolveDiscordBoundConversationRoute(params) {
|
|
218
|
-
return resolveDiscordEffectiveRoute({
|
|
219
|
-
route: resolveDiscordConversationRoute({
|
|
220
|
-
cfg: params.cfg,
|
|
221
|
-
accountId: params.accountId,
|
|
222
|
-
guildId: params.guildId,
|
|
223
|
-
memberRoleIds: params.memberRoleIds,
|
|
224
|
-
peer: buildDiscordRoutePeer({
|
|
225
|
-
isDirectMessage: params.isDirectMessage,
|
|
226
|
-
isGroupDm: params.isGroupDm,
|
|
227
|
-
directUserId: params.directUserId,
|
|
228
|
-
conversationId: params.conversationId
|
|
229
|
-
}),
|
|
230
|
-
parentConversationId: params.parentConversationId
|
|
231
|
-
}),
|
|
232
|
-
boundSessionKey: params.boundSessionKey,
|
|
233
|
-
configuredRoute: params.configuredRoute,
|
|
234
|
-
matchedBy: params.matchedBy
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
function resolveDiscordEffectiveRoute(params) {
|
|
238
|
-
const boundSessionKey = params.boundSessionKey?.trim();
|
|
239
|
-
if (!boundSessionKey) return params.configuredRoute?.route ?? params.route;
|
|
240
|
-
return {
|
|
241
|
-
...params.route,
|
|
242
|
-
sessionKey: boundSessionKey,
|
|
243
|
-
agentId: resolveAgentIdFromSessionKey(boundSessionKey),
|
|
244
|
-
lastRoutePolicy: deriveLastRoutePolicy({
|
|
245
|
-
sessionKey: boundSessionKey,
|
|
246
|
-
mainSessionKey: params.route.mainSessionKey
|
|
247
|
-
}),
|
|
248
|
-
...params.matchedBy ? { matchedBy: params.matchedBy } : {}
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
function hasExplicitRuntimeBindingIntent(record) {
|
|
252
|
-
if (record.targetKind === "subagent") return true;
|
|
253
|
-
if (isAcpSessionKey(record.targetSessionKey) || isSubagentSessionKey(record.targetSessionKey)) return true;
|
|
254
|
-
const metadata = record.metadata;
|
|
255
|
-
if (!metadata || typeof metadata !== "object") return false;
|
|
256
|
-
return typeof metadata.boundBy === "string" || typeof metadata.label === "string" || typeof metadata.threadName === "string" || metadata.pluginBindingOwner === "plugin";
|
|
257
|
-
}
|
|
258
|
-
function shouldIgnoreStaleDiscordRouteBinding(params) {
|
|
259
|
-
const bindingRecord = params.bindingRecord;
|
|
260
|
-
const boundSessionKey = bindingRecord?.targetSessionKey?.trim();
|
|
261
|
-
if (!bindingRecord || !boundSessionKey || hasExplicitRuntimeBindingIntent(bindingRecord)) return false;
|
|
262
|
-
const bound = parseAgentSessionKey(boundSessionKey);
|
|
263
|
-
const routed = parseAgentSessionKey(params.route.sessionKey);
|
|
264
|
-
if (!bound || !routed || bound.rest !== routed.rest) return false;
|
|
265
|
-
return bound.agentId !== params.route.agentId;
|
|
266
|
-
}
|
|
267
|
-
//#endregion
|
|
268
|
-
export { shouldIgnoreStaleDiscordRouteBinding as a, resolveDiscordTextCommandAccess as c, resolveDiscordEffectiveRoute as i, resolveDiscordBoundConversationRoute as n, handleDiscordDmCommandDecision as o, resolveDiscordConversationRoute as r, resolveDiscordDmCommandAccess as s, buildDiscordRoutePeer as t };
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-message";
|
|
2
|
-
//#region extensions/discord/src/send.receipt.ts
|
|
3
|
-
function createDiscordSendReceipt(params) {
|
|
4
|
-
return createMessageReceiptFromOutboundResults({
|
|
5
|
-
results: params.platformMessageIds.map((messageId) => messageId.trim()).filter((messageId) => messageId && messageId !== "unknown").map((messageId) => {
|
|
6
|
-
const result = {
|
|
7
|
-
channel: "discord",
|
|
8
|
-
messageId
|
|
9
|
-
};
|
|
10
|
-
if (params.channelId) result.channelId = params.channelId;
|
|
11
|
-
return result;
|
|
12
|
-
}),
|
|
13
|
-
kind: params.kind,
|
|
14
|
-
threadId: params.threadId,
|
|
15
|
-
replyToId: params.replyToId
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
function createDiscordSendResult(params) {
|
|
19
|
-
const messageId = params.result.id || "unknown";
|
|
20
|
-
const channelId = params.result.channel_id ?? params.fallbackChannelId;
|
|
21
|
-
const receiptParams = {
|
|
22
|
-
platformMessageIds: params.result.platformMessageIds?.length ? params.result.platformMessageIds : [messageId],
|
|
23
|
-
channelId,
|
|
24
|
-
kind: params.kind
|
|
25
|
-
};
|
|
26
|
-
if (params.threadId != null) receiptParams.threadId = String(params.threadId);
|
|
27
|
-
if (params.replyToId) receiptParams.replyToId = params.replyToId;
|
|
28
|
-
return {
|
|
29
|
-
messageId,
|
|
30
|
-
channelId,
|
|
31
|
-
receipt: createDiscordSendReceipt(receiptParams)
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
//#endregion
|
|
35
|
-
export { createDiscordSendResult as n, createDiscordSendReceipt as t };
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { Ft as __exportAll } from "./discord-BqYcwxvG.js";
|
|
2
|
-
import { presentationToInteractiveControlsReply, reduceInteractiveReply } from "openclaw/plugin-sdk/interactive-runtime";
|
|
3
|
-
//#region extensions/discord/src/shared-interactive.ts
|
|
4
|
-
var shared_interactive_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
-
buildDiscordInteractiveComponents: () => buildDiscordInteractiveComponents,
|
|
6
|
-
buildDiscordPresentationComponents: () => buildDiscordPresentationComponents
|
|
7
|
-
});
|
|
8
|
-
function resolveDiscordInteractiveButtonStyle(style) {
|
|
9
|
-
return style ?? "secondary";
|
|
10
|
-
}
|
|
11
|
-
const DISCORD_INTERACTIVE_BUTTON_ROW_SIZE = 5;
|
|
12
|
-
function buildDiscordInteractiveComponents(interactive) {
|
|
13
|
-
const blocks = reduceInteractiveReply(interactive, [], (state, block) => {
|
|
14
|
-
if (block.type === "text") {
|
|
15
|
-
const text = block.text.trim();
|
|
16
|
-
if (text) state.push({
|
|
17
|
-
type: "text",
|
|
18
|
-
text
|
|
19
|
-
});
|
|
20
|
-
return state;
|
|
21
|
-
}
|
|
22
|
-
if (block.type === "buttons") {
|
|
23
|
-
if (block.buttons.length === 0) return state;
|
|
24
|
-
for (let index = 0; index < block.buttons.length; index += DISCORD_INTERACTIVE_BUTTON_ROW_SIZE) state.push({
|
|
25
|
-
type: "actions",
|
|
26
|
-
buttons: block.buttons.slice(index, index + DISCORD_INTERACTIVE_BUTTON_ROW_SIZE).map((button) => {
|
|
27
|
-
const spec = {
|
|
28
|
-
label: button.label,
|
|
29
|
-
style: button.url ? "link" : resolveDiscordInteractiveButtonStyle(button.style)
|
|
30
|
-
};
|
|
31
|
-
if (button.value) spec.callbackData = button.value;
|
|
32
|
-
if (button.url) spec.url = button.url;
|
|
33
|
-
return spec;
|
|
34
|
-
})
|
|
35
|
-
});
|
|
36
|
-
return state;
|
|
37
|
-
}
|
|
38
|
-
if (block.type === "select" && block.options.length > 0) state.push({
|
|
39
|
-
type: "actions",
|
|
40
|
-
select: {
|
|
41
|
-
type: "string",
|
|
42
|
-
placeholder: block.placeholder,
|
|
43
|
-
options: block.options.map((option) => ({
|
|
44
|
-
label: option.label,
|
|
45
|
-
value: option.value
|
|
46
|
-
}))
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
return state;
|
|
50
|
-
});
|
|
51
|
-
return blocks.length > 0 ? { blocks } : void 0;
|
|
52
|
-
}
|
|
53
|
-
function buildDiscordPresentationComponents(presentation) {
|
|
54
|
-
if (!presentation) return;
|
|
55
|
-
const spec = { blocks: [] };
|
|
56
|
-
if (presentation.title) spec.blocks?.push({
|
|
57
|
-
type: "text",
|
|
58
|
-
text: presentation.title
|
|
59
|
-
});
|
|
60
|
-
for (const block of presentation.blocks) {
|
|
61
|
-
if (block.type === "text" || block.type === "context") {
|
|
62
|
-
const text = block.text.trim();
|
|
63
|
-
if (text) spec.blocks?.push({
|
|
64
|
-
type: "text",
|
|
65
|
-
text: block.type === "context" ? `-# ${text}` : text
|
|
66
|
-
});
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (block.type === "divider") {
|
|
70
|
-
spec.blocks?.push({ type: "separator" });
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const interactiveSpec = buildDiscordInteractiveComponents(presentationToInteractiveControlsReply(presentation));
|
|
75
|
-
if (interactiveSpec?.blocks?.length) spec.blocks?.push(...interactiveSpec.blocks);
|
|
76
|
-
return spec.blocks?.length ? spec : void 0;
|
|
77
|
-
}
|
|
78
|
-
//#endregion
|
|
79
|
-
export { buildDiscordPresentationComponents as n, shared_interactive_exports as r, buildDiscordInteractiveComponents as t };
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { buildMessagingTarget, parseMentionPrefixOrAtUserTarget, requireTargetKind } from "openclaw/plugin-sdk/messaging-targets";
|
|
2
|
-
//#region extensions/discord/src/target-parsing.ts
|
|
3
|
-
function parseDiscordTarget(raw, options = {}) {
|
|
4
|
-
const trimmed = raw.trim();
|
|
5
|
-
if (!trimmed) return;
|
|
6
|
-
const providerPrefixedTarget = parseDiscordProviderPrefixedTarget(trimmed);
|
|
7
|
-
if (providerPrefixedTarget) return providerPrefixedTarget;
|
|
8
|
-
const userTarget = parseMentionPrefixOrAtUserTarget({
|
|
9
|
-
raw: trimmed,
|
|
10
|
-
mentionPattern: /^<@!?(\d+)>$/,
|
|
11
|
-
prefixes: [
|
|
12
|
-
{
|
|
13
|
-
prefix: "user:",
|
|
14
|
-
kind: "user"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
prefix: "channel:",
|
|
18
|
-
kind: "channel"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
prefix: "discord:",
|
|
22
|
-
kind: "user"
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
atUserPattern: /^\d+$/,
|
|
26
|
-
atUserErrorMessage: "Discord DMs require a user id (use user:<id> or a <@id> mention)"
|
|
27
|
-
});
|
|
28
|
-
if (userTarget) return userTarget;
|
|
29
|
-
if (/^\d+$/.test(trimmed)) {
|
|
30
|
-
if (options.defaultKind) return buildMessagingTarget(options.defaultKind, trimmed, trimmed);
|
|
31
|
-
throw new Error(options.ambiguousMessage ?? `Ambiguous Discord recipient "${trimmed}". For DMs use "user:${trimmed}" or "<@${trimmed}>"; for channels use "channel:${trimmed}".`);
|
|
32
|
-
}
|
|
33
|
-
return buildMessagingTarget("channel", trimmed, trimmed);
|
|
34
|
-
}
|
|
35
|
-
function parseDiscordProviderPrefixedTarget(raw) {
|
|
36
|
-
const match = /^discord:(channel|user):(.+)$/i.exec(raw);
|
|
37
|
-
if (!match) return;
|
|
38
|
-
const kind = match[1]?.toLowerCase();
|
|
39
|
-
const id = match[2]?.trim();
|
|
40
|
-
if (!kind || !id) return;
|
|
41
|
-
return buildMessagingTarget(kind, id, `${kind}:${id}`);
|
|
42
|
-
}
|
|
43
|
-
function resolveDiscordChannelId(raw) {
|
|
44
|
-
return requireTargetKind({
|
|
45
|
-
platform: "Discord",
|
|
46
|
-
target: parseDiscordTarget(raw, { defaultKind: "channel" }),
|
|
47
|
-
kind: "channel"
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
//#endregion
|
|
51
|
-
export { resolveDiscordChannelId as n, parseDiscordTarget as t };
|
package/dist/targets-DToZUkgV.js
DELETED