fix(telegram): preserve DM topic thread id for outbound media#7261
fix(telegram): preserve DM topic thread id for outbound media#7261ViffyGwaanl wants to merge 5 commits intoopenclaw:mainfrom
Conversation
src/telegram/send.ts
Outdated
| // Detect DM vs forum: positive chatId = DM, negative (especially -100...) = forum | ||
| const isPrivateChat = /^-?\d+$/.test(chatId) && Number.parseInt(chatId, 10) > 0; | ||
| const scope = isPrivateChat ? "dm" : "forum"; |
There was a problem hiding this comment.
[P2] Avoid re-parsing chatId here; use target info or existing helpers.
normalizeChatId() already ensures numeric IDs match /^-?\d+$/ and parseTelegramTarget(to) typically contains enough structure to determine DM vs group/forum. Re-checking with RegExp + parseInt adds duplication and can misclassify non-numeric chat identifiers (e.g. @username) as forum even if they’re private/user chats; if messageThreadId is present in that case, we’ll send it with scope: "forum" and may incorrectly drop id=1.
Also appears in src/telegram/send.ts:705-708.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/send.ts
Line: 225:227
Comment:
[P2] Avoid re-parsing `chatId` here; use target info or existing helpers.
`normalizeChatId()` already ensures numeric IDs match `/^-?\d+$/` and `parseTelegramTarget(to)` typically contains enough structure to determine DM vs group/forum. Re-checking with `RegExp` + `parseInt` adds duplication and can misclassify non-numeric chat identifiers (e.g. `@username`) as `forum` even if they’re private/user chats; if `messageThreadId` is present in that case, we’ll send it with `scope: "forum"` and may incorrectly drop `id=1`.
Also appears in `src/telegram/send.ts:705-708`.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Done in dc9f363fd:
- Removed regex/parseInt re-parsing and the
as constassertion. - Added
resolveTelegramThreadScope(chatId)that usesNumber(chatId)(finite + >0 => dm, else forum). Non-numeric chat IDs (e.g.@username) are treated as non-DM.
This preserves DM topic thread ids (includingmessage_thread_id=1) while still omitting forum general-topic thread id.
| it("omits message_thread_id=1 for forum general topic", async () => { | ||
| const chatId = "-1001234567890"; | ||
| const sendMessage = vi.fn().mockResolvedValue({ | ||
| message_id: 59, | ||
| chat: { id: chatId }, | ||
| }); | ||
| const api = { sendMessage } as unknown as { | ||
| sendMessage: typeof sendMessage; | ||
| }; | ||
|
|
||
| await sendMessageTelegram(chatId, "general topic message", { | ||
| token: "tok", | ||
| api, | ||
| messageThreadId: 1, | ||
| }); | ||
|
|
||
| expect(sendMessage).toHaveBeenCalledWith(chatId, "general topic message", { | ||
| parse_mode: "HTML", | ||
| // message_thread_id should be omitted for forum general topic (id=1) | ||
| }); |
There was a problem hiding this comment.
[P3] This assertion doesn’t actually verify omission of message_thread_id.
toHaveBeenCalledWith(chatId, "general topic message", { parse_mode: "HTML" }) will pass even if the implementation adds extra keys (e.g. message_thread_id: 1) unless you assert on the exact object or explicitly assert the absence via expect.objectContaining + checking keys. As written, the comment in the expected object is ignored at runtime.
Also impacts the sticker general-topic test at src/telegram/send.returns-undefined-empty-input.test.ts:748-766 (it uses undefined params, but could still miss cases where a params object is passed without message_thread_id).
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/send.returns-undefined-empty-input.test.ts
Line: 599:618
Comment:
[P3] This assertion doesn’t actually verify omission of `message_thread_id`.
`toHaveBeenCalledWith(chatId, "general topic message", { parse_mode: "HTML" })` will pass even if the implementation adds extra keys (e.g. `message_thread_id: 1`) unless you assert on the exact object or explicitly assert the absence via `expect.objectContaining` + checking keys. As written, the comment in the expected object is ignored at runtime.
Also impacts the sticker general-topic test at `src/telegram/send.returns-undefined-empty-input.test.ts:748-766` (it uses `undefined` params, but could still miss cases where a params object is passed without `message_thread_id`).
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Updated the tests in dc9f363fd:
- Use
expect.objectContaining({ parse_mode: "HTML" })for the params bag. - Explicitly assert
message_thread_idis omitted:expect(params?.message_thread_id).toBeUndefined().
This makes the “forum general topic (id=1) omits thread id” behavior actually enforced.
|
更新:我已经把分支 rebase 到最新 我之前提到的 我已 force-push 更新分支并触发了新的 CI(现在 checks 都在 pending 跑)。谢谢! |
76487ec to
00b9b9e
Compare
|
CI update: Windows
I pushed a stabilization fix to the PR branch:
This wraps the CWD mutation in a helper that restores cwd best-effort (and resets to New CI run has been triggered (run: 21636153404). |
b8e9d20 to
bb15e98
Compare
bb15e98 to
eb1cd04
Compare
bfc1ccb to
f92900f
Compare
Problem
In Telegram private chats with topics (Bot API 9.3+), async followup sends (routeReply/outbound → sendMessageTelegram) could drop
message_thread_idwhen the DM thread id is1, becausesendMessageTelegramalways treated thread ids as forum scope.This causes outbound media/documents to land in the main DM window instead of the correct DM topic.
Fix
threadSpecwith scopedmfor private chats andforumotherwise, sobuildTelegramThreadParamsonly omits id=1 for forum General topic, but keeps id=1 for DM topics.Tests
message_thread_id=1for media/doc sends and stickers.message_thread_id.This should fix delayed media/file replies in DM topics while preserving existing forum behavior.
Greptile Overview
Greptile Summary
This PR updates Telegram outbound sending to preserve
message_thread_id=1when sending to DM topics (Bot API 9.3+), while continuing to omitmessage_thread_id=1for forum “General” topic sends. It does this by inferring whether the destination is a private chat vs a forum chat and passing a correspondingscopeintobuildTelegramThreadParams, plus adds unit tests covering DM topicid=1for documents/media and stickers and forum general-topic omission.Confidence Score: 3/5
buildTelegramThreadParamsbehavior, but it duplicates chat-id parsing logic in two places and can misclassify non-numeric chat IDs (e.g.,@username). Additionally, the new “omit message_thread_id” test does not robustly assert absence of the field, reducing confidence that the intended regression is covered.(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!