openclaw/extensions/telegram/src/bot-native-commands.test-helpers.ts
scoootscooob e5bca0832f
refactor: move Telegram channel implementation to extensions/ (#45635)
* refactor: move Telegram channel implementation to extensions/telegram/src/

Move all Telegram channel code (123 files + 10 bot/ files + 8 channel plugin
files) from src/telegram/ and src/channels/plugins/*/telegram.ts to
extensions/telegram/src/. Leave thin re-export shims at original locations so
cross-cutting src/ imports continue to resolve.

- Fix all relative import paths in moved files (../X/ -> ../../../src/X/)
- Fix vi.mock paths in 60 test files
- Fix inline typeof import() expressions
- Update tsconfig.plugin-sdk.dts.json rootDir to "." for cross-directory DTS
- Update write-plugin-sdk-entry-dts.ts for new rootDir structure
- Move channel plugin files with correct path remapping

* fix: support keyed telegram send deps

* fix: sync telegram extension copies with latest main

* fix: correct import paths and remove misplaced files in telegram extension

* fix: sync outbound-adapter with main (add sendTelegramPayloadMessages) and fix delivery.test import path
2026-03-14 02:50:17 -07:00

179 lines
6.5 KiB
TypeScript

import { vi } from "vitest";
import type { OpenClawConfig } from "../../../src/config/config.js";
import type { ChannelGroupPolicy } from "../../../src/config/group-policy.js";
import type { TelegramAccountConfig } from "../../../src/config/types.js";
import type { RuntimeEnv } from "../../../src/runtime.js";
import type { MockFn } from "../../../src/test-utils/vitest-mock-fn.js";
import { registerTelegramNativeCommands } from "./bot-native-commands.js";
type RegisterTelegramNativeCommandsParams = Parameters<typeof registerTelegramNativeCommands>[0];
type GetPluginCommandSpecsFn =
typeof import("../../../src/plugins/commands.js").getPluginCommandSpecs;
type MatchPluginCommandFn = typeof import("../../../src/plugins/commands.js").matchPluginCommand;
type ExecutePluginCommandFn =
typeof import("../../../src/plugins/commands.js").executePluginCommand;
type AnyMock = MockFn<(...args: unknown[]) => unknown>;
type AnyAsyncMock = MockFn<(...args: unknown[]) => Promise<unknown>>;
type NativeCommandHarness = {
handlers: Record<string, (ctx: unknown) => Promise<void>>;
sendMessage: AnyAsyncMock;
setMyCommands: AnyAsyncMock;
log: AnyMock;
bot: {
api: {
setMyCommands: AnyAsyncMock;
sendMessage: AnyAsyncMock;
};
command: (name: string, handler: (ctx: unknown) => Promise<void>) => void;
};
};
const pluginCommandMocks = vi.hoisted(() => ({
getPluginCommandSpecs: vi.fn<GetPluginCommandSpecsFn>(() => []),
matchPluginCommand: vi.fn<MatchPluginCommandFn>(() => null),
executePluginCommand: vi.fn<ExecutePluginCommandFn>(async () => ({ text: "ok" })),
}));
export const getPluginCommandSpecs = pluginCommandMocks.getPluginCommandSpecs;
export const matchPluginCommand = pluginCommandMocks.matchPluginCommand;
export const executePluginCommand = pluginCommandMocks.executePluginCommand;
vi.mock("../../../src/plugins/commands.js", () => ({
getPluginCommandSpecs: pluginCommandMocks.getPluginCommandSpecs,
matchPluginCommand: pluginCommandMocks.matchPluginCommand,
executePluginCommand: pluginCommandMocks.executePluginCommand,
}));
const deliveryMocks = vi.hoisted(() => ({
deliverReplies: vi.fn(async () => {}),
}));
export const deliverReplies = deliveryMocks.deliverReplies;
vi.mock("./bot/delivery.js", () => ({ deliverReplies: deliveryMocks.deliverReplies }));
vi.mock("../../../src/pairing/pairing-store.js", () => ({
readChannelAllowFromStore: vi.fn(async () => []),
}));
export function createNativeCommandTestParams(
params: Partial<RegisterTelegramNativeCommandsParams> = {},
): RegisterTelegramNativeCommandsParams {
const log = vi.fn();
return {
bot:
params.bot ??
({
api: {
setMyCommands: vi.fn().mockResolvedValue(undefined),
sendMessage: vi.fn().mockResolvedValue(undefined),
},
command: vi.fn(),
} as unknown as RegisterTelegramNativeCommandsParams["bot"]),
cfg: params.cfg ?? ({} as OpenClawConfig),
runtime:
params.runtime ?? ({ log } as unknown as RegisterTelegramNativeCommandsParams["runtime"]),
accountId: params.accountId ?? "default",
telegramCfg: params.telegramCfg ?? ({} as RegisterTelegramNativeCommandsParams["telegramCfg"]),
allowFrom: params.allowFrom ?? [],
groupAllowFrom: params.groupAllowFrom ?? [],
replyToMode: params.replyToMode ?? "off",
textLimit: params.textLimit ?? 4000,
useAccessGroups: params.useAccessGroups ?? false,
nativeEnabled: params.nativeEnabled ?? true,
nativeSkillsEnabled: params.nativeSkillsEnabled ?? false,
nativeDisabledExplicit: params.nativeDisabledExplicit ?? false,
resolveGroupPolicy:
params.resolveGroupPolicy ??
(() =>
({
allowlistEnabled: false,
allowed: true,
}) as ReturnType<RegisterTelegramNativeCommandsParams["resolveGroupPolicy"]>),
resolveTelegramGroupConfig:
params.resolveTelegramGroupConfig ??
(() => ({ groupConfig: undefined, topicConfig: undefined })),
shouldSkipUpdate: params.shouldSkipUpdate ?? (() => false),
opts: params.opts ?? { token: "token" },
};
}
export function createNativeCommandsHarness(params?: {
cfg?: OpenClawConfig;
runtime?: RuntimeEnv;
telegramCfg?: TelegramAccountConfig;
allowFrom?: string[];
groupAllowFrom?: string[];
useAccessGroups?: boolean;
nativeEnabled?: boolean;
groupConfig?: Record<string, unknown>;
resolveGroupPolicy?: () => ChannelGroupPolicy;
}): NativeCommandHarness {
const handlers: Record<string, (ctx: unknown) => Promise<void>> = {};
const sendMessage: AnyAsyncMock = vi.fn(async () => undefined);
const setMyCommands: AnyAsyncMock = vi.fn(async () => undefined);
const log: AnyMock = vi.fn();
const bot: NativeCommandHarness["bot"] = {
api: {
setMyCommands,
sendMessage,
},
command: (name: string, handler: (ctx: unknown) => Promise<void>) => {
handlers[name] = handler;
},
} as const;
registerTelegramNativeCommands({
bot: bot as unknown as Parameters<typeof registerTelegramNativeCommands>[0]["bot"],
cfg: params?.cfg ?? ({} as OpenClawConfig),
runtime: params?.runtime ?? ({ log } as unknown as RuntimeEnv),
accountId: "default",
telegramCfg: params?.telegramCfg ?? ({} as TelegramAccountConfig),
allowFrom: params?.allowFrom ?? [],
groupAllowFrom: params?.groupAllowFrom ?? [],
replyToMode: "off",
textLimit: 4000,
useAccessGroups: params?.useAccessGroups ?? false,
nativeEnabled: params?.nativeEnabled ?? true,
nativeSkillsEnabled: false,
nativeDisabledExplicit: false,
resolveGroupPolicy:
params?.resolveGroupPolicy ??
(() =>
({
allowlistEnabled: false,
allowed: true,
}) as ChannelGroupPolicy),
resolveTelegramGroupConfig: () => ({
groupConfig: params?.groupConfig as undefined,
topicConfig: undefined,
}),
shouldSkipUpdate: () => false,
opts: { token: "token" },
});
return { handlers, sendMessage, setMyCommands, log, bot };
}
export function createTelegramGroupCommandContext(params?: {
senderId?: number;
username?: string;
threadId?: number;
}) {
return {
message: {
chat: { id: -100999, type: "supergroup", is_forum: true },
from: {
id: params?.senderId ?? 12345,
username: params?.username ?? "testuser",
},
message_thread_id: params?.threadId ?? 42,
message_id: 1,
date: 1700000000,
},
match: "",
};
}
export function findNotAuthorizedCalls(sendMessage: AnyAsyncMock) {
return sendMessage.mock.calls.filter(
(call) => typeof call[1] === "string" && call[1].includes("not authorized"),
);
}