{"_id":"@askchannelai/telegram","name":"@askchannelai/telegram","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@askchannelai/telegram","version":"0.1.0","description":"Telegram glue for AskChannel bots — parse commands, build inline-picker dropdowns, and render ready-to-send HTML for the ask + import flows. Dependency-free; built on @askchannelai/sdk.","keywords":["askchannel","telegram","bot","grammy","youtube","transcripts","inline-mode"],"license":"MIT","type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=18"},"scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"peerDependencies":{"@askchannelai/sdk":">=0.3.0"},"devDependencies":{"@askchannelai/sdk":"*","tsup":"^8.0.0","typescript":"^5.4.0"},"publishConfig":{"access":"public"},"gitHead":"06de75f1b7714f5b3b8f9e2047b4c12ff55929e8","_id":"@askchannelai/telegram@0.1.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-AKKWYzViXzFfl/0YToeuirtSBBtveoIVbOOaR/IEGIZ+/K5KqO2MBMUGN2dUzGnVJjzoaHmlK7PGNkl934Pbuw==","shasum":"a5455e373624ba8362c93d9f71cbcd067c03d395","tarball":"https://registry.npmjs.org/@askchannelai/telegram/-/telegram-0.1.0.tgz","fileCount":7,"unpackedSize":48555,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDzxQ7/w/Udjm6vYYPHlc+AL1VhoWxmZwxAkn5pGujXHQIhAOI5rwrr6eMBMTUiX1X41Nu9LkRJ812val6aDbfBt7RZ"}]},"_npmUser":{"name":"askchannel","email":"beastse@gmail.com"},"directories":{},"maintainers":[{"name":"askchannel","email":"beastse@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/telegram_0.1.0_1780852474491_0.6218805419608169"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-07T17:14:34.301Z","0.1.0":"2026-06-07T17:14:34.664Z","modified":"2026-06-07T17:14:34.899Z"},"maintainers":[{"name":"askchannel","email":"beastse@gmail.com"}],"description":"Telegram glue for AskChannel bots — parse commands, build inline-picker dropdowns, and render ready-to-send HTML for the ask + import flows. Dependency-free; built on @askchannelai/sdk.","keywords":["askchannel","telegram","bot","grammy","youtube","transcripts","inline-mode"],"license":"MIT","readme":"# @askchannelai/telegram\n\nTelegram glue for [AskChannel](https://askchannel.ai) bots, on top of\n[`@askchannelai/sdk`](../sdk). Pure, dependency-free helpers that turn inbound\nTelegram text into AskChannel calls and turn AskChannel responses into\n**ready-to-send HTML** — so you write almost no glue.\n\nYour bot keeps the token, the HTTP, and the platform wiring; this package owns\nthe AskChannel-specific parts:\n\n- **Parse** `/askchannel @handle …` commands and `@handle` mentions into\n  `{ channel, question }`.\n- **Build** the inline channel-picker dropdown (`searchChannels` → articles).\n- **Recover** a picked channel from the user's reply — fully stateless.\n- **Render** answer errors and the whole **import** flow (search → confirm cost\n  → progress → done) as HTML strings.\n\nWorks with [grammY](https://grammy.dev), [Telegraf](https://telegraf.js.org), or\nraw Bot API calls; long-polling or webhooks.\n\n## Install\n\n```bash\nnpm install @askchannelai/sdk @askchannelai/telegram\n```\n\n`@askchannelai/sdk` is a **peer dependency** (the error renderers narrow on the\nSDK's `AskChannelError`), so install both.\n\n## Quick start (grammY)\n\n```ts\nimport { Bot } from \"grammy\";\nimport { createAskChannelClient } from \"@askchannelai/sdk\";\nimport {\n  buildInlineResults,\n  channelRefFromPickReply,\n  qaErrorMessage,\n} from \"@askchannelai/telegram\";\n\nconst ac = createAskChannelClient({ token: process.env.ASKCHANNEL_TOKEN });\nconst bot = new Bot(process.env.TELEGRAM_BOT_TOKEN!);\n\n// Inline dropdown of indexed channels.\nbot.on(\"inline_query\", async (ctx) => {\n  const channels = await ac.searchChannels(ctx.inlineQuery.query);\n  await ctx.answerInlineQuery(buildInlineResults(channels));\n});\n\n// A reply to a picked channel = the question for it.\nbot.on(\"message:text\", async (ctx) => {\n  const reply = ctx.message.reply_to_message;\n  const ref = reply\n    ? channelRefFromPickReply(\n        { via_bot: reply.via_bot, entities: reply.entities },\n        ctx.me.username,\n      )\n    : null;\n  if (!ref) return;\n  try {\n    const res = await ac.ask({ channel: ref, question: ctx.message.text, platform: \"telegram\" });\n    await ctx.reply(res.rendered as string, { parse_mode: \"HTML\" });\n  } catch (e) {\n    await ctx.reply(qaErrorMessage(ref, e), { parse_mode: \"HTML\" });\n  }\n});\n```\n\nSee [`examples/telegram-bot`](../../examples/telegram-bot) for the full bot\n(commands, search button, placeholder-then-edit).\n\n## API\n\nAll helpers are pure (no I/O, no env). Anything that needs your bot's username\nor web origin takes it as an argument.\n\n### Ask flow\n\n| Export | Description |\n|--------|-------------|\n| `parseChannelMention(text, botUsername)` | Pull `{ handle, prompt }` from a message that @-mentions a channel (never your own bot). `null` if none. |\n| `parseAskChannelCommand(text, botUsername)` | Parse `/askchannel @handle …` (tolerates `/askchannel@yourbot`). Returns `ok` \\| `usage` \\| `null`. |\n| `qaErrorMessage(handle, error)` | Friendly HTML for a failed `ask()`, keyed on `AskChannelError.code`. |\n| `ASKCHANNEL_USAGE` | Usage-hint HTML string. |\n\n### Inline channel picker\n\n| Export | Description |\n|--------|-------------|\n| `parseInlineAskChannelQuery(query)` | Gate the dropdown behind a `/askchannel` inline prefix; returns the search term or `null`. |\n| `buildInlineResults(channels, { baseUrl? })` | SDK channels → inline-query article rows. |\n| `pickPromptMessage(channel, { baseUrl? })` | The HTML message sent when a channel is tapped (carries the channel ref in an `ask=` link). |\n| `channelRefFromPickReply(reply, botUsername)` | Recover the picked channel's ref from a reply. Stateless. |\n| `askRef(channel)` | The channel's QA route ref (handle without `@`, else id). |\n\n### Import flow (`/askchannel-import`)\n\n| Export | Description |\n|--------|-------------|\n| `IMPORT_INLINE_PREFIX`, `IMPORT_CALLBACK_RE` | The inline prefix and the `aci:go\\|x:<UCid>` callback-data pattern. |\n| `parseInlineImportQuery(query)` | Gate the import dropdown behind `/askchannel-import`. |\n| `buildImportInlineResults(channels)` | YouTube search results → inline article rows. |\n| `importChannelIdFromMessage(msg, botUsername)` | Recover the `UC…` id from a picked import-prompt. |\n| `importConfirmMessage(quote)` | Cost-confirm message + `✅ Import` / `✖ Cancel` keyboard. |\n| `importStartedMessage` / `importProgressMessage` / `importDoneMessage` | Lifecycle copy for triggered / polling / completed imports. |\n| `importErrorMessage(error, title)`, `quoteLabel(quote)`, `importLabelFromMessage(msg)` | Error copy and display-label helpers. |\n\n### Utilities\n\n| Export | Description |\n|--------|-------------|\n| `escapeHtml(s)` | Escape `&`, `<`, `>` for `parse_mode: \"HTML\"`. |\n| Types | `InlineKeyboardButton`, `InlineKeyboardMarkup`, `InlineQueryResultArticle`, `ChannelMention`, `AskChannelCommand`, `PickerOptions`. |\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-0a0f9ebdb5ca63caec280930ff689de0"}