Merge pull request #821 from gumadeiras/fix-bindings-telegram-webhook
Telegram: fix webhook multi-account routing (respect bindings.accountId)
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
- Onboarding/Configure: refuse to proceed with invalid configs; run `clawdbot doctor` first to avoid wiping custom fields. (#764 — thanks @mukhtharcm)
|
||||
- Anthropic: merge consecutive user turns (preserve newest metadata) before validation to avoid “Incorrect role information” errors. (#804 — thanks @ThomsenDrake)
|
||||
- Discord/Slack: centralize reply-thread planning so auto-thread replies stay in the created thread without parent reply refs.
|
||||
- Telegram: respect account-scoped bindings when webhook mode is enabled. (#821 — thanks @gumadeiras)
|
||||
- Update: run `clawdbot doctor --non-interactive` during updates to avoid TTY hangs. (#781 — thanks @ronyrus)
|
||||
- Browser tools: treat explicit `maxChars: 0` as unlimited while keeping the default limit only when omitted. (#796 — thanks @gabriel-trigo)
|
||||
- Tools: allow Claude/Gemini tool param aliases (`file_path`, `old_string`, `new_string`) while enforcing required params at runtime. (#793 — thanks @hsrvc)
|
||||
|
||||
@@ -887,6 +887,53 @@ describe("createTelegramBot", () => {
|
||||
expect(replySpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("routes DMs by telegram accountId binding", async () => {
|
||||
onSpy.mockReset();
|
||||
const replySpy = replyModule.__replySpy as unknown as ReturnType<
|
||||
typeof vi.fn
|
||||
>;
|
||||
replySpy.mockReset();
|
||||
|
||||
loadConfig.mockReturnValue({
|
||||
telegram: {
|
||||
accounts: {
|
||||
opie: {
|
||||
botToken: "tok-opie",
|
||||
dmPolicy: "open",
|
||||
},
|
||||
},
|
||||
},
|
||||
bindings: [
|
||||
{
|
||||
agentId: "opie",
|
||||
match: { provider: "telegram", accountId: "opie" },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
createTelegramBot({ token: "tok", accountId: "opie" });
|
||||
const handler = getOnHandler("message") as (
|
||||
ctx: Record<string, unknown>,
|
||||
) => Promise<void>;
|
||||
|
||||
await handler({
|
||||
message: {
|
||||
chat: { id: 123, type: "private" },
|
||||
from: { id: 999, username: "testuser" },
|
||||
text: "hello",
|
||||
date: 1736380800,
|
||||
message_id: 42,
|
||||
},
|
||||
me: { username: "clawdbot_bot" },
|
||||
getFile: async () => ({ download: async () => new Uint8Array() }),
|
||||
});
|
||||
|
||||
expect(replySpy).toHaveBeenCalledTimes(1);
|
||||
const payload = replySpy.mock.calls[0][0];
|
||||
expect(payload.AccountId).toBe("opie");
|
||||
expect(payload.SessionKey).toBe("agent:opie:main");
|
||||
});
|
||||
|
||||
it("allows per-group requireMention override", async () => {
|
||||
onSpy.mockReset();
|
||||
const replySpy = replyModule.__replySpy as unknown as ReturnType<
|
||||
|
||||
@@ -96,6 +96,8 @@ export async function monitorTelegramProvider(opts: MonitorTelegramOpts = {}) {
|
||||
if (opts.useWebhook) {
|
||||
await startTelegramWebhook({
|
||||
token,
|
||||
accountId: account.accountId,
|
||||
config: cfg,
|
||||
path: opts.webhookPath,
|
||||
port: opts.webhookPort,
|
||||
secret: opts.webhookSecret,
|
||||
|
||||
@@ -14,25 +14,37 @@ const handlerSpy = vi.fn(
|
||||
const setWebhookSpy = vi.fn();
|
||||
const stopSpy = vi.fn();
|
||||
|
||||
const createTelegramBotSpy = vi.fn(() => ({
|
||||
api: { setWebhook: setWebhookSpy },
|
||||
stop: stopSpy,
|
||||
}));
|
||||
|
||||
vi.mock("grammy", () => ({
|
||||
webhookCallback: () => handlerSpy,
|
||||
}));
|
||||
|
||||
vi.mock("./bot.js", () => ({
|
||||
createTelegramBot: () => ({
|
||||
api: { setWebhook: setWebhookSpy },
|
||||
stop: stopSpy,
|
||||
}),
|
||||
createTelegramBot: (...args: unknown[]) => createTelegramBotSpy(...args),
|
||||
}));
|
||||
|
||||
describe("startTelegramWebhook", () => {
|
||||
it("starts server, registers webhook, and serves health", async () => {
|
||||
createTelegramBotSpy.mockClear();
|
||||
const abort = new AbortController();
|
||||
const cfg = { bindings: [] };
|
||||
const { server } = await startTelegramWebhook({
|
||||
token: "tok",
|
||||
accountId: "opie",
|
||||
config: cfg,
|
||||
port: 0, // random free port
|
||||
abortSignal: abort.signal,
|
||||
});
|
||||
expect(createTelegramBotSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
accountId: "opie",
|
||||
config: expect.objectContaining({ bindings: [] }),
|
||||
}),
|
||||
);
|
||||
const address = server.address();
|
||||
if (!address || typeof address === "string") throw new Error("no address");
|
||||
const url = `http://127.0.0.1:${address.port}`;
|
||||
@@ -46,13 +58,23 @@ describe("startTelegramWebhook", () => {
|
||||
|
||||
it("invokes webhook handler on matching path", async () => {
|
||||
handlerSpy.mockClear();
|
||||
createTelegramBotSpy.mockClear();
|
||||
const abort = new AbortController();
|
||||
const cfg = { bindings: [] };
|
||||
const { server } = await startTelegramWebhook({
|
||||
token: "tok",
|
||||
accountId: "opie",
|
||||
config: cfg,
|
||||
port: 0,
|
||||
abortSignal: abort.signal,
|
||||
path: "/hook",
|
||||
});
|
||||
expect(createTelegramBotSpy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
accountId: "opie",
|
||||
config: expect.objectContaining({ bindings: [] }),
|
||||
}),
|
||||
);
|
||||
const addr = server.address();
|
||||
if (!addr || typeof addr === "string") throw new Error("no addr");
|
||||
await fetch(`http://127.0.0.1:${addr.port}/hook`, { method: "POST" });
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createServer } from "node:http";
|
||||
|
||||
import { webhookCallback } from "grammy";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
@@ -8,6 +9,8 @@ import { createTelegramBot } from "./bot.js";
|
||||
|
||||
export async function startTelegramWebhook(opts: {
|
||||
token: string;
|
||||
accountId?: string;
|
||||
config?: ClawdbotConfig;
|
||||
path?: string;
|
||||
port?: number;
|
||||
host?: string;
|
||||
@@ -27,6 +30,8 @@ export async function startTelegramWebhook(opts: {
|
||||
token: opts.token,
|
||||
runtime,
|
||||
proxyFetch: opts.fetch,
|
||||
config: opts.config,
|
||||
accountId: opts.accountId,
|
||||
});
|
||||
const handler = webhookCallback(bot, "http", {
|
||||
secretToken: opts.secret,
|
||||
|
||||
Reference in New Issue
Block a user