Skip to content

fix(telegram): normalize delivery-only group chat ids#42571

Open
sonwr wants to merge 1 commit intoopenclaw:mainfrom
sonwr:fix/telegram-group-prefix-delivery-normalization
Open

fix(telegram): normalize delivery-only group chat ids#42571
sonwr wants to merge 1 commit intoopenclaw:mainfrom
sonwr:fix/telegram-group-prefix-delivery-normalization

Conversation

@sonwr
Copy link
Copy Markdown

@sonwr sonwr commented Mar 10, 2026

Summary

  • normalize bare group:<numeric_chat_id> targets in Telegram delivery helpers
  • apply the delivery-only normalization in both chat-id and lookup-target paths
  • add regression coverage for direct normalization and send-time delivery

Testing

  • pnpm exec vitest run src/telegram/targets.test.ts -t "normalizes bare delivery-only group prefixes for numeric chat ids"
  • pnpm exec vitest run src/telegram/send.test.ts -t "sends bare group-prefixed numeric delivery targets without lookup"
  • node --import tsx -e "import { normalizeTelegramChatId, normalizeTelegramLookupTarget } from './src/telegram/targets.ts'; console.log(JSON.stringify({ chatId: normalizeTelegramChatId('group:-1003786508776'), lookup: normalizeTelegramLookupTarget('group:-1003786508776') }));"

@openclaw-barnacle openclaw-barnacle Bot added channel: telegram Channel integration: telegram size: XS labels Mar 10, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 10, 2026

Greptile Summary

This PR introduces normalizeTelegramDeliveryGroupChatId and applies it in normalizeTelegramChatId and normalizeTelegramLookupTarget, which correctly handles the negative-ID case (e.g., group:-100123) end-to-end. However, the fix is incomplete because parseTelegramTarget — the entry point for all send helpers and resolveTelegramTargetChatType — is not updated.

Functional issues:

  1. Positive-ID send path is broken (group:123456789): The colonMatch regex in parseTelegramTarget splits "group:123456789" as chatId = "group" and messageThreadId = 123456789. The subsequent resolveChatId("group", …) call then matches "group" as a 5-character username and makes a spurious getChat("@group") API call instead of delivering to the intended chat.

  2. resolveTelegramTargetChatType returns "unknown" for group: prefixed targets: Because parseTelegramTarget does not apply normalization, resolveTelegramTargetChatType("group:-1001234567890") resolves to "unknown" instead of "group". In exec-approvals.ts, approval buttons are silently suppressed for group-prefixed targets when the approval target is configured as "channel", since the condition only enables buttons for target === "channel" when chatType === "group".

Confidence Score: 1/5

  • Not safe to merge — the PR is incomplete and leaves two functional regressions that will cause broken sends and suppressed approval buttons for group-prefixed targets.
  • The normalization helper is correct and negative-ID cases work end-to-end, but parseTelegramTarget is not updated. This leaves two real bugs: (1) positive-ID group:... inputs are misparsed and trigger spurious API calls, and (2) chat-type resolution returns "unknown" instead of "group", causing approval buttons to be silently suppressed for group targets when configured as "channel". These are functional regressions against the invariants the PR's own tests establish.
  • src/telegram/targets.ts — specifically parseTelegramTarget (line 97) and resolveTelegramTargetChatType (line 124) need to apply normalizeTelegramDeliveryGroupChatId before the colon-match logic runs.

Comments Outside Diff (2)

  1. src/telegram/targets.ts, line 97-122 (link)

    parseTelegramTarget does not apply normalizeTelegramDeliveryGroupChatId, leaving the positive-ID send path broken.

    For input "group:123456789", the colonMatch regex /^(.+):(\d+)$/ on line 109 will eagerly match and split the string as chatId = "group" and messageThreadId = 123456789. The downstream resolveChatId("group", …) call in send.ts then runs normalizeTelegramLookupTarget("group"), which matches the TELEGRAM_USERNAME_REGEX (5 alphanumeric characters) and returns "@group", causing an unexpected getChat("@group") API call instead of delivering to the intended chat ID.

    Note: negative-ID inputs like "group:-100123" are unaffected because the colonMatch regex requires digits after the colon (not minus), so it fails to match and the full string is passed through.

    Fix: Apply normalizeTelegramDeliveryGroupChatId to normalized early in parseTelegramTarget, before the colon-match logic runs — analogous to how it is now applied in normalizeTelegramChatId and normalizeTelegramLookupTarget.

  2. src/telegram/targets.ts, line 124-126 (link)

    resolveTelegramTargetChatType returns wrong type for group: prefixed targets.

    Since parseTelegramTarget does not apply normalizeTelegramDeliveryGroupChatId, inputs like "group:-1001234567890" are not normalized and remain unparseable, causing parseTelegramTarget to return chatType: "unknown" instead of the correct "group" type.

    This has a concrete downstream effect in exec-approvals.ts. When a user's approval target is configured as "channel", the approval-button logic only enables buttons if chatType === "group":

    if (chatType === "group")  { return target === "channel" || target === "both"; }
    return target === "both";   // ← exec-approval buttons silently suppressed when chatType is "unknown"

    With chatType resolving to "unknown" for group:... targets, the condition falls through and approval buttons are silently suppressed for users who configure the approval target as "channel".

    Fix: Updating parseTelegramTarget to apply normalizeTelegramDeliveryGroupChatId (as noted in the previous comment) will also resolve this issue.

Last reviewed commit: 8e2b50c

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label Apr 27, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 27, 2026

Codex review: needs changes before merge.

Summary
The PR adds a helper in old src/telegram code to strip bare numeric group: prefixes in chat-id and lookup normalization, plus normalization and send-path regression tests.

Reproducibility: yes. from source inspection: current main keeps bare group: prefixes in the active Telegram target stripper, and delivery parses targets before lookup. I did not execute tests in this read-only review.

Next step before merge
This is a narrow repair candidate because the bug path, active files, regression coverage, and changelog requirement are clear while the source branch is stale and incomplete.

Security
Cleared: The diff only changes Telegram target string normalization and tests, with no dependency, workflow, credential, permission, or package-execution surface.

Review findings

  • [P2] Retarget the active Telegram plugin — src/telegram/targets.ts:36
  • [P2] Normalize group targets before parsing — src/telegram/targets.ts:36
  • [P3] Add the Telegram delivery changelog entry — src/telegram/targets.ts:36
Review details

Best possible solution:

Land a repaired or replacement PR against extensions/telegram/src that normalizes bare numeric group: targets at the shared strip/parse boundary, with send, chat-type/topic, and changelog coverage.

Do we have a high-confidence way to reproduce the issue?

Yes, from source inspection: current main keeps bare group: prefixes in the active Telegram target stripper, and delivery parses targets before lookup. I did not execute tests in this read-only review.

Is this the best way to solve the issue?

No. This PR is not the best current fix because it targets removed paths and only normalizes chat-id/lookup helpers; the maintainable fix belongs in the active extension's shared target strip/parse path.

Full review comments:

  • [P2] Retarget the active Telegram plugin — src/telegram/targets.ts:36
    Current main no longer ships the Telegram implementation from src/telegram; the active code is under extensions/telegram/src. As written, this branch cannot update the current parser or tests without rebasing/retargeting the same fix to the active plugin files.
    Confidence: 0.94
  • [P2] Normalize group targets before parsing — src/telegram/targets.ts:36
    Adding normalization only in chat-id and lookup helpers leaves the send parser unnormalized. The send path parses to first, so group:123456789 can still become chatId group with a topic id, and bare negative group targets still resolve as unknown for chat-type users.
    Confidence: 0.95
  • [P3] Add the Telegram delivery changelog entry — src/telegram/targets.ts:36
    This is a user-facing Telegram delivery fix, but the PR does not update CHANGELOG.md. Repo policy requires a changelog entry for user-visible fixes before merge.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.93

Acceptance criteria:

  • pnpm test extensions/telegram/src/targets.test.ts extensions/telegram/src/send.test.ts extensions/telegram/src/exec-approvals.test.ts extensions/telegram/src/inline-buttons.test.ts
  • pnpm exec oxfmt --check --threads=1 extensions/telegram/src/targets.ts extensions/telegram/src/targets.test.ts extensions/telegram/src/send.test.ts extensions/telegram/src/exec-approvals.test.ts extensions/telegram/src/inline-buttons.test.ts CHANGELOG.md
  • pnpm check:changed

What I checked:

  • Current main still preserves bare group prefixes: stripTelegramInternalPrefixes only strips group: after a prior telegram:/tg: prefix, and the current test explicitly expects stripTelegramInternalPrefixes("group:-100123") to preserve the prefix. (extensions/telegram/src/targets.ts:20, a7c5a0425988)
  • Parser remains affected before send resolution: parseTelegramTarget runs stripTelegramInternalPrefixes before topic parsing; group:123456789 can match the generic colon topic pattern as chatId group, while group:-100... remains an unknown chat type. (extensions/telegram/src/targets.ts:91, a7c5a0425988)
  • Delivery and approval paths depend on that parser: sendMessageTelegram parses to before chat-id lookup, and approval-button injection branches on resolveTelegramTargetChatType(params.to), so the parser behavior reaches both delivery and inline approval UI. (extensions/telegram/src/send.ts:591, a7c5a0425988)
  • PR targets inactive paths: The PR diff modifies src/telegram/*, but current main has no src/telegram directory and the active implementation is under extensions/telegram/src. (src/telegram/targets.ts:36, 8e2b50c888b3)
  • Related discussion identified the same root boundary: The linked related PR discussion describes the stronger fix as changing the shared stripTelegramInternalPrefixes path so parseTelegramTarget, chat-id normalization, and lookup normalization all agree; current main still has the old guarded behavior. (extensions/telegram/src/targets.ts:10, a7c5a0425988)

Likely related people:

  • steipete: GitHub path history shows refactor(telegram): centralize target parsing and recent Telegram send/session maintenance, including files on the affected parser and delivery path. (role: introduced parser and recent Telegram maintainer; confidence: high; commits: 0373574f0bce, 2f828dbde964, 49e9cdeb98e2; files: src/telegram/targets.ts, extensions/telegram/src/send.ts, src/agents/tools/sessions-send-helpers.ts)
  • obviyus: History for the old Telegram target path includes target handling refactors, topic auto-threading, and runtime target persistence work that the current bug flows through. (role: target-handling contributor; confidence: medium; commits: b6a9741ba41c, dcc52850c33c, 01db1dde1ad7; files: src/telegram/targets.ts, src/telegram/send.ts, extensions/telegram/src/target-writeback.ts)
  • scoootscooob: The PR is stale mainly because the Telegram implementation was moved from src/telegram to extensions/telegram/src and the old shim directories were removed in their migration commits. (role: extension migration owner; confidence: high; commits: e5bca0832fbd, 439c21e078f1; files: extensions/telegram/src/targets.ts, src/telegram/targets.ts, extensions/telegram/src/send.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against a7c5a0425988.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: telegram Channel integration: telegram size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant