{"id":13461885,"url":"https://github.com/yagop/node-telegram-bot-api","last_synced_at":"2026-07-02T00:00:19.000Z","repository":{"id":37906188,"uuid":"38216778","full_name":"yagop/node-telegram-bot-api","owner":"yagop","description":"Telegram Bot API for NodeJS","archived":false,"fork":false,"pushed_at":"2026-06-29T22:45:26.000Z","size":3560,"stargazers_count":9183,"open_issues_count":27,"forks_count":1642,"subscribers_count":155,"default_branch":"master","last_synced_at":"2026-06-29T23:23:31.074Z","etag":null,"topics":["api","bot","bot-framework","chatbot","nodejs","telegram"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yagop.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2015-06-28T22:35:33.000Z","updated_at":"2026-06-29T22:06:14.000Z","dependencies_parsed_at":"2023-02-12T21:45:34.677Z","dependency_job_id":"7a482217-38e1-4e0f-a403-de44a9386997","html_url":"https://github.com/yagop/node-telegram-bot-api","commit_stats":{"total_commits":537,"total_committers":87,"mean_commits":6.172413793103448,"dds":0.7057728119180633,"last_synced_commit":"6077f9ba103cb969753199f5a4fc92c78eef902c"},"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"purl":"pkg:github/yagop/node-telegram-bot-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yagop%2Fnode-telegram-bot-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yagop%2Fnode-telegram-bot-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yagop%2Fnode-telegram-bot-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yagop%2Fnode-telegram-bot-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yagop","download_url":"https://codeload.github.com/yagop/node-telegram-bot-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yagop%2Fnode-telegram-bot-api/sbom","scorecard":{"id":1240418,"data":{"date":"2025-12-08","repo":{"name":"github.com/yagop/node-telegram-bot-api","commit":"5d95b43bc013af1b8b73032d94ff3541eb6b263a"},"scorecard":{"version":"v5.4.1-0.20251211185148-6c8b5dbbedcf","commit":"6c8b5dbbedcf26e5511695b853fecfe7cbf2235d"},"score":4.7,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"9 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":3,"reason":"Found 9/30 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'","Warn: branch protection not enabled for branch 'release'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/6c8b5dbbedcf26e5511695b853fecfe7cbf2235d/docs/checks.md#sast"}}]},"last_synced_at":"2025-12-14T17:57:07.470Z","repository_id":37906188,"created_at":"2025-12-14T17:57:07.470Z","updated_at":"2025-12-14T17:57:07.470Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35027341,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","bot","bot-framework","chatbot","nodejs","telegram"],"created_at":"2024-07-31T12:00:26.382Z","updated_at":"2026-07-02T00:00:18.993Z","avatar_url":"https://github.com/yagop.png","language":"TypeScript","funding_links":[],"categories":["Bot Libraries","JavaScript","Backend \u0026 Infrastructure","后端开发框架及项目","Description","Telegram Libraries","Bots","Libraries","TypeScript","Chatbots \u0026 Virtual Companions","一般机器人（bots）"],"sub_categories":["Bots \u0026 Messaging","管理面板","Node","Bot Libs","Node.js","Unofficial","Telegram","机器人类库"],"readme":"\u003ch1 align=\"center\"\u003e✨ A Modern Telegram Bot API Library ✨\u003c/h1\u003e\n\n\u003cdiv align=center\u003e\n\n[![Bot API](https://img.shields.io/badge/Bot%20API-v.10.1-00aced.svg?style=flat-square\u0026logo=telegram)](https://core.telegram.org/bots/api)\n[![npm package](https://img.shields.io/npm/v/node-telegram-bot-api?logo=npm\u0026style=flat-square)](https://www.npmjs.org/package/node-telegram-bot-api)\n\n[![https://telegram.me/node_telegram_bot_api](https://img.shields.io/badge/💬%20Telegram-Channel-blue.svg?style=flat-square)](https://telegram.me/node_telegram_bot_api)\n[![https://t.me/+_IC8j_b1wSFlZTVk](https://img.shields.io/badge/💬%20Telegram-Group-blue.svg?style=flat-square)](https://t.me/+_IC8j_b1wSFlZTVk)\n[![https://telegram.me/Yago_Perez](https://img.shields.io/badge/💬%20Telegram-Yago_Perez-blue.svg?style=flat-square)](https://telegram.me/Yago_Perez)\n\n\u003c/div\u003e\n\n\u003e **v2 is a from-scratch redesign, no v1 compatibility.** Coming from v1? See the [v1 -\u003e v2 migration guide](./CHANGELOG.md) in the changelog.\n\n## 📦 Install\n\n```sh\nnpm install node-telegram-bot-api@next\n```\n\n\u003e **Runs on **Bun, modern Node.js, Deno, Cloudflare Workers and Vercel Functions λ**\n\n## 🚀 Usage\n\n```ts\nimport { Bot, InlineKeyboardBuilder } from \"node-telegram-bot-api\";\nimport { run } from \"node-telegram-bot-api/node\"; // managed runner: wires Ctrl-C to bot.stop()\n\nconst bot = new Bot(process.env.BOT_TOKEN!);\n\n// commands, regex and update types are all middleware - registration order wins\nbot.command(\"start\", (ctx) =\u003e ctx.reply(\"Hi! Send me anything.\"));\nbot.hears(/echo (.+)/, (ctx) =\u003e ctx.reply(ctx.match![1]!));\n\nbot.on(\"message\", (ctx) =\u003e\n  ctx.reply(\"Pick one:\", {\n    reply_markup: new InlineKeyboardBuilder()\n      .text(\"👍\", \"up\")\n      .text(\"👎\", \"down\")\n      .build(),\n  }),\n);\n\n// 🔘 a tapped inline button comes back as a callback_query\nbot.on(\"callback_query\", async (ctx) =\u003e {\n  await ctx.answerCallbackQuery({ text: `You tapped ${ctx.callbackQuery!.data}` });\n});\n\nawait run(bot); // core-only alternative that runs anywhere: await bot.startPolling()\n```\n\n## 📡 Calling the API directly\n\n`Api` mirrors the wire API 1:1 - one method per Bot API method, each taking a single params object.\n\n```ts\nimport { Api } from \"node-telegram-bot-api\";\n\nconst api = new Api(process.env.BOT_TOKEN!);\nconst me = await api.getMe();\nawait api.sendMessage({ chat_id: 12345, text: \"hello\" });\n// the same client is also on bot.api and ctx.api\n```\n\n## 🧩 Middleware\n\nkoa-style middleware around every update; `on`/`command`/`hears` are filters in the same chain. Wrap downstream work with `await next()`.\n\n```ts\n// ⏱️ time every update - and catch anything thrown downstream\nbot.use(async (ctx, next) =\u003e {\n  const start = Date.now();\n  try {\n    await next();\n  } finally {\n    console.log(`update took ${Date.now() - start}ms`);\n  }\n});\n\n// 🧯 last-resort error handler\nbot.catch((err, ctx) =\u003e console.error(\"handler failed\", err));\n```\n\n## ⌨️ Keyboards \u0026 formatting\n\nStructured fields are plain typed objects - pass a literal or use a fluent builder; the pipeline serializes either.\n\n```ts\nimport { Bot, InlineKeyboardBuilder, ReplyKeyboardBuilder, EntityBuilder } from \"node-telegram-bot-api\";\n\nconst bot = new Bot(process.env.BOT_TOKEN!);\n\n// 🎛️ inline keyboard as reply_markup\nawait bot.api.sendMessage({\n  chat_id,\n  text: \"Choose:\",\n  reply_markup: new InlineKeyboardBuilder()\n    .text(\"A\", \"a\")\n    .url(\"Docs\", \"https://core.telegram.org/bots/api\")\n    .row()\n    .text(\"B\", \"b\")\n    .build(),\n});\n\n// ⌨️ reply keyboard as reply_markup\nawait bot.api.sendMessage({\n  chat_id,\n  text: \"Yes or no?\",\n  reply_markup: new ReplyKeyboardBuilder()\n    .text(\"Yes\")\n    .text(\"No\")\n    .build({ resize_keyboard: true }),\n});\n\n// ✍️ rich text - EntityBuilder computes UTF-16 offsets for you\nconst { text, entities } = new EntityBuilder()\n  .plain(\"Hello \")\n  .bold(\"world\")\n  .link(\"docs\", \"https://github.com/yagop/node-telegram-bot-api\")\n  .build();\nawait bot.api.sendMessage({ chat_id, text, entities });\n\n// any structured field is just a plain object - no wrapper needed\nawait bot.api.sendMessage({ chat_id, text: \"hi\", link_preview_options: { is_disabled: true } });\n```\n\n## 📤 Uploads\n\nA bare string is always a `file_id` or URL. Wrap raw bytes to upload them. Pass a\n`filename` with the right extension - the core does no content sniffing, so the name is\nwhat Telegram sees (`fromPath` uses the basename).\n\n```ts\nimport { Bot, InputFile, MediaGroupBuilder } from \"node-telegram-bot-api\";\nimport { fromPath } from \"node-telegram-bot-api/node\";\n\nconst bot = new Bot(process.env.BOT_TOKEN!);\n\n// upload from disk (Node only)\nawait bot.api.sendPhoto({ chat_id, photo: await fromPath(\"./cat.jpg\") });\n// upload raw bytes (web-standard, runs anywhere)\nawait bot.api.sendDocument({ chat_id, document: new InputFile(bytes, { filename: \"report.pdf\" }) });\n\n// a raw InputFile nested in a structure is auto-hoisted to an attach:// part\nawait bot.api.sendMediaGroup({\n  chat_id,\n  media: [\n    { type: \"photo\", media: new InputFile(bytesA, { filename: \"a.jpg\" }), caption: \"A\" },\n    { type: \"photo\", media: \"https://telegram.org/example/photo.jpg\" },\n  ],\n});\n\n// MediaGroupBuilder: optional sugar for the same array\nawait bot.api.sendMediaGroup({\n  chat_id,\n  media: new MediaGroupBuilder()\n    .photo({ media: new InputFile(bytesA, { filename: \"a.jpg\" }), caption: \"A\" })\n    .photo({ media: \"https://telegram.org/example/photo.jpg\" })\n    .build(),\n});\n```\n\nBuilders cover the other `attach://` methods; each `.build()` returns the plain shape.\n\n```ts\nimport {\n  Bot,\n  InputFile,\n  StickerSetBuilder,\n  StaticProfilePhotoBuilder,\n  PhotoStoryBuilder,\n} from \"node-telegram-bot-api\";\n\nconst bot = new Bot(process.env.BOT_TOKEN!);\n\n// collect a sticker set\nawait bot.api.createNewStickerSet({\n  user_id,\n  name,\n  title,\n  stickers: new StickerSetBuilder()\n    .add({ sticker: new InputFile(pngBytes, { filename: \"sticker.png\" }), format: \"static\", emoji_list: [\"🙂\"] })\n    .build(),\n});\n\n// a single sticker is a plain InputSticker - no builder needed\nawait bot.api.addStickerToSet({\n  user_id,\n  name,\n  sticker: { sticker: new InputFile(pngBytes, { filename: \"sticker.png\" }), format: \"static\", emoji_list: [\"🙂\"] },\n});\n\n// profile photo: Static / AnimatedProfilePhotoBuilder\nawait bot.api.setMyProfilePhoto({\n  photo: new StaticProfilePhotoBuilder({ photo: new InputFile(pngBytes, { filename: \"avatar.png\" }) }).build(),\n});\n\n// story: Photo / VideoStoryBuilder\nawait bot.api.postStory({\n  business_connection_id,\n  active_period,\n  content: new PhotoStoryBuilder({ photo: new InputFile(pngBytes, { filename: \"story.png\" }) }).build(),\n});\n```\n\n## 🪝 Webhooks\n\nThe web-standard callback is a pure `(Request) =\u003e Promise\u003cResponse\u003e` - one function for every serverless runtime.\n\n**Cloudflare Workers / Bun.serve / Deno Deploy / Vercel Edge:**\n\n```ts\nimport { Bot, webhookCallback } from \"node-telegram-bot-api\";\n\nconst bot = new Bot(TOKEN);\nbot.on(\"message\", (ctx) =\u003e ctx.reply(\"hi from the edge\"));\n\nexport default {\n  fetch: webhookCallback(bot, { secretToken: SECRET }),\n};\n```\n\nBy default the callback awaits your handler before `200`. For slow handlers, opt into **early-ACK**:\n\n```ts\nexport default {\n  // ✅ return 200 immediately, then finish the handler in the background\n  // waitUntil keeps the platform alive until it settles (fastAck: true = fire-and-forget)\n  fetch: (req: Request, _env: unknown, ctx: { waitUntil(promise: Promise\u003cunknown\u003e): void }) =\u003e\n    webhookCallback(bot, { secretToken: SECRET, waitUntil: (p) =\u003e ctx.waitUntil(p) })(req),\n};\n```\n\n**Next.js App Router** (`app/api/bot/route.ts`):\n\n```ts\nimport { Bot, nextAppWebhook } from \"node-telegram-bot-api\";\nconst bot = new Bot(process.env.BOT_TOKEN!);\nexport const POST = nextAppWebhook(bot, { secretToken: process.env.SECRET });\n```\n\n**Express** (mount on an app you already have):\n\n```ts\nimport express from \"express\";\nimport { Bot, registerExpressWebhook } from \"node-telegram-bot-api\";\n\nconst app = express();\nconst bot = new Bot(TOKEN);\nregisterExpressWebhook(bot, app, { path: \"/telegram\", secretToken: SECRET });\napp.listen(3000);\n```\n\n**Self-hosted Node server** (`node-telegram-bot-api/node`):\n\n```ts\nimport { Bot } from \"node-telegram-bot-api\";\nimport { createWebhookServer, startWebhook } from \"node-telegram-bot-api/node\";\n\n// Low-level: you own the server and the port.\nconst server = createWebhookServer(new Bot(TOKEN), { path: \"/telegram\", secretToken: SECRET });\nserver.listen(8080);\n\n// Or the managed one-liner (listen + graceful shutdown, the webhook peer of run()):\nawait startWebhook(new Bot(TOKEN), { port: 8080, path: \"/telegram\", secretToken: SECRET });\n```\n\nRegister the URL once: `api.setWebhook({ url, secret_token })`. The `secret_token` is the only thing authenticating callers (payloads aren't signed) - treat it as required in production, and terminate TLS at your proxy.\n\n## ⚠️ Errors\n\nErrors expose structured fields, so you branch on values, not message text.\n\n```ts\nimport { TelegramApiError, NetworkError, TimeoutError } from \"node-telegram-bot-api\";\n\ntry {\n  await api.sendMessage({ chat_id, text });\n} catch (err) {\n  // 🔁 429s are auto-retried (honoring retry_after) by default - this is the manual form\n  if (err instanceof TelegramApiError \u0026\u0026 err.errorCode === 429) {\n    await sleep((err.retryAfter ?? 1) * 1000);\n  } else if (err instanceof NetworkError || err instanceof TimeoutError) {\n    // transient transport failure\n  }\n}\n```\n\n### 🧯 Handler errors: the boundary contract\n\nAn error thrown by a handler never stops the bot. It is routed to the error boundary, which by default logs it via `console.error` and consumes the update - polling keeps pumping, and a webhook delivery is ACKed (Telegram does not redeliver it). Install your own boundary with `bot.catch()`:\n\n```ts\nbot.catch((err, ctx) =\u003e {\n  console.error(\"update\", ctx.update.update_id, \"failed:\", err);\n});\n```\n\nThrowing from the boundary opts back into fail-loud: `startPolling()` rejects (the update was never confirmed, so Telegram redelivers it on restart) and `webhookCallback` responds 500 (Telegram redelivers). `bot.catch((err) =\u003e { throw err; })` is the explicit fail-loud opt-in.\n\n## 🛡️ Resilience \u0026 rate limiting\n\nSafe defaults out of the box - set only what you want to change.\n\n```ts\nimport { Api } from \"node-telegram-bot-api\";\n\nconst api = new Api(TOKEN, {\n  // 🔁 retries 429 (retry_after first), network/timeout/5xx with jittered backoff\n  maxRetries: 2,        // default 2\n  retryBackoffMs: 300,  // default 300\n\n  // 🚦 opt-in throttle (requests/sec); omit for zero overhead\n  rateLimit: { global: 30, perChat: 1 },\n});\n```\n\nLong polling resumes through transient errors instead of dying on the first blip:\n\n```ts\nimport { longPoll } from \"node-telegram-bot-api\";\n\nfor await (const update of longPoll(api, {\n  timeout: 30,\n  retry: true,          // default true - resume on transient errors, keep the offset\n  maxBackoffMs: 60_000, // default 60s - cap between failed polls\n  onError: (err) =\u003e console.warn(\"poll failed, backing off\", err),\n}, signal)) {\n  // ... fatal 4xx still stops the loop; an aborted signal returns cleanly\n}\n```\n\n## 🌊 Low-level update stream\n\n`longPoll` is a plain async generator - `for await`, `take(n)`, filter, batch or fan out as you like.\n\n```ts\nimport { Api, longPoll } from \"node-telegram-bot-api\";\n\nconst api = new Api(TOKEN);\nconst ac = new AbortController();\nfor await (const update of longPoll(api, { timeout: 30 }, ac.signal)) {\n  console.log(update.update_id);\n}\n```\n\n## 🐛 Debugging\n\nSet `DEBUG` (the `debug` convention) to trace request lifecycle, polling and webhooks to **stderr**:\n\n```sh\nDEBUG=\"node-telegram-bot-api:*\" node app.js\n# node-telegram-bot-api:transport -\u003e sendMessage\n# node-telegram-bot-api:transport \u003c- sendMessage ok +142ms\n```\n\nNamespaces: `:transport`, `:polling`, `:webhook` (filter, or exclude one with a leading `-`). Tracing is Node-only - wired up by importing `node-telegram-bot-api/node`; on edge runtimes it's an inert no-op.\n\n## 🛠️ Development\n\n```sh\nbun run generate:types   # regenerate types + client from the live Bot API docs\nbun run check            # tsc (strict) + core-isolation lint + edge bundle + unit tests\nbun run build            # emit dist/\n```\n\n## 👥 Contributors\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/yagop/node-telegram-bot-api/graphs/contributors\"\u003e\n    \u003cimg src=\"https://contrib.rocks/image?repo=yagop/node-telegram-bot-api\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## 📄 License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyagop%2Fnode-telegram-bot-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyagop%2Fnode-telegram-bot-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyagop%2Fnode-telegram-bot-api/lists"}