telegraf
Version:
📡 Modern Telegram bot framework
259 lines (187 loc) • 6.41 kB
Markdown
# Introduction
## Application
A Telegraf application is an object containing an array of middlewares which are composed
and executed in a stack-like manner upon request. Is similar to many other middleware systems
that you may have encountered such as Koa, Ruby's Rack, Connect.
## Middleware
Middleware is an essential part of any modern framework.
It allows you to modify requests and responses as they pass between the Telegram and your bot.
You can imagine middleware as a chain of logic connection your bot to the Telegram request.
Middleware normally takes two parameters (ctx, next), `ctx` is the context for one Telegram message,
`next` is a function that is invoked to execute the downstream middleware.
It returns a Promise with a then function for running code after completion.
```js
const app = new Telegraf(process.env.BOT_TOKEN)
app.use((ctx, next) => {
const start = new Date()
return next(ctx).then(() => {
const ms = new Date() - start
console.log('Response time %sms', ms)
})
})
app.on('text', (ctx) => ctx.reply('Hello World'))
```
#### Cascading with async functions
You might need Babel(or `node >=v.7.x` with harmony flags) for running following example.
```js
app.use(async (ctx, next) => {
const start = new Date()
await next()
const ms = new Date() - start
console.log('Response time %sms', ms)
})
```
#### Known middleware
- [Internationalization](https://github.com/telegraf/telegraf-i18n)
- [Redis powered session](https://github.com/telegraf/telegraf-session-redis)
- [Local powered session (via lowdb)](https://github.com/RealSpeaker/telegraf-session-local) - Supports in-memory/(a)sync files/... & JSON/YAML/XML/...
- [Stateful chatbots engine](https://github.com/telegraf/telegraf-flow)
- [Rate-limiting](https://github.com/telegraf/telegraf-ratelimit)
- [Natural language processing via wit.ai](https://github.com/telegraf/telegraf-wit)
- [Natural language processing via recast.ai](https://github.com/telegraf/telegraf-recast)
- [Multivariate and A/B testing](https://github.com/telegraf/telegraf-experiments)
- [Powerfull bot stats via Mixpanel](https://github.com/telegraf/telegraf-mixpanel)
- [statsd integration](https://github.com/telegraf/telegraf-statsd)
- [and more...](https://www.npmjs.com/search?q=telegraf-)
## Error handling
By default Telegraf will print all errors to stderr and rethrow error.
To perform custom error-handling logic use following snippet:
```js
const app = new Telegraf(process.env.BOT_TOKEN)
app.catch((err) => {
console.log('Ooops', err)
})
```
## Context
A Telegraf context encapsulates telegram update.
```js
app.on('sticker', (ctx) => {
console.log(ctx.message.sticker)
return ctx.reply('Hey there!')
})
```
[Context documentation](context.md)
## State
The recommended namespace to share information between middlewares.
```js
const app = new Telegraf(process.env.BOT_TOKEN)
// Auth middleware
app.use((ctx, next) => {
ctx.state.role = getUserRole(ctx.message)
return next()
})
app.on('text', (ctx) => {
return ctx.reply(`Hello ${ctx.state.role}`)
})
```
## Session
```js
const app = new Telegraf(process.env.BOT_TOKEN)
app.use(Telegraf.memorySession())
app.on('text', (ctx) => {
ctx.session.counter = ctx.session.counter || 0
ctx.session.counter++
return ctx.reply(`Message counter:${ctx.session.counter}`)
})
```
**Note: For persistent sessions you might use any of [`telegraf-session-*`](https://www.npmjs.com/search?q=telegraf-session) middleware.**
## Update types
Supported update types:
- `message`
- `edited_message`
- `callback_query`
- `inline_query`
- `shipping_query`
- `pre_checkout_query`
- `chosen_inline_result`
- `channel_post`
- `edited_channel_post`
Available update sub-types:
`text`, `audio`, `document`, `photo`, `sticker`, `video`, `voice`, `contact`,
`location`, `venue`, `new_chat_members`, `left_chat_member`, `new_chat_title`,
`new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `migrate_to_chat_id`,
`supergroup_chat_created`, `channel_chat_created`, `migrate_from_chat_id`,
`pinned_message`, `game`, `video_note`, `invoice`, `successful_payment`.
```js
// Handle message update
bot.on('message', (ctx) => {
return ctx.reply('Hey there!')
})
// Handle sticker or photo update
bot.on(['sticker', 'photo'], (ctx) => {
console.log(ctx.message)
return ctx.reply('Cool!')
})
```
<sub>[Related Telegram api docs](https://core.telegram.org/bots/api#message)</sub>
## Webhooks
```js
const app = new Telegraf(process.env.BOT_TOKEN)
// TLS options
const tlsOptions = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ca: [
// This is necessary only if the client uses the self-signed certificate.
fs.readFileSync('client-cert.pem')
]
}
// Set telegram webhook
app.telegram.setWebhook('https://server.tld:8443/secret-path', {
source: fs.readFileSync('server-cert.pem')
})
// Start https webhook
app.startWebhook('/secret-path', tlsOptions, 8443)
// Http webhook, for nginx/heroku users.
app.startWebhook('/secret-path', null, 5000)
```
Use webhookCallback() if you want to attach telegraf to existing http server
```js
require('http')
.createServer(app.webhookCallback('/secret-path'))
.listen(3000)
require('https')
.createServer(tlsOptions, app.webhookCallback('/secret-path'))
.listen(8443)
```
Connect/Express.js integration
```js
const express = require('express')
const expressApp = express()
expressApp.use(app.webhookCallback('/secret-path'))
expressApp.get('/', (req, res) => {
res.send('Hello World!')
})
expressApp.listen(3000, () => {
console.log('Example app listening on port 3000!')
})
```
## Working with files
Supported file sources:
- `Existing file_id`
- `File path`
- `Url`
- `Buffer`
- `ReadStream`
Also you can provide optional name of file as `filename`.
```js
bot.on(['sticker', 'photo'], (ctx) => {
// resend existing file by file_id
ctx.answerWithSticker('123123jkbhj6b')
// send file
ctx.answerWithVideo({ source: '/path/to/video.mp4' })
// send stream
ctx.answerWithVideo({
source: fs.createReadStream('/path/to/video.mp4')
})
// send buffer
ctx.answerWithVoice({
source: new Buffer()
})
// send url
ctx.answerWithPhoto({
url: 'http://lorempixel.com/400/200/cats/',
filename: 'kitten.jpg'
})
})
```