test: remove telegram extension dependency from reply command tests

This commit is contained in:
Shakker 2026-03-30 16:42:44 +01:00 committed by Shakker
parent 17d0be02f2
commit 4c45fc3575
1 changed files with 200 additions and 2 deletions

View File

@ -2,13 +2,20 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { telegramCommandTestPlugin } from "../../../extensions/telegram/test-support.js";
import type { ChannelPlugin } from "../../channels/plugins/types.js";
import type { OpenClawConfig } from "../../config/config.js";
import { updateSessionStore, type SessionEntry } from "../../config/sessions.js";
import { formatAllowFromLowercase } from "../../plugin-sdk/allow-from.js";
import { buildDmGroupAccountAllowlistAdapter } from "../../plugin-sdk/allowlist-config-edit.js";
import { createApproverRestrictedNativeApprovalAdapter } from "../../plugin-sdk/approval-runtime.js";
import { createScopedChannelConfigAdapter } from "../../plugin-sdk/channel-config-helpers.js";
import { setActivePluginRegistry } from "../../plugins/runtime.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../routing/session-key.js";
import { loadBundledPluginPublicSurfaceSync } from "../../test-utils/bundled-plugin-public-surface.js";
import { createTestRegistry } from "../../test-utils/channel-plugins.js";
import {
createChannelTestPluginBase,
createTestRegistry,
} from "../../test-utils/channel-plugins.js";
import { typedCases } from "../../test-utils/typed-cases.js";
import { INTERNAL_MESSAGE_CHANNEL } from "../../utils/message-channel.js";
import type { MsgContext } from "../templating.js";
@ -157,6 +164,197 @@ const { createTaskRecord, resetTaskRegistryForTests } =
let testWorkspaceDir = os.tmpdir();
type TelegramTestAccountConfig = {
enabled?: boolean;
allowFrom?: Array<string | number>;
groupAllowFrom?: Array<string | number>;
dmPolicy?: string;
groupPolicy?: string;
configWrites?: boolean;
execApprovals?: {
enabled?: boolean;
approvers?: string[];
target?: "dm" | "channel" | "both";
};
};
type TelegramTestSectionConfig = TelegramTestAccountConfig & {
accounts?: Record<string, TelegramTestAccountConfig>;
};
function listConfiguredTelegramAccountIds(cfg: OpenClawConfig): string[] {
const channel = cfg.channels?.telegram as TelegramTestSectionConfig | undefined;
const accountIds = Object.keys(channel?.accounts ?? {});
if (accountIds.length > 0) {
return accountIds;
}
if (!channel) {
return [];
}
const { accounts: _accounts, ...base } = channel;
return Object.values(base).some((value) => value !== undefined) ? [DEFAULT_ACCOUNT_ID] : [];
}
function resolveTelegramTestAccount(
cfg: OpenClawConfig,
accountId?: string | null,
): TelegramTestAccountConfig {
const resolvedAccountId = normalizeAccountId(accountId);
const channel = cfg.channels?.telegram as TelegramTestSectionConfig | undefined;
const scoped = channel?.accounts?.[resolvedAccountId];
const base = resolvedAccountId === DEFAULT_ACCOUNT_ID ? channel : undefined;
return {
...base,
...scoped,
enabled:
typeof scoped?.enabled === "boolean"
? scoped.enabled
: typeof channel?.enabled === "boolean"
? channel.enabled
: true,
};
}
function normalizeTelegramAllowFromEntries(values: Array<string | number>): string[] {
return formatAllowFromLowercase({ allowFrom: values });
}
function normalizeTelegramDirectApproverId(value: string | number): string | undefined {
const normalized = String(value).trim();
if (!normalized || normalized.startsWith("-")) {
return undefined;
}
return normalized.replace(/^(?:tg|telegram):/i, "");
}
function getTelegramExecApprovalApprovers(params: {
cfg: OpenClawConfig;
accountId?: string | null;
}): string[] {
const account = resolveTelegramTestAccount(params.cfg, params.accountId);
const explicit = account.execApprovals?.approvers;
const allowFrom = account.allowFrom;
const source = Array.isArray(explicit) ? explicit : Array.isArray(allowFrom) ? allowFrom : [];
return source
.map((entry) => normalizeTelegramDirectApproverId(entry))
.filter((entry): entry is string => Boolean(entry));
}
function isTelegramExecApprovalTargetRecipient(params: {
cfg: OpenClawConfig;
senderId?: string | null;
accountId?: string | null;
}): boolean {
const senderId = params.senderId?.trim();
const execApprovals = params.cfg.approvals?.exec;
if (
!senderId ||
execApprovals?.enabled !== true ||
(execApprovals.mode !== "targets" && execApprovals.mode !== "both")
) {
return false;
}
const accountId = params.accountId ? normalizeAccountId(params.accountId) : undefined;
return (execApprovals.targets ?? []).some((target) => {
if (target.channel?.trim().toLowerCase() !== "telegram") {
return false;
}
if (accountId && target.accountId && normalizeAccountId(target.accountId) !== accountId) {
return false;
}
const to = target.to ? normalizeTelegramDirectApproverId(target.to) : undefined;
return Boolean(to && to === senderId);
});
}
function isTelegramExecApprovalAuthorizedSender(params: {
cfg: OpenClawConfig;
accountId?: string | null;
senderId?: string | null;
}): boolean {
const senderId = params.senderId?.trim();
if (!senderId) {
return false;
}
return (
getTelegramExecApprovalApprovers(params).includes(senderId) ||
isTelegramExecApprovalTargetRecipient(params)
);
}
function isTelegramExecApprovalClientEnabled(params: {
cfg: OpenClawConfig;
accountId?: string | null;
}): boolean {
const config = resolveTelegramTestAccount(params.cfg, params.accountId).execApprovals;
return Boolean(config?.enabled && getTelegramExecApprovalApprovers(params).length > 0);
}
function resolveTelegramExecApprovalTarget(params: {
cfg: OpenClawConfig;
accountId?: string | null;
}): "dm" | "channel" | "both" {
return resolveTelegramTestAccount(params.cfg, params.accountId).execApprovals?.target ?? "dm";
}
const telegramNativeApprovalAdapter = createApproverRestrictedNativeApprovalAdapter({
channel: "telegram",
channelLabel: "Telegram",
listAccountIds: listConfiguredTelegramAccountIds,
hasApprovers: ({ cfg, accountId }) =>
getTelegramExecApprovalApprovers({ cfg, accountId }).length > 0,
isExecAuthorizedSender: isTelegramExecApprovalAuthorizedSender,
isPluginAuthorizedSender: ({ cfg, accountId, senderId }) => {
const normalizedSenderId = senderId?.trim();
return Boolean(
normalizedSenderId &&
getTelegramExecApprovalApprovers({ cfg, accountId }).includes(normalizedSenderId),
);
},
isNativeDeliveryEnabled: isTelegramExecApprovalClientEnabled,
resolveNativeDeliveryMode: resolveTelegramExecApprovalTarget,
requireMatchingTurnSourceChannel: true,
});
const telegramCommandTestPlugin: ChannelPlugin = {
...createChannelTestPluginBase({
id: "telegram",
label: "Telegram",
docsPath: "/channels/telegram",
capabilities: {
chatTypes: ["direct", "group", "channel", "thread"],
reactions: true,
threads: true,
media: true,
polls: true,
nativeCommands: true,
blockStreaming: true,
},
}),
config: createScopedChannelConfigAdapter({
sectionKey: "telegram",
listAccountIds: listConfiguredTelegramAccountIds,
resolveAccount: (cfg, accountId) => resolveTelegramTestAccount(cfg, accountId),
defaultAccountId: () => DEFAULT_ACCOUNT_ID,
clearBaseFields: [],
resolveAllowFrom: (account) => account.allowFrom,
formatAllowFrom: normalizeTelegramAllowFromEntries,
}),
auth: telegramNativeApprovalAdapter.auth,
pairing: {
idLabel: "telegramUserId",
},
allowlist: buildDmGroupAccountAllowlistAdapter({
channelId: "telegram",
resolveAccount: ({ cfg, accountId }) => resolveTelegramTestAccount(cfg, accountId),
normalize: ({ values }) => normalizeTelegramAllowFromEntries(values),
resolveDmAllowFrom: (account) => account.allowFrom,
resolveGroupAllowFrom: (account) => account.groupAllowFrom,
resolveDmPolicy: (account) => account.dmPolicy,
resolveGroupPolicy: (account) => account.groupPolicy,
}),
};
function setMinimalChannelPluginRegistryForTests(): void {
setActivePluginRegistry(
createTestRegistry([