import type { AllowlistMatch, ChannelGroupContext, GroupToolPolicyConfig, } from "openclaw/plugin-sdk"; import { normalizeFeishuTarget } from "./targets.js"; import type { FeishuConfig, FeishuGroupConfig } from "./types.js"; export type FeishuAllowlistMatch = AllowlistMatch<"wildcard" | "id">; function normalizeFeishuAllowEntry(raw: string): string { const trimmed = raw.trim(); if (!trimmed) { return ""; } if (trimmed === "*") { return "*"; } const withoutProviderPrefix = trimmed.replace(/^feishu:/i, ""); const normalized = normalizeFeishuTarget(withoutProviderPrefix) ?? withoutProviderPrefix; return normalized.trim().toLowerCase(); } export function resolveFeishuAllowlistMatch(params: { allowFrom: Array; senderId: string; senderIds?: Array; senderName?: string | null; }): FeishuAllowlistMatch { const allowFrom = params.allowFrom .map((entry) => normalizeFeishuAllowEntry(String(entry))) .filter(Boolean); if (allowFrom.length === 0) { return { allowed: false }; } if (allowFrom.includes("*")) { return { allowed: true, matchKey: "*", matchSource: "wildcard" }; } // Feishu allowlists are ID-based; mutable display names must never grant access. const senderCandidates = [params.senderId, ...(params.senderIds ?? [])] .map((entry) => normalizeFeishuAllowEntry(String(entry ?? ""))) .filter(Boolean); for (const senderId of senderCandidates) { if (allowFrom.includes(senderId)) { return { allowed: true, matchKey: senderId, matchSource: "id" }; } } return { allowed: false }; } export function resolveFeishuGroupConfig(params: { cfg?: FeishuConfig; groupId?: string | null; }): FeishuGroupConfig | undefined { const groups = params.cfg?.groups ?? {}; const groupId = params.groupId?.trim(); if (!groupId) { return undefined; } const direct = groups[groupId]; if (direct) { return direct; } const lowered = groupId.toLowerCase(); const matchKey = Object.keys(groups).find((key) => key.toLowerCase() === lowered); return matchKey ? groups[matchKey] : undefined; } export function resolveFeishuGroupToolPolicy( params: ChannelGroupContext, ): GroupToolPolicyConfig | undefined { const cfg = params.cfg.channels?.feishu as FeishuConfig | undefined; if (!cfg) { return undefined; } const groupConfig = resolveFeishuGroupConfig({ cfg, groupId: params.groupId, }); return groupConfig?.tools; } export function isFeishuGroupAllowed(params: { groupPolicy: "open" | "allowlist" | "disabled"; allowFrom: Array; senderId: string; senderIds?: Array; senderName?: string | null; }): boolean { const { groupPolicy } = params; if (groupPolicy === "disabled") { return false; } if (groupPolicy === "open") { return true; } return resolveFeishuAllowlistMatch(params).allowed; } export function resolveFeishuReplyPolicy(params: { isDirectMessage: boolean; globalConfig?: FeishuConfig; groupConfig?: FeishuGroupConfig; }): { requireMention: boolean } { if (params.isDirectMessage) { return { requireMention: false }; } const requireMention = params.groupConfig?.requireMention ?? params.globalConfig?.requireMention ?? true; return { requireMention }; }