UNPKG

13.6 kBMarkdownView Raw
1<header>
2<img src="docs/assets/logo.svg" alt="logo" height="90" align="left">
3<h1 style="display: inline">telegraf.js</h1>
4
5Modern Telegram Bot API framework for Node.js
6
7[![Bot API Version](https://img.shields.io/badge/Bot%20API-v5.3-f36caf.svg?style=flat-square)](https://core.telegram.org/bots/api)
8[![install size](https://flat.badgen.net/packagephobia/install/telegraf)](https://packagephobia.com/result?p=telegraf,node-telegram-bot-api)
9[![GitHub top language](https://img.shields.io/github/languages/top/telegraf/telegraf?style=flat-square&logo=github)](https://github.com/telegraf/telegraf)
10[![Russian chat](https://img.shields.io/badge/Russian%20chat-grey?style=flat-square&logo=telegram)](https://t.me/telegraf_ru)
11[![English chat](https://img.shields.io/badge/English%20chat-grey?style=flat-square&logo=telegram)](https://t.me/TelegrafJSChat)
12</header>
13
14## New maintainer needed!
15
16Details and applications: https://github.com/telegraf/telegraf/discussions/1526
17
18## For 3.x users
19
20- [3.x docs](https://telegraf.js.org/v3)
21- [4.0 release notes](https://github.com/telegraf/telegraf/releases/tag/v4.0.0)
22
23## Introduction
24
25Bots are special [Telegram](https://telegram.org) accounts designed to handle messages automatically.
26Users can interact with bots by sending them command messages in private or group chats.
27These accounts serve as an interface for code running somewhere on your server.
28
29Telegraf is a library that makes it simple for you to develop your own Telegram bots using JavaScript or [TypeScript](https://www.typescriptlang.org/).
30
31### Features
32
33- Full [Telegram Bot API 5.3](https://core.telegram.org/bots/api) support
34- [Excellent TypeScript typings](https://github.com/telegraf/telegraf/releases/tag/v4.0.0)
35- [Lightweight](https://packagephobia.com/result?p=telegraf,node-telegram-bot-api)
36- [AWS **λ**](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html)
37 / [Firebase](https://firebase.google.com/products/functions/)
38 / [Glitch](https://glitch.com/edit/#!/dashing-light)
39 / [Heroku](https://devcenter.heroku.com/articles/getting-started-with-nodejs#introduction)
40 / Whatever ready
41- `http/https/fastify/Connect.js/express.js` compatible webhooks
42- Extensible
43
44### Example
45
46```js
47const { Telegraf } = require('telegraf')
48
49const bot = new Telegraf(process.env.BOT_TOKEN)
50bot.start((ctx) => ctx.reply('Welcome'))
51bot.help((ctx) => ctx.reply('Send me a sticker'))
52bot.on('sticker', (ctx) => ctx.reply('👍'))
53bot.hears('hi', (ctx) => ctx.reply('Hey there'))
54bot.launch()
55
56// Enable graceful stop
57process.once('SIGINT', () => bot.stop('SIGINT'))
58process.once('SIGTERM', () => bot.stop('SIGTERM'))
59```
60
61```js
62const { Telegraf } = require('telegraf')
63
64const bot = new Telegraf(process.env.BOT_TOKEN)
65bot.command('oldschool', (ctx) => ctx.reply('Hello'))
66bot.command('hipster', Telegraf.reply('λ'))
67bot.launch()
68
69// Enable graceful stop
70process.once('SIGINT', () => bot.stop('SIGINT'))
71process.once('SIGTERM', () => bot.stop('SIGTERM'))
72```
73
74For additional bot examples see [`examples`](https://github.com/telegraf/telegraf/tree/develop/docs/examples) folder.
75
76### Resources
77
78- [Getting started](#getting-started)
79- [API reference](https://telegraf.js.org/modules.html)
80- Telegram groups (sorted by number of members):
81 * [Russian](https://t.me/telegraf_ru)
82 * [English](https://t.me/TelegrafJSChat)
83 * [Uzbek](https://t.me/telegrafJS_uz)
84 * [Ethiopian](https://t.me/telegraf_et)
85- [GitHub Discussions](https://github.com/telegraf/telegraf/discussions)
86- [Dependent repositories](https://libraries.io/npm/telegraf/dependent_repositories)
87
88## Getting started
89
90### Telegram token
91
92To use the [Telegram Bot API](https://core.telegram.org/bots/api),
93you first have to [get a bot account](https://core.telegram.org/bots)
94by [chatting with BotFather](https://core.telegram.org/bots#6-botfather).
95
96BotFather will give you a *token*, something like `123456789:AbCdfGhIJKlmNoQQRsTUVwxyZ`.
97
98### Installation
99
100```shellscript
101$ npm install telegraf
102```
103or
104```shellscript
105$ yarn add telegraf
106```
107or
108```shellscript
109$ pnpm add telegraf
110```
111
112### `Telegraf` class
113
114[`Telegraf`] instance represents your bot. It's responsible for obtaining updates and passing them to your handlers.
115
116Start by [listening to commands](https://telegraf.js.org/classes/telegraf.html#command) and [launching](https://telegraf.js.org/classes/telegraf.html#launch) your bot.
117
118### `Context` class
119
120`ctx` you can see in every example is a [`Context`] instance.
121[`Telegraf`] creates one for each incoming update and passes it to your middleware.
122It contains the `update`, `botInfo`, and `telegram` for making arbitrary Bot API requests,
123as well as shorthand methods and getters.
124
125This is probably the class you'll be using the most.
126
127
128<!--
129Here is a list of
130
131#### Known middleware
132
133- [Internationalization](https://github.com/telegraf/telegraf-i18n)—simplifies selecting the right translation to use when responding to a user.
134- [Redis powered session](https://github.com/telegraf/telegraf-session-redis)—store session data using Redis.
135- [Local powered session (via lowdb)](https://github.com/RealSpeaker/telegraf-session-local)—store session data in a local file.
136- [Rate-limiting](https://github.com/telegraf/telegraf-ratelimit)—apply rate limitting to chats or users.
137- [Bottleneck powered throttling](https://github.com/KnightNiwrem/telegraf-throttler)—apply throttling to both incoming updates and outgoing API calls.
138- [Menus via inline keyboards](https://github.com/EdJoPaTo/telegraf-inline-menu)—simplify creating interfaces based on menus.
139- [Stateless Questions](https://github.com/EdJoPaTo/telegraf-stateless-question)—create stateless questions to Telegram users working in privacy mode.
140- [Natural language processing via wit.ai](https://github.com/telegraf/telegraf-wit)
141- [Natural language processing via recast.ai](https://github.com/telegraf/telegraf-recast)
142- [Multivariate and A/B testing](https://github.com/telegraf/telegraf-experiments)—add experiments to see how different versions of a feature are used.
143- [Powerfull bot stats via Mixpanel](https://github.com/telegraf/telegraf-mixpanel)
144- [statsd integration](https://github.com/telegraf/telegraf-statsd)
145- [and more...](https://www.npmjs.com/search?q=telegraf-)
146-->
147
148#### Shorthand methods
149
150```js
151import { Telegraf } from 'telegraf'
152
153const bot = new Telegraf(process.env.BOT_TOKEN)
154
155bot.command('quit', (ctx) => {
156 // Explicit usage
157 ctx.telegram.leaveChat(ctx.message.chat.id)
158
159 // Using context shortcut
160 ctx.leaveChat()
161})
162
163bot.on('text', (ctx) => {
164 // Explicit usage
165 ctx.telegram.sendMessage(ctx.message.chat.id, `Hello ${ctx.state.role}`)
166
167 // Using context shortcut
168 ctx.reply(`Hello ${ctx.state.role}`)
169})
170
171bot.on('callback_query', (ctx) => {
172 // Explicit usage
173 ctx.telegram.answerCbQuery(ctx.callbackQuery.id)
174
175 // Using context shortcut
176 ctx.answerCbQuery()
177})
178
179bot.on('inline_query', (ctx) => {
180 const result = []
181 // Explicit usage
182 ctx.telegram.answerInlineQuery(ctx.inlineQuery.id, result)
183
184 // Using context shortcut
185 ctx.answerInlineQuery(result)
186})
187
188bot.launch()
189
190// Enable graceful stop
191process.once('SIGINT', () => bot.stop('SIGINT'))
192process.once('SIGTERM', () => bot.stop('SIGTERM'))
193```
194
195## Production
196
197### Webhooks
198
199```js
200const { Telegraf } = require('telegraf')
201const fs = require('fs')
202require('dotenv')
203
204const bot = new Telegraf(process.env.BOT_TOKEN)
205
206// TLS options
207const tlsOptions = {
208 key: fs.readFileSync('server-key.pem'),
209 cert: fs.readFileSync('server-cert.pem'),
210 ca: [
211 // This is necessary only if the client uses a self-signed certificate.
212 fs.readFileSync('client-cert.pem')
213 ]
214}
215
216// Set telegram webhook
217// The second argument is necessary only if the client uses a self-signed
218// certificate. Including it for a verified certificate may cause things to break.
219bot.telegram.setWebhook('https://server.tld:8443/secret-path', {
220 source: 'server-cert.pem'
221})
222
223// Start https webhook
224bot.startWebhook('/secret-path', tlsOptions, 8443)
225
226// Http webhook, for nginx/heroku users.
227bot.startWebhook('/secret-path', null, 5000)
228```
229
230Use `webhookCallback()` if you want to attach Telegraf to an existing http server.
231
232<!-- global bot, tlsOptions -->
233
234```js
235require('http')
236 .createServer(bot.webhookCallback('/secret-path'))
237 .listen(3000)
238
239require('https')
240 .createServer(tlsOptions, bot.webhookCallback('/secret-path'))
241 .listen(8443)
242```
243
244- [AWS Lambda example integration](https://github.com/telegraf/telegraf/blob/develop/docs/examples/aws-lambda.js)
245- [`express` example integration](https://github.com/telegraf/telegraf/blob/develop/docs/examples/express-webhook-bot.ts)
246- [`fastify` example integration](https://github.com/telegraf/telegraf/blob/develop/docs/examples/fastify-webhook-bot.js)
247- [Google Cloud Functions example integration](https://github.com/telegraf/telegraf/blob/develop/docs/examples/google-cloud-function.ts)
248- [`koa` example integration](https://github.com/telegraf/telegraf/blob/develop/docs/examples/koa-webhook-bot.js)
249- [NestJS framework integration module](https://github.com/bukhalo/nestjs-telegraf)
250- Use [`bot.handleUpdate`](https://telegraf.js.org/classes/telegraf.html#handleupdate) to write new integrations
251
252### Error handling
253
254If middleware throws an error or times out, Telegraf calls `bot.handleError`. If it rethrows, update source closes, and then the error is printed to console and process [hopefully](https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode) terminates. If it does not rethrow, the error is swallowed.
255
256Default `bot.handleError` always rethrows. You can overwrite it using `bot.catch` if you need to.
257
258⚠️ Always rethrow `TimeoutError`!
259
260⚠️ Swallowing unknown errors might leave the process in invalid state!
261
262ℹ️ In production, `systemd` or [`pm2`](https://www.npmjs.com/package/pm2) can restart your bot if it exits for any reason.
263
264## Advanced topics
265
266### Working with files
267
268Supported file sources:
269
270- `Existing file_id`
271- `File path`
272- `Url`
273- `Buffer`
274- `ReadStream`
275
276Also, you can provide an optional name of a file as `filename` when you send the file.
277
278<!-- global bot, fs -->
279
280```js
281bot.on('message', (ctx) => {
282 // resend existing file by file_id
283 ctx.replyWithSticker('123123jkbhj6b')
284
285 // send file
286 ctx.replyWithVideo({ source: '/path/to/video.mp4' })
287
288 // send stream
289 ctx.replyWithVideo({
290 source: fs.createReadStream('/path/to/video.mp4')
291 })
292
293 // send buffer
294 ctx.replyWithVoice({
295 source: Buffer.alloc()
296 })
297
298 // send url via Telegram server
299 ctx.replyWithPhoto('https://picsum.photos/200/300/')
300
301 // pipe url content
302 ctx.replyWithPhoto({
303 url: 'https://picsum.photos/200/300/?random',
304 filename: 'kitten.jpg'
305 })
306})
307```
308
309### Middleware
310
311In addition to `ctx: Context`, each middleware receives `next: () => Promise<void>`.
312
313As in Koa and some other middleware-based libraries,
314`await next()` will call next middleware and wait for it to finish:
315
316```js
317import { Telegraf } from 'telegraf'
318
319const bot = new Telegraf(process.env.BOT_TOKEN)
320
321bot.use(async (ctx, next) => {
322 console.time(`Processing update ${ctx.update.update_id}`)
323 await next() // runs next middleware
324 // runs after next middleware finishes
325 console.timeEnd(`Processing update ${ctx.update.update_id}`)
326})
327
328bot.on('text', (ctx) => ctx.reply('Hello World'))
329bot.launch()
330
331// Enable graceful stop
332process.once('SIGINT', () => bot.stop('SIGINT'))
333process.once('SIGTERM', () => bot.stop('SIGTERM'))
334```
335
336With this simple ability, you can:
337- extract information from updates and then `await next()` to avoid disrupting other middleware,
338- like [`Composer`] and [`Router`], `await next()` for updates you don't wish to handle,
339- like [`session`] and [`Scenes`], [extend the context](#extending-context) by mutating `ctx` before `await next()`,
340- [intercept API calls](https://github.com/telegraf/telegraf/discussions/1267#discussioncomment-254525),
341- reuse [other people's code](https://www.npmjs.com/search?q=telegraf-),
342- do whatever **you** come up with!
343
344[`Composer`]: https://telegraf.js.org/classes/composer.html
345[`Context`]: https://telegraf.js.org/classes/context.html
346[`Router`]: https://telegraf.js.org/classes/router.html
347[`session`]: https://telegraf.js.org/modules.html#session
348[`Scenes`]: https://telegraf.js.org/modules/scenes.html
349[`Telegraf`]: https://telegraf.js.org/classes/telegraf.html
350
351### Usage with TypeScript
352
353Telegraf is written in TypeScript and therefore ships with declaration files for the entire library.
354Moreover, it includes types for the complete Telegram API via the [`typegram`](https://github.com/KnorpelSenf/typegram) package.
355While most types of Telegraf's API surface are self-explanatory, there's some notable things to keep in mind.
356
357#### Extending `Context`
358
359The exact shape of `ctx` can vary based on the installed middleware.
360Some custom middleware might register properties on the context object that Telegraf is not aware of.
361Consequently, you can change the type of `ctx` to fit your needs in order for you to have proper TypeScript types for your data.
362This is done through Generics:
363
364```ts
365import { Context, Telegraf } from 'telegraf'
366
367// Define your own context type
368interface MyContext extends Context {
369 myProp?: string
370 myOtherProp?: number
371}
372
373// Create your bot and tell it about your context type
374const bot = new Telegraf<MyContext>('SECRET TOKEN')
375
376// Register middleware and launch your bot as usual
377bot.use((ctx, next) => {
378 // Yay, `myProp` is now available here as `string | undefined`!
379 ctx.myProp = ctx.chat?.first_name?.toUpperCase()
380 return next()
381})
382// ...
383```