Skip to content

feat: add @chat-adapter/telegram package#107

Open
reloadlife wants to merge 4 commits intovercel:mainfrom
reloadlife:feat/telegram
Open

feat: add @chat-adapter/telegram package#107
reloadlife wants to merge 4 commits intovercel:mainfrom
reloadlife:feat/telegram

Conversation

@reloadlife
Copy link

@reloadlife reloadlife commented Feb 25, 2026

Summary

Add @chat-adapter/telegram package implementing the Telegram Bot API adapter using the grammy framework (TypeScript-first, webhook-ready).

  • Support for sending/receiving text messages, reactions (add/remove via setMessageReaction), inline keyboard buttons, typing indicators, and DMs
  • Webhook verification via X-Telegram-Bot-Api-Secret-Token header validation
  • Card rendering with inline keyboard buttons when actions are present, falling back to MarkdownV2 formatted text
  • Photo attachment support with largest-size selection from Telegram's multi-resolution photo array
  • File upload support via grammy's InputFile with Buffer conversion for cross-platform compatibility
  • Forum topic (supergroup thread) support via message_thread_id
  • All private chats detected as DMs via positive chat ID heuristic
  • Full test suite (54 tests) covering adapter logic, webhook handling, card rendering, and markdown conversion
  • Configuration updates across turbo.json, @chat-adapter/shared (PlatformName), and chat emoji utilities

Details

Capabilities

Feature Support
Post message Yes
Edit message Yes
Delete message Yes
Reactions Yes (add and remove)
Typing indicator Yes (sendChatAction("typing"))
DMs Yes (private chats)
Cards/Buttons Yes (inline keyboard buttons + text)
File upload Yes (documents via InputFile)
Forum topics Yes (supergroup threads)
Streaming No
Message history No (not exposed by Bot API)
Modals No

Media support

Inbound photo messages are exposed as Attachment objects on the Message with:

  • type"image"
  • width / height — from largest photo size
  • size — file size in bytes (when available)

Outbound file uploads convert FileUpload.data (Buffer/ArrayBuffer/Blob) to grammy InputFile with caption support (1024 char limit).

Thread ID format

telegram:{chatId}:{messageThreadId}

  • Regular chat: telegram:123456789:0
  • Forum topic: telegram:-1001234567890:42

Environment variables

  • TELEGRAM_BOT_TOKEN — Bot API token from @Botfather
  • TELEGRAM_SECRET_TOKEN — Secret token for webhook signature verification

Test plan

  • Unit tests pass for adapter core (encode/decode thread IDs, webhook verification, message parsing)
  • Unit tests pass for callback query handling (action ID/value parsing, answer callback)
  • Unit tests pass for isMention detection (via @username and entities)
  • Unit tests pass for card rendering (inline keyboard buttons, link buttons, text fallback, dividers)
  • Unit tests pass for markdown conversion (MarkdownV2 bold/italic/strikethrough/code/links, escaping)
  • pnpm typecheck passes across all packages
  • pnpm check (lint/format) passes
  • pnpm knip (unused exports/deps) passes
  • pnpm test passes (54 Telegram adapter tests + all existing tests)

Add a new Telegram adapter using grammy for Bot API interactions.
Supports webhook handling, MarkdownV2 formatting, inline keyboard
cards, reactions, typing indicators, and forum topic threads.
Copilot AI review requested due to automatic review settings February 25, 2026 06:53
@vercel
Copy link
Contributor

vercel bot commented Feb 25, 2026

@reloadlife is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@socket-security
Copy link

socket-security bot commented Feb 25, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedgrammy@​1.40.09710010092100

View full report

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds a new Telegram adapter to the chat SDK using the grammy library for Bot API interactions. The adapter enables Telegram bot integration with support for webhook handling, MarkdownV2 formatting, inline keyboard cards, reactions, typing indicators, and forum topic threads.

Changes:

  • Adds @chat-adapter/telegram package with full adapter implementation
  • Extends emoji placeholder conversion and card utilities to support Telegram platform
  • Configures environment variables for Telegram bot token and secret token in turbo.json

Reviewed changes

Copilot reviewed 13 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
turbo.json Adds TELEGRAM_BOT_TOKEN and TELEGRAM_SECRET_TOKEN environment variables
pnpm-lock.yaml Adds grammy dependency (v1.40.0) and related packages
packages/chat/src/emoji.ts Extends convertEmojiPlaceholders to support "telegram" platform using unicode emoji
packages/adapter-shared/src/card-utils.ts Adds "telegram" to PlatformName type and button style mappings
packages/adapter-telegram/package.json Package configuration for the new adapter
packages/adapter-telegram/tsconfig.json TypeScript configuration
packages/adapter-telegram/tsup.config.ts Build configuration
packages/adapter-telegram/src/types.ts Type definitions for Telegram-specific data structures
packages/adapter-telegram/src/markdown.ts MarkdownV2 format converter implementation
packages/adapter-telegram/src/markdown.test.ts Tests for markdown conversion
packages/adapter-telegram/src/index.ts Main TelegramAdapter implementation
packages/adapter-telegram/src/index.test.ts Tests for adapter functionality
packages/adapter-telegram/src/cards.ts Card to Telegram inline keyboard converter
packages/adapter-telegram/src/cards.test.ts Tests for card conversion
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +102 to +103
if (headerToken !== this.secretToken) {
return new Response("Invalid secret token", { status: 401 });
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The secret token comparison should use a timing-safe comparison function to prevent timing attacks. Simple string comparison (===) can leak information about the secret through timing side-channels. Use crypto.timingSafeEqual for comparing secrets, similar to how the Slack adapter does it (see packages/adapter-slack/src/index.ts around line 1095). Import timingSafeEqual from 'node:crypto' and convert both strings to buffers before comparing.

Copilot uses AI. Check for mistakes.
reloadlife and others added 3 commits February 25, 2026 10:28
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
const telegramCard = cardToTelegram(card);
const result = await this.api.sendMessage(
chatId,
telegramCard.text || cardToFallbackText(card),
Copy link
Contributor

Choose a reason for hiding this comment

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

Card fallback text sent to Telegram with parse_mode: "MarkdownV2" is not escaped, causing API errors when the text contains MarkdownV2 special characters.

Fix on Vercel

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.

2 participants