mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-25 08:52:12 +00:00
* 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
115 lines
3.9 KiB
TypeScript
115 lines
3.9 KiB
TypeScript
import { afterEach, beforeAll, beforeEach, expect, vi, type Mock } from "vitest";
|
|
import * as ssrf from "../../../src/infra/net/ssrf.js";
|
|
import { onSpy, sendChatActionSpy } from "./bot.media.e2e-harness.js";
|
|
|
|
type StickerSpy = Mock<(...args: unknown[]) => unknown>;
|
|
|
|
export const cacheStickerSpy: StickerSpy = vi.fn();
|
|
export const getCachedStickerSpy: StickerSpy = vi.fn();
|
|
export const describeStickerImageSpy: StickerSpy = vi.fn();
|
|
|
|
const resolvePinnedHostname = ssrf.resolvePinnedHostname;
|
|
const lookupMock = vi.fn();
|
|
let resolvePinnedHostnameSpy: ReturnType<typeof vi.spyOn> = null;
|
|
|
|
export const TELEGRAM_TEST_TIMINGS = {
|
|
mediaGroupFlushMs: 20,
|
|
textFragmentGapMs: 30,
|
|
} as const;
|
|
|
|
const TELEGRAM_BOT_IMPORT_TIMEOUT_MS = process.platform === "win32" ? 180_000 : 150_000;
|
|
|
|
let createTelegramBotRef: typeof import("./bot.js").createTelegramBot;
|
|
let replySpyRef: ReturnType<typeof vi.fn>;
|
|
|
|
export async function createBotHandler(): Promise<{
|
|
handler: (ctx: Record<string, unknown>) => Promise<void>;
|
|
replySpy: ReturnType<typeof vi.fn>;
|
|
runtimeError: ReturnType<typeof vi.fn>;
|
|
}> {
|
|
return createBotHandlerWithOptions({});
|
|
}
|
|
|
|
export async function createBotHandlerWithOptions(options: {
|
|
proxyFetch?: typeof fetch;
|
|
runtimeLog?: ReturnType<typeof vi.fn>;
|
|
runtimeError?: ReturnType<typeof vi.fn>;
|
|
}): Promise<{
|
|
handler: (ctx: Record<string, unknown>) => Promise<void>;
|
|
replySpy: ReturnType<typeof vi.fn>;
|
|
runtimeError: ReturnType<typeof vi.fn>;
|
|
}> {
|
|
onSpy.mockClear();
|
|
replySpyRef.mockClear();
|
|
sendChatActionSpy.mockClear();
|
|
|
|
const runtimeError = options.runtimeError ?? vi.fn();
|
|
const runtimeLog = options.runtimeLog ?? vi.fn();
|
|
createTelegramBotRef({
|
|
token: "tok",
|
|
testTimings: TELEGRAM_TEST_TIMINGS,
|
|
...(options.proxyFetch ? { proxyFetch: options.proxyFetch } : {}),
|
|
runtime: {
|
|
log: runtimeLog as (...data: unknown[]) => void,
|
|
error: runtimeError as (...data: unknown[]) => void,
|
|
exit: () => {
|
|
throw new Error("exit");
|
|
},
|
|
},
|
|
});
|
|
const handler = onSpy.mock.calls.find((call) => call[0] === "message")?.[1] as (
|
|
ctx: Record<string, unknown>,
|
|
) => Promise<void>;
|
|
expect(handler).toBeDefined();
|
|
return { handler, replySpy: replySpyRef, runtimeError };
|
|
}
|
|
|
|
export function mockTelegramFileDownload(params: {
|
|
contentType: string;
|
|
bytes: Uint8Array;
|
|
}): ReturnType<typeof vi.spyOn> {
|
|
return vi.spyOn(globalThis, "fetch").mockResolvedValueOnce({
|
|
ok: true,
|
|
status: 200,
|
|
statusText: "OK",
|
|
headers: { get: () => params.contentType },
|
|
arrayBuffer: async () => params.bytes.buffer,
|
|
} as unknown as Response);
|
|
}
|
|
|
|
export function mockTelegramPngDownload(): ReturnType<typeof vi.spyOn> {
|
|
return vi.spyOn(globalThis, "fetch").mockResolvedValue({
|
|
ok: true,
|
|
status: 200,
|
|
statusText: "OK",
|
|
headers: { get: () => "image/png" },
|
|
arrayBuffer: async () => new Uint8Array([0x89, 0x50, 0x4e, 0x47]).buffer,
|
|
} as unknown as Response);
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.useRealTimers();
|
|
lookupMock.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]);
|
|
resolvePinnedHostnameSpy = vi
|
|
.spyOn(ssrf, "resolvePinnedHostname")
|
|
.mockImplementation((hostname) => resolvePinnedHostname(hostname, lookupMock));
|
|
});
|
|
|
|
afterEach(() => {
|
|
lookupMock.mockClear();
|
|
resolvePinnedHostnameSpy?.mockRestore();
|
|
resolvePinnedHostnameSpy = null;
|
|
});
|
|
|
|
beforeAll(async () => {
|
|
({ createTelegramBot: createTelegramBotRef } = await import("./bot.js"));
|
|
const replyModule = await import("../../../src/auto-reply/reply.js");
|
|
replySpyRef = (replyModule as unknown as { __replySpy: ReturnType<typeof vi.fn> }).__replySpy;
|
|
}, TELEGRAM_BOT_IMPORT_TIMEOUT_MS);
|
|
|
|
vi.mock("./sticker-cache.js", () => ({
|
|
cacheSticker: (...args: unknown[]) => cacheStickerSpy(...args),
|
|
getCachedSticker: (...args: unknown[]) => getCachedStickerSpy(...args),
|
|
describeStickerImage: (...args: unknown[]) => describeStickerImageSpy(...args),
|
|
}));
|