Skip to content

feat(core-api,console): add Telegram bot pairing flow - #542

Merged
l1ttps merged 2 commits into
mainfrom
feat/telegram-connect
Jul 16, 2026
Merged

feat(core-api,console): add Telegram bot pairing flow#542
l1ttps merged 2 commits into
mainfrom
feat/telegram-connect

Conversation

@l1ttps

@l1ttps l1ttps commented Jul 15, 2026

Copy link
Copy Markdown
Member
  • Add TelegramConnect entity, DTOs, and migration for pairing tokens
  • Implement telegram-connect, telegram-polling, telegram-webhook services
  • Add /integrations/:id/connects endpoints for token generation and status
  • Add /integrations/:id/webhook/:integrationId endpoint for Telegram updates
  • Create console Telegram connect UI with QR code display and polling
  • Add CopyableValue component for token display
  • Update Integration entity with telegramConnects relation
  • Update generated API hooks (orval)

Summary by CodeRabbit

  • New Features

    • Added Telegram pairing flow with QR/deep link and “Open Telegram” from integration details.
    • Added Telegram connection management: view connected chats, refresh status, and disconnect.
    • Telegram notifications now send to confirmed connected chats.
    • Telegram integrations support both webhook delivery and a local polling fallback.
    • Introduced reusable copy-to-clipboard UI and applied it to workspace API keys.
  • Bug Fixes

    • Improved Telegram connection handling, including token expiration, duplicate prevention, and more resilient error recovery during pairing and delivery.

- Add TelegramConnect entity, DTOs, and migration for pairing tokens
- Implement telegram-connect, telegram-polling, telegram-webhook services
- Add /integrations/:id/connects endpoints for token generation and status
- Add /integrations/:id/webhook/:integrationId endpoint for Telegram updates
- Create console Telegram connect UI with QR code display and polling
- Add CopyableValue component for token display
- Update Integration entity with telegramConnects relation
- Update generated API hooks (orval)
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ff346d9-e288-4d03-99e1-a9ac1aa15926

📥 Commits

Reviewing files that changed from the base of the PR and between bef1f4b and a546bfe.

📒 Files selected for processing (8)
  • console/package.json
  • console/src/components/common/copyable-value.tsx
  • console/src/pages/integrations/components/telegram-connect.tsx
  • core-api/src/modules/integrations/connectors/telegram.connector.ts
  • core-api/src/modules/integrations/entities/telegram-connect.entity.ts
  • core-api/src/modules/integrations/integrations.controller.ts
  • core-api/src/modules/integrations/telegram-connect.service.ts
  • core-api/src/modules/integrations/telegram-webhook.service.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • core-api/src/modules/integrations/entities/telegram-connect.entity.ts
  • console/src/components/common/copyable-value.tsx
  • core-api/src/modules/integrations/integrations.controller.ts
  • core-api/src/modules/integrations/telegram-webhook.service.ts
  • core-api/src/modules/integrations/connectors/telegram.connector.ts
  • core-api/src/modules/integrations/telegram-connect.service.ts
  • console/src/pages/integrations/components/telegram-connect.tsx

📝 Walkthrough

Walkthrough

Telegram integrations now support persisted pairing connections, webhook or polling-based /start handling, connected-chat notifications, and console pairing/disconnect UI. API key copying is centralized in a reusable CopyableValue component.

Changes

Telegram pairing and delivery

Layer / File(s) Summary
Connection contracts and persistence
core-api/src/common/enums/enum.ts, core-api/src/database/migrations/..., core-api/src/modules/integrations/entities/*, core-api/src/modules/auth/entities/user.entity.ts, core-api/src/modules/integrations/dto/*, core-api/src/modules/integrations/schemas/*
Adds Telegram connection statuses, DTOs, the TelegramConnect entity, integration and user relations, migration support, and enables the Telegram schema.
Pairing API and update processing
core-api/src/modules/integrations/telegram-connect.service.ts, core-api/src/modules/integrations/telegram-webhook.service.ts, core-api/src/modules/integrations/integrations.controller.ts, core-api/src/modules/integrations/integrations.module.ts, core-api/src/modules/integrations/integrations.service.ts
Adds pairing lifecycle management, webhook update handling, connection listing and disconnection endpoints, module wiring, and automatic Telegram webhook configuration.
Polling and connected-chat delivery
core-api/src/modules/integrations/telegram-polling.service.ts, core-api/src/modules/integrations/connectors/telegram.connector.ts, core-api/src/modules/notifications/processors/notifications.processor.ts, core-api/src/services/redis/distributed-lock.service.ts
Adds Redis-locked Telegram polling and changes notification delivery to resolve active connected chat IDs from telegram_connects.
Telegram connection console UI
console/src/pages/integrations/components/*, console/package.json
Adds QR/deep-link pairing, connection polling, connected-device management, disconnect actions, and the QR-code dependency in the integration details sheet.

Reusable API key copy control

Layer / File(s) Summary
Copyable value integration
console/src/components/common/copyable-value.tsx, console/src/pages/settings/components/api-keys-settings.tsx
Adds reusable clipboard feedback behavior and replaces API-key-specific copy state and rendering with CopyableValue.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Console
  participant IntegrationsController
  participant TelegramConnectService
  participant Database
  participant Telegram
  participant TelegramWebhookService
  Console->>IntegrationsController: Request pairing token
  IntegrationsController->>TelegramConnectService: createPairing
  TelegramConnectService->>Database: Store pending connection
  Telegram->>IntegrationsController: Send /start webhook update
  IntegrationsController->>TelegramWebhookService: processUpdate
  TelegramWebhookService->>TelegramConnectService: confirmConnection
  TelegramConnectService->>Database: Mark connection CONNECTED
  Console->>IntegrationsController: Poll connected connections
  IntegrationsController->>Database: Read connection records
  Database-->>Console: Return connected devices
Loading

Possibly related PRs

  • oasm-platform/open-asm#522: Adds the Telegram integration framework and connector behavior that this change extends to use persisted connected chats and integrationId.

Suggested reviewers: dependabot[bot]

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a Telegram bot pairing flow across core-api and console.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/telegram-connect

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
core-api/src/modules/integrations/connectors/telegram.connector.ts (3)

131-135: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add a timeout to each Telegram API request.

Without an abort timeout, an unresponsive Telegram request can hold this notification worker indefinitely. Apply the project-standard HTTP timeout and propagate a bounded failure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/connectors/telegram.connector.ts` around
lines 131 - 135, Update the Telegram API request in the connector’s fetch flow
to use the project-standard HTTP timeout via an abort signal, ensuring every
request is bounded. Propagate the timeout as a failure through the existing
error-handling path rather than allowing the notification worker to remain
blocked indefinitely.

129-159: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Remove Telegram chat IDs and raw API bodies from logs.

chatId is a persistent user identifier, while errorBody may contain additional Telegram account details. Log the integration ID, HTTP status, and a sanitized error instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/connectors/telegram.connector.ts` around
lines 129 - 159, Update the Telegram send flow around the response error
handling to remove chatId and raw errorBody from logs. In the logger.error call
within the fetch response check, log the integration ID, HTTP status, and a
sanitized error message instead, while preserving the existing thrown error
behavior unless required to sanitize its logging only.

121-160: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not abort fan-out after the first failed chat.

A blocked or deleted first chat throws immediately, preventing all later connected chats from receiving the alert. Attempt every destination and aggregate/report failures after the loop.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/connectors/telegram.connector.ts` around
lines 121 - 160, Update the chatId fan-out loop to continue sending to every
destination when a fetch or Telegram response fails instead of throwing
immediately. Capture each chat-specific failure, complete all attempts, then
aggregate and report the failures after the loop while preserving successful
sends and existing error details.
🧹 Nitpick comments (1)
console/src/components/common/copyable-value.tsx (1)

20-26: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Handle clipboard write errors gracefully.

navigator.clipboard.writeText can throw an error or reject the promise if the document lacks focus or if the browser blocks the clipboard permission. Wrapping the call in a try/catch prevents an unhandled promise rejection and allows you to notify the user if the copy action fails.

🛡️ Proposed fix to handle clipboard errors
   const handleCopy = async () => {
     if (!value) return;
-    await navigator.clipboard.writeText(value);
-    setCopied(true);
-    toast.success('Copied to clipboard');
-    setTimeout(() => setCopied(false), 2000);
+    try {
+      await navigator.clipboard.writeText(value);
+      setCopied(true);
+      toast.success('Copied to clipboard');
+      setTimeout(() => setCopied(false), 2000);
+    } catch (err) {
+      toast.error('Failed to copy to clipboard');
+    }
   };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@console/src/components/common/copyable-value.tsx` around lines 20 - 26,
Update handleCopy to wrap navigator.clipboard.writeText in try/catch, keeping
the success state, toast, and reset timer only after a successful write. In the
catch path, notify the user that copying failed and prevent the rejected promise
from propagating.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@console/package.json`:
- Line 82: Remove the duplicate qrcode.react entry from the package
dependencies, keeping only one declaration and preserving its existing version
constraint so Biome’s duplicate-key validation passes.

In `@console/src/pages/integrations/components/telegram-connect.tsx`:
- Around line 412-442: Update the empty-state condition in the Telegram
connections component so it also requires connectsQuery.isError to be false,
preventing “No connected devices yet” from rendering after a failed query while
preserving the existing loading and activeConnects checks.
- Around line 152-155: Update the deepLink construction to use Telegram’s start
query parameter with the encoded pairingToken, while preserving the existing
pairingToken and effectiveBotUsername guard and URL structure.

In `@core-api/src/modules/integrations/entities/telegram-connect.entity.ts`:
- Line 4: Update the TypeORM import in the Telegram connect entity to import
Relation as a type-only symbol, while keeping the runtime imports Column,
Entity, Index, JoinColumn, and ManyToOne unchanged.

In `@core-api/src/modules/integrations/telegram-connect.service.ts`:
- Around line 171-178: Update the failure messages sent through
sendTelegramMessage in the invalid-token and expired-token branches to use
Telegram-compatible HTML markup instead of Markdown asterisks, preserving the
existing message text and parse_mode behavior.
- Around line 280-292: Update the disconnect flow in the Telegram integration
controller and service to accept and propagate userId. In disconnect, include
userId alongside workspace and integration identifiers in the connection lookup
before deletion, while preserving the existing not-found behavior.
- Around line 124-126: All Telegram API requests need per-request deadlines
instead of relying only on shutdown cancellation. Update fetchBotUsername and
sendTelegramMessage in
core-api/src/modules/integrations/telegram-connect.service.ts (lines 124-126 and
381-390), the relevant request in integrations.service.ts (lines 51-59), and
getUpdates in telegram-polling.service.ts (lines 114-117) to use timeout-based
AbortSignals, while preserving the polling service’s existing app-shutdown
cancellation by combining both abort conditions.

In `@core-api/src/modules/integrations/telegram-polling.service.ts`:
- Around line 9-11: Persist the Telegram update offset durably rather than
keeping it only in worker memory, and restore it when acquiring a lease so
polling resumes after restarts or TTL expiry without replaying updates. Extend
LOCK_TTL_MS beyond the 30-second POLL_TIMEOUT with sufficient processing
headroom, while preserving the existing polling and lease flow.

In `@core-api/src/modules/integrations/telegram-webhook.service.ts`:
- Around line 69-75: Update the success log in the Telegram connection flow to
remove all pairing-token content, including the token prefix from
token.substring. Use the available connection or integration ID for correlation
instead, while preserving the existing success message context and failure
logging in the surrounding method.
- Around line 45-67: Bind Telegram updates and pairing-token confirmation to the
receiving integration. In
core-api/src/modules/integrations/telegram-webhook.service.ts:45-67, accept
integrationId in processUpdate and pass it to confirmConnection; in
core-api/src/modules/integrations/integrations.controller.ts:213-220, forward
the route integrationId; in
core-api/src/modules/integrations/telegram-polling.service.ts:136-140, forward
integration.id; and in
core-api/src/modules/integrations/telegram-connect.service.ts:153-155, include
integrationId in the pending-token lookup.

---

Outside diff comments:
In `@core-api/src/modules/integrations/connectors/telegram.connector.ts`:
- Around line 131-135: Update the Telegram API request in the connector’s fetch
flow to use the project-standard HTTP timeout via an abort signal, ensuring
every request is bounded. Propagate the timeout as a failure through the
existing error-handling path rather than allowing the notification worker to
remain blocked indefinitely.
- Around line 129-159: Update the Telegram send flow around the response error
handling to remove chatId and raw errorBody from logs. In the logger.error call
within the fetch response check, log the integration ID, HTTP status, and a
sanitized error message instead, while preserving the existing thrown error
behavior unless required to sanitize its logging only.
- Around line 121-160: Update the chatId fan-out loop to continue sending to
every destination when a fetch or Telegram response fails instead of throwing
immediately. Capture each chat-specific failure, complete all attempts, then
aggregate and report the failures after the loop while preserving successful
sends and existing error details.

---

Nitpick comments:
In `@console/src/components/common/copyable-value.tsx`:
- Around line 20-26: Update handleCopy to wrap navigator.clipboard.writeText in
try/catch, keeping the success state, toast, and reset timer only after a
successful write. In the catch path, notify the user that copying failed and
prevent the rejected promise from propagating.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ccbaced1-e057-4373-b32f-e4045b5f3307

📥 Commits

Reviewing files that changed from the base of the PR and between a4758a2 and bef1f4b.

⛔ Files ignored due to path filters (4)
  • console/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • console/src/services/apis/gen/queries.ts is excluded by !**/gen/**
  • package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (22)
  • console/package.json
  • console/src/components/common/copyable-value.tsx
  • console/src/pages/integrations/components/integration-detail-sheet.tsx
  • console/src/pages/integrations/components/telegram-connect.tsx
  • console/src/pages/settings/components/api-keys-settings.tsx
  • core-api/src/common/enums/enum.ts
  • core-api/src/database/migrations/1784101236391-AddTelegramConnects.ts
  • core-api/src/modules/auth/entities/user.entity.ts
  • core-api/src/modules/integrations/connectors/telegram.connector.ts
  • core-api/src/modules/integrations/dto/create-telegram-pairing.dto.ts
  • core-api/src/modules/integrations/dto/telegram-connect.dto.ts
  • core-api/src/modules/integrations/entities/integration.entity.ts
  • core-api/src/modules/integrations/entities/telegram-connect.entity.ts
  • core-api/src/modules/integrations/integrations.controller.ts
  • core-api/src/modules/integrations/integrations.module.ts
  • core-api/src/modules/integrations/integrations.service.ts
  • core-api/src/modules/integrations/schemas/telegram.schema.ts
  • core-api/src/modules/integrations/telegram-connect.service.ts
  • core-api/src/modules/integrations/telegram-polling.service.ts
  • core-api/src/modules/integrations/telegram-webhook.service.ts
  • core-api/src/modules/notifications/processors/notifications.processor.ts
  • core-api/src/services/redis/distributed-lock.service.ts
💤 Files with no reviewable changes (1)
  • core-api/src/services/redis/distributed-lock.service.ts

Comment thread console/package.json
Comment on lines +152 to +155
const deepLink =
pairingToken && effectiveBotUsername
? `https://t.me/${effectiveBotUsername}?text=${encodeURIComponent('/start ' + pairingToken)}`
: null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='console/src/pages/integrations/components/telegram-connect.tsx'

echo '--- file outline ---'
ast-grep outline "$file" --view expanded || true

echo
echo '--- relevant lines ---'
sed -n '130,175p' "$file"

Repository: oasm-platform/open-asm

Length of output: 2885


🌐 Web query:

Telegram bot deep link parameter start t.me bot features text parameter

💡 Result:

Telegram deep linking is a feature that allows you to pass additional parameters to a bot when a user initiates a conversation [1][2]. By using a specifically formatted URL, you can trigger the bot with the /start command and include a payload that the bot can interpret to perform custom actions [1][3][4]. The standard format for a deep link is: https://t.me/your_bot_username?start=payload When a user clicks this link, their Telegram client opens the bot's chat and displays a Start button [4]. Once the user clicks Start, the bot receives the /start command, and the provided payload is passed as an argument to the command handler [3][4]. Key features and considerations: 1. Payload Content: The payload is typically a string. While basic alphanumeric characters (A-Z, a-z, 0-9), underscores (_), and hyphens (-) are generally safe, you can use base64url encoding to support special characters or more complex data structures [2][5][6]. 2. Use Cases: Common applications include passing authentication tokens to link a user's Telegram account with an external service, triggering specific onboarding flows, or directing users to specific content within the bot [2][6]. 3. Implementation: Most major Telegram bot frameworks (such as aiogram or python-telegram-bot) provide utility functions to simplify the creation of these links [2][5][6]. These utilities often handle the necessary formatting and, if requested, the base64url encoding of the payload [2][6]. 4. Developer Handling: On the backend, you define a handler for the /start command. Your code should extract the arguments provided with the command and parse the payload to determine the appropriate response or action [2][3][7]. For group or channel links, Telegram also supports similar functionality (often using startgroup) to initiate a bot's inclusion in a chat with a specific parameter [8][2][6].

Citations:


Use the Telegram start deep link parameter. ?text= won’t pass the pairing token into the bot’s /start flow; use ?start=${encodeURIComponent(pairingToken)} instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@console/src/pages/integrations/components/telegram-connect.tsx` around lines
152 - 155, Update the deepLink construction to use Telegram’s start query
parameter with the encoded pairingToken, while preserving the existing
pairingToken and effectiveBotUsername guard and URL structure.

Comment thread console/src/pages/integrations/components/telegram-connect.tsx
Comment thread core-api/src/modules/integrations/entities/telegram-connect.entity.ts Outdated
Comment on lines +124 to +126
private async fetchBotUsername(botToken: string): Promise<string> {
const url = `${TELEGRAM_API_BASE}/bot${botToken}/getMe`;
const response = await fetch(url);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- telegram-connect.service.ts relevant sections ---'
sed -n '110,150p' core-api/src/modules/integrations/telegram-connect.service.ts
echo
sed -n '370,405p' core-api/src/modules/integrations/telegram-connect.service.ts

echo '--- integrations.service.ts relevant section ---'
sed -n '1,90p' core-api/src/modules/integrations/integrations.service.ts

echo '--- telegram-polling.service.ts relevant section ---'
sed -n '90,160p' core-api/src/modules/integrations/telegram-polling.service.ts

echo '--- search for AbortController / timeout / fetch wrappers in integrations module ---'
rg -n "AbortController|setTimeout\\(|timeout|signal:|fetch\\(" core-api/src/modules/integrations

Repository: oasm-platform/open-asm

Length of output: 9251


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo 'ping'

Repository: oasm-platform/open-asm

Length of output: 165


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path

paths = [
    "core-api/src/modules/integrations/telegram-connect.service.ts",
    "core-api/src/modules/integrations/integrations.service.ts",
    "core-api/src/modules/integrations/telegram-polling.service.ts",
]
for p in paths:
    print(f"\n=== {p} ===")
    text = Path(p).read_text()
    for i, line in enumerate(text.splitlines(), 1):
        if "fetch(" in line or "AbortController" in line or "AbortSignal" in line or "signal" in line or "timeout" in line:
            start = max(1, i-3)
            end = min(len(text.splitlines()), i+5)
            print(f"-- around line {i} --")
            for j in range(start, end+1):
                print(f"{j:4}: {text.splitlines()[j-1]}")
PY

Repository: oasm-platform/open-asm

Length of output: 4885


Add request deadlines to Telegram API calls
These fetch calls can still hang indefinitely: fetchBotUsername, sendTelegramMessage, and autoConfigureTelegramWebhook have no timeout, and getUpdates only has the app-shutdown AbortController, not a per-request deadline. A stalled Telegram endpoint can tie up request handlers and the polling loop.

  • core-api/src/modules/integrations/telegram-connect.service.ts#L124-L126
  • core-api/src/modules/integrations/telegram-connect.service.ts#L381-L390
  • core-api/src/modules/integrations/integrations.service.ts#L51-L59
  • core-api/src/modules/integrations/telegram-polling.service.ts#L114-L117
📍 Affects 3 files
  • core-api/src/modules/integrations/telegram-connect.service.ts#L124-L126 (this comment)
  • core-api/src/modules/integrations/telegram-connect.service.ts#L381-L390
  • core-api/src/modules/integrations/integrations.service.ts#L51-L59
  • core-api/src/modules/integrations/telegram-polling.service.ts#L114-L117
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/telegram-connect.service.ts` around lines
124 - 126, All Telegram API requests need per-request deadlines instead of
relying only on shutdown cancellation. Update fetchBotUsername and
sendTelegramMessage in
core-api/src/modules/integrations/telegram-connect.service.ts (lines 124-126 and
381-390), the relevant request in integrations.service.ts (lines 51-59), and
getUpdates in telegram-polling.service.ts (lines 114-117) to use timeout-based
AbortSignals, while preserving the polling service’s existing app-shutdown
cancellation by combining both abort conditions.

Comment thread core-api/src/modules/integrations/telegram-connect.service.ts
Comment thread core-api/src/modules/integrations/telegram-connect.service.ts
Comment on lines +9 to +11
const POLL_TIMEOUT = 30; // seconds
const POLL_INTERVAL_MS = 3000; // 3 seconds between poll cycles
const LOCK_TTL_MS = 35_000; // 35 seconds — must be > POLL_TIMEOUT * 1000

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and nearby symbols first.
ast-grep outline core-api/src/modules/integrations/telegram-polling.service.ts --view expanded || true

# Show line numbers around the referenced ranges.
sed -n '1,240p' core-api/src/modules/integrations/telegram-polling.service.ts | cat -n

# Find related polling/offset/lock references in the module.
rg -n "offset|lock|poll|lease|redis|telegram" core-api/src/modules/integrations -S

Repository: oasm-platform/open-asm

Length of output: 40697


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the Redis lock implementation to see whether the lease is renewed.
sed -n '1,260p' core-api/src/services/redis/distributed-lock.service.ts | cat -n

# Inspect usages of withLock to understand expected lock lifetime semantics.
rg -n "withLock\(" core-api/src -S

Repository: oasm-platform/open-asm

Length of output: 6356


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether duplicate update delivery is idempotent or side-effectful.
sed -n '1,220p' core-api/src/modules/integrations/telegram-webhook.service.ts | cat -n

Repository: oasm-platform/open-asm

Length of output: 2777


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect confirmConnection to see whether replayed /start updates are idempotent.
sed -n '140,280p' core-api/src/modules/integrations/telegram-connect.service.ts | cat -n

Repository: oasm-platform/open-asm

Length of output: 5675


Persist the Telegram offset outside memory. A worker that wins the next lease after a restart or TTL expiry starts from 0, so already-processed getUpdates results can be replayed. The 35s lock also leaves little headroom over the 30s long poll, so longer update handling can overlap the next poll. Storing offsets durably and extending the lease would avoid that.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/telegram-polling.service.ts` around lines 9
- 11, Persist the Telegram update offset durably rather than keeping it only in
worker memory, and restore it when acquiring a lease so polling resumes after
restarts or TTL expiry without replaying updates. Extend LOCK_TTL_MS beyond the
30-second POLL_TIMEOUT with sufficient processing headroom, while preserving the
existing polling and lease flow.

Comment on lines +45 to +67
async processUpdate(update: TelegramUpdate): Promise<void> {
const message = update.message;
if (!message?.text) return;

// Parse /start <token> or /start
const text = message.text.trim();
if (!text.startsWith('/start')) return;

const token = text.split(/\s+/)[1];
if (!token) {
this.logger.debug('Ignored /start without token');
return;
}

const chatId = String(message.chat.id);

try {
await this.telegramConnectService.confirmConnection(token, {
chatId,
username: message.chat.username ?? message.from?.username,
firstName: message.chat.first_name ?? message.from?.first_name,
lastName: message.chat.last_name ?? message.from?.last_name,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Bind every update and pairing token to the bot integration that received it. Currently any bot's webhook or poller can confirm a token belonging to another integration.

  • core-api/src/modules/integrations/telegram-webhook.service.ts#L45-L67: accept an integrationId and pass it into confirmation.
  • core-api/src/modules/integrations/integrations.controller.ts#L213-L220: forward the route's integrationId.
  • core-api/src/modules/integrations/telegram-polling.service.ts#L136-L140: forward integration.id from the active poller.
  • core-api/src/modules/integrations/telegram-connect.service.ts#L153-L155: include integrationId in the pending-token lookup.
📍 Affects 4 files
  • core-api/src/modules/integrations/telegram-webhook.service.ts#L45-L67 (this comment)
  • core-api/src/modules/integrations/integrations.controller.ts#L213-L220
  • core-api/src/modules/integrations/telegram-polling.service.ts#L136-L140
  • core-api/src/modules/integrations/telegram-connect.service.ts#L153-L155
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/telegram-webhook.service.ts` around lines
45 - 67, Bind Telegram updates and pairing-token confirmation to the receiving
integration. In
core-api/src/modules/integrations/telegram-webhook.service.ts:45-67, accept
integrationId in processUpdate and pass it to confirmConnection; in
core-api/src/modules/integrations/integrations.controller.ts:213-220, forward
the route integrationId; in
core-api/src/modules/integrations/telegram-polling.service.ts:136-140, forward
integration.id; and in
core-api/src/modules/integrations/telegram-connect.service.ts:153-155, include
integrationId in the pending-token lookup.

Comment on lines +69 to +75
this.logger.log(
`Telegram chat ${chatId} connected via token (first ${token.substring(0, 8)}...)`,
);
} catch (error: unknown) {
const err = error as Error;
this.logger.warn(
`Failed to connect Telegram chat ${chatId}: ${err.message}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Do not log any portion of the pairing token.

The token is an authentication capability. Remove the prefix from the success log and use the connection or integration ID for correlation instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core-api/src/modules/integrations/telegram-webhook.service.ts` around lines
69 - 75, Update the success log in the Telegram connection flow to remove all
pairing-token content, including the token prefix from token.substring. Use the
available connection or integration ID for correlation instead, while preserving
the existing success message context and failure logging in the surrounding
method.

Source: Linters/SAST tools

- console/package.json: remove duplicate qrcode.react entry
- console/copyable-value.tsx: wrap clipboard write in try/catch
- console/telegram-connect.tsx: add !isError to empty state, fix deepLink to use ?start=
- core-api/telegram-connect.entity.ts: type-only import for Relation
- core-api/telegram-connect.service.ts: fix HTML markup (*bold* -> <b>bold</b>),
  add userId scope to disconnect(), add AbortSignal.timeout to fetch calls
- core-api/telegram-webhook.service.ts: stop logging token prefix
- core-api/telegram.connector.ts: add AbortSignal.timeout, continue on per-chat
  failure instead of throwing on first error
- core-api/integrations.controller.ts: forward userId to disconnect
@l1ttps
l1ttps merged commit 0fa3052 into main Jul 16, 2026
18 checks passed
@l1ttps
l1ttps deleted the feat/telegram-connect branch July 16, 2026 08:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant