@openclaw/discord 2026.6.11 → 2026.7.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-runtime-api.js +1 -1
- package/dist/{api-4GFMoWu0.js → api-CJvEMuA6.js} +9 -2
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-SsFtZQA6.js → approval-handler.runtime-Cg7CuLSc.js} +3 -3
- package/dist/{audit-CAnmyf2A.js → audit-BCVhE9Oe.js} +3 -3
- package/dist/{channel-YA7AbYP3.js → channel-CfngVOjW.js} +17 -37
- package/dist/{channel-actions-BJ3n5Z1l.js → channel-actions-DJ_i4v9b.js} +3 -6
- package/dist/{channel-actions.runtime-D2QTRgZ9.js → channel-actions.runtime-BDW12z0o.js} +5 -5
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-B1zDEAR7.js → channel.setup-BYZ78cmU.js} +3 -3
- package/dist/{components-Dm4c_ce6.js → components-CBPNJhVP.js} +1 -1
- package/dist/{conversation-identity-DZ0BD7xO.js → conversation-identity-CnYbx3sO.js} +2 -2
- package/dist/{directory-config-BK1OhHa3.js → directory-config-CouAqvDj.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-DP3CmwGf.js → directory-live-C8lwwDJo.js} +2 -2
- package/dist/{doctor-D3ngpo-Y.js → doctor-CKIw8urm.js} +1 -1
- package/dist/{handle-action.guild-admin-B2cOoU2D.js → handle-action.guild-admin-CHMDXefq.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{manager.runtime-CPHxr9B3.js → manager.runtime-BkMOU8kh.js} +4 -4
- package/dist/{message-handler-CKaTgBIV.js → message-handler-B2cEpj5S.js} +11 -15
- package/dist/{message-handler.preflight--eAiaewz.js → message-handler.preflight-B93Az6zg.js} +15 -41
- package/dist/{message-handler.process-PhKAmrEd.js → message-handler.process-CW5mMw4o.js} +204 -33
- package/dist/{message-utils-O1vK3kPu.js → message-utils-Dy9KeClm.js} +1 -1
- package/dist/{outbound-adapter-fO_7hbTh.js → outbound-adapter-n_qRwyHZ.js} +17 -23
- package/dist/{pluralkit-B3MzPaPU.js → pluralkit-DaWTJTmF.js} +3 -3
- package/dist/{preflight-audio-ClWbnQto.js → preflight-audio-DecwnhEA.js} +2 -5
- package/dist/{probe-CxnDikWm.js → probe-Bkf8mJlj.js} +3 -2
- package/dist/{probe.runtime-DLFkSDVB.js → probe.runtime-3Rerer9g.js} +1 -1
- package/dist/{provider-BJaJ20MY.js → provider-BuTO6czP.js} +68 -60
- package/dist/{provider-session.runtime-D6xc-60s.js → provider-session.runtime-DmBTGaQX.js} +3 -3
- package/dist/provider.runtime-CqZpKOCE.js +2 -0
- package/dist/{resolve-allowlist-common-BDpBb8dF.js → resolve-allowlist-common-BDNoAQll.js} +1 -1
- package/dist/{resolve-channels-iJIjYfRw.js → resolve-channels-C_rAwrkj.js} +3 -3
- package/dist/{resolve-users-_fv1mm1f.js → resolve-users-Cz1tkemy.js} +3 -3
- package/dist/{runtime-ywXByivr.js → runtime-DaaaVvJm.js} +330 -303
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +19 -19
- package/dist/runtime-api.lookup.js +5 -5
- package/dist/runtime-api.monitor-ChuqOjHq.js +6 -0
- package/dist/runtime-api.monitor.js +4 -4
- package/dist/runtime-api.send.js +5 -5
- package/dist/runtime-api.threads.js +3 -3
- package/dist/{send-Dc5uQX5H.js → send-B_yfprXu.js} +18 -9
- package/dist/{send.components-D4bl20xr.js → send.components-C2psXc7A.js} +4 -4
- package/dist/{send.outbound-5axvwLkl.js → send.outbound-BPcCF1v2.js} +5 -4
- package/dist/{send.receipt-B21MspvT.js → send.receipt-CK162xD0.js} +28 -1
- package/dist/{send.shared-9082A2sO.js → send.shared-CUTfqvXx.js} +4 -15
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{shared-D11J9bXI.js → shared-AnStShZr.js} +3 -10
- package/dist/{subagent-hooks-NTv6B4up.js → subagent-hooks-DkO-jpvh.js} +2 -2
- package/dist/subagent-hooks-api.js +2 -5
- package/dist/{system-events-BzaI1WpN.js → system-events-XRYuwB2n.js} +1 -1
- package/dist/{target-resolver-agnOrtOU.js → target-resolver-DYufMbXm.js} +2 -2
- package/dist/targets-BA7gf0K0.js +3 -0
- package/dist/{thread-bindings-DNitaHVh.js → thread-bindings-BuXtcLSp.js} +4 -4
- package/dist/{thread-bindings.discord-api-CjYNuvZa.js → thread-bindings.discord-api-CetgvIbE.js} +4 -4
- package/dist/{thread-bindings.manager-PZvJ4TJx.js → thread-bindings.manager-B7AHjU4s.js} +3 -3
- package/dist/{transcripts-source-Bi8N6h5X.js → transcripts-source-DW6d1eCL.js} +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/dist/{typing-BdRqXUN3.js → typing-BMQEI8OW.js} +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/package.json +4 -4
- package/dist/provider.runtime-jNlHxUSW.js +0 -2
- package/dist/runtime-api.monitor-Bb5AaRzg.js +0 -6
- package/dist/targets-ClUPljCU.js +0 -3
|
@@ -1,17 +1,57 @@
|
|
|
1
|
-
import { Ut as resolveDiscordChannelId } from "./send.receipt-
|
|
1
|
+
import { Ut as resolveDiscordChannelId } from "./send.receipt-CK162xD0.js";
|
|
2
2
|
import { a as mergeDiscordAccountConfig, o as resolveDefaultDiscordAccountId, t as createDiscordActionGate } from "./accounts-P19jm1lf.js";
|
|
3
|
-
import { d as readDiscordComponentSpec } from "./components-
|
|
4
|
-
import { _ as withNormalizedTimestamp, c as jsonResult, d as readNonNegativeIntegerParam, f as readPositiveIntegerParam, g as resolvePollMaxSelections, h as readStringParam, l as parseAvailableTags, m as readStringArrayParam, p as readReactionParams, r as sendDiscordComponentMessage, s as assertMediaNotDataUrl, u as readBooleanParam } from "./send.components-
|
|
3
|
+
import { d as readDiscordComponentSpec } from "./components-CBPNJhVP.js";
|
|
4
|
+
import { _ as withNormalizedTimestamp, c as jsonResult, d as readNonNegativeIntegerParam, f as readPositiveIntegerParam, g as resolvePollMaxSelections, h as readStringParam, l as parseAvailableTags, m as readStringArrayParam, p as readReactionParams, r as sendDiscordComponentMessage, s as assertMediaNotDataUrl, u as readBooleanParam } from "./send.components-C2psXc7A.js";
|
|
5
5
|
import { n as getGateway, o as getPresence } from "./gateway-registry-DPxmW0Db.js";
|
|
6
|
-
import { E as canManageGuildRoleDiscord, L as createDiscordRuntimeAccountContext, M as hasAnyGuildPermissionDiscord, N as isThreadChannelType$1, O as fetchChannelPermissionsDiscord, T as canManageGuildMemberRoleDiscord, d as resolveDiscordTargetChannelId, j as hasAnyChannelPermissionDiscord } from "./send.shared-
|
|
6
|
+
import { E as canManageGuildRoleDiscord, L as createDiscordRuntimeAccountContext, M as hasAnyGuildPermissionDiscord, N as isThreadChannelType$1, O as fetchChannelPermissionsDiscord, T as canManageGuildMemberRoleDiscord, d as resolveDiscordTargetChannelId, j as hasAnyChannelPermissionDiscord } from "./send.shared-CUTfqvXx.js";
|
|
7
7
|
import { a as normalizeDiscordSlug, c as resolveDiscordChannelConfigWithFallback, n as isDiscordGroupAllowedByPolicy } from "./allow-list-C-MqM-B_.js";
|
|
8
|
-
import { A as listScheduledEventsDiscord, B as moveChannelDiscord, C as fetchChannelInfoDiscord, D as fetchVoiceStatusDiscord, E as fetchRoleInfoDiscord, F as uploadEmojiDiscord, H as setChannelPermissionDiscord, I as uploadStickerDiscord, L as createChannelDiscord, M as resolveEventCoverImage, N as timeoutMemberDiscord, O as kickMemberDiscord, P as listGuildEmojisDiscord, R as deleteChannelDiscord, S as createScheduledEventDiscord, T as fetchMemberInfoDiscord, V as removeChannelPermissionDiscord, _ as readMessagesDiscord, a as removeReactionDiscord, b as addRoleDiscord, d as deleteMessageDiscord, f as editMessageDiscord, g as pinMessageDiscord, h as listThreadsDiscord, i as removeOwnReactionsDiscord, j as removeRoleDiscord, k as listGuildChannelsDiscord, l as DiscordThreadInitialMessageError, m as listPinsDiscord, n as fetchReactionsDiscord, p as fetchMessageDiscord, r as reactMessageDiscord, s as sendVoiceMessageDiscord, u as createThreadDiscord, v as searchMessagesDiscord, w as fetchGuildInfoDiscord, x as banMemberDiscord, y as unpinMessageDiscord, z as editChannelDiscord } from "./send-
|
|
9
|
-
import { n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-
|
|
10
|
-
import "./targets-
|
|
8
|
+
import { A as listScheduledEventsDiscord, B as moveChannelDiscord, C as fetchChannelInfoDiscord, D as fetchVoiceStatusDiscord, E as fetchRoleInfoDiscord, F as uploadEmojiDiscord, H as setChannelPermissionDiscord, I as uploadStickerDiscord, L as createChannelDiscord, M as resolveEventCoverImage, N as timeoutMemberDiscord, O as kickMemberDiscord, P as listGuildEmojisDiscord, R as deleteChannelDiscord, S as createScheduledEventDiscord, T as fetchMemberInfoDiscord, V as removeChannelPermissionDiscord, _ as readMessagesDiscord, a as removeReactionDiscord, b as addRoleDiscord, d as deleteMessageDiscord, f as editMessageDiscord, g as pinMessageDiscord, h as listThreadsDiscord, i as removeOwnReactionsDiscord, j as removeRoleDiscord, k as listGuildChannelsDiscord, l as DiscordThreadInitialMessageError, m as listPinsDiscord, n as fetchReactionsDiscord, p as fetchMessageDiscord, r as reactMessageDiscord, s as sendVoiceMessageDiscord, u as createThreadDiscord, v as searchMessagesDiscord, w as fetchGuildInfoDiscord, x as banMemberDiscord, y as unpinMessageDiscord, z as editChannelDiscord } from "./send-B_yfprXu.js";
|
|
9
|
+
import { n as sendPollDiscord, r as sendStickerDiscord, t as sendMessageDiscord } from "./send.outbound-BPcCF1v2.js";
|
|
10
|
+
import "./targets-BA7gf0K0.js";
|
|
11
11
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
12
12
|
import { ChannelType, PermissionFlagsBits } from "discord-api-types/v10";
|
|
13
13
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
14
14
|
import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
15
|
+
//#region extensions/discord/src/actions/runtime.messaging.runtime.ts
|
|
16
|
+
const discordMessagingActionRuntime = {
|
|
17
|
+
createThreadDiscord,
|
|
18
|
+
deleteMessageDiscord,
|
|
19
|
+
editChannelDiscord,
|
|
20
|
+
editMessageDiscord,
|
|
21
|
+
fetchChannelInfoDiscord,
|
|
22
|
+
fetchGuildInfoDiscord,
|
|
23
|
+
fetchChannelPermissionsDiscord,
|
|
24
|
+
fetchMessageDiscord,
|
|
25
|
+
fetchReactionsDiscord,
|
|
26
|
+
listPinsDiscord,
|
|
27
|
+
listThreadsDiscord,
|
|
28
|
+
pinMessageDiscord,
|
|
29
|
+
reactMessageDiscord,
|
|
30
|
+
readDiscordComponentSpec,
|
|
31
|
+
readMessagesDiscord,
|
|
32
|
+
removeOwnReactionsDiscord,
|
|
33
|
+
removeReactionDiscord,
|
|
34
|
+
resolveDiscordReactionTargetChannelId,
|
|
35
|
+
resolveDiscordChannelId,
|
|
36
|
+
searchMessagesDiscord,
|
|
37
|
+
sendDiscordComponentMessage,
|
|
38
|
+
sendMessageDiscord,
|
|
39
|
+
sendPollDiscord,
|
|
40
|
+
sendStickerDiscord,
|
|
41
|
+
sendVoiceMessageDiscord,
|
|
42
|
+
unpinMessageDiscord
|
|
43
|
+
};
|
|
44
|
+
async function resolveDiscordReactionTargetChannelId(params) {
|
|
45
|
+
try {
|
|
46
|
+
return resolveDiscordChannelId(params.target);
|
|
47
|
+
} catch {
|
|
48
|
+
return (await resolveDiscordTargetChannelId(params.target, {
|
|
49
|
+
cfg: params.cfg,
|
|
50
|
+
accountId: params.accountId
|
|
51
|
+
})).channelId;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
15
55
|
//#region extensions/discord/src/actions/runtime.shared.ts
|
|
16
56
|
function readDiscordParentIdParam(params) {
|
|
17
57
|
if (params.clearParent === true) return null;
|
|
@@ -66,6 +106,239 @@ function readDiscordChannelMoveParams(params) {
|
|
|
66
106
|
};
|
|
67
107
|
}
|
|
68
108
|
//#endregion
|
|
109
|
+
//#region extensions/discord/src/actions/runtime.messaging.shared.ts
|
|
110
|
+
function hasDiscordGuildEntries(guilds) {
|
|
111
|
+
return Boolean(guilds && Object.keys(guilds).length > 0);
|
|
112
|
+
}
|
|
113
|
+
function allowsAllDiscordGuildChannels(channels) {
|
|
114
|
+
const wildcard = channels?.["*"];
|
|
115
|
+
if (!wildcard || wildcard.enabled === false) return false;
|
|
116
|
+
return Object.values(channels ?? {}).every((entry) => entry?.enabled !== false);
|
|
117
|
+
}
|
|
118
|
+
function resolveDiscordActionGuildEntry(params) {
|
|
119
|
+
const guildId = params.guildId?.trim();
|
|
120
|
+
if (!params.guilds) return null;
|
|
121
|
+
if (guildId && params.guilds[guildId]) return {
|
|
122
|
+
...params.guilds[guildId],
|
|
123
|
+
id: guildId
|
|
124
|
+
};
|
|
125
|
+
if (guildId) {
|
|
126
|
+
const byConfiguredId = Object.values(params.guilds).find((guild) => guild?.id === guildId);
|
|
127
|
+
if (byConfiguredId) return {
|
|
128
|
+
...byConfiguredId,
|
|
129
|
+
id: guildId
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const guildSlug = params.guildName ? normalizeDiscordSlug(params.guildName) : "";
|
|
133
|
+
if (guildSlug) {
|
|
134
|
+
const bySlug = params.guilds[guildSlug] ?? Object.values(params.guilds).find((guild) => guild?.slug === guildSlug);
|
|
135
|
+
if (bySlug) return {
|
|
136
|
+
...bySlug,
|
|
137
|
+
id: guildId,
|
|
138
|
+
slug: guildSlug || bySlug.slug
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (params.includeWildcard === false) return null;
|
|
142
|
+
const wildcard = params.guilds["*"];
|
|
143
|
+
return wildcard ? {
|
|
144
|
+
...wildcard,
|
|
145
|
+
id: guildId
|
|
146
|
+
} : null;
|
|
147
|
+
}
|
|
148
|
+
function readDiscordChannelStringField(value, ...keys) {
|
|
149
|
+
if (!value || typeof value !== "object") return;
|
|
150
|
+
const record = value;
|
|
151
|
+
for (const key of keys) {
|
|
152
|
+
const candidate = record[key];
|
|
153
|
+
if (typeof candidate === "string" && candidate.trim()) return candidate.trim();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function readDiscordChannelType(value) {
|
|
157
|
+
if (!value || typeof value !== "object") return;
|
|
158
|
+
const type = value.type;
|
|
159
|
+
return typeof type === "number" ? type : void 0;
|
|
160
|
+
}
|
|
161
|
+
function isDiscordThreadChannel(value) {
|
|
162
|
+
const type = readDiscordChannelType(value);
|
|
163
|
+
return type === 10 || type === 11 || type === 12;
|
|
164
|
+
}
|
|
165
|
+
function isDiscordReadTargetAllowedInGuild(params) {
|
|
166
|
+
if (resolveDiscordChannelConfigWithFallback({
|
|
167
|
+
guildInfo: params.guildInfo,
|
|
168
|
+
channelId: params.target.channelId,
|
|
169
|
+
channelName: params.target.channelName,
|
|
170
|
+
channelSlug: params.target.channelSlug,
|
|
171
|
+
parentId: params.target.parentId,
|
|
172
|
+
parentName: params.target.parentName,
|
|
173
|
+
parentSlug: params.target.parentSlug,
|
|
174
|
+
scope: params.target.scope
|
|
175
|
+
})?.allowed === false) return false;
|
|
176
|
+
return isDiscordGroupAllowedByPolicy({
|
|
177
|
+
groupPolicy: params.groupPolicy,
|
|
178
|
+
guildAllowlisted: Boolean(params.guildInfo),
|
|
179
|
+
channelAllowlistConfigured: hasDiscordGuildEntries(params.guildInfo?.channels),
|
|
180
|
+
channelAllowed: true
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function isDiscordReadTargetExplicitlyAllowedById(params) {
|
|
184
|
+
const channelEntry = params.guildInfo?.channels?.[params.target.channelId];
|
|
185
|
+
if (!channelEntry || channelEntry.enabled === false) return false;
|
|
186
|
+
return isDiscordGroupAllowedByPolicy({
|
|
187
|
+
groupPolicy: params.groupPolicy,
|
|
188
|
+
guildAllowlisted: Boolean(params.guildInfo),
|
|
189
|
+
channelAllowlistConfigured: true,
|
|
190
|
+
channelAllowed: true
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function createDiscordMessagingActionContext(params) {
|
|
194
|
+
const accountId = readStringParam(params.input, "accountId");
|
|
195
|
+
const cfgOptions = { cfg: params.cfg };
|
|
196
|
+
const accountConfig = mergeDiscordAccountConfig(params.cfg, accountId ?? resolveDefaultDiscordAccountId(params.cfg));
|
|
197
|
+
const guilds = accountConfig.guilds;
|
|
198
|
+
const hasGuildEntries = Object.keys(guilds ?? {}).length > 0;
|
|
199
|
+
const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
|
|
200
|
+
providerConfigPresent: params.cfg.channels?.discord !== void 0,
|
|
201
|
+
groupPolicy: accountConfig.groupPolicy,
|
|
202
|
+
defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy
|
|
203
|
+
});
|
|
204
|
+
const withOpts = (extra) => createDiscordActionOptions({
|
|
205
|
+
cfg: params.cfg,
|
|
206
|
+
accountId,
|
|
207
|
+
extra
|
|
208
|
+
});
|
|
209
|
+
const resolvedReactionAccountId = accountId ?? resolveDefaultDiscordAccountId(params.cfg);
|
|
210
|
+
const reactionRuntimeOptions = resolvedReactionAccountId ? createDiscordRuntimeAccountContext({
|
|
211
|
+
cfg: params.cfg,
|
|
212
|
+
accountId: resolvedReactionAccountId
|
|
213
|
+
}) : cfgOptions;
|
|
214
|
+
const guildNameById = /* @__PURE__ */ new Map();
|
|
215
|
+
const resolveGuildName = async (guildId) => {
|
|
216
|
+
if (guildNameById.has(guildId)) return guildNameById.get(guildId) ?? null;
|
|
217
|
+
try {
|
|
218
|
+
const guildName = readDiscordChannelStringField(await discordMessagingActionRuntime.fetchGuildInfoDiscord(guildId, withOpts()), "name") ?? null;
|
|
219
|
+
guildNameById.set(guildId, guildName);
|
|
220
|
+
return guildName;
|
|
221
|
+
} catch {
|
|
222
|
+
guildNameById.set(guildId, null);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
const resolveReadGuildEntry = async (guildId) => {
|
|
227
|
+
const direct = resolveDiscordActionGuildEntry({
|
|
228
|
+
guilds,
|
|
229
|
+
guildId,
|
|
230
|
+
includeWildcard: false
|
|
231
|
+
});
|
|
232
|
+
if (direct || !guildId) return direct;
|
|
233
|
+
const named = resolveDiscordActionGuildEntry({
|
|
234
|
+
guilds,
|
|
235
|
+
guildId,
|
|
236
|
+
guildName: await resolveGuildName(guildId) ?? void 0,
|
|
237
|
+
includeWildcard: false
|
|
238
|
+
});
|
|
239
|
+
if (named) return named;
|
|
240
|
+
return resolveDiscordActionGuildEntry({
|
|
241
|
+
guilds,
|
|
242
|
+
guildId
|
|
243
|
+
});
|
|
244
|
+
};
|
|
245
|
+
const resolveReadTargetContext = async (channelId) => {
|
|
246
|
+
const fallback = {
|
|
247
|
+
channelId,
|
|
248
|
+
channelSlug: normalizeDiscordSlug(channelId) || channelId
|
|
249
|
+
};
|
|
250
|
+
let channelInfo;
|
|
251
|
+
try {
|
|
252
|
+
channelInfo = await discordMessagingActionRuntime.fetchChannelInfoDiscord(channelId, withOpts());
|
|
253
|
+
} catch {
|
|
254
|
+
return fallback;
|
|
255
|
+
}
|
|
256
|
+
const channelName = readDiscordChannelStringField(channelInfo, "name");
|
|
257
|
+
const target = {
|
|
258
|
+
channelId,
|
|
259
|
+
channelSlug: channelName ? normalizeDiscordSlug(channelName) : fallback.channelSlug
|
|
260
|
+
};
|
|
261
|
+
const targetGuildId = readDiscordChannelStringField(channelInfo, "guild_id", "guildId");
|
|
262
|
+
if (targetGuildId) target.guildId = targetGuildId;
|
|
263
|
+
if (channelName) target.channelName = channelName;
|
|
264
|
+
if (!isDiscordThreadChannel(channelInfo)) return target;
|
|
265
|
+
target.scope = "thread";
|
|
266
|
+
target.parentId = readDiscordChannelStringField(channelInfo, "parent_id", "parentId");
|
|
267
|
+
if (!target.parentId) return target;
|
|
268
|
+
try {
|
|
269
|
+
const parentName = readDiscordChannelStringField(await discordMessagingActionRuntime.fetchChannelInfoDiscord(target.parentId, withOpts()), "name");
|
|
270
|
+
if (parentName) {
|
|
271
|
+
target.parentName = parentName;
|
|
272
|
+
target.parentSlug = normalizeDiscordSlug(parentName);
|
|
273
|
+
}
|
|
274
|
+
} catch {}
|
|
275
|
+
return target;
|
|
276
|
+
};
|
|
277
|
+
return {
|
|
278
|
+
action: params.action,
|
|
279
|
+
params: params.input,
|
|
280
|
+
isActionEnabled: params.isActionEnabled,
|
|
281
|
+
cfg: params.cfg,
|
|
282
|
+
options: params.options,
|
|
283
|
+
accountId,
|
|
284
|
+
resolveChannelId: () => discordMessagingActionRuntime.resolveDiscordChannelId(readStringParam(params.input, "channelId", { required: true })),
|
|
285
|
+
assertReadTargetAllowed: async ({ guildId, channelId }) => {
|
|
286
|
+
const targetChannelId = discordMessagingActionRuntime.resolveDiscordChannelId(channelId);
|
|
287
|
+
if (!hasGuildEntries && groupPolicy !== "disabled" && groupPolicy !== "allowlist") return;
|
|
288
|
+
const target = await resolveReadTargetContext(targetChannelId);
|
|
289
|
+
if (guildId) {
|
|
290
|
+
if (target.guildId && target.guildId !== guildId) throw new Error("Discord read target channel is not allowed.");
|
|
291
|
+
if (!isDiscordReadTargetAllowedInGuild({
|
|
292
|
+
groupPolicy,
|
|
293
|
+
guildInfo: await resolveReadGuildEntry(guildId),
|
|
294
|
+
target
|
|
295
|
+
})) throw new Error("Discord read target channel is not allowed.");
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (target.guildId) {
|
|
299
|
+
if (!isDiscordReadTargetAllowedInGuild({
|
|
300
|
+
groupPolicy,
|
|
301
|
+
guildInfo: await resolveReadGuildEntry(target.guildId),
|
|
302
|
+
target
|
|
303
|
+
})) throw new Error("Discord read target channel is not allowed.");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (!Object.values(guilds ?? {}).some((guildInfo) => isDiscordReadTargetExplicitlyAllowedById({
|
|
307
|
+
groupPolicy,
|
|
308
|
+
guildInfo: guildInfo ?? null,
|
|
309
|
+
target
|
|
310
|
+
}))) throw new Error("Discord read target channel is not allowed.");
|
|
311
|
+
},
|
|
312
|
+
assertGuildReadTargetAllowed: async ({ guildId, channelTargetRequiredMessage }) => {
|
|
313
|
+
const guildInfo = await resolveReadGuildEntry(guildId);
|
|
314
|
+
if (!isDiscordGroupAllowedByPolicy({
|
|
315
|
+
groupPolicy,
|
|
316
|
+
guildAllowlisted: Boolean(guildInfo),
|
|
317
|
+
channelAllowlistConfigured: false,
|
|
318
|
+
channelAllowed: true
|
|
319
|
+
})) throw new Error("Discord read target channel is not allowed.");
|
|
320
|
+
if (hasDiscordGuildEntries(guildInfo?.channels) && !allowsAllDiscordGuildChannels(guildInfo.channels)) throw new Error(channelTargetRequiredMessage ?? "Discord message search requires channelId or channelIds so each read target can be authorized.");
|
|
321
|
+
},
|
|
322
|
+
resolveReactionChannelId: async () => {
|
|
323
|
+
const target = readStringParam(params.input, "channelId") ?? readStringParam(params.input, "to", { required: true });
|
|
324
|
+
return await discordMessagingActionRuntime.resolveDiscordReactionTargetChannelId({
|
|
325
|
+
target,
|
|
326
|
+
cfg: params.cfg,
|
|
327
|
+
accountId: resolvedReactionAccountId
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
withOpts,
|
|
331
|
+
withReactionRuntimeOptions: (extra) => ({
|
|
332
|
+
...reactionRuntimeOptions ?? cfgOptions,
|
|
333
|
+
...extra
|
|
334
|
+
}),
|
|
335
|
+
normalizeMessage: (message) => {
|
|
336
|
+
if (!message || typeof message !== "object") return message;
|
|
337
|
+
return withNormalizedTimestamp(message, message.timestamp);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
//#endregion
|
|
69
342
|
//#region extensions/discord/src/actions/runtime.guild.ts
|
|
70
343
|
const discordGuildActionRuntime = {
|
|
71
344
|
addRoleDiscord,
|
|
@@ -245,15 +518,29 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
245
518
|
accountId,
|
|
246
519
|
cfg
|
|
247
520
|
});
|
|
521
|
+
const readTargetGate = createDiscordMessagingActionContext({
|
|
522
|
+
action,
|
|
523
|
+
input: params,
|
|
524
|
+
isActionEnabled,
|
|
525
|
+
cfg,
|
|
526
|
+
options
|
|
527
|
+
});
|
|
248
528
|
const withOpts = (extra) => createDiscordActionOptions({
|
|
249
529
|
cfg,
|
|
250
530
|
accountId,
|
|
251
531
|
extra
|
|
252
532
|
});
|
|
533
|
+
const assertGuildMetadataReadAllowed = async (guildId) => {
|
|
534
|
+
await readTargetGate.assertGuildReadTargetAllowed({
|
|
535
|
+
guildId,
|
|
536
|
+
channelTargetRequiredMessage: "Discord guild metadata reads require a wildcard channel allowlist for this guild."
|
|
537
|
+
});
|
|
538
|
+
};
|
|
253
539
|
switch (action) {
|
|
254
540
|
case "memberInfo": {
|
|
255
541
|
if (!isActionEnabled("memberInfo")) throw new Error("Discord member info is disabled.");
|
|
256
542
|
const guildId = readStringParam(params, "guildId", { required: true });
|
|
543
|
+
await assertGuildMetadataReadAllowed(guildId);
|
|
257
544
|
const userId = readStringParam(params, "userId", { required: true });
|
|
258
545
|
const effectiveAccountId = accountId ?? resolveDefaultDiscordAccountId(cfg);
|
|
259
546
|
const member = await discordGuildActionRuntime.fetchMemberInfoDiscord(guildId, userId, createDiscordActionOptions({
|
|
@@ -275,6 +562,7 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
275
562
|
case "roleInfo": {
|
|
276
563
|
if (!isActionEnabled("roleInfo")) throw new Error("Discord role info is disabled.");
|
|
277
564
|
const guildId = readStringParam(params, "guildId", { required: true });
|
|
565
|
+
await assertGuildMetadataReadAllowed(guildId);
|
|
278
566
|
return jsonResult({
|
|
279
567
|
ok: true,
|
|
280
568
|
roles: await discordGuildActionRuntime.fetchRoleInfoDiscord(guildId, withOpts())
|
|
@@ -283,6 +571,7 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
283
571
|
case "emojiList": {
|
|
284
572
|
if (!isActionEnabled("reactions")) throw new Error("Discord reactions are disabled.");
|
|
285
573
|
const guildId = readStringParam(params, "guildId", { required: true });
|
|
574
|
+
await assertGuildMetadataReadAllowed(guildId);
|
|
286
575
|
return jsonResult({
|
|
287
576
|
ok: true,
|
|
288
577
|
emojis: await discordGuildActionRuntime.listGuildEmojisDiscord(guildId, withOpts())
|
|
@@ -343,6 +632,7 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
343
632
|
case "channelInfo": {
|
|
344
633
|
if (!isActionEnabled("channelInfo")) throw new Error("Discord channel info is disabled.");
|
|
345
634
|
const channelId = readStringParam(params, "channelId", { required: true });
|
|
635
|
+
await readTargetGate.assertReadTargetAllowed({ channelId });
|
|
346
636
|
return jsonResult({
|
|
347
637
|
ok: true,
|
|
348
638
|
channel: await discordGuildActionRuntime.fetchChannelInfoDiscord(channelId, withOpts())
|
|
@@ -351,6 +641,7 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
351
641
|
case "channelList": {
|
|
352
642
|
if (!isActionEnabled("channelInfo")) throw new Error("Discord channel info is disabled.");
|
|
353
643
|
const guildId = readStringParam(params, "guildId", { required: true });
|
|
644
|
+
await assertGuildMetadataReadAllowed(guildId);
|
|
354
645
|
return jsonResult({
|
|
355
646
|
ok: true,
|
|
356
647
|
channels: await discordGuildActionRuntime.listGuildChannelsDiscord(guildId, withOpts())
|
|
@@ -359,6 +650,7 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
359
650
|
case "voiceStatus": {
|
|
360
651
|
if (!isActionEnabled("voiceStatus")) throw new Error("Discord voice status is disabled.");
|
|
361
652
|
const guildId = readStringParam(params, "guildId", { required: true });
|
|
653
|
+
await assertGuildMetadataReadAllowed(guildId);
|
|
362
654
|
const userId = readStringParam(params, "userId", { required: true });
|
|
363
655
|
return jsonResult({
|
|
364
656
|
ok: true,
|
|
@@ -368,6 +660,7 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
368
660
|
case "eventList": {
|
|
369
661
|
if (!isActionEnabled("events")) throw new Error("Discord events are disabled.");
|
|
370
662
|
const guildId = readStringParam(params, "guildId", { required: true });
|
|
663
|
+
await assertGuildMetadataReadAllowed(guildId);
|
|
371
664
|
return jsonResult({
|
|
372
665
|
ok: true,
|
|
373
666
|
events: await discordGuildActionRuntime.listScheduledEventsDiscord(guildId, withOpts())
|
|
@@ -459,66 +752,26 @@ async function handleDiscordGuildAction(action, params, isActionEnabled, cfg, op
|
|
|
459
752
|
}
|
|
460
753
|
case "channelPermissionSet": {
|
|
461
754
|
if (!isActionEnabled("channels")) throw new Error("Discord channel management is disabled.");
|
|
462
|
-
const { channelId, targetId } = readChannelPermissionTarget(params);
|
|
463
|
-
const targetType = readStringParam(params, "targetType", { required: true }) === "member" ? 1 : 0;
|
|
464
|
-
const allow = readStringParam(params, "allow");
|
|
465
|
-
const deny = readStringParam(params, "deny");
|
|
466
|
-
await discordGuildActionRuntime.setChannelPermissionDiscord({
|
|
467
|
-
channelId,
|
|
468
|
-
targetId,
|
|
469
|
-
targetType,
|
|
470
|
-
allow: allow ?? void 0,
|
|
471
|
-
deny: deny ?? void 0
|
|
472
|
-
}, withOpts());
|
|
473
|
-
return jsonResult({ ok: true });
|
|
474
|
-
}
|
|
475
|
-
case "channelPermissionRemove": {
|
|
476
|
-
if (!isActionEnabled("channels")) throw new Error("Discord channel management is disabled.");
|
|
477
|
-
const { channelId, targetId } = readChannelPermissionTarget(params);
|
|
478
|
-
await discordGuildActionRuntime.removeChannelPermissionDiscord(channelId, targetId, withOpts());
|
|
479
|
-
return jsonResult({ ok: true });
|
|
480
|
-
}
|
|
481
|
-
default: throw new Error(`Unknown action: ${action}`);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
//#endregion
|
|
485
|
-
//#region extensions/discord/src/actions/runtime.messaging.runtime.ts
|
|
486
|
-
const discordMessagingActionRuntime = {
|
|
487
|
-
createThreadDiscord,
|
|
488
|
-
deleteMessageDiscord,
|
|
489
|
-
editChannelDiscord,
|
|
490
|
-
editMessageDiscord,
|
|
491
|
-
fetchChannelInfoDiscord,
|
|
492
|
-
fetchGuildInfoDiscord,
|
|
493
|
-
fetchChannelPermissionsDiscord,
|
|
494
|
-
fetchMessageDiscord,
|
|
495
|
-
fetchReactionsDiscord,
|
|
496
|
-
listPinsDiscord,
|
|
497
|
-
listThreadsDiscord,
|
|
498
|
-
pinMessageDiscord,
|
|
499
|
-
reactMessageDiscord,
|
|
500
|
-
readDiscordComponentSpec,
|
|
501
|
-
readMessagesDiscord,
|
|
502
|
-
removeOwnReactionsDiscord,
|
|
503
|
-
removeReactionDiscord,
|
|
504
|
-
resolveDiscordReactionTargetChannelId,
|
|
505
|
-
resolveDiscordChannelId,
|
|
506
|
-
searchMessagesDiscord,
|
|
507
|
-
sendDiscordComponentMessage,
|
|
508
|
-
sendMessageDiscord,
|
|
509
|
-
sendPollDiscord,
|
|
510
|
-
sendStickerDiscord,
|
|
511
|
-
sendVoiceMessageDiscord,
|
|
512
|
-
unpinMessageDiscord
|
|
513
|
-
};
|
|
514
|
-
async function resolveDiscordReactionTargetChannelId(params) {
|
|
515
|
-
try {
|
|
516
|
-
return resolveDiscordChannelId(params.target);
|
|
517
|
-
} catch {
|
|
518
|
-
return (await resolveDiscordTargetChannelId(params.target, {
|
|
519
|
-
cfg: params.cfg,
|
|
520
|
-
accountId: params.accountId
|
|
521
|
-
})).channelId;
|
|
755
|
+
const { channelId, targetId } = readChannelPermissionTarget(params);
|
|
756
|
+
const targetType = readStringParam(params, "targetType", { required: true }) === "member" ? 1 : 0;
|
|
757
|
+
const allow = readStringParam(params, "allow");
|
|
758
|
+
const deny = readStringParam(params, "deny");
|
|
759
|
+
await discordGuildActionRuntime.setChannelPermissionDiscord({
|
|
760
|
+
channelId,
|
|
761
|
+
targetId,
|
|
762
|
+
targetType,
|
|
763
|
+
allow: allow ?? void 0,
|
|
764
|
+
deny: deny ?? void 0
|
|
765
|
+
}, withOpts());
|
|
766
|
+
return jsonResult({ ok: true });
|
|
767
|
+
}
|
|
768
|
+
case "channelPermissionRemove": {
|
|
769
|
+
if (!isActionEnabled("channels")) throw new Error("Discord channel management is disabled.");
|
|
770
|
+
const { channelId, targetId } = readChannelPermissionTarget(params);
|
|
771
|
+
await discordGuildActionRuntime.removeChannelPermissionDiscord(channelId, targetId, withOpts());
|
|
772
|
+
return jsonResult({ ok: true });
|
|
773
|
+
}
|
|
774
|
+
default: throw new Error(`Unknown action: ${action}`);
|
|
522
775
|
}
|
|
523
776
|
}
|
|
524
777
|
//#endregion
|
|
@@ -678,13 +931,12 @@ async function handleDiscordMessageManagementAction(ctx) {
|
|
|
678
931
|
ok: true,
|
|
679
932
|
results
|
|
680
933
|
});
|
|
681
|
-
const
|
|
682
|
-
const messages = resultsRecord.messages;
|
|
934
|
+
const messages = results.messages;
|
|
683
935
|
const normalizedMessages = Array.isArray(messages) ? messages.map((group) => Array.isArray(group) ? group.map((msg) => ctx.normalizeMessage(msg)) : group) : messages;
|
|
684
936
|
return jsonResult({
|
|
685
937
|
ok: true,
|
|
686
938
|
results: {
|
|
687
|
-
...
|
|
939
|
+
...results,
|
|
688
940
|
messages: normalizedMessages
|
|
689
941
|
}
|
|
690
942
|
});
|
|
@@ -966,6 +1218,14 @@ async function handleDiscordMessageSendAction(ctx) {
|
|
|
966
1218
|
const includeArchived = readBooleanParam(ctx.params, "includeArchived");
|
|
967
1219
|
const before = readStringParam(ctx.params, "before");
|
|
968
1220
|
const limit = readPositiveIntegerParam(ctx.params, "limit");
|
|
1221
|
+
if (channelId && includeArchived === true) await ctx.assertReadTargetAllowed({
|
|
1222
|
+
guildId,
|
|
1223
|
+
channelId
|
|
1224
|
+
});
|
|
1225
|
+
else await ctx.assertGuildReadTargetAllowed({
|
|
1226
|
+
guildId,
|
|
1227
|
+
channelTargetRequiredMessage: "Discord active thread lists require a wildcard channel allowlist so each read target can be authorized."
|
|
1228
|
+
});
|
|
969
1229
|
return jsonResult(normalizeDiscordThreadListActionResult({
|
|
970
1230
|
value: await discordMessagingActionRuntime.listThreadsDiscord({
|
|
971
1231
|
guildId,
|
|
@@ -1002,239 +1262,6 @@ async function handleDiscordMessageSendAction(ctx) {
|
|
|
1002
1262
|
}
|
|
1003
1263
|
}
|
|
1004
1264
|
//#endregion
|
|
1005
|
-
//#region extensions/discord/src/actions/runtime.messaging.shared.ts
|
|
1006
|
-
function hasDiscordGuildEntries(guilds) {
|
|
1007
|
-
return Boolean(guilds && Object.keys(guilds).length > 0);
|
|
1008
|
-
}
|
|
1009
|
-
function allowsAllDiscordGuildChannels(channels) {
|
|
1010
|
-
const wildcard = channels?.["*"];
|
|
1011
|
-
if (!wildcard || wildcard.enabled === false) return false;
|
|
1012
|
-
return Object.values(channels ?? {}).every((entry) => entry?.enabled !== false);
|
|
1013
|
-
}
|
|
1014
|
-
function resolveDiscordActionGuildEntry(params) {
|
|
1015
|
-
const guildId = params.guildId?.trim();
|
|
1016
|
-
if (!params.guilds) return null;
|
|
1017
|
-
if (guildId && params.guilds[guildId]) return {
|
|
1018
|
-
...params.guilds[guildId],
|
|
1019
|
-
id: guildId
|
|
1020
|
-
};
|
|
1021
|
-
if (guildId) {
|
|
1022
|
-
const byConfiguredId = Object.values(params.guilds).find((guild) => guild?.id === guildId);
|
|
1023
|
-
if (byConfiguredId) return {
|
|
1024
|
-
...byConfiguredId,
|
|
1025
|
-
id: guildId
|
|
1026
|
-
};
|
|
1027
|
-
}
|
|
1028
|
-
const guildSlug = params.guildName ? normalizeDiscordSlug(params.guildName) : "";
|
|
1029
|
-
if (guildSlug) {
|
|
1030
|
-
const bySlug = params.guilds[guildSlug] ?? Object.values(params.guilds).find((guild) => guild?.slug === guildSlug);
|
|
1031
|
-
if (bySlug) return {
|
|
1032
|
-
...bySlug,
|
|
1033
|
-
id: guildId,
|
|
1034
|
-
slug: guildSlug || bySlug.slug
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
if (params.includeWildcard === false) return null;
|
|
1038
|
-
const wildcard = params.guilds["*"];
|
|
1039
|
-
return wildcard ? {
|
|
1040
|
-
...wildcard,
|
|
1041
|
-
id: guildId
|
|
1042
|
-
} : null;
|
|
1043
|
-
}
|
|
1044
|
-
function readDiscordChannelStringField(value, ...keys) {
|
|
1045
|
-
if (!value || typeof value !== "object") return;
|
|
1046
|
-
const record = value;
|
|
1047
|
-
for (const key of keys) {
|
|
1048
|
-
const candidate = record[key];
|
|
1049
|
-
if (typeof candidate === "string" && candidate.trim()) return candidate.trim();
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
function readDiscordChannelType(value) {
|
|
1053
|
-
if (!value || typeof value !== "object") return;
|
|
1054
|
-
const type = value.type;
|
|
1055
|
-
return typeof type === "number" ? type : void 0;
|
|
1056
|
-
}
|
|
1057
|
-
function isDiscordThreadChannel(value) {
|
|
1058
|
-
const type = readDiscordChannelType(value);
|
|
1059
|
-
return type === 10 || type === 11 || type === 12;
|
|
1060
|
-
}
|
|
1061
|
-
function isDiscordReadTargetAllowedInGuild(params) {
|
|
1062
|
-
if (resolveDiscordChannelConfigWithFallback({
|
|
1063
|
-
guildInfo: params.guildInfo,
|
|
1064
|
-
channelId: params.target.channelId,
|
|
1065
|
-
channelName: params.target.channelName,
|
|
1066
|
-
channelSlug: params.target.channelSlug,
|
|
1067
|
-
parentId: params.target.parentId,
|
|
1068
|
-
parentName: params.target.parentName,
|
|
1069
|
-
parentSlug: params.target.parentSlug,
|
|
1070
|
-
scope: params.target.scope
|
|
1071
|
-
})?.allowed === false) return false;
|
|
1072
|
-
return isDiscordGroupAllowedByPolicy({
|
|
1073
|
-
groupPolicy: params.groupPolicy,
|
|
1074
|
-
guildAllowlisted: Boolean(params.guildInfo),
|
|
1075
|
-
channelAllowlistConfigured: hasDiscordGuildEntries(params.guildInfo?.channels),
|
|
1076
|
-
channelAllowed: true
|
|
1077
|
-
});
|
|
1078
|
-
}
|
|
1079
|
-
function isDiscordReadTargetExplicitlyAllowedById(params) {
|
|
1080
|
-
const channelEntry = params.guildInfo?.channels?.[params.target.channelId];
|
|
1081
|
-
if (!channelEntry || channelEntry.enabled === false) return false;
|
|
1082
|
-
return isDiscordGroupAllowedByPolicy({
|
|
1083
|
-
groupPolicy: params.groupPolicy,
|
|
1084
|
-
guildAllowlisted: Boolean(params.guildInfo),
|
|
1085
|
-
channelAllowlistConfigured: true,
|
|
1086
|
-
channelAllowed: true
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
function createDiscordMessagingActionContext(params) {
|
|
1090
|
-
const accountId = readStringParam(params.input, "accountId");
|
|
1091
|
-
const cfgOptions = { cfg: params.cfg };
|
|
1092
|
-
const accountConfig = mergeDiscordAccountConfig(params.cfg, accountId ?? resolveDefaultDiscordAccountId(params.cfg));
|
|
1093
|
-
const guilds = accountConfig.guilds;
|
|
1094
|
-
const hasGuildEntries = Object.keys(guilds ?? {}).length > 0;
|
|
1095
|
-
const { groupPolicy } = resolveOpenProviderRuntimeGroupPolicy({
|
|
1096
|
-
providerConfigPresent: params.cfg.channels?.discord !== void 0,
|
|
1097
|
-
groupPolicy: accountConfig.groupPolicy,
|
|
1098
|
-
defaultGroupPolicy: params.cfg.channels?.defaults?.groupPolicy
|
|
1099
|
-
});
|
|
1100
|
-
const withOpts = (extra) => createDiscordActionOptions({
|
|
1101
|
-
cfg: params.cfg,
|
|
1102
|
-
accountId,
|
|
1103
|
-
extra
|
|
1104
|
-
});
|
|
1105
|
-
const resolvedReactionAccountId = accountId ?? resolveDefaultDiscordAccountId(params.cfg);
|
|
1106
|
-
const reactionRuntimeOptions = resolvedReactionAccountId ? createDiscordRuntimeAccountContext({
|
|
1107
|
-
cfg: params.cfg,
|
|
1108
|
-
accountId: resolvedReactionAccountId
|
|
1109
|
-
}) : cfgOptions;
|
|
1110
|
-
const guildNameById = /* @__PURE__ */ new Map();
|
|
1111
|
-
const resolveGuildName = async (guildId) => {
|
|
1112
|
-
if (guildNameById.has(guildId)) return guildNameById.get(guildId) ?? null;
|
|
1113
|
-
try {
|
|
1114
|
-
const guildName = readDiscordChannelStringField(await discordMessagingActionRuntime.fetchGuildInfoDiscord(guildId, withOpts()), "name") ?? null;
|
|
1115
|
-
guildNameById.set(guildId, guildName);
|
|
1116
|
-
return guildName;
|
|
1117
|
-
} catch {
|
|
1118
|
-
guildNameById.set(guildId, null);
|
|
1119
|
-
return null;
|
|
1120
|
-
}
|
|
1121
|
-
};
|
|
1122
|
-
const resolveReadGuildEntry = async (guildId) => {
|
|
1123
|
-
const direct = resolveDiscordActionGuildEntry({
|
|
1124
|
-
guilds,
|
|
1125
|
-
guildId,
|
|
1126
|
-
includeWildcard: false
|
|
1127
|
-
});
|
|
1128
|
-
if (direct || !guildId) return direct;
|
|
1129
|
-
const named = resolveDiscordActionGuildEntry({
|
|
1130
|
-
guilds,
|
|
1131
|
-
guildId,
|
|
1132
|
-
guildName: await resolveGuildName(guildId) ?? void 0,
|
|
1133
|
-
includeWildcard: false
|
|
1134
|
-
});
|
|
1135
|
-
if (named) return named;
|
|
1136
|
-
return resolveDiscordActionGuildEntry({
|
|
1137
|
-
guilds,
|
|
1138
|
-
guildId
|
|
1139
|
-
});
|
|
1140
|
-
};
|
|
1141
|
-
const resolveReadTargetContext = async (channelId) => {
|
|
1142
|
-
const fallback = {
|
|
1143
|
-
channelId,
|
|
1144
|
-
channelSlug: normalizeDiscordSlug(channelId) || channelId
|
|
1145
|
-
};
|
|
1146
|
-
let channelInfo;
|
|
1147
|
-
try {
|
|
1148
|
-
channelInfo = await discordMessagingActionRuntime.fetchChannelInfoDiscord(channelId, withOpts());
|
|
1149
|
-
} catch {
|
|
1150
|
-
return fallback;
|
|
1151
|
-
}
|
|
1152
|
-
const channelName = readDiscordChannelStringField(channelInfo, "name");
|
|
1153
|
-
const target = {
|
|
1154
|
-
channelId,
|
|
1155
|
-
channelSlug: channelName ? normalizeDiscordSlug(channelName) : fallback.channelSlug
|
|
1156
|
-
};
|
|
1157
|
-
const targetGuildId = readDiscordChannelStringField(channelInfo, "guild_id", "guildId");
|
|
1158
|
-
if (targetGuildId) target.guildId = targetGuildId;
|
|
1159
|
-
if (channelName) target.channelName = channelName;
|
|
1160
|
-
if (!isDiscordThreadChannel(channelInfo)) return target;
|
|
1161
|
-
target.scope = "thread";
|
|
1162
|
-
target.parentId = readDiscordChannelStringField(channelInfo, "parent_id", "parentId");
|
|
1163
|
-
if (!target.parentId) return target;
|
|
1164
|
-
try {
|
|
1165
|
-
const parentName = readDiscordChannelStringField(await discordMessagingActionRuntime.fetchChannelInfoDiscord(target.parentId, withOpts()), "name");
|
|
1166
|
-
if (parentName) {
|
|
1167
|
-
target.parentName = parentName;
|
|
1168
|
-
target.parentSlug = normalizeDiscordSlug(parentName);
|
|
1169
|
-
}
|
|
1170
|
-
} catch {}
|
|
1171
|
-
return target;
|
|
1172
|
-
};
|
|
1173
|
-
return {
|
|
1174
|
-
action: params.action,
|
|
1175
|
-
params: params.input,
|
|
1176
|
-
isActionEnabled: params.isActionEnabled,
|
|
1177
|
-
cfg: params.cfg,
|
|
1178
|
-
options: params.options,
|
|
1179
|
-
accountId,
|
|
1180
|
-
resolveChannelId: () => discordMessagingActionRuntime.resolveDiscordChannelId(readStringParam(params.input, "channelId", { required: true })),
|
|
1181
|
-
assertReadTargetAllowed: async ({ guildId, channelId }) => {
|
|
1182
|
-
const targetChannelId = discordMessagingActionRuntime.resolveDiscordChannelId(channelId);
|
|
1183
|
-
if (!hasGuildEntries && groupPolicy !== "disabled" && groupPolicy !== "allowlist") return;
|
|
1184
|
-
const target = await resolveReadTargetContext(targetChannelId);
|
|
1185
|
-
if (guildId) {
|
|
1186
|
-
if (target.guildId && target.guildId !== guildId) throw new Error("Discord read target channel is not allowed.");
|
|
1187
|
-
if (!isDiscordReadTargetAllowedInGuild({
|
|
1188
|
-
groupPolicy,
|
|
1189
|
-
guildInfo: await resolveReadGuildEntry(guildId),
|
|
1190
|
-
target
|
|
1191
|
-
})) throw new Error("Discord read target channel is not allowed.");
|
|
1192
|
-
return;
|
|
1193
|
-
}
|
|
1194
|
-
if (target.guildId) {
|
|
1195
|
-
if (!isDiscordReadTargetAllowedInGuild({
|
|
1196
|
-
groupPolicy,
|
|
1197
|
-
guildInfo: await resolveReadGuildEntry(target.guildId),
|
|
1198
|
-
target
|
|
1199
|
-
})) throw new Error("Discord read target channel is not allowed.");
|
|
1200
|
-
return;
|
|
1201
|
-
}
|
|
1202
|
-
if (!Object.values(guilds ?? {}).some((guildInfo) => isDiscordReadTargetExplicitlyAllowedById({
|
|
1203
|
-
groupPolicy,
|
|
1204
|
-
guildInfo: guildInfo ?? null,
|
|
1205
|
-
target
|
|
1206
|
-
}))) throw new Error("Discord read target channel is not allowed.");
|
|
1207
|
-
},
|
|
1208
|
-
assertGuildReadTargetAllowed: async ({ guildId }) => {
|
|
1209
|
-
const guildInfo = await resolveReadGuildEntry(guildId);
|
|
1210
|
-
if (!isDiscordGroupAllowedByPolicy({
|
|
1211
|
-
groupPolicy,
|
|
1212
|
-
guildAllowlisted: Boolean(guildInfo),
|
|
1213
|
-
channelAllowlistConfigured: false,
|
|
1214
|
-
channelAllowed: true
|
|
1215
|
-
})) throw new Error("Discord read target channel is not allowed.");
|
|
1216
|
-
if (hasDiscordGuildEntries(guildInfo?.channels) && !allowsAllDiscordGuildChannels(guildInfo.channels)) throw new Error("Discord message search requires channelId or channelIds so each read target can be authorized.");
|
|
1217
|
-
},
|
|
1218
|
-
resolveReactionChannelId: async () => {
|
|
1219
|
-
const target = readStringParam(params.input, "channelId") ?? readStringParam(params.input, "to", { required: true });
|
|
1220
|
-
return await discordMessagingActionRuntime.resolveDiscordReactionTargetChannelId({
|
|
1221
|
-
target,
|
|
1222
|
-
cfg: params.cfg,
|
|
1223
|
-
accountId: resolvedReactionAccountId
|
|
1224
|
-
});
|
|
1225
|
-
},
|
|
1226
|
-
withOpts,
|
|
1227
|
-
withReactionRuntimeOptions: (extra) => ({
|
|
1228
|
-
...reactionRuntimeOptions ?? cfgOptions,
|
|
1229
|
-
...extra
|
|
1230
|
-
}),
|
|
1231
|
-
normalizeMessage: (message) => {
|
|
1232
|
-
if (!message || typeof message !== "object") return message;
|
|
1233
|
-
return withNormalizedTimestamp(message, message.timestamp);
|
|
1234
|
-
}
|
|
1235
|
-
};
|
|
1236
|
-
}
|
|
1237
|
-
//#endregion
|
|
1238
1265
|
//#region extensions/discord/src/actions/runtime.messaging.ts
|
|
1239
1266
|
async function handleDiscordMessagingAction(action, params, isActionEnabled, cfg, options) {
|
|
1240
1267
|
if (!cfg) throw new Error("Discord messaging actions require a resolved runtime config.");
|