mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-05 17:40:24 +00:00
fix(telegram): restore thread_id=1 handling for DMs (regression from 19b8416a8) (openclaw#10942) thanks @garnetlyx
Verified: - pnpm install --frozen-lockfile - pnpm build - pnpm test:macmini Co-authored-by: garnetlyx <12513503+garnetlyx@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
@@ -169,7 +169,7 @@ describe("deliverReplies", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps message_thread_id=1 when allowed", async () => {
|
||||
it("does not include message_thread_id for DMs (threads don't exist in private chats)", async () => {
|
||||
const runtime = { error: vi.fn(), log: vi.fn() };
|
||||
const sendMessage = vi.fn().mockResolvedValue({
|
||||
message_id: 4,
|
||||
@@ -191,7 +191,7 @@ describe("deliverReplies", () => {
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
"123",
|
||||
expect.any(String),
|
||||
expect.objectContaining({
|
||||
expect.not.objectContaining({
|
||||
message_thread_id: 1,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -43,9 +43,24 @@ describe("buildTelegramThreadParams", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps thread id=1 for dm threads", () => {
|
||||
expect(buildTelegramThreadParams({ id: 1, scope: "dm" })).toEqual({
|
||||
message_thread_id: 1,
|
||||
it("skips thread id for dm threads (DMs don't have threads)", () => {
|
||||
expect(buildTelegramThreadParams({ id: 1, scope: "dm" })).toBeUndefined();
|
||||
expect(buildTelegramThreadParams({ id: 2, scope: "dm" })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("normalizes and skips thread id for dm threads even with edge values", () => {
|
||||
expect(buildTelegramThreadParams({ id: 0, scope: "dm" })).toBeUndefined();
|
||||
expect(buildTelegramThreadParams({ id: -1, scope: "dm" })).toBeUndefined();
|
||||
expect(buildTelegramThreadParams({ id: 1.9, scope: "dm" })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("handles thread id 0 for non-dm scopes", () => {
|
||||
// id=0 should be included for forum and none scopes (not falsy)
|
||||
expect(buildTelegramThreadParams({ id: 0, scope: "forum" })).toEqual({
|
||||
message_thread_id: 0,
|
||||
});
|
||||
expect(buildTelegramThreadParams({ id: 0, scope: "none" })).toEqual({
|
||||
message_thread_id: 0,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -56,17 +56,34 @@ export function resolveTelegramThreadSpec(params: {
|
||||
|
||||
/**
|
||||
* Build thread params for Telegram API calls (messages, media).
|
||||
*
|
||||
* IMPORTANT: Thread IDs behave differently based on chat type:
|
||||
* - DMs (private chats): Never send thread_id (threads don't exist)
|
||||
* - Forum topics: Skip thread_id=1 (General topic), include others
|
||||
* - Regular groups: Thread IDs are ignored by Telegram
|
||||
*
|
||||
* General forum topic (id=1) must be treated like a regular supergroup send:
|
||||
* Telegram rejects sendMessage/sendMedia with message_thread_id=1 ("thread not found").
|
||||
*
|
||||
* @param thread - Thread specification with ID and scope
|
||||
* @returns API params object or undefined if thread_id should be omitted
|
||||
*/
|
||||
export function buildTelegramThreadParams(thread?: TelegramThreadSpec | null) {
|
||||
if (!thread?.id) {
|
||||
if (thread?.id == null) {
|
||||
return undefined;
|
||||
}
|
||||
const normalized = Math.trunc(thread.id);
|
||||
if (normalized === TELEGRAM_GENERAL_TOPIC_ID && thread.scope === "forum") {
|
||||
|
||||
// Never send thread_id for DMs (threads don't exist in private chats)
|
||||
if (thread.scope === "dm") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Telegram rejects message_thread_id=1 for General forum topic
|
||||
if (normalized === TELEGRAM_GENERAL_TOPIC_ID) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return { message_thread_id: normalized };
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ describe("createTelegramDraftStream", () => {
|
||||
await vi.waitFor(() => expect(api.sendMessage).toHaveBeenCalledWith(123, "Hello", undefined));
|
||||
});
|
||||
|
||||
it("keeps message_thread_id for dm threads and clears preview on cleanup", async () => {
|
||||
it("omits message_thread_id for dm threads and clears preview on cleanup", async () => {
|
||||
const api = {
|
||||
sendMessage: vi.fn().mockResolvedValue({ message_id: 17 }),
|
||||
editMessageText: vi.fn().mockResolvedValue(true),
|
||||
@@ -108,9 +108,7 @@ describe("createTelegramDraftStream", () => {
|
||||
});
|
||||
|
||||
stream.update("Hello");
|
||||
await vi.waitFor(() =>
|
||||
expect(api.sendMessage).toHaveBeenCalledWith(123, "Hello", { message_thread_id: 1 }),
|
||||
);
|
||||
await vi.waitFor(() => expect(api.sendMessage).toHaveBeenCalledWith(123, "Hello", undefined));
|
||||
await stream.clear();
|
||||
|
||||
expect(api.deleteMessage).toHaveBeenCalledWith(123, 17);
|
||||
|
||||
Reference in New Issue
Block a user