mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 03:30:30 +00:00
fix: stabilize gate and extension boundary checks
This commit is contained in:
39
extensions/telegram/src/action-threading.test.ts
Normal file
39
extensions/telegram/src/action-threading.test.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { ChannelThreadingToolContext } from "openclaw/plugin-sdk/channel-contract";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveTelegramAutoThreadId } from "./action-threading.js";
|
||||
|
||||
function createToolContext(
|
||||
overrides: Partial<ChannelThreadingToolContext> = {},
|
||||
): ChannelThreadingToolContext {
|
||||
return {
|
||||
currentChannelId: "tg:group:-100123",
|
||||
currentThreadTs: "thread-1",
|
||||
replyToMode: "all",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("resolveTelegramAutoThreadId", () => {
|
||||
it("matches chats across Telegram target formats", () => {
|
||||
expect(
|
||||
resolveTelegramAutoThreadId({
|
||||
to: "telegram:group:-100123:topic:77",
|
||||
toolContext: createToolContext(),
|
||||
}),
|
||||
).toBe("thread-1");
|
||||
|
||||
expect(
|
||||
resolveTelegramAutoThreadId({
|
||||
to: "-100999:77",
|
||||
toolContext: createToolContext(),
|
||||
}),
|
||||
).toBeUndefined();
|
||||
|
||||
expect(
|
||||
resolveTelegramAutoThreadId({
|
||||
to: "-100123",
|
||||
toolContext: createToolContext({ currentChannelId: undefined }),
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -295,6 +295,67 @@ describe("registerTelegramNativeCommands", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards topic-scoped binding context to Telegram plugin commands", async () => {
|
||||
const commandHandlers = new Map<string, (ctx: unknown) => Promise<void>>();
|
||||
|
||||
pluginCommandMocks.getPluginCommandSpecs.mockReturnValue([
|
||||
{
|
||||
name: "plug",
|
||||
description: "Plugin command",
|
||||
},
|
||||
] as never);
|
||||
pluginCommandMocks.matchPluginCommand.mockReturnValue({
|
||||
command: { key: "plug", requireAuth: false },
|
||||
args: undefined,
|
||||
} as never);
|
||||
pluginCommandMocks.executePluginCommand.mockResolvedValue({ text: "ok" } as never);
|
||||
|
||||
registerTelegramNativeCommands({
|
||||
...createNativeCommandTestParams(
|
||||
{},
|
||||
{
|
||||
bot: {
|
||||
api: {
|
||||
setMyCommands: vi.fn().mockResolvedValue(undefined),
|
||||
sendMessage: vi.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
command: vi.fn((name: string, cb: (ctx: unknown) => Promise<void>) => {
|
||||
commandHandlers.set(name, cb);
|
||||
}),
|
||||
} as unknown as Parameters<typeof registerTelegramNativeCommands>[0]["bot"],
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
const handler = commandHandlers.get("plug");
|
||||
expect(handler).toBeTruthy();
|
||||
await handler?.({
|
||||
match: "",
|
||||
message: {
|
||||
message_id: 2,
|
||||
date: Math.floor(Date.now() / 1000),
|
||||
chat: {
|
||||
id: -1001234567890,
|
||||
type: "supergroup",
|
||||
title: "Forum Group",
|
||||
is_forum: true,
|
||||
},
|
||||
message_thread_id: 77,
|
||||
from: { id: 200, username: "bob" },
|
||||
},
|
||||
});
|
||||
|
||||
expect(pluginCommandMocks.executePluginCommand).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
channel: "telegram",
|
||||
accountId: "default",
|
||||
from: "telegram:group:-1001234567890:topic:77",
|
||||
to: "telegram:-1001234567890",
|
||||
messageThreadId: 77,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("treats Telegram forum #General commands as topic 1 when Telegram omits topic metadata", async () => {
|
||||
const commandHandlers = new Map<string, (ctx: unknown) => Promise<void>>();
|
||||
const getChat = vi.fn(async () => ({ id: -1001234567890, type: "supergroup", is_forum: true }));
|
||||
@@ -348,9 +409,58 @@ describe("registerTelegramNativeCommands", () => {
|
||||
expect(getChat).toHaveBeenCalledWith(-1001234567890);
|
||||
expect(pluginCommandMocks.executePluginCommand).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
accountId: "default",
|
||||
from: "telegram:group:-1001234567890:topic:1",
|
||||
to: "telegram:-1001234567890",
|
||||
messageThreadId: 1,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards direct-message binding context to Telegram plugin commands", async () => {
|
||||
const commandHandlers = new Map<string, (ctx: unknown) => Promise<void>>();
|
||||
|
||||
pluginCommandMocks.getPluginCommandSpecs.mockReturnValue([
|
||||
{
|
||||
name: "plug",
|
||||
description: "Plugin command",
|
||||
},
|
||||
] as never);
|
||||
pluginCommandMocks.matchPluginCommand.mockReturnValue({
|
||||
command: { key: "plug", requireAuth: false },
|
||||
args: undefined,
|
||||
} as never);
|
||||
pluginCommandMocks.executePluginCommand.mockResolvedValue({ text: "ok" } as never);
|
||||
|
||||
registerTelegramNativeCommands({
|
||||
...createNativeCommandTestParams(
|
||||
{},
|
||||
{
|
||||
bot: {
|
||||
api: {
|
||||
setMyCommands: vi.fn().mockResolvedValue(undefined),
|
||||
sendMessage: vi.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
command: vi.fn((name: string, cb: (ctx: unknown) => Promise<void>) => {
|
||||
commandHandlers.set(name, cb);
|
||||
}),
|
||||
} as unknown as Parameters<typeof registerTelegramNativeCommands>[0]["bot"],
|
||||
},
|
||||
),
|
||||
});
|
||||
|
||||
const handler = commandHandlers.get("plug");
|
||||
expect(handler).toBeTruthy();
|
||||
await handler?.(createPrivateCommandContext({ chatId: 100, userId: 200 }));
|
||||
|
||||
expect(pluginCommandMocks.executePluginCommand).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
channel: "telegram",
|
||||
accountId: "default",
|
||||
from: "telegram:100",
|
||||
to: "telegram:100",
|
||||
messageThreadId: undefined,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user