@molecule/api-channel-telegram
v1.0.1
Published
Telegram channel bond.
Readme
@molecule/api-channel-telegram
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Telegram channel provider for molecule.dev.
Implements the framework-agnostic {@link ChannelProvider} interface
over the Telegram Bot API. Bond under the named-multi-provider
'channel' category at app startup:
Quick Start
import { setProvider } from '@molecule/api-channel'
import { provider } from '@molecule/api-channel-telegram'
setProvider('telegram', provider)Type
provider
Installation
npm install @molecule/api-channel-telegram @molecule/api-channel @molecule/api-secretsAPI
Interfaces
ProcessEnv
Environment variables consumed by the Telegram channel provider.
interface ProcessEnv {
/** Bot API token (`<bot_id>:<auth_string>`). */
CHANNEL_TELEGRAM_BOT_TOKEN: string
/** Shared `secret_token` value Telegram echoes back on webhook calls. */
CHANNEL_TELEGRAM_WEBHOOK_SECRET: string
}TelegramCallbackQuery
Subset of the Telegram CallbackQuery object used to surface button
clicks via {@link InboundMessage.payload}.
interface TelegramCallbackQuery {
/** Identifier of this callback query. */
id: string
/** User who triggered the callback. */
from: TelegramUser
/** Message the inline keyboard was attached to. */
message?: TelegramMessage
/** Opaque payload originally set on the inline keyboard button. */
data?: string
}TelegramChat
Subset of the Telegram Chat object used for inbound normalization.
interface TelegramChat {
/** Chat identifier (positive for users, negative for groups). */
id: number
/** Chat kind (`'private'`, `'group'`, `'supergroup'`, `'channel'`). */
type?: string
/** Title for group / channel chats. */
title?: string
/** Username for public chats. */
username?: string
}TelegramConfig
Configuration for the Telegram channel provider.
The bot token is the credential that authorizes Bot API calls — it is
deliberately accepted only via this config (or the
CHANNEL_TELEGRAM_BOT_TOKEN env var) and is NEVER included in error
messages, log lines, or normalized payloads.
interface TelegramConfig {
/**
* Telegram bot token (`<bot_id>:<auth_string>`). Defaults to the
* `CHANNEL_TELEGRAM_BOT_TOKEN` env var.
*
* Treat as a secret — providers redact this value in any user-facing
* output.
*/
botToken?: string
/**
* Shared secret value Telegram echoes back via the
* `X-Telegram-Bot-Api-Secret-Token` header on every webhook request.
*
* Must match the `secret_token` registered via
* `setWebhook?secret_token=...`. Defaults to the
* `CHANNEL_TELEGRAM_WEBHOOK_SECRET` env var.
*
* If unset, {@link TelegramChannelProvider.verifyWebhookSignature}
* returns `false`.
*/
webhookSecret?: string
/**
* Default `parse_mode` for outbound messages — `'HTML'` or
* `'MarkdownV2'`. Defaults to `'HTML'`.
*/
defaultParseMode?: TelegramParseMode
/**
* Bot API base URL. Override only for tests / self-hosted Bot API
* servers. Defaults to `https://api.telegram.org`.
*/
apiBaseUrl?: string
/**
* Per-request timeout in milliseconds. Defaults to 10000.
*/
timeoutMs?: number
}TelegramDocument
Subset of the Telegram Document object.
interface TelegramDocument {
/** Identifier used to download the file via `getFile`. */
file_id: string
/** Stable identifier across bots for the same file. */
file_unique_id?: string
/** Original filename, if available. */
file_name?: string
/** Reported MIME type. */
mime_type?: string
/** File size in bytes, if known. */
file_size?: number
}TelegramInlineQuery
Subset of the Telegram InlineQuery object surfaced via
{@link InboundMessage.payload}.
interface TelegramInlineQuery {
/** Identifier of this inline query. */
id: string
/** User issuing the query. */
from: TelegramUser
/** Free-text query body. */
query: string
}TelegramMessage
Subset of the Telegram Message object inspected during inbound
normalization.
interface TelegramMessage {
/** Sequential message identifier within the chat. */
message_id: number
/** Unix timestamp (seconds) the message was sent. */
date?: number
/** Author of the message. */
from?: TelegramUser
/** Chat the message belongs to. */
chat: TelegramChat
/** Plain-text body, if any. */
text?: string
/** Caption on a media message. */
caption?: string
/** Photo size variants attached to the message. */
photo?: TelegramPhotoSize[]
/** Document attached to the message. */
document?: TelegramDocument
/** Forum topic identifier (when posted in a forum supergroup). */
message_thread_id?: number
/** Whether the message was sent inside a forum topic. */
is_topic_message?: boolean
}TelegramPhotoSize
Subset of the Telegram PhotoSize object.
interface TelegramPhotoSize {
/** Identifier used to download the file via `getFile`. */
file_id: string
/** Stable identifier across bots for the same file. */
file_unique_id?: string
/** Photo width in pixels. */
width?: number
/** Photo height in pixels. */
height?: number
/** File size in bytes, if known. */
file_size?: number
}TelegramUpdate
Subset of the Telegram Update object delivered to the webhook
endpoint. Only the variants the provider parses are typed; additional
fields are passed through opaquely on
{@link InboundMessage.payload}.
interface TelegramUpdate {
/** Incremental update identifier. */
update_id: number
/** Standard chat message. */
message?: TelegramMessage
/** Edited standard chat message. */
edited_message?: TelegramMessage
/** Channel post. */
channel_post?: TelegramMessage
/** Edited channel post. */
edited_channel_post?: TelegramMessage
/** Inline keyboard button click. */
callback_query?: TelegramCallbackQuery
/** Inline-mode query. */
inline_query?: TelegramInlineQuery
}TelegramUser
Subset of the Telegram User object used when normalizing inbound
payloads. Only fields the provider actually inspects are typed.
interface TelegramUser {
/** Telegram user identifier. */
id: number
/** Whether the user is a bot. */
is_bot?: boolean
/** First name (displayed in clients). */
first_name?: string
/** Optional last name. */
last_name?: string
/** Optional `@username`. */
username?: string
}Types
TelegramParseMode
Telegram message formatting flavours supported by the Bot API. Plain text is sent when no parse mode is set.
type TelegramParseMode = 'HTML' | 'MarkdownV2'Classes
TelegramChannelProvider
Telegram channel provider — implements the framework-agnostic {@link ChannelProvider} contract on top of the Bot API.
Functions
createProvider(config)
Convenience factory for the named-multi-provider bond pattern.
function createProvider(config?: TelegramConfig): TelegramChannelProviderconfig— Optional Telegram config.
Returns: A new {@link TelegramChannelProvider} instance.
Constants
channelTelegramSecretDefinitions
Secret definitions required by the Telegram channel bond.
const channelTelegramSecretDefinitions: SecretDefinition[]provider
Lazily-instantiated singleton instance for app-startup wiring. Reads configuration from environment variables on first use.
const provider: ChannelProviderCore Interface
Implements @molecule/api-channel interface.
Injection Notes
Requirements
Peer dependencies:
@molecule/api-channel^1.0.1@molecule/api-secrets^1.0.1
Environment Variables
CHANNEL_TELEGRAM_BOT_TOKEN(required) — Telegram bot token- Setup: Create a bot with @BotFather in Telegram (/newbot) and copy the token.
- Get it here: https://t.me/BotFather
- Example:
123456789:ABC-DEF...
CHANNEL_TELEGRAM_WEBHOOK_SECRET(optional) — Telegram webhook secret- Auto-generated at scaffold — no manual setup.
Runtime Dependencies
@molecule/api-channel@molecule/api-secretsInbound updates require a one-time webhook registration the bond does not perform. Call Telegram's
setWebhookonce with your public URL andsecret_token=CHANNEL_TELEGRAM_WEBHOOK_SECRET:https://api.telegram.org/bot<token>/setWebhook?url=<https-url>&secret_token=<secret>. OutboundsendMessage()works without this.verifyWebhookSignature()compares theX-Telegram-Bot-Api-Secret-Tokenheader againstCHANNEL_TELEGRAM_WEBHOOK_SECRETand is FAIL-CLOSED: with no secret configured (or a secret never passed tosetWebhook) every inbound update is rejected. Treat the secret as required whenever the app consumes inbound Telegram messages.
E2E Tests
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:
- [ ] Each channel-notifying flow the app defines (a Slack/Discord alert on
a new order, a status-change message) actually produces a message. The
sandbox CAPTURES channel messages instead of sending — read them with the
read_activitytool (filter type 'channel'); never mock the flow or modify production code to expose the message. - [ ] The captured message targets the configured channel/provider name and
carries the app's real content (readable text, no
undefinedplaceholders, no secrets). - [ ] A failed send (unbonded or misconfigured provider) is visible in logs/UI — never silently swallowed.
