UNPKG

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