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

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