diff --git a/src/channels/allowlists/resolve-utils.ts b/src/channels/allowlists/resolve-utils.ts index 0e302836a..640194399 100644 --- a/src/channels/allowlists/resolve-utils.ts +++ b/src/channels/allowlists/resolve-utils.ts @@ -1,5 +1,11 @@ import type { RuntimeEnv } from "../../runtime.js"; +export type AllowlistUserResolutionLike = { + input: string; + resolved: boolean; + id?: string; +}; + export function mergeAllowlist(params: { existing?: Array; additions: string[]; @@ -27,6 +33,36 @@ export function mergeAllowlist(params: { return merged; } +export function buildAllowlistResolutionSummary( + resolvedUsers: T[], +): { + resolvedMap: Map; + mapping: string[]; + unresolved: string[]; +} { + const resolvedMap = new Map(resolvedUsers.map((entry) => [entry.input, entry])); + const mapping = resolvedUsers + .filter((entry) => entry.resolved && entry.id) + .map((entry) => `${entry.input}→${entry.id}`); + const unresolved = resolvedUsers.filter((entry) => !entry.resolved).map((entry) => entry.input); + return { resolvedMap, mapping, unresolved }; +} + +export function resolveAllowlistIdAdditions(params: { + existing: Array; + resolvedMap: Map; +}): string[] { + const additions: string[] = []; + for (const entry of params.existing) { + const trimmed = String(entry).trim(); + const resolved = params.resolvedMap.get(trimmed); + if (resolved?.resolved && resolved.id) { + additions.push(resolved.id); + } + } + return additions; +} + export function summarizeMapping( label: string, mapping: string[], diff --git a/src/discord/monitor/provider.ts b/src/discord/monitor/provider.ts index 62c2ba19f..6624ff709 100644 --- a/src/discord/monitor/provider.ts +++ b/src/discord/monitor/provider.ts @@ -7,7 +7,12 @@ import type { OpenClawConfig, ReplyToMode } from "../../config/config.js"; import { resolveTextChunkLimit } from "../../auto-reply/chunk.js"; import { listNativeCommandSpecsForConfig } from "../../auto-reply/commands-registry.js"; import { listSkillCommandsForAgents } from "../../auto-reply/skill-commands.js"; -import { mergeAllowlist, summarizeMapping } from "../../channels/allowlists/resolve-utils.js"; +import { + buildAllowlistResolutionSummary, + mergeAllowlist, + resolveAllowlistIdAdditions, + summarizeMapping, +} from "../../channels/allowlists/resolve-utils.js"; import { isNativeCommandsExplicitlyDisabled, resolveNativeCommandsEnabled, @@ -331,13 +336,8 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) { token, entries: Array.from(userEntries), }); - const resolvedMap = new Map(resolvedUsers.map((entry) => [entry.input, entry])); - const mapping = resolvedUsers - .filter((entry) => entry.resolved && entry.id) - .map((entry) => `${entry.input}→${entry.id}`); - const unresolved = resolvedUsers - .filter((entry) => !entry.resolved) - .map((entry) => entry.input); + const { resolvedMap, mapping, unresolved } = + buildAllowlistResolutionSummary(resolvedUsers); const nextGuilds = { ...guildEntries }; for (const [guildKey, guildConfig] of Object.entries(guildEntries ?? {})) { @@ -347,14 +347,7 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) { const nextGuild = { ...guildConfig } as Record; const users = (guildConfig as { users?: Array }).users; if (Array.isArray(users) && users.length > 0) { - const additions: string[] = []; - for (const entry of users) { - const trimmed = String(entry).trim(); - const resolved = resolvedMap.get(trimmed); - if (resolved?.resolved && resolved.id) { - additions.push(resolved.id); - } - } + const additions = resolveAllowlistIdAdditions({ existing: users, resolvedMap }); nextGuild.users = mergeAllowlist({ existing: users, additions }); } const channels = (guildConfig as { channels?: Record }).channels ?? {}; @@ -368,14 +361,10 @@ export async function monitorDiscordProvider(opts: MonitorDiscordOpts = {}) { if (!Array.isArray(channelUsers) || channelUsers.length === 0) { continue; } - const additions: string[] = []; - for (const entry of channelUsers) { - const trimmed = String(entry).trim(); - const resolved = resolvedMap.get(trimmed); - if (resolved?.resolved && resolved.id) { - additions.push(resolved.id); - } - } + const additions = resolveAllowlistIdAdditions({ + existing: channelUsers, + resolvedMap, + }); nextChannels[channelKey] = { ...channelConfig, users: mergeAllowlist({ existing: channelUsers, additions }), diff --git a/src/slack/monitor/provider.ts b/src/slack/monitor/provider.ts index 275b9e37c..454bf89df 100644 --- a/src/slack/monitor/provider.ts +++ b/src/slack/monitor/provider.ts @@ -4,7 +4,12 @@ import type { SessionScope } from "../../config/sessions.js"; import type { MonitorSlackOpts } from "./types.js"; import { resolveTextChunkLimit } from "../../auto-reply/chunk.js"; import { DEFAULT_GROUP_HISTORY_LIMIT } from "../../auto-reply/reply/history.js"; -import { mergeAllowlist, summarizeMapping } from "../../channels/allowlists/resolve-utils.js"; +import { + buildAllowlistResolutionSummary, + mergeAllowlist, + resolveAllowlistIdAdditions, + summarizeMapping, +} from "../../channels/allowlists/resolve-utils.js"; import { loadConfig } from "../../config/config.js"; import { warn } from "../../globals.js"; import { installRequestBodyLimitGuard } from "../../infra/http-body.js"; @@ -322,13 +327,8 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) { token: resolveToken, entries: Array.from(userEntries), }); - const resolvedMap = new Map(resolvedUsers.map((entry) => [entry.input, entry])); - const mapping = resolvedUsers - .filter((entry) => entry.resolved && entry.id) - .map((entry) => `${entry.input}→${entry.id}`); - const unresolved = resolvedUsers - .filter((entry) => !entry.resolved) - .map((entry) => entry.input); + const { resolvedMap, mapping, unresolved } = + buildAllowlistResolutionSummary(resolvedUsers); const nextChannels = { ...channelsConfig }; for (const [channelKey, channelConfig] of Object.entries(channelsConfig)) { @@ -339,14 +339,10 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) { if (!Array.isArray(channelUsers) || channelUsers.length === 0) { continue; } - const additions: string[] = []; - for (const entry of channelUsers) { - const trimmed = String(entry).trim(); - const resolved = resolvedMap.get(trimmed); - if (resolved?.resolved && resolved.id) { - additions.push(resolved.id); - } - } + const additions = resolveAllowlistIdAdditions({ + existing: channelUsers, + resolvedMap, + }); nextChannels[channelKey] = { ...channelConfig, users: mergeAllowlist({ existing: channelUsers, additions }),