@openclaw/slack 2026.5.14-beta.1 → 2026.5.16-beta.1
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-gtC-RM3r.js → action-runtime-p39JLqwf.js} +4 -4
- package/dist/action-runtime.runtime-BzrPV3EA.js +2 -0
- package/dist/{media-B-nNpS2G.js → actions-BCRbHv1Q.js} +309 -3
- package/dist/{actions.runtime-DD6hfFCA.js → actions.runtime-CpywQR3D.js} +1 -1
- package/dist/api.js +16 -16
- package/dist/{approval-handler.runtime-DeYBuIaU.js → approval-handler.runtime-DXrdRbkT.js} +3 -4
- package/dist/{blocks-render-BdLueE_v.js → blocks-render-BAVfd6r0.js} +1 -1
- package/dist/{channel-CC04F-xs.js → channel-CVSopl66.js} +23 -27
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-jzYjY634.js → channel.setup-DknBgufI.js} +3 -3
- package/dist/{client-8r7r7aZ3.js → client-C_IaJbi5.js} +20 -1
- package/dist/{config-schema-Bueih4yH.js → config-schema-CNRousxw.js} +1 -1
- package/dist/contract-api.js +4 -4
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-CuaWaGnM.js → directory-live-CZPzpQZF.js} +1 -1
- package/dist/{doctor-contract-DCkS8eNN.js → doctor-contract-B8QIWMs1.js} +1 -1
- package/dist/doctor-contract-api.js +1 -1
- package/dist/http-routes-api.js +1 -1
- package/dist/inbound-contract-test-api.js +2 -2
- package/dist/interactive-replies-api.js +1 -1
- package/dist/{message-tool-api-B_bKUmP0.js → message-tool-api-C7gc7goF.js} +1 -1
- package/dist/message-tool-api.js +1 -1
- package/dist/{monitor-B3QB1ysK.js → monitor-CdVxsuHi.js} +3 -3
- package/dist/{outbound-adapter-DsAvCwpZ.js → outbound-adapter-CHm6e-0Q.js} +4 -5
- package/dist/outbound-payload-test-api.js +1 -1
- package/dist/{outbound-payload.test-harness-DM9ZdY2f.js → outbound-payload.test-harness-C0CW7_CE.js} +2 -2
- package/dist/{pipeline.runtime-D-YJZZaI.js → pipeline.runtime-CakcaQh9.js} +119 -143
- package/dist/{plugin-routes-Dt_jh9W8.js → plugin-routes-CRnfsTTX.js} +1 -1
- package/dist/{prepare-CXI8nHbJ.js → prepare-DSRUr44d.js} +223 -85
- package/dist/{prepare.test-helpers-BhFHtbz3.js → prepare.test-helpers-CU1qB54Q.js} +1 -1
- package/dist/{probe-D1wYA05H.js → probe-FL4sUJsH.js} +2 -2
- package/dist/{provider-Ut7IF0Mn.js → provider-bKg1hkf5.js} +158 -24
- package/dist/{replies-CzfjCaLG.js → replies-Fg1T3ZzU.js} +4 -4
- package/dist/reply-blocks-BFaJ_ejG.js +134 -0
- package/dist/{resolve-channels-BiVxSLVm.js → resolve-channels-B_eKaOkE.js} +2 -2
- package/dist/{resolve-users-CcpSlYw-.js → resolve-users-BzBAJwvq.js} +2 -2
- package/dist/{room-context-D0hGOp8m.js → room-context-Cd8jFpS-.js} +2 -2
- package/dist/{runtime-api-D8wiG9BS.js → runtime-api-B5HGOzX3.js} +2 -2
- package/dist/runtime-api.js +12 -12
- package/dist/runtime-setter-api.js +1 -1
- package/dist/{scopes-BTkB8PPE.js → scopes-Bvg_ZzqZ.js} +2 -2
- package/dist/secret-contract-api.js +1 -1
- package/dist/security-contract-api.js +1 -1
- package/dist/{send-ioky2Xpy.js → send-CxXFbqN1.js} +5 -6
- package/dist/send.runtime-BHCPpSj_.js +2 -0
- package/dist/send.runtime-CDG5AgU3.js +2 -0
- package/dist/{setup-core-DgLJ7dQY.js → setup-core-B7pou7oe.js} +23 -22
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-B6w9gtds.js → setup-surface-D6LLzeRz.js} +16 -15
- package/dist/{shared-CSiHkaVO.js → shared-7Vi9j4aV.js} +7 -7
- package/dist/{slash-dispatch.runtime-DNr1EDON.js → slash-dispatch.runtime-Cg7uU92H.js} +1 -1
- package/dist/test-api.js +7 -7
- package/dist/thread-ts-As_dcNbD.js +52 -0
- package/package.json +5 -5
- package/dist/action-runtime.runtime-DbVd7_Na.js +0 -2
- package/dist/actions-Cqyj7oRr.js +0 -309
- package/dist/approval-auth-D3xf0sS6.js +0 -28
- package/dist/blocks-input-BJZ8vv03.js +0 -29
- package/dist/channel-api-BfBK89IN.js +0 -20
- package/dist/exec-approvals-BLn4Zx7V.js +0 -58
- package/dist/group-policy-utF2iWnE.js +0 -41
- package/dist/mrkdwn-18IzcEAY.js +0 -6
- package/dist/reply-blocks-DWoZrUll.js +0 -14
- package/dist/send.runtime-5Kl3Wzbf.js +0 -2
- package/dist/send.runtime-DoifekaA.js +0 -2
- package/dist/thread-ts-o-QBwB3k.js +0 -24
- /package/dist/{accounts.runtime-CkfFIisb.js → accounts.runtime-BhbEu1ZK.js} +0 -0
- /package/dist/{allow-list-T7ZDpUsF.js → allow-list-nwXs_eCP.js} +0 -0
- /package/dist/{config-api-B48Z4H47.js → config-api-CmgE_ORg.js} +0 -0
- /package/dist/{directory-config-BKKNBkCq.js → directory-config-CMvFiswf.js} +0 -0
- /package/dist/{errors-BrtayXHa.js → errors-C_sW0Zgl.js} +0 -0
- /package/dist/{interactive-replies-CawNPL-h.js → interactive-replies-BSg5hXhj.js} +0 -0
- /package/dist/{magic-string.es-BLAi6qQC.js → magic-string.es-9lw4MGoF.js} +0 -0
- /package/dist/{registry-BdfKYina.js → registry-D2cWOLZV.js} +0 -0
- /package/dist/{resolve-allowlist-common-rhfyDyWi.js → resolve-allowlist-common-DLub2I2i.js} +0 -0
- /package/dist/{runtime--VlVtTPu.js → runtime-DQxkf7k2.js} +0 -0
- /package/dist/{secret-contract-BurGIyhv.js → secret-contract-0TL3L5Kb.js} +0 -0
- /package/dist/{security-audit-DvOpSaZM.js → security-audit-BJzADAw3.js} +0 -0
- /package/dist/{slash-commands.runtime-DRkNgIQ2.js → slash-commands.runtime-bcDwsGnu.js} +0 -0
- /package/dist/{slash-plugin-commands.runtime-Dj5h8hmv.js → slash-plugin-commands.runtime-DBHGUSj2.js} +0 -0
- /package/dist/{slash-skill-commands.runtime-B-_KAk0C.js → slash-skill-commands.runtime-rrY2hXvN.js} +0 -0
- /package/dist/{streaming-compat-C6rySwiD.js → streaming-compat-eu5Rj5gj.js} +0 -0
|
@@ -2,7 +2,7 @@ import { a as resolveSlackAccount } from "./accounts-yk5K3wQU.js";
|
|
|
2
2
|
import { t as inspectSlackAccount } from "./account-inspect-BJyQLSkN.js";
|
|
3
3
|
import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
|
|
4
4
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
|
-
import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createEnvPatchedAccountSetupAdapter, createLegacyCompatChannelDmPolicy, createStandardChannelSetupStatus, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
|
|
5
|
+
import { DEFAULT_ACCOUNT_ID, createAccountScopedAllowFromSection, createAccountScopedGroupAccessSection, createAllowlistSetupWizardProxy, createEnvPatchedAccountSetupAdapter, createLegacyCompatChannelDmPolicy, createSetupTranslator, createStandardChannelSetupStatus, parseMentionOrPrefixedId, patchChannelConfigForAccount, setSetupChannelEnabled } from "openclaw/plugin-sdk/setup-runtime";
|
|
6
6
|
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
|
7
7
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
8
8
|
//#region extensions/slack/src/setup-shared.ts
|
|
@@ -113,6 +113,7 @@ function describeSlackSetupAccount(account) {
|
|
|
113
113
|
}
|
|
114
114
|
//#endregion
|
|
115
115
|
//#region extensions/slack/src/setup-core.ts
|
|
116
|
+
const t = createSetupTranslator();
|
|
116
117
|
function enableSlackAccount(cfg, accountId) {
|
|
117
118
|
return patchChannelConfigForAccount({
|
|
118
119
|
cfg,
|
|
@@ -201,10 +202,10 @@ function createSlackSetupWizardBase(handlers) {
|
|
|
201
202
|
channel: SLACK_CHANNEL,
|
|
202
203
|
status: createStandardChannelSetupStatus({
|
|
203
204
|
channelLabel: "Slack",
|
|
204
|
-
configuredLabel: "
|
|
205
|
-
unconfiguredLabel: "
|
|
206
|
-
configuredHint: "
|
|
207
|
-
unconfiguredHint: "
|
|
205
|
+
configuredLabel: t("wizard.channels.statusConfigured"),
|
|
206
|
+
unconfiguredLabel: t("wizard.channels.statusNeedsTokens"),
|
|
207
|
+
configuredHint: t("wizard.channels.statusConfigured"),
|
|
208
|
+
unconfiguredHint: t("wizard.channels.statusNeedsTokens"),
|
|
208
209
|
configuredScore: 2,
|
|
209
210
|
unconfiguredScore: 1,
|
|
210
211
|
resolveConfigured: ({ cfg, accountId }) => inspectSlackAccount({
|
|
@@ -213,7 +214,7 @@ function createSlackSetupWizardBase(handlers) {
|
|
|
213
214
|
}).configured
|
|
214
215
|
}),
|
|
215
216
|
introNote: {
|
|
216
|
-
title: "
|
|
217
|
+
title: t("wizard.slack.socketModeTokensTitle"),
|
|
217
218
|
lines: buildSlackSetupLines(),
|
|
218
219
|
shouldShow: ({ cfg, accountId }) => !isSlackSetupAccountConfigured(resolveSlackAccount({
|
|
219
220
|
cfg,
|
|
@@ -230,7 +231,7 @@ function createSlackSetupWizardBase(handlers) {
|
|
|
230
231
|
else await prompter.note(manifest, "Slack manifest JSON");
|
|
231
232
|
},
|
|
232
233
|
envShortcut: {
|
|
233
|
-
prompt: "
|
|
234
|
+
prompt: t("wizard.slack.envPrompt"),
|
|
234
235
|
preferredEnvVar: "SLACK_BOT_TOKEN",
|
|
235
236
|
isAvailable: ({ cfg, accountId }) => accountId === DEFAULT_ACCOUNT_ID && Boolean(process.env.SLACK_BOT_TOKEN?.trim()) && Boolean(process.env.SLACK_APP_TOKEN?.trim()) && !isSlackSetupAccountConfigured(resolveSlackAccount({
|
|
236
237
|
cfg,
|
|
@@ -241,34 +242,34 @@ function createSlackSetupWizardBase(handlers) {
|
|
|
241
242
|
credentials: [createSlackTokenCredential({
|
|
242
243
|
inputKey: "botToken",
|
|
243
244
|
providerHint: "slack-bot",
|
|
244
|
-
credentialLabel: "
|
|
245
|
+
credentialLabel: t("wizard.slack.botToken"),
|
|
245
246
|
preferredEnvVar: "SLACK_BOT_TOKEN",
|
|
246
|
-
keepPrompt: "
|
|
247
|
-
inputPrompt: "
|
|
247
|
+
keepPrompt: t("wizard.slack.botTokenKeep"),
|
|
248
|
+
inputPrompt: t("wizard.slack.botTokenInput")
|
|
248
249
|
}), createSlackTokenCredential({
|
|
249
250
|
inputKey: "appToken",
|
|
250
251
|
providerHint: "slack-app",
|
|
251
|
-
credentialLabel: "
|
|
252
|
+
credentialLabel: t("wizard.slack.appToken"),
|
|
252
253
|
preferredEnvVar: "SLACK_APP_TOKEN",
|
|
253
|
-
keepPrompt: "
|
|
254
|
-
inputPrompt: "
|
|
254
|
+
keepPrompt: t("wizard.slack.appTokenKeep"),
|
|
255
|
+
inputPrompt: t("wizard.slack.appTokenInput")
|
|
255
256
|
})],
|
|
256
257
|
dmPolicy: slackDmPolicy,
|
|
257
258
|
allowFrom: createAccountScopedAllowFromSection({
|
|
258
259
|
channel: SLACK_CHANNEL,
|
|
259
260
|
credentialInputKey: "botToken",
|
|
260
|
-
helpTitle: "
|
|
261
|
+
helpTitle: t("wizard.slack.allowlistTitle"),
|
|
261
262
|
helpLines: [
|
|
262
|
-
"
|
|
263
|
-
"
|
|
263
|
+
t("wizard.slack.allowlistIntro"),
|
|
264
|
+
t("wizard.slack.examples"),
|
|
264
265
|
"- U12345678",
|
|
265
266
|
"- @alice",
|
|
266
|
-
"
|
|
267
|
-
|
|
267
|
+
t("wizard.slack.multipleEntries"),
|
|
268
|
+
t("wizard.channels.docs", { link: formatDocsLink("/slack", "slack") })
|
|
268
269
|
],
|
|
269
|
-
message: "
|
|
270
|
+
message: t("wizard.slack.allowFromPrompt"),
|
|
270
271
|
placeholder: "@alice, U12345678",
|
|
271
|
-
invalidWithoutCredentialNote: "
|
|
272
|
+
invalidWithoutCredentialNote: t("wizard.slack.allowFromInvalidWithoutToken"),
|
|
272
273
|
parseId: (value) => parseMentionOrPrefixedId({
|
|
273
274
|
value,
|
|
274
275
|
mentionPattern: /^<@([A-Z0-9]+)>$/i,
|
|
@@ -280,7 +281,7 @@ function createSlackSetupWizardBase(handlers) {
|
|
|
280
281
|
}),
|
|
281
282
|
groupAccess: createAccountScopedGroupAccessSection({
|
|
282
283
|
channel: SLACK_CHANNEL,
|
|
283
|
-
label: "
|
|
284
|
+
label: t("wizard.slack.channelsLabel"),
|
|
284
285
|
placeholder: "#general, #private, C123",
|
|
285
286
|
currentPolicy: ({ cfg, accountId }) => resolveSlackAccount({
|
|
286
287
|
cfg,
|
|
@@ -302,7 +303,7 @@ function createSlackSetupWizardBase(handlers) {
|
|
|
302
303
|
if (hasSlackInteractiveRepliesConfig(cfg, accountId)) return;
|
|
303
304
|
if (options?.quickstartDefaults) return { cfg: setSlackInteractiveReplies(cfg, accountId, true) };
|
|
304
305
|
return { cfg: setSlackInteractiveReplies(cfg, accountId, await prompter.confirm({
|
|
305
|
-
message: "
|
|
306
|
+
message: t("wizard.slack.interactiveRepliesPrompt"),
|
|
306
307
|
initialValue: true
|
|
307
308
|
})) };
|
|
308
309
|
},
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as slackSetupPlugin } from "./channel.setup-
|
|
1
|
+
import { t as slackSetupPlugin } from "./channel.setup-DknBgufI.js";
|
|
2
2
|
export { slackSetupPlugin };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { a as resolveSlackAccount, i as resolveDefaultSlackAccountId, o as resolveSlackAccountAllowFrom } from "./accounts-yk5K3wQU.js";
|
|
2
|
-
import "./shared-
|
|
3
|
-
import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-
|
|
4
|
-
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-
|
|
5
|
-
import { t as resolveSlackUserAllowlist } from "./resolve-users-
|
|
2
|
+
import "./shared-7Vi9j4aV.js";
|
|
3
|
+
import { i as SLACK_CHANNEL, t as createSlackSetupWizardBase } from "./setup-core-B7pou7oe.js";
|
|
4
|
+
import { t as resolveSlackChannelAllowlist } from "./resolve-channels-B_eKaOkE.js";
|
|
5
|
+
import { t as resolveSlackUserAllowlist } from "./resolve-users-BzBAJwvq.js";
|
|
6
6
|
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
7
|
-
import { noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, promptLegacyChannelAllowFromForAccount, resolveEntriesWithOptionalToken } from "openclaw/plugin-sdk/setup-runtime";
|
|
7
|
+
import { createSetupTranslator, noteChannelLookupFailure, noteChannelLookupSummary, parseMentionOrPrefixedId, promptLegacyChannelAllowFromForAccount, resolveEntriesWithOptionalToken } from "openclaw/plugin-sdk/setup-runtime";
|
|
8
8
|
import { formatDocsLink } from "openclaw/plugin-sdk/setup-tools";
|
|
9
9
|
//#region extensions/slack/src/setup-surface.ts
|
|
10
|
+
const t = createSetupTranslator();
|
|
10
11
|
async function resolveSlackAllowFromEntries(params) {
|
|
11
12
|
return await resolveEntriesWithOptionalToken({
|
|
12
13
|
token: params.token,
|
|
@@ -46,19 +47,19 @@ async function promptSlackAllowFrom(params) {
|
|
|
46
47
|
accountId: account.accountId
|
|
47
48
|
}) ?? [],
|
|
48
49
|
resolveToken: (account) => account.userToken ?? account.botToken ?? "",
|
|
49
|
-
noteTitle: "
|
|
50
|
+
noteTitle: t("wizard.slack.allowlistTitle"),
|
|
50
51
|
noteLines: [
|
|
51
|
-
"
|
|
52
|
-
"
|
|
52
|
+
t("wizard.slack.allowlistIntro"),
|
|
53
|
+
t("wizard.slack.examples"),
|
|
53
54
|
"- U12345678",
|
|
54
55
|
"- @alice",
|
|
55
|
-
"
|
|
56
|
-
|
|
56
|
+
t("wizard.slack.multipleEntries"),
|
|
57
|
+
t("wizard.channels.docs", { link: formatDocsLink("/slack", "slack") })
|
|
57
58
|
],
|
|
58
|
-
message: "
|
|
59
|
+
message: t("wizard.slack.allowFromPrompt"),
|
|
59
60
|
placeholder: "@alice, U12345678",
|
|
60
61
|
parseId,
|
|
61
|
-
invalidWithoutTokenNote: "
|
|
62
|
+
invalidWithoutTokenNote: t("wizard.slack.allowFromInvalidWithoutToken"),
|
|
62
63
|
resolveEntries: async ({ token, entries }) => (await resolveSlackUserAllowlist({
|
|
63
64
|
token,
|
|
64
65
|
entries
|
|
@@ -94,9 +95,9 @@ async function resolveSlackGroupAllowlist(params) {
|
|
|
94
95
|
keys = [...resolvedKeys, ...unresolved.map((entry) => entry.trim()).filter(Boolean)];
|
|
95
96
|
await noteChannelLookupSummary({
|
|
96
97
|
prompter: params.prompter,
|
|
97
|
-
label: "
|
|
98
|
+
label: t("wizard.slack.channelsLabel"),
|
|
98
99
|
resolvedSections: [{
|
|
99
|
-
title: "
|
|
100
|
+
title: t("wizard.channels.resolvedTitle"),
|
|
100
101
|
values: resolvedKeys
|
|
101
102
|
}],
|
|
102
103
|
unresolved
|
|
@@ -104,7 +105,7 @@ async function resolveSlackGroupAllowlist(params) {
|
|
|
104
105
|
} catch (error) {
|
|
105
106
|
await noteChannelLookupFailure({
|
|
106
107
|
prompter: params.prompter,
|
|
107
|
-
label: "
|
|
108
|
+
label: t("wizard.slack.channelsLabel"),
|
|
108
109
|
error
|
|
109
110
|
});
|
|
110
111
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { a as resolveSlackAccount, c as resolveSlackConfigAccessorAccount, i as resolveDefaultSlackAccountId, n as listSlackAccountIds, o as resolveSlackAccountAllowFrom, s as resolveSlackAccountDmPolicy } from "./accounts-yk5K3wQU.js";
|
|
2
2
|
import { t as inspectSlackAccount } from "./account-inspect-BJyQLSkN.js";
|
|
3
|
-
import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-
|
|
4
|
-
import {
|
|
5
|
-
import { i as SLACK_CHANNEL } from "./setup-core-
|
|
6
|
-
import { t as SlackChannelConfigSchema } from "./config-schema-
|
|
7
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
8
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
3
|
+
import { n as isSlackInteractiveRepliesEnabled } from "./interactive-replies-BSg5hXhj.js";
|
|
4
|
+
import { f as getChatChannelMeta } from "./client-C_IaJbi5.js";
|
|
5
|
+
import { i as SLACK_CHANNEL } from "./setup-core-B7pou7oe.js";
|
|
6
|
+
import { t as SlackChannelConfigSchema } from "./config-schema-CNRousxw.js";
|
|
7
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-B8QIWMs1.js";
|
|
8
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-0TL3L5Kb.js";
|
|
9
9
|
import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
10
10
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
11
11
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
@@ -45,7 +45,7 @@ const collectSlackSecurityWarnings = createOpenProviderConfiguredRouteWarningCol
|
|
|
45
45
|
remediation: "Set channels.slack.groupPolicy=\"allowlist\" and configure channels.slack.channels"
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
-
const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-
|
|
48
|
+
const loadSlackSecurityAuditModule = createLazyRuntimeModule(() => import("./security-audit-BJzADAw3.js").then((n) => n.n));
|
|
49
49
|
const slackSecurityAdapter = {
|
|
50
50
|
resolveDmPolicy: resolveSlackDmPolicy,
|
|
51
51
|
collectWarnings: collectSlackSecurityWarnings,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as deliverSlackSlashReplies$1 } from "./replies-
|
|
1
|
+
import { r as deliverSlackSlashReplies$1 } from "./replies-Fg1T3ZzU.js";
|
|
2
2
|
import { resolveAgentRoute as resolveAgentRoute$1 } from "openclaw/plugin-sdk/routing";
|
|
3
3
|
import { resolveMarkdownTableMode as resolveMarkdownTableMode$1 } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
4
4
|
import { recordInboundSessionMetaSafe as recordInboundSessionMetaSafe$1, resolveConversationLabel as resolveConversationLabel$1 } from "openclaw/plugin-sdk/conversation-runtime";
|
package/dist/test-api.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as createSlackActions, t as slackPlugin } from "./channel-
|
|
2
|
-
import { n as setSlackRuntime } from "./runtime
|
|
3
|
-
import { t as sendMessageSlack } from "./send-
|
|
4
|
-
import { t as prepareSlackMessage } from "./prepare-
|
|
5
|
-
import { t as createInboundSlackTestContext } from "./prepare.test-helpers-
|
|
6
|
-
import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-
|
|
7
|
-
import { n as slackOutbound } from "./outbound-adapter-
|
|
1
|
+
import { a as createSlackActions, t as slackPlugin } from "./channel-CVSopl66.js";
|
|
2
|
+
import { n as setSlackRuntime } from "./runtime-DQxkf7k2.js";
|
|
3
|
+
import { t as sendMessageSlack } from "./send-CxXFbqN1.js";
|
|
4
|
+
import { t as prepareSlackMessage } from "./prepare-DSRUr44d.js";
|
|
5
|
+
import { t as createInboundSlackTestContext } from "./prepare.test-helpers-CU1qB54Q.js";
|
|
6
|
+
import { t as createSlackOutboundPayloadHarness } from "./outbound-payload.test-harness-C0CW7_CE.js";
|
|
7
|
+
import { n as slackOutbound } from "./outbound-adapter-CHm6e-0Q.js";
|
|
8
8
|
export { createInboundSlackTestContext, createSlackActions, createSlackOutboundPayloadHarness, prepareSlackMessage, sendMessageSlack, setSlackRuntime, slackOutbound, slackPlugin };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
//#region extensions/slack/src/truncate.ts
|
|
3
|
+
function truncateSlackText(value, max) {
|
|
4
|
+
const trimmed = value.trim();
|
|
5
|
+
if (trimmed.length <= max) return trimmed;
|
|
6
|
+
if (max <= 1) return trimmed.slice(0, max);
|
|
7
|
+
return `${trimmed.slice(0, max - 1)}…`;
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region extensions/slack/src/limits.ts
|
|
11
|
+
const SLACK_TEXT_LIMIT = 8e3;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region extensions/slack/src/blocks-input.ts
|
|
14
|
+
const SLACK_MAX_BLOCKS = 50;
|
|
15
|
+
function parseBlocksJson(raw) {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(raw);
|
|
18
|
+
} catch {
|
|
19
|
+
throw new Error("blocks must be valid JSON");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function assertBlocksArray(raw) {
|
|
23
|
+
if (!Array.isArray(raw)) throw new Error("blocks must be an array");
|
|
24
|
+
if (raw.length === 0) throw new Error("blocks must contain at least one block");
|
|
25
|
+
if (raw.length > 50) throw new Error(`blocks cannot exceed 50 items`);
|
|
26
|
+
for (const block of raw) {
|
|
27
|
+
if (!block || typeof block !== "object" || Array.isArray(block)) throw new Error("each block must be an object");
|
|
28
|
+
const type = block.type;
|
|
29
|
+
if (typeof type !== "string" || type.trim().length === 0) throw new Error("each block must include a non-empty string type");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function validateSlackBlocksArray(raw) {
|
|
33
|
+
assertBlocksArray(raw);
|
|
34
|
+
return raw;
|
|
35
|
+
}
|
|
36
|
+
function parseSlackBlocksInput(raw) {
|
|
37
|
+
if (raw == null) return;
|
|
38
|
+
return validateSlackBlocksArray(typeof raw === "string" ? parseBlocksJson(raw) : raw);
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region extensions/slack/src/thread-ts.ts
|
|
42
|
+
const SLACK_THREAD_TS_PATTERN = /^\d+\.\d+$/;
|
|
43
|
+
function normalizeSlackThreadTsCandidate(value) {
|
|
44
|
+
if (typeof value !== "string") return;
|
|
45
|
+
const normalized = normalizeOptionalString(value);
|
|
46
|
+
return normalized && SLACK_THREAD_TS_PATTERN.test(normalized) ? normalized : void 0;
|
|
47
|
+
}
|
|
48
|
+
function resolveSlackThreadTsValue(params) {
|
|
49
|
+
return normalizeSlackThreadTsCandidate(params.replyToId) ?? normalizeSlackThreadTsCandidate(params.threadId);
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { validateSlackBlocksArray as a, parseSlackBlocksInput as i, resolveSlackThreadTsValue as n, SLACK_TEXT_LIMIT as o, SLACK_MAX_BLOCKS as r, truncateSlackText as s, normalizeSlackThreadTsCandidate as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/slack",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.16-beta.1",
|
|
4
4
|
"description": "OpenClaw Slack channel plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@slack/bolt": "4.7.2",
|
|
12
12
|
"@slack/types": "2.21.1",
|
|
13
|
-
"@slack/web-api": "7.
|
|
13
|
+
"@slack/web-api": "7.16.0",
|
|
14
14
|
"https-proxy-agent": "9.0.0",
|
|
15
15
|
"typebox": "1.1.38",
|
|
16
16
|
"zod": "4.4.3"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"openclaw": "workspace:*"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"openclaw": ">=2026.5.
|
|
23
|
+
"openclaw": ">=2026.5.16-beta.1"
|
|
24
24
|
},
|
|
25
25
|
"peerDependenciesMeta": {
|
|
26
26
|
"openclaw": {
|
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
"minHostVersion": ">=2026.5.12-beta.1"
|
|
65
65
|
},
|
|
66
66
|
"compat": {
|
|
67
|
-
"pluginApi": ">=2026.5.
|
|
67
|
+
"pluginApi": ">=2026.5.16-beta.1"
|
|
68
68
|
},
|
|
69
69
|
"build": {
|
|
70
|
-
"openclawVersion": "2026.5.
|
|
70
|
+
"openclawVersion": "2026.5.16-beta.1",
|
|
71
71
|
"bundledDist": false
|
|
72
72
|
},
|
|
73
73
|
"release": {
|
package/dist/actions-Cqyj7oRr.js
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import { a as resolveSlackAccount, d as resolveSlackBotToken } from "./accounts-yk5K3wQU.js";
|
|
2
|
-
import { i as truncateSlackText, r as SLACK_TEXT_LIMIT } from "./thread-ts-o-QBwB3k.js";
|
|
3
|
-
import { a as getSlackWriteClient, r as createSlackWebClient } from "./client-8r7r7aZ3.js";
|
|
4
|
-
import { r as validateSlackBlocksArray } from "./blocks-input-BJZ8vv03.js";
|
|
5
|
-
import { c as buildSlackBlocksFallbackText, t as sendMessageSlack } from "./send-ioky2Xpy.js";
|
|
6
|
-
import { n as resolveSlackMedia } from "./media-B-nNpS2G.js";
|
|
7
|
-
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
8
|
-
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
|
9
|
-
import { z } from "zod";
|
|
10
|
-
//#region extensions/slack/src/edit-text.ts
|
|
11
|
-
function buildSlackEditTextPayload(content, blocks) {
|
|
12
|
-
const trimmedContent = content.trim();
|
|
13
|
-
if (trimmedContent) return trimmedContent;
|
|
14
|
-
if (blocks?.length) return truncateSlackText(buildSlackBlocksFallbackText(blocks), SLACK_TEXT_LIMIT);
|
|
15
|
-
return " ";
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
//#region extensions/slack/src/actions.ts
|
|
19
|
-
function resolveToken(explicit, accountId, cfg) {
|
|
20
|
-
if (explicit?.trim()) {
|
|
21
|
-
const token = resolveSlackBotToken(explicit);
|
|
22
|
-
if (token) return token;
|
|
23
|
-
}
|
|
24
|
-
if (!cfg) throw new Error("Slack actions requires a resolved runtime config. Load and resolve config at the command or gateway boundary, then pass cfg through the runtime path.");
|
|
25
|
-
const account = resolveSlackAccount({
|
|
26
|
-
cfg: requireRuntimeConfig(cfg, "Slack actions"),
|
|
27
|
-
accountId
|
|
28
|
-
});
|
|
29
|
-
const token = resolveSlackBotToken(account.botToken ?? void 0);
|
|
30
|
-
if (!token) {
|
|
31
|
-
logVerbose(`slack actions: missing bot token for account=${account.accountId} explicit=${Boolean(explicit)} source=${account.botTokenSource ?? "unknown"}`);
|
|
32
|
-
throw new Error("SLACK_BOT_TOKEN or channels.slack.botToken is required for Slack actions");
|
|
33
|
-
}
|
|
34
|
-
return token;
|
|
35
|
-
}
|
|
36
|
-
function normalizeEmoji(raw) {
|
|
37
|
-
const trimmed = raw.trim();
|
|
38
|
-
if (!trimmed) throw new Error("Emoji is required for Slack reactions");
|
|
39
|
-
return trimmed.replace(/^:+|:+$/g, "");
|
|
40
|
-
}
|
|
41
|
-
const SLACK_TIMESTAMP_RE = /^\d+(?:\.\d+)?$/;
|
|
42
|
-
const ISO_8601_TIMESTAMP_SCHEMA = z.iso.datetime({ offset: true });
|
|
43
|
-
function formatEpochSeconds(milliseconds) {
|
|
44
|
-
const seconds = milliseconds / 1e3;
|
|
45
|
-
if (Number.isInteger(seconds)) return String(seconds);
|
|
46
|
-
return seconds.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
|
|
47
|
-
}
|
|
48
|
-
function normalizeSlackReadTimestamp(raw, field) {
|
|
49
|
-
const trimmed = raw?.trim();
|
|
50
|
-
if (!trimmed) return;
|
|
51
|
-
if (SLACK_TIMESTAMP_RE.test(trimmed)) return trimmed;
|
|
52
|
-
if (!ISO_8601_TIMESTAMP_SCHEMA.safeParse(trimmed).success) throw new Error(`Invalid Slack read ${field} timestamp "${trimmed}": expected a Slack timestamp or ISO-8601 date string`);
|
|
53
|
-
const parsed = Date.parse(trimmed);
|
|
54
|
-
if (!Number.isFinite(parsed)) throw new Error(`Invalid Slack read ${field} timestamp "${trimmed}": expected a Slack timestamp or ISO-8601 date string`);
|
|
55
|
-
return formatEpochSeconds(parsed);
|
|
56
|
-
}
|
|
57
|
-
function hasSlackPlatformError(err, code) {
|
|
58
|
-
if (!err || typeof err !== "object") return false;
|
|
59
|
-
const data = err.data;
|
|
60
|
-
if (!data || typeof data !== "object") return false;
|
|
61
|
-
return data.error === code;
|
|
62
|
-
}
|
|
63
|
-
async function getClient(opts = {}, mode = "read") {
|
|
64
|
-
if (opts.client) return opts.client;
|
|
65
|
-
const token = resolveToken(opts.token, opts.accountId, opts.cfg);
|
|
66
|
-
return mode === "write" ? getSlackWriteClient(token) : createSlackWebClient(token);
|
|
67
|
-
}
|
|
68
|
-
async function resolveBotUserId(client) {
|
|
69
|
-
const auth = await client.auth.test();
|
|
70
|
-
if (!auth?.user_id) throw new Error("Failed to resolve Slack bot user id");
|
|
71
|
-
return auth.user_id;
|
|
72
|
-
}
|
|
73
|
-
async function reactSlackMessage(channelId, messageId, emoji, opts = {}) {
|
|
74
|
-
const client = await getClient(opts, "write");
|
|
75
|
-
try {
|
|
76
|
-
await client.reactions.add({
|
|
77
|
-
channel: channelId,
|
|
78
|
-
timestamp: messageId,
|
|
79
|
-
name: normalizeEmoji(emoji)
|
|
80
|
-
});
|
|
81
|
-
} catch (err) {
|
|
82
|
-
if (hasSlackPlatformError(err, "already_reacted")) return;
|
|
83
|
-
throw err;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async function removeSlackReaction(channelId, messageId, emoji, opts = {}) {
|
|
87
|
-
const client = await getClient(opts, "write");
|
|
88
|
-
try {
|
|
89
|
-
await client.reactions.remove({
|
|
90
|
-
channel: channelId,
|
|
91
|
-
timestamp: messageId,
|
|
92
|
-
name: normalizeEmoji(emoji)
|
|
93
|
-
});
|
|
94
|
-
} catch (err) {
|
|
95
|
-
if (hasSlackPlatformError(err, "no_reaction")) return;
|
|
96
|
-
throw err;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async function removeOwnSlackReactions(channelId, messageId, opts = {}) {
|
|
100
|
-
const client = await getClient(opts, "write");
|
|
101
|
-
const userId = await resolveBotUserId(client);
|
|
102
|
-
const reactions = await listSlackReactions(channelId, messageId, { client });
|
|
103
|
-
const toRemove = /* @__PURE__ */ new Set();
|
|
104
|
-
for (const reaction of reactions ?? []) {
|
|
105
|
-
const name = reaction?.name;
|
|
106
|
-
if (!name) continue;
|
|
107
|
-
if ((reaction?.users ?? []).includes(userId)) toRemove.add(name);
|
|
108
|
-
}
|
|
109
|
-
if (toRemove.size === 0) return [];
|
|
110
|
-
await Promise.all(Array.from(toRemove, (name) => removeSlackReaction(channelId, messageId, name, {
|
|
111
|
-
...opts,
|
|
112
|
-
client
|
|
113
|
-
})));
|
|
114
|
-
return Array.from(toRemove);
|
|
115
|
-
}
|
|
116
|
-
async function listSlackReactions(channelId, messageId, opts = {}) {
|
|
117
|
-
return (await (await getClient(opts)).reactions.get({
|
|
118
|
-
channel: channelId,
|
|
119
|
-
timestamp: messageId,
|
|
120
|
-
full: true
|
|
121
|
-
})).message?.reactions ?? [];
|
|
122
|
-
}
|
|
123
|
-
async function sendSlackMessage(to, content, opts) {
|
|
124
|
-
return await sendMessageSlack(to, content, {
|
|
125
|
-
accountId: opts.accountId,
|
|
126
|
-
cfg: opts.cfg,
|
|
127
|
-
token: opts.token,
|
|
128
|
-
mediaUrl: opts.mediaUrl,
|
|
129
|
-
mediaAccess: opts.mediaAccess,
|
|
130
|
-
mediaLocalRoots: opts.mediaLocalRoots,
|
|
131
|
-
mediaReadFile: opts.mediaReadFile,
|
|
132
|
-
client: opts.client,
|
|
133
|
-
threadTs: opts.threadTs,
|
|
134
|
-
replyBroadcast: opts.replyBroadcast,
|
|
135
|
-
...opts.uploadFileName ? { uploadFileName: opts.uploadFileName } : {},
|
|
136
|
-
...opts.uploadTitle ? { uploadTitle: opts.uploadTitle } : {},
|
|
137
|
-
blocks: opts.blocks
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
async function editSlackMessage(channelId, messageId, content, opts = {}) {
|
|
141
|
-
const client = await getClient(opts, "write");
|
|
142
|
-
const blocks = opts.blocks == null ? void 0 : validateSlackBlocksArray(opts.blocks);
|
|
143
|
-
await client.chat.update({
|
|
144
|
-
channel: channelId,
|
|
145
|
-
ts: messageId,
|
|
146
|
-
text: buildSlackEditTextPayload(content, blocks),
|
|
147
|
-
...blocks ? { blocks } : {}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
async function deleteSlackMessage(channelId, messageId, opts = {}) {
|
|
151
|
-
await (await getClient(opts, "write")).chat.delete({
|
|
152
|
-
channel: channelId,
|
|
153
|
-
ts: messageId
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
async function readSlackMessages(channelId, opts = {}) {
|
|
157
|
-
const exactMessageId = opts.messageId?.trim();
|
|
158
|
-
const readLimit = exactMessageId ? 1 : opts.limit;
|
|
159
|
-
const exactBounds = exactMessageId ? {
|
|
160
|
-
inclusive: true,
|
|
161
|
-
latest: exactMessageId,
|
|
162
|
-
oldest: void 0
|
|
163
|
-
} : {
|
|
164
|
-
latest: normalizeSlackReadTimestamp(opts.before, "before"),
|
|
165
|
-
oldest: normalizeSlackReadTimestamp(opts.after, "after")
|
|
166
|
-
};
|
|
167
|
-
const client = await getClient(opts);
|
|
168
|
-
if (opts.threadId) {
|
|
169
|
-
const result = await client.conversations.replies({
|
|
170
|
-
channel: channelId,
|
|
171
|
-
ts: opts.threadId,
|
|
172
|
-
limit: readLimit,
|
|
173
|
-
...exactBounds
|
|
174
|
-
});
|
|
175
|
-
return {
|
|
176
|
-
messages: (result.messages ?? []).filter((message) => {
|
|
177
|
-
if (exactMessageId) return message.ts === exactMessageId;
|
|
178
|
-
return message.ts !== opts.threadId;
|
|
179
|
-
}),
|
|
180
|
-
hasMore: exactMessageId ? false : Boolean(result.has_more)
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
const result = await client.conversations.history({
|
|
184
|
-
channel: channelId,
|
|
185
|
-
limit: readLimit,
|
|
186
|
-
...exactBounds
|
|
187
|
-
});
|
|
188
|
-
return {
|
|
189
|
-
messages: (result.messages ?? []).filter((message) => !exactMessageId || message.ts === exactMessageId),
|
|
190
|
-
hasMore: exactMessageId ? false : Boolean(result.has_more)
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
async function getSlackMemberInfo(userId, opts = {}) {
|
|
194
|
-
return await (await getClient(opts)).users.info({ user: userId });
|
|
195
|
-
}
|
|
196
|
-
async function listSlackEmojis(opts = {}) {
|
|
197
|
-
return await (await getClient(opts)).emoji.list();
|
|
198
|
-
}
|
|
199
|
-
async function pinSlackMessage(channelId, messageId, opts = {}) {
|
|
200
|
-
await (await getClient(opts, "write")).pins.add({
|
|
201
|
-
channel: channelId,
|
|
202
|
-
timestamp: messageId
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
async function unpinSlackMessage(channelId, messageId, opts = {}) {
|
|
206
|
-
await (await getClient(opts, "write")).pins.remove({
|
|
207
|
-
channel: channelId,
|
|
208
|
-
timestamp: messageId
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
async function listSlackPins(channelId, opts = {}) {
|
|
212
|
-
return (await (await getClient(opts)).pins.list({ channel: channelId })).items ?? [];
|
|
213
|
-
}
|
|
214
|
-
function normalizeSlackScopeValue(value) {
|
|
215
|
-
const trimmed = value?.trim();
|
|
216
|
-
return trimmed ? trimmed : void 0;
|
|
217
|
-
}
|
|
218
|
-
function collectSlackDirectShareChannelIds(file) {
|
|
219
|
-
const ids = /* @__PURE__ */ new Set();
|
|
220
|
-
for (const group of [
|
|
221
|
-
file.channels,
|
|
222
|
-
file.groups,
|
|
223
|
-
file.ims
|
|
224
|
-
]) {
|
|
225
|
-
if (!Array.isArray(group)) continue;
|
|
226
|
-
for (const entry of group) {
|
|
227
|
-
if (typeof entry !== "string") continue;
|
|
228
|
-
const normalized = normalizeSlackScopeValue(entry);
|
|
229
|
-
if (normalized) ids.add(normalized);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
return ids;
|
|
233
|
-
}
|
|
234
|
-
function collectSlackShareMaps(file) {
|
|
235
|
-
if (!file.shares || typeof file.shares !== "object" || Array.isArray(file.shares)) return [];
|
|
236
|
-
const shares = file.shares;
|
|
237
|
-
return [shares.public, shares.private].filter((value) => Boolean(value) && typeof value === "object" && !Array.isArray(value));
|
|
238
|
-
}
|
|
239
|
-
function collectSlackSharedChannelIds(file) {
|
|
240
|
-
const ids = /* @__PURE__ */ new Set();
|
|
241
|
-
for (const shareMap of collectSlackShareMaps(file)) for (const channelId of Object.keys(shareMap)) {
|
|
242
|
-
const normalized = normalizeSlackScopeValue(channelId);
|
|
243
|
-
if (normalized) ids.add(normalized);
|
|
244
|
-
}
|
|
245
|
-
return ids;
|
|
246
|
-
}
|
|
247
|
-
function collectSlackThreadShares(file, channelId) {
|
|
248
|
-
const matches = [];
|
|
249
|
-
for (const shareMap of collectSlackShareMaps(file)) {
|
|
250
|
-
const rawEntries = shareMap[channelId];
|
|
251
|
-
if (!Array.isArray(rawEntries)) continue;
|
|
252
|
-
for (const rawEntry of rawEntries) {
|
|
253
|
-
if (!rawEntry || typeof rawEntry !== "object" || Array.isArray(rawEntry)) continue;
|
|
254
|
-
const entry = rawEntry;
|
|
255
|
-
const ts = typeof entry.ts === "string" ? normalizeSlackScopeValue(entry.ts) : void 0;
|
|
256
|
-
const threadTs = typeof entry.thread_ts === "string" ? normalizeSlackScopeValue(entry.thread_ts) : void 0;
|
|
257
|
-
matches.push({
|
|
258
|
-
channelId,
|
|
259
|
-
ts,
|
|
260
|
-
threadTs
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return matches;
|
|
265
|
-
}
|
|
266
|
-
function hasSlackScopeMismatch(params) {
|
|
267
|
-
const channelId = normalizeSlackScopeValue(params.channelId);
|
|
268
|
-
if (!channelId) return false;
|
|
269
|
-
const threadId = normalizeSlackScopeValue(params.threadId);
|
|
270
|
-
const directIds = collectSlackDirectShareChannelIds(params.file);
|
|
271
|
-
const sharedIds = collectSlackSharedChannelIds(params.file);
|
|
272
|
-
const hasChannelEvidence = directIds.size > 0 || sharedIds.size > 0;
|
|
273
|
-
const inChannel = directIds.has(channelId) || sharedIds.has(channelId);
|
|
274
|
-
if (hasChannelEvidence && !inChannel) return true;
|
|
275
|
-
if (!threadId) return false;
|
|
276
|
-
const threadShares = collectSlackThreadShares(params.file, channelId);
|
|
277
|
-
if (threadShares.length === 0) return false;
|
|
278
|
-
const threadEvidence = threadShares.filter((entry) => entry.threadTs || entry.ts);
|
|
279
|
-
if (threadEvidence.length === 0) return false;
|
|
280
|
-
return !threadEvidence.some((entry) => entry.threadTs === threadId || entry.ts === threadId);
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Downloads a Slack file by ID and saves it to the local media store.
|
|
284
|
-
* Fetches a fresh download URL via files.info to avoid using stale private URLs.
|
|
285
|
-
* Returns null when the file cannot be found or downloaded.
|
|
286
|
-
*/
|
|
287
|
-
async function downloadSlackFile(fileId, opts) {
|
|
288
|
-
const token = resolveToken(opts.token, opts.accountId, opts.cfg);
|
|
289
|
-
const file = (await (await getClient(opts)).files.info({ file: fileId })).file;
|
|
290
|
-
if (!file?.url_private_download && !file?.url_private) return null;
|
|
291
|
-
if (hasSlackScopeMismatch({
|
|
292
|
-
file,
|
|
293
|
-
channelId: opts.channelId,
|
|
294
|
-
threadId: opts.threadId
|
|
295
|
-
})) return null;
|
|
296
|
-
return (await resolveSlackMedia({
|
|
297
|
-
files: [{
|
|
298
|
-
id: file.id,
|
|
299
|
-
name: file.name,
|
|
300
|
-
mimetype: file.mimetype,
|
|
301
|
-
url_private: file.url_private,
|
|
302
|
-
url_private_download: file.url_private_download
|
|
303
|
-
}],
|
|
304
|
-
token,
|
|
305
|
-
maxBytes: opts.maxBytes
|
|
306
|
-
}))?.[0] ?? null;
|
|
307
|
-
}
|
|
308
|
-
//#endregion
|
|
309
|
-
export { listSlackEmojis as a, pinSlackMessage as c, removeOwnSlackReactions as d, removeSlackReaction as f, buildSlackEditTextPayload as h, getSlackMemberInfo as i, reactSlackMessage as l, unpinSlackMessage as m, downloadSlackFile as n, listSlackPins as o, sendSlackMessage as p, editSlackMessage as r, listSlackReactions as s, deleteSlackMessage as t, readSlackMessages as u };
|