New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

telegraf

Package Overview
Dependencies
Maintainers
1
Versions
241
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

telegraf - npm Package Compare versions

Comparing version 1.1.2 to 2.0.0-alpha.0

lib/context.js

581

api.md
# API reference
- [Telegraf-API](#telegraf-api)
- [Context](#context)
- [Telegraf](#telegraf-api)
- [Telegram](#telegram-api)
- [Uploading files](#file)
- [Shortcuts](#shortcuts)
## Context
A Telegraf Context encapsulates telegram message.
Context is created per request and contains following props:
```js
app.use((ctx) => {
ctx.telegram // Telegram instance
ctx.updateType // Update type(message, inline_query, etc.)
[ctx.updateSubType] // Update subtype(text, sticker, audio, etc.)
[ctx.message] // Received message
[ctx.editedMessage] // Edited message
[ctx.inlineQuery] // Received inline query
[ctx.chosenInlineResult] // Received inline query result
[ctx.callbackQuery] // Received callback query
[ctx.chat] // Current chat info
[ctx.from] // Sender info
[ctx.match] // Regex match (available only for `hears` handler)
})
```
The recommended way to extend application context.
```js
const app = new Telegraf(process.env.BOT_TOKEN)
app.context.db = {
getScores: () => { return 42 }
}
app.on('text', (ctx) => {
const scores = ctx.db.getScores(ctx.message.from.username)
return ctx.reply(`${ctx.message.from.username}: ${score}`)
})
```
Context shortcuts for **message** update:
- `ctx.getChat() -> `[`ctx.telegram.getChat()`](#getchat)
- `ctx.getChatAdministrators() -> `[`ctx.telegram.getChatAdministrators()`](#getchatadministrators)
- `ctx.getChatMember() -> `[`ctx.telegram.getChatMember()`](#getchatmember)
- `ctx.getChatMembersCount() -> `[`ctx.telegram.getChatMembersCount()`](#getchatmemberscount)
- `ctx.leaveChat() -> `[`ctx.telegram.leaveChat()`](#leavechat)
- `ctx.reply() -> `[`ctx.telegram.sendMessage()`](#sendmessage)
- `ctx.replyWithMarkdown() -> `[`ctx.telegram.sendMessage()`](#sendmessage)
- `ctx.replyWithHTML() -> `[`ctx.telegram.sendMessage()`](#sendmessage)
- `ctx.replyWithAudio() -> `[`ctx.telegram.sendAudio()`](#sendaudio)
- `ctx.replyWithChatAction() -> `[`ctx.telegram.sendChatAction()`](#sendchataction)
- `ctx.replyWithDocument() -> `[`ctx.telegram.sendDocument()`](#senddocument)
- `ctx.replyWithLocation() -> `[`ctx.telegram.sendLocation()`](#sendlocation)
- `ctx.replyWithPhoto() -> `[`ctx.telegram.sendPhoto()`](#sendphoto)
- `ctx.replyWithSticker() -> `[`ctx.telegram.sendSticker()`](#sendsticker)
- `ctx.replyWithVideo() -> `[`ctx.telegram.sendVideo()`](#sendvideo)
- `ctx.replyWithVoice() -> `[`ctx.telegram.sendVoice()`](#sendvoice)
Context shortcuts for **callback_query** update:
- `ctx.answerCallbackQuery() -> `[`ctx.telegram.answerCallbackQuery()`](#answercallbackquery)
- `ctx.getChat() -> `[`ctx.telegram.getChat()`](#getchat)
- `ctx.getChatAdministrators() -> `[`ctx.telegram.getChatAdministrators()`](#getchatadministrators)
- `ctx.getChatMember() -> `[`ctx.telegram.getChatMember()`](#getchatmember)
- `ctx.getChatMembersCount() -> `[`ctx.telegram.getChatMembersCount()`](#getchatmemberscount)
- `ctx.leaveChat() -> `[`ctx.telegram.leaveChat()`](#leavechat)
- `ctx.reply() -> `[`ctx.telegram.sendMessage()`](#sendmessage)
- `ctx.replyWithMarkdown() -> `[`ctx.telegram.sendMessage()`](#sendmessage)
- `ctx.replyWithHTML() -> `[`ctx.telegram.sendMessage()`](#sendmessage)
- `ctx.replyWithAudio() -> `[`ctx.telegram.sendAudio()`](#sendaudio)
- `ctx.replyWithChatAction() -> `[`ctx.telegram.sendChatAction()`](#sendchataction)
- `ctx.replyWithDocument() -> `[`ctx.telegram.sendDocument()`](#senddocument)
- `ctx.replyWithLocation() -> `[`ctx.telegram.sendLocation()`](#sendlocation)
- `ctx.replyWithPhoto() -> `[`ctx.telegram.sendPhoto()`](#sendphoto)
- `ctx.replyWithSticker() -> `[`ctx.telegram.sendSticker()`](#sendsticker)
- `ctx.replyWithVideo() -> `[`ctx.telegram.sendVideo()`](#sendvideo)
- `ctx.replyWithVoice() -> `[`ctx.telegram.sendVoice()`](#sendvoice)
Context shortcuts for **inline_query** update:
- `ctx.answerInlineQuery() -> `[`ctx.telegram.answerInlineQuery()`](#answerinlinequery)
### Examples
```js
var bot = new Telegraf(process.env.BOT_TOKEN)
bot.on('text', (ctx) => {
// Simple usage
ctx.telegram.sendMessage(ctx.message.chat.id, `Hello ${ctx.state.role}`)
// Using shortcut
ctx.reply(`Hello ${ctx.state.role}`)
// If you want to mark message as reply to source message
ctx.reply(`Hello ${ctx.state.role}`, { reply_to_message_id: ctx.message.id })
})
bot.on('/quit', (ctx) => {
// Simple usage
ctx.telegram.leaveChat(ctx.message.chat.id)
// Using shortcut
ctx.leaveChat()
})
bot.on('callback_query', (ctx) => {
// Simple usage
ctx.telegram.answerCallbackQuery(ctx.callbackQuery.id)
// Using shortcut
ctx.answerCallbackQuery()
})
bot.on('inline_query', (ctx) => {
var result = []
// Simple usage
ctx.telegram.answerInlineQuery(ctx.inlineQuery.id, result)
// Using shortcut
ctx.answerInlineQuery(result)
})
```
## Telegraf API
- [`Telegraf.mount(messageType, handler, [handler...])`](#mount)
```js
const Telegraf = require('telegraf')
```
- [`Telegraf.mount(messageType, handler)`](#mount)
- [`Telegraf.compose(handlers)`](#compose)
- [`new Telegraf(token)`](#new)
- [`new Telegraf(token)`](#new-telegraf)
- [`.use(function)`](#use)
- [`.on(messageType, handler, [handler...])`](#on)
- [`.hears(string|ReGex, handler, [handler...])`](#hears)
- [`.startPolling(timeout, limit)`](#startPolling)
- [`.startWebHook(webHookPath, tlsOptions, port, [host])`](#startwebhook)
- [`.stop()`](#stop)
- [`.webHookCallback(webHookPath)`](#webhookcallback)
- [`.handleUpdate(rawUpdate, response)`](#handleupdate)
* * *
<a name="mount"></a>
#### `Telegraf.mount(updateType, handler) => function`
Generates middleware for handling provided [update type](#update-types).
| Param | Type | Description |
| --- | --- | --- |
| updateType | `string`\|`string[]` | [update type](#update-types) |
| handler | `function` | Handler |
* * *
<a name="compose"></a>
#### `Telegraf.compose(handlers) => function`
Compose `middleware` returning a fully valid middleware comprised of all those which are passed.
| Param | Type | Description |
| --- | --- | --- |
| handlers | `function[]` | Array of handlers |
* * *
<a name="new-telegraf"></a>
#### `new Telegraf(token)`
Initialize new Telegraf app.
| Param | Type | Description |
| --- | --- | --- |
| token | `string` | [Bot Token](https://core.telegram.org/bots#3-how-do-i-create-a-bot) |
* * *
<a name="use"></a>
#### `telegraf.use(middleware)`
Registers a middleware.
| Param | Type | Description |
| --- | --- | --- |
| middleware | `function` | Middleware function |
* * *
<a name="on"></a>
#### `telegraf.on(updateType, handler, [handler...])`
Registers handler for provided [update type](#update-types).
| Param | Type | Description |
| --- | --- | --- |
| updateType | `string`\|`string[]` | [update type](#update-types) |
| handler | `function` | Handler |
* * *
<a name="hears"></a>
#### `telegraf.hears(pattern, handler, [handler...])`
Registers handler only for `text` updates using string pattern or RegEx.
| Param | Type | Description |
| --- | --- | --- |
| pattern | `string`\|`RegEx` | Pattern or RegEx |
| handler | `function` | Handler |
* * *
<a name="startPolling"></a>
#### `telegraf.startPolling(timeout, limit)`
Start poll updates.
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| timeout | `number` | 0 | Poll timeout |
| limit | `number` | 100 | Limits the number of updates to be retrieved |
* * *
<a name="startwebhook"></a>
#### `telegraf.startWebHook(webHookPath, tlsOptions, port, [host])`
Start listening @ `https://host:port/webHookPath` for Telegram calls.
| Param | Type | Description |
| --- | --- | --- |
| webHookPath | `string` | Webhook url path (see Telegraf.setWebHook) |
| tlsOptions | `object` | (Optional) [TLS server options](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener). Pass null to use http |
| port | `number` | Port number |
| [host] | `string` | (Optional) Hostname |
* * *
<a name="stop"></a>
#### `telegraf.stop()`
Stop WebHook and polling
* * *
<a name="webhookcallback"></a>
#### `telegraf.webHookCallback(webHookPath) => Function`
Return a callback function suitable for the http[s].createServer() method to handle a request.
You may also use this callback function to mount your telegraf app in a Koa/Connect/Express app.
| Param | Type | Description |
| --- | --- | --- |
| webHookPath | `string` | Webhook url path (see Telegraf.setWebHook) |
* * *
<a name="handleupdate"></a>
#### `telegraf.handleUpdate(rawUpdate, [webHookResponse])`
Handle raw Telegram update.
In case you use centralized webhook server, queue, etc.
| Param | Type | Description |
| --- | --- | --- |
| rawUpdate | `object` | Telegram update payload |
| [webHookResponse] | `object` | (Optional) [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) |
## Telegram API
```js
const Telegram = require('telegraf').Telegram
```
- [`new Telegram(token)`](#new-telegram)
- [`.answerCallbackQuery(callbackQueryId, text, showAlert)`](#answercallbackquery)

@@ -27,7 +296,4 @@ - [`.answerInlineQuery(inlineQueryId, results, extra)`](#answerinlinequery)

- [`.getUserProfilePhotos(userId, offset, limit)`](#getuserprofilephotos)
- [`.handleUpdate(rawUpdate, response)`](#handleupdate)
- [`.hears(string|ReGex, handler, [handler...])`](#hears)
- [`.kickChatMember(chatId, userId)`](#kickchatmember)
- [`.leaveChat(chatId)`](#leavechat)
- [`.on(messageType, handler, [handler...])`](#on)
- [`.removeWebHook()`](#removewebhook)

@@ -46,37 +312,9 @@ - [`.sendAudio(chatId, audio, extra)`](#sendaudio)

- [`.setWebHook(url, cert)`](#setwebhook)
- [`.startPolling(timeout, limit)`](#startPolling)
- [`.startWebHook(webHookPath, tlsOptions, port, [host])`](#startwebhook)
- [`.stop()`](#stop)
- [`.unbanChatMember(chatId, userId)`](#unbanchatmember)
- [`.use(function)`](#use)
- [`.webHookCallback(webHookPath)`](#webhookcallback)
***
<a name="mount"></a>
#### `Telegraf.mount(updateType, handler, [handler...]) => GeneratorFunction`
Generates middleware for handling provided [update type](#update-types).
| Param | Type | Description |
| --- | --- | --- |
| updateType | `string`\|`string[]` | [update type](#update-types) |
| handler | `GeneratorFunction` | Handler |
* * *
<a name="compose"></a>
#### `Telegraf.compose(handlers) => GeneratorFunction`
<a name="new-telegram"></a>
#### `new Telegram(token, options)`
Compose `middleware` returning a fully valid middleware comprised of all those which are passed.
| Param | Type | Description |
| --- | --- | --- |
| handlers | `GeneratorFunction[]` | Array of handlers |
* * *
<a name="new"></a>
#### `new Telegraf(token)`
Initialize new Telegraf app.

@@ -87,7 +325,9 @@

| token | `string` | [Bot Token](https://core.telegram.org/bots#3-how-do-i-create-a-bot) |
| token | `object` | Options |
* * *
<a name="answercallbackquery"></a>
#### `telegraf.answerCallbackQuery(callbackQueryId, text, showAlert) => Promise`
#### `telegram.answerCallbackQuery(callbackQueryId, text, showAlert) => Promise`

@@ -107,3 +347,3 @@ Use this method to send answers to callback queries.

<a name="answerinlinequery"></a>
#### `telegraf.answerInlineQuery(inlineQueryId, results, extra) => Promise`
#### `telegram.answerInlineQuery(inlineQueryId, results, extra) => Promise`

@@ -121,3 +361,3 @@ Use this method to send answers to an inline query.

<a name="editmessagecaption"></a>
#### `telegraf.editMessageCaption(chatId, messageId, caption, extra) => Promise`
#### `telegram.editMessageCaption(chatId, messageId, caption, extra) => Promise`

@@ -136,3 +376,3 @@ Use this method to edit captions of messages sent by the bot or via the bot

<a name="editmessagereplymarkup"></a>
#### `telegraf.editMessageReplyMarkup(chatId, messageId, markup, extra) => Promise`
#### `telegram.editMessageReplyMarkup(chatId, messageId, markup, extra) => Promise`

@@ -151,3 +391,3 @@ Use this method to edit only the reply markup of messages sent by the bot or via the bot.

<a name="editmessagetext"></a>
#### `telegraf.editMessageText(chatId, messageId, text, extra) => Promise`
#### `telegram.editMessageText(chatId, messageId, text, extra) => Promise`

@@ -166,3 +406,3 @@ Use this method to edit text messages sent by the bot or via the bot.

<a name="forwardmessage"></a>
#### `telegraf.forwardMessage(chatId, fromChatId, messageId, extra) => Promise`
#### `telegram.forwardMessage(chatId, fromChatId, messageId, extra) => Promise`

@@ -182,3 +422,3 @@ Forwards message.

<a name="sendcopy"></a>
#### `telegraf.sendCopy(chatId, message, extra) => Promise`
#### `telegram.sendCopy(chatId, message, extra) => Promise`

@@ -196,3 +436,3 @@ Sends message copy.

<a name="getchat"></a>
#### `telegraf.getChat(chatId) => Promise`
#### `telegram.getChat(chatId) => Promise`

@@ -210,3 +450,3 @@ Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.).

<a name="getchatadministrators"></a>
#### `telegraf.getChatAdministrators(chatId) => Promise`
#### `telegram.getChatAdministrators(chatId) => Promise`

@@ -224,3 +464,3 @@ Use this method to get a list of administrators in a chat. On success, returns an Array of ChatMember objects that contains information about all chat administrators except other bots. If the chat is a group or a supergroup and no administrators were appointed, only the creator will be returned.

<a name="getchatmember"></a>
#### `telegraf.getChatMember(chatId) => Promise`
#### `telegram.getChatMember(chatId) => Promise`

@@ -237,3 +477,3 @@ Use this method to get information about a member of a chat.

<a name="getchatmemberscount"></a>
#### `telegraf.getChatMembersCount(chatId) => Promise`
#### `telegram.getChatMembersCount(chatId) => Promise`

@@ -251,3 +491,3 @@ Use this method to get the number of members in a chat.

<a name="getfile"></a>
#### `telegraf.getFile(fileId) => Promise`
#### `telegram.getFile(fileId) => Promise`

@@ -265,3 +505,3 @@ Returns basic info about a file and prepare it for downloading.

<a name="getFileLink"></a>
#### `telegraf.getFileLink(fileId) => Promise`
#### `telegram.getFileLink(fileId) => Promise`

@@ -279,3 +519,3 @@ Returns link to file.

<a name="getme"></a>
#### `telegraf.getMe() => Promise`
#### `telegram.getMe() => Promise`

@@ -289,3 +529,3 @@ Returns basic information about the bot.

<a name="getuserprofilephotos"></a>
#### `telegraf.getUserProfilePhotos(userId, offset, limit) => Promise`
#### `telegram.getUserProfilePhotos(userId, offset, limit) => Promise`

@@ -304,29 +544,4 @@ Returns profiles photos for provided user.

<a name="handleupdate"></a>
#### `telegraf.handleUpdate(rawUpdate, [webHookResponse])`
Handle raw Telegram update.
In case you use centralized webhook server, queue, etc.
| Param | Type | Description |
| --- | --- | --- |
| rawUpdate | `object` | Telegram update payload |
| [webHookResponse] | `object` | (Optional) [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) |
* * *
<a name="hears"></a>
#### `telegraf.hears(pattern, handler, [handler...])`
Registers handler only for `text` updates using string pattern or RegEx.
| Param | Type | Description |
| --- | --- | --- |
| pattern | `string`\|`RegEx` | Pattern or RegEx |
| handler | `GeneratorFunction` | Handler |
* * *
<a name="kickchatmember"></a>
#### `telegraf.kickChatMember(chatId, userId) => Promise`
#### `telegram.kickChatMember(chatId, userId) => Promise`

@@ -346,3 +561,3 @@ Use this method to kick a user from a group or a supergroup.

<a name="leavechat"></a>
#### `telegraf.leaveChat(chatId) => Promise`
#### `telegram.leaveChat(chatId) => Promise`

@@ -359,24 +574,13 @@ Use this method for your bot to leave a group, supergroup or channel.

<a name="on"></a>
#### `telegraf.on(updateType, handler, [handler...])`
Registers handler for provided [update type](#update-types).
| Param | Type | Description |
| --- | --- | --- |
| updateType | `string`\|`string[]` | [update type](#update-types) |
| handler | `GeneratorFunction` | Handler |
* * *
<a name="removewebhook"></a>
#### `telegraf.removeWebHook() => Promise`
#### `telegram.removeWebHook() => Promise`
Removes webhook. Shortcut for `Telegraf.setWebHook('')`
Removes webhook. Shortcut for `Telegram.setWebHook('')`
<sub>[Related Telegram api docs](https://core.telegram.org/bots/api#removewebhook)</sub>
* * *
<a name="sendaudio"></a>
#### `telegraf.sendAudio(chatId, audio, extra) => Promise`
#### `telegram.sendAudio(chatId, audio, extra) => Promise`

@@ -394,3 +598,3 @@ Sends audio.

<a name="sendchataction"></a>
#### `telegraf.sendChatAction(chatId, action) => Promise`
#### `telegram.sendChatAction(chatId, action) => Promise`

@@ -407,3 +611,3 @@ Sends chat action.

<a name="sendcontact"></a>
#### `telegraf.sendContact(chatId, phoneNumber, firstName, extra) => Promise`
#### `telegram.sendContact(chatId, phoneNumber, firstName, extra) => Promise`

@@ -422,3 +626,3 @@ Sends document.

<a name="senddocument"></a>
#### `telegraf.sendDocument(chatId, doc, extra) => Promise`
#### `telegram.sendDocument(chatId, doc, extra) => Promise`

@@ -436,3 +640,3 @@ Sends document.

<a name="sendlocation"></a>
#### `telegraf.sendLocation(chatId, latitude, longitude, extra) => Promise`
#### `telegram.sendLocation(chatId, latitude, longitude, extra) => Promise`

@@ -451,3 +655,3 @@ Sends location.

<a name="sendmessage"></a>
#### `telegraf.sendMessage(chatId, text, extra) => Promise`
#### `telegram.sendMessage(chatId, text, extra) => Promise`

@@ -465,3 +669,3 @@ Sends text message.

<a name="sendphoto"></a>
#### `telegraf.sendPhoto(chatId, photo, extra) => Promise`
#### `telegram.sendPhoto(chatId, photo, extra) => Promise`

@@ -479,3 +683,3 @@ Sends photo.

<a name="sendsticker"></a>
#### `telegraf.sendSticker(chatId, sticker, extra) => Promise`
#### `telegram.sendSticker(chatId, sticker, extra) => Promise`

@@ -493,3 +697,3 @@ Sends sticker.

<a name="sendvenue"></a>
#### `telegraf.sendVenue(chatId, latitude, longitude, title, address, extra) => Promise`
#### `telegram.sendVenue(chatId, latitude, longitude, title, address, extra) => Promise`

@@ -510,3 +714,3 @@ Sends venue information.

<a name="sendvideo"></a>
#### `telegraf.sendVideo(chatId, video, extra) => Promise`
#### `telegram.sendVideo(chatId, video, extra) => Promise`

@@ -524,3 +728,3 @@ Sends video.

<a name="sendvoice"></a>
#### `telegraf.sendVoice(chatId, voice, extra) => Promise`
#### `telegram.sendVoice(chatId, voice, extra) => Promise`

@@ -538,3 +742,3 @@ Sends voice.

<a name="setwebhook"></a>
#### `telegraf.setWebHook(url, [cert]) => Promise`
#### `telegram.setWebHook(url, [cert]) => Promise`

@@ -552,37 +756,4 @@ Specifies an url to receive incoming updates via an outgoing webhook.

<a name="startwebhook"></a>
#### `telegraf.startWebHook(webHookPath, tlsOptions, port, [host])`
Start listening @ `https://host:port/webHookPath` for Telegram calls.
| Param | Type | Description |
| --- | --- | --- |
| webHookPath | `string` | Webhook url path (see Telegraf.setWebHook) |
| tlsOptions | `object` | (Optional) [TLS server options](https://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener). Pass null to use http |
| port | `number` | Port number |
| [host] | `string` | (Optional) Hostname |
* * *
<a name="startPolling"></a>
#### `telegraf.startPolling(timeout, limit)`
Start poll updates.
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| timeout | `number` | 0 | Poll timeout |
| limit | `number` | 100 | Limits the number of updates to be retrieved |
* * *
<a name="stop"></a>
#### `telegraf.stop()`
Stop WebHook and polling
* * *
<a name="unbanchatmember"></a>
#### `telegraf.unbanChatMember(chatId, userId) => Promise`
#### `telegram.unbanChatMember(chatId, userId) => Promise`

@@ -600,25 +771,2 @@ Use this method to unban a previously kicked user in a supergroup.

<a name="use"></a>
#### `telegraf.use(middleware)`
Registers a middleware.
| Param | Type | Description |
| --- | --- | --- |
| middleware | `function` | Middleware function |
* * *
<a name="webhookcallback"></a>
#### `telegraf.webHookCallback(webHookPath) => Function`
Return a callback function suitable for the http[s].createServer() method to handle a request.
You may also use this callback function to mount your telegraf app in a Koa/Connect/Express app.
| Param | Type | Description |
| --- | --- | --- |
| webHookPath | `string` | Webhook url path (see Telegraf.setWebHook) |
* * *
### Update types

@@ -640,10 +788,10 @@

// Handle message update
telegraf.on('message', function * () {
this.reply('Hey there!')
telegraf.on('message', (ctx) => {
return ctx.reply('Hey there!')
})
// Handle sticker update
telegraf.on(['sticker', 'photo'], function * () {
console.log(this.message)
this.reply('Cool!')
telegraf.on(['sticker', 'photo'], (ctx) => {
console.log(ctx.message)
return ctx.reply('Cool!')
})

@@ -668,3 +816,3 @@

*FYI: Telegram servers detect content type using file extension(May 2016).*
*FYI: Telegram servers detect content type using file extension (May 2016).*

@@ -675,6 +823,6 @@ Example:

// resend existing file by file_id
telegraf.sendSticker('chatId', '123123jkbhj6b')
telegram.sendSticker('chatId', '123123jkbhj6b')
// send file
telegraf.sendVideo('chatId', {
telegram.sendVideo('chatId', {
source: '/path/to/video.mp4'

@@ -684,3 +832,3 @@ })

// send stream
telegraf.sendVideo('chatId', {
telegram.sendVideo('chatId', {
source: fs.createReadStream('/path/to/video.mp4')

@@ -690,3 +838,3 @@ })

// send buffer
telegraf.sendVoice('chatId', {
telegram.sendVoice('chatId', {
source: new Buffer()

@@ -696,3 +844,3 @@ })

// send url
telegraf.sendPhoto('chatId', {
telegram.sendPhoto('chatId', {
url: 'http://lorempixel.com/400/200/cats/',

@@ -704,88 +852,1 @@ filename: 'kitten.jpg'

<sub>[Related Telegram api docs](https://core.telegram.org/bots/api#file)</sub>
## Shortcuts
Available shortcuts for **message** update:
- `this.getChat() -> `[`telegraf.getChat()`](#getchat)
- `this.getChatAdministrators() -> `[`telegraf.getChatAdministrators()`](#getchatadministrators)
- `this.getChatMember() -> `[`telegraf.getChatMember()`](#getchatmember)
- `this.getChatMembersCount() -> `[`telegraf.getChatMembersCount()`](#getchatmemberscount)
- `this.leaveChat() -> `[`telegraf.leaveChat()`](#leavechat)
- `this.reply() -> `[`telegraf.sendMessage()`](#sendmessage)
- `this.replyWithMarkdown() -> `[`telegraf.sendMessage()`](#sendmessage)
- `this.replyWithHTML() -> `[`telegraf.sendMessage()`](#sendmessage)
- `this.replyWithAudio() -> `[`telegraf.sendAudio()`](#sendaudio)
- `this.replyWithChatAction() -> `[`telegraf.sendChatAction()`](#sendchataction)
- `this.replyWithDocument() -> `[`telegraf.sendDocument()`](#senddocument)
- `this.replyWithLocation() -> `[`telegraf.sendLocation()`](#sendlocation)
- `this.replyWithPhoto() -> `[`telegraf.sendPhoto()`](#sendphoto)
- `this.replyWithSticker() -> `[`telegraf.sendSticker()`](#sendsticker)
- `this.replyWithVideo() -> `[`telegraf.sendVideo()`](#sendvideo)
- `this.replyWithVoice() -> `[`telegraf.sendVoice()`](#sendvoice)
Available shortcuts for **callback_query** update:
- `this.answerCallbackQuery() -> `[`telegraf.answerCallbackQuery()`](#answercallbackquery)
- `this.getChat() -> `[`telegraf.getChat()`](#getchat)
- `this.getChatAdministrators() -> `[`telegraf.getChatAdministrators()`](#getchatadministrators)
- `this.getChatMember() -> `[`telegraf.getChatMember()`](#getchatmember)
- `this.getChatMembersCount() -> `[`telegraf.getChatMembersCount()`](#getchatmemberscount)
- `this.leaveChat() -> `[`telegraf.leaveChat()`](#leavechat)
- `this.reply() -> `[`telegraf.sendMessage()`](#sendmessage)
- `this.replyWithMarkdown() -> `[`telegraf.sendMessage()`](#sendmessage)
- `this.replyWithHTML() -> `[`telegraf.sendMessage()`](#sendmessage)
- `this.replyWithAudio() -> `[`telegraf.sendAudio()`](#sendaudio)
- `this.replyWithChatAction() -> `[`telegraf.sendChatAction()`](#sendchataction)
- `this.replyWithDocument() -> `[`telegraf.sendDocument()`](#senddocument)
- `this.replyWithLocation() -> `[`telegraf.sendLocation()`](#sendlocation)
- `this.replyWithPhoto() -> `[`telegraf.sendPhoto()`](#sendphoto)
- `this.replyWithSticker() -> `[`telegraf.sendSticker()`](#sendsticker)
- `this.replyWithVideo() -> `[`telegraf.sendVideo()`](#sendvideo)
- `this.replyWithVoice() -> `[`telegraf.sendVoice()`](#sendvoice)
Available shortcuts for **inline_query** update:
- `this.answerInlineQuery() -> `[`telegraf.answerInlineQuery()`](#answerinlinequery)
### Examples
```js
var telegraf = new Telegraf(process.env.BOT_TOKEN)
telegraf.on('text', function * (){
// Simple usage
telegraf.sendMessage(this.message.chat.id, `Hello ${this.state.role}`)
// Using shortcut
this.reply(`Hello ${this.state.role}`)
// If you want to mark message as reply to source message
this.reply(`Hello ${this.state.role}`, { reply_to_message_id: this.message.id })
})
telegraf.on('/quit', function * (){
// Simple usage
telegraf.leaveChat(this.message.chat.id)
// Using shortcut
this.leaveChat()
})
telegraf.on('callback_query', function * (){
// Simple usage
telegraf.answerCallbackQuery(this.callbackQuery.id)
// Using shortcut
this.answerCallbackQuery()
})
telegraf.on('inline_query', function * (){
var result = []
// Simple usage
telegraf.answerInlineQuery(this.inlineQuery.id, result)
// Using shortcut
this.answerInlineQuery(result)
})
```

@@ -12,12 +12,12 @@ var debug = require('debug')('telegraf:session-memory')

return function * (next) {
var key = opts.getSessionKey(this)
return (ctx, next) => {
var key = opts.getSessionKey(ctx)
if (!key) {
return yield next
return next()
}
var session = {}
this.__defineGetter__('session', function () {
ctx.__defineGetter__('session', function () {
return session
})
this.__defineSetter__('session', function (val) {
ctx.__defineSetter__('session', function (val) {
session = Object.assign({}, val)

@@ -28,5 +28,3 @@ })

session = db[key] || {}
yield next
} catch (err) {
throw err
return next()
} finally {

@@ -33,0 +31,0 @@ debug('save session', session)

@@ -1,3 +0,1 @@

var _ = require('lodash')
module.exports = {

@@ -41,20 +39,2 @@ defaultExtensions: {

],
chatShortcuts: [
{ name: 'reply', target: 'sendMessage' },
{ name: 'getChat', target: 'getChat' },
{ name: 'leaveChat', target: 'leaveChat' },
{ name: 'getChatAdministrators', target: 'getChatAdministrators' },
{ name: 'getChatMember', target: 'getChatMember' },
{ name: 'getChatMembersCount', target: 'getChatMembersCount' },
{ name: 'replyWithPhoto', target: 'sendPhoto' },
{ name: 'replyWithAudio', target: 'sendAudio' },
{ name: 'replyWithDocument', target: 'sendDocument' },
{ name: 'replyWithSticker', target: 'sendSticker' },
{ name: 'replyWithVideo', target: 'sendVideo' },
{ name: 'replyWithVoice', target: 'sendVoice' },
{ name: 'replyWithChatAction', target: 'sendChatAction' },
{ name: 'replyWithLocation', target: 'sendLocation' },
{ name: 'replyWithVenue', target: 'sendVenue' },
{ name: 'replyWithContact', target: 'sendContact' }
],
webHookAnswerBlacklist: [

@@ -92,4 +72,4 @@ 'getChat',

sticker: (message) => message.sticker.file_id,
photo: (message) => _.max(message.photo, 'file_size').file_id
photo: (message) => message.photo[message.photo.length - 1].file_id
}
}

@@ -1,397 +0,318 @@

var debug = require('debug')('telegraf:core')
var Promise = require('bluebird')
var ware = require('co-ware')
var util = require('util')
var Telegram = require('./telegram-api')
var memorySession = require('./memory-session')
var platform = require('./platform')
const debug = require('debug')('telegraf:core')
const Promise = require('bluebird')
const Telegram = require('./telegram')
const memorySession = require('./memory-session')
const TelegrafContext = require('./context')
/**
* Represents a Telegraf app.
* @constructor
* @param {string} token - Telegram token.
* @param {object} options - Additional options.
*/
function Telegraf (token, options) {
this.options = Object.assign({webHookAnswer: true}, options)
this.middleware = []
this.context = {}
this.polling = {
offset: 0,
started: false
}
Telegram.call(this, token, this.options.apiRoot)
}
// String -> RegEx magic!
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g
util.inherits(Telegraf, Telegram)
class Telegraf {
/**
* Expose `Telegraf`.
*/
module.exports = Telegraf
/**
* Initialize a new `Telegraf` application.
* @param {string} token - Telegram token.
* @param {object} options - Additional options.
* @api public
*/
constructor (token, options) {
const opts = Object.assign({webHookAnswer: true}, options)
this.token = token
this.telegram = new Telegram(token)
this.options = opts
this.middleware = []
this.context = {}
this.polling = {
offset: 0,
started: false
}
}
/**
* Telegraf prototype.
*/
var telegraf = Telegraf.prototype
/**
* Default error handler.
*
* @param {Error} err
* @api private
*/
onError (err) {
const msg = err.stack || err.toString()
console.error()
console.error(msg.replace(/^/gm, ' '))
console.error()
throw err
}
/**
* Expose `memorySession`.
*/
Telegraf.memorySession = memorySession
/**
* Start polling loop.
*
* @param {number} timeout
* @param {number} limit
* @return {Telegraf} self
* @api public
*/
startPolling (timeout, limit) {
this.polling.started = true
this.polling.timeout = timeout || 0
this.polling.limit = limit || 100
this.pollingLoop()
return this
}
/**
* O(1)
*
* @api private
*/
function * noop () {}
/**
* Compose `middleware` returning
* a fully valid middleware comprised
* of all those which are passed.
*
* @param {GeneratorFumction[]} middleware
* @return {GeneratorFumction}
* @api public
*/
Telegraf.compose = function (middleware) {
return function * (next) {
if (!next) {
next = noop()
/**
* Return a callback function suitable for the http[s].createServer() method to handle a request.
* You may also use this callback function to mount your telegraf app in a Koa/Connect/Express app.
*
* @param {string} webHookPath - Webhook secret path
* @return {Function}
* @api public
*/
webHookCallback (webHookPath) {
webHookPath = webHookPath || '/'
return (req, res, next) => {
if (req.method !== 'POST' || req.url !== `${webHookPath}`) {
if (next && typeof next === 'function') {
return next()
}
res.statusCode = 403
return res.end()
}
var body = ''
req.on('data', (chunk) => {
body += chunk.toString()
})
req.on('end', () => {
try {
const update = JSON.parse(body)
this.handleUpdate(update, res)
.then(() => {
if (!res.finished) {
res.writeHead(200)
res.end()
}
})
.catch((err) => {
debug('webhook error', err)
res.writeHead(500)
res.end()
})
} catch (error) {
this.onError(error)
res.writeHead(415)
res.end()
}
})
}
var i = middleware.length
while (i--) {
next = middleware[i].call(this, next)
}
return yield * next
}
}
/**
* Generates `middleware` for handling provided update types.
*
* @param {string|string[]} updateTypes
* @param {(GeneratorFunction|GeneratorFunction[])} fn - middleware
* @api public
*/
Telegraf.mount = function (updateTypes) {
if (typeof updateTypes === 'string') {
updateTypes = [updateTypes]
/**
* Start WebHook.
*
* @param {string} webHookPath - Webhook secret path
* @param {Object} tlsOptions - TLS options
* @param {number} port - Port number
* @param {string} [host] - WebHook secret path
* @return {Telegraf} self
* @api public
*/
startWebHook (webHookPath, tlsOptions, port, host) {
const callback = this.webHookCallback(webHookPath)
this.webhookServer = tlsOptions
? require('https').createServer(tlsOptions, callback)
: require('http').createServer(callback)
this.webhookServer.listen(port, host, () => {
debug('WebHook listening on port: %s', port)
})
return this
}
var fns = [].slice.call(arguments, 1)
return function * (next) {
if (updateTypes.indexOf(this.updateType) !== -1 || updateTypes.indexOf(this.updateSubType) !== -1) {
yield Telegraf.compose(fns)
/**
* Stop WebHook/Polling.
*
* @return {Telegraf} self
* @api public
*/
stop () {
this.polling.started = false
if (this.webhookServer) {
this.webhookServer.close()
}
yield next
return this
}
}
/**
* Default error handler.
*
* @param {Error} err
* @api private
*/
telegraf.onError = function (err) {
var msg = err.stack || err.toString()
console.error()
console.error(msg.replace(/^/gm, ' '))
console.error()
throw err
}
/**
* Register a middleware.
*
* @param {Function} fn - middleware
* @return {Telegraf} self
* @api public
*/
use (fn) {
if (typeof fn !== 'function') {
throw new TypeError('Middleware must be composed of functions')
}
this.middleware.push(fn)
return this
}
/**
* Start polling loop.
*
* @param {number} timeout
* @param {number} limit
* @return {Telegraf} self
* @api public
*/
telegraf.startPolling = function (timeout, limit) {
this.polling.started = true
this.polling.timeout = timeout || 0
this.polling.limit = limit || 100
this.pollingLoop()
return this
}
/**
* Use the given middleware as handler for `updateType`.
*
* @param {string} updateType - Update type
* @param {(Function|Function[])} fn - middleware
* @return {Telegraf} self
* @api public
*/
on (updateTypes) {
const fns = [].slice.call(arguments, 1)
if (fns.length === 0) {
throw new TypeError('At least one Middleware must be provided')
}
this.use(Telegraf.mount(updateTypes, Telegraf.compose(fns)))
return this
}
/**
* Return a callback function suitable for the http[s].createServer() method to handle a request.
* You may also use this callback function to mount your telegraf app in a Koa/Connect/Express app.
*
* @param {string} webHookPath - Webhook secret path
* @return {Function}
* @api public
*/
telegraf.webHookCallback = function (webHookPath) {
webHookPath = webHookPath || '/'
return (req, res, next) => {
if (req.method !== 'POST' || req.url !== `${webHookPath}`) {
if (next && typeof next === 'function') {
return next()
/**
* Use the given middleware as handler for text `trigger`.
*
* @param {(string|RegEx)} trigger - Text trigger
* @param {(Function|Function[])} fn - middleware
* @return {Telegraf} self
* @api public
*/
hears (trigger) {
const regex = trigger instanceof RegExp
? trigger
: new RegExp(trigger.replace(matchOperatorsRe, '\\$&'))
const fns = [].slice.call(arguments, 1)
const handler = Telegraf.compose(fns)
var middleware = (ctx, next) => {
const result = regex.exec(ctx.message.text)
if (result) {
ctx.match = result || []
return handler(ctx, next)
}
res.statusCode = 403
return res.end()
return next()
}
var body = ''
req.on('data', (chunk) => {
body += chunk.toString()
})
req.on('end', () => {
try {
var update = JSON.parse(body)
this.handleUpdate(update, res)
.then(() => {
if (!res.finished) {
res.writeHead(200)
res.end()
}
})
.catch((err) => {
debug('webhook error', err)
res.writeHead(500)
res.end()
})
} catch (error) {
this.onError(error)
res.writeHead(415)
res.end()
}
})
this.use(Telegraf.mount('text', middleware))
return this
}
}
/**
* Start WebHook.
*
* @param {string} webHookPath - Webhook secret path
* @param {Object} tlsOptions - TLS options
* @param {number} port - Port number
* @param {string} [host] - WebHook secret path
* @return {Telegraf} self
* @api public
*/
telegraf.startWebHook = function (webHookPath, tlsOptions, port, host) {
var callback = this.webHookCallback(webHookPath)
this.webhookServer = tlsOptions
? require('https').createServer(tlsOptions, callback)
: require('http').createServer(callback)
this.webhookServer.listen(port, host, () => {
debug('WebHook listening on port: %s', port)
})
return this
}
/**
* Handle Telegram update
*
* @param {Object} update - Telegram update object
* @param {Object} [webHookResponse] - http.ServerResponse
* @return {Promise}
* @api public
*/
handleUpdate (update, webHookResponse) {
debug('⚡ update', update.update_id)
const ctx = new TelegrafContext(this.token, update, webHookResponse)
for (let key in this.context) {
ctx[key] = this.context[key]
}
const fn = Telegraf.compose(this.middleware)
return fn(ctx).catch(this.onError)
}
/**
* Stop WebHook/Polling.
*
* @return {Telegraf} self
* @api public
*/
telegraf.stop = function () {
this.polling.started = false
if (this.webhookServer) {
this.webhookServer.close()
/**
* Polling loop
*
* @api private
*/
pollingLoop () {
if (!this.polling.started) {
return
}
this.telegram.getUpdates(this.polling.timeout, this.polling.limit, this.polling.offset)
.catch((err) => {
console.error('Telegraf: network error', err)
return new Promise((resolve) => {
setTimeout(() => resolve([]), 1000)
})
})
.map((update) => {
return this.handleUpdate(update).then(() => {
this.polling.offset = update.update_id + 1
})
}, {concurrency: 1})
.then(() => this.pollingLoop())
.catch((err) => {
console.error('Telegraf: polling error', err)
this.polling.started = false
})
}
return this
}
/**
* Register a middleware.
*
* @param {GeneratorFunction} fn - middleware
* @return {Telegraf} self
* @api public
* Expose `memorySession`.
*/
telegraf.use = function (fn) {
this.middleware.push(fn)
return this
}
Telegraf.memorySession = memorySession
/**
* Use the given middleware as handler for `updateType`.
*
* @param {string} updateType - Update type
* @param {(GeneratorFunction|GeneratorFunction[])} fn - middleware
* @return {Telegraf} self
* @api public
* Expose `Telegram`.
*/
telegraf.on = function (updateTypes) {
var fns = [].slice.call(arguments, 1)
this.use(Telegraf.mount(updateTypes, Telegraf.compose(fns)))
return this
}
Telegraf.Telegram = Telegram
// String -> RegEx magic!
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g
/**
* Use the given middleware as handler for text `trigger`.
* Compose `middleware` returning
* a fully valid middleware comprised
* of all those which are passed.
*
* @param {(string|RegEx)} trigger - Text trigger
* @param {(GeneratorFunction|GeneratorFunction[])} fn - middleware
* @return {Telegraf} self
* @param {Function[]} middleware
* @return {Function}
* @api public
*/
telegraf.hears = function (trigger) {
var regex = trigger instanceof RegExp
? trigger
: new RegExp(trigger.replace(matchOperatorsRe, '\\$&'))
var fns = [].slice.call(arguments, 1)
var middleware = Telegraf.mount('text', function * (next) {
var result = regex.exec(this.message.text)
if (result) {
this.__defineGetter__('match', function () {
return result || []
})
yield Telegraf.compose(fns)
Telegraf.compose = function (middleware) {
if (!Array.isArray(middleware)) {
middleware = [middleware]
}
for (const fn of middleware) {
if (typeof fn !== 'function') {
throw new TypeError('Middleware must be composed of functions')
}
yield next
})
this.use(middleware)
return this
}
/**
* Polling loop
*
* @api private
*/
telegraf.pollingLoop = function () {
if (!this.polling.started) {
return
}
this.getUpdates(this.polling.timeout, this.polling.limit, this.polling.offset)
.catch((err) => {
console.error('Telegraf: network error', err)
return new Promise((resolve) => {
setTimeout(() => resolve([]), 1000)
})
})
.map((update) => {
return this.handleUpdate(update).then(() => {
this.polling.offset = update.update_id + 1
})
}, {concurrency: 1})
.then(() => this.pollingLoop())
.catch((err) => {
console.error('Telegraf: polling error', err)
this.polling.started = false
})
}
/**
* Extract raw Telegram update
*
* @param {Object} update - raw Telegram update
* @return {Object} normalized update
* @api private
*/
telegraf.extractUpdate = function (update) {
var result = {}
platform.updateTypes.forEach((key) => {
if (update[key]) {
result.payload = update[key]
result.type = key
return (ctx, next) => {
let index = -1
return dispatch(0)
function dispatch (i) {
if (i <= index) {
return Promise.reject(new Error('next() called multiple times'))
}
index = i
const fn = middleware[i] || next
if (!fn) {
return Promise.resolve()
}
try {
return Promise.resolve(fn(ctx, () => dispatch(i + 1)))
} catch (err) {
return Promise.reject(err)
}
}
})
if (update.message) {
platform.messageSubTypes.forEach((messageType) => {
if (update.message[messageType]) {
result.subType = messageType
}
})
}
return result
}
/**
* Handle Telegram update
* Generates `middleware` for handling provided update types.
*
* @param {Object} rawUpdate - Telegram update object
* @param {Object} [webHookResponse] - http.ServerResponse
* @return {Promise}
* @param {string|string[]} updateTypes
* @param {(Function)} fn - middleware
* @api public
*/
telegraf.handleUpdate = function (rawUpdate, webHookResponse) {
var update = this.extractUpdate(rawUpdate)
if (!update.type) {
throw new Error('Undefined update type')
Telegraf.mount = function (updateTypes, middleware) {
if (typeof updateTypes === 'string') {
updateTypes = [updateTypes]
}
debug('⚡ update', update.type, update.subType || '-')
var chat = {id: ''}
var sender = {id: ''}
if (update.payload.from) {
sender = update.payload.from
}
if (update.payload && update.payload.chat) {
chat = update.payload.chat
}
if (update.payload && update.payload.message && update.payload.message.chat) {
chat = update.payload.message.chat
}
var state = {}
var context = Object.assign({
telegraf: this,
updateType: update.type,
updateSubType: update.subType,
chat: chat,
from: sender,
state: state
}, this.context)
var proxy = this
if (this.options.webHookAnswer && webHookResponse) {
var self = this
// 🐵-patching
proxy = {
sendRequest: function (method, options) {
return self.sendRequest(method, options, webHookResponse)
}
return (ctx, next) => {
if (updateTypes.indexOf(ctx.updateType) !== -1 || updateTypes.indexOf(ctx.updateSubType) !== -1) {
return middleware(ctx, next)
}
return next()
}
}
var payload = update.payload
var chatId = (payload.chat && payload.chat.id) ||
(payload.message && payload.message.chat && payload.message.chat.id)
if (chatId) {
platform.chatShortcuts.forEach((command) => {
context[command.name] = this[command.target].bind(proxy, chatId)
})
context.replyWithMarkdown = function (markdown, extra) {
return context.reply(markdown, Object.assign({ parse_mode: 'Markdown' }, extra))
}
context.replyWithHTML = function (html, extra) {
return context.reply(html, Object.assign({ parse_mode: 'HTML' }, extra))
}
}
// 🐫-case
var payloadName = update.type.replace(/^([A-Z])|[\s-_](\w)/g, (match, group1, group2) => {
return group2 ? group2.toUpperCase() : group1.toLowerCase()
})
context.__defineGetter__(payloadName, function () {
return payload
})
if (update.type === 'callback_query') {
context.answerCallbackQuery = this.answerCallbackQuery.bind(proxy, payload.id)
}
if (update.type === 'inline_query') {
context.answerInlineQuery = this.answerInlineQuery.bind(proxy, payload.id)
}
var ctx = ware()
ctx.context = context
ctx.use(Telegraf.compose(this.middleware))
ctx.on('error', this.onError)
return ctx.run()
}
/**
* Expose `Telegraf`.
*/
module.exports = Telegraf
{
"name": "telegraf",
"version": "1.1.2",
"version": "2.0.0-alpha.0",
"description": "📢 Modern Telegram bot framework",

@@ -33,3 +33,4 @@ "main": "lib/telegraf.js",

"lib/telegraf.js",
"lib/telegram-api.js",
"lib/telegram.js",
"lib/context.js",
"lib/platform.js",

@@ -43,6 +44,4 @@ "lib/memory-session.js"

"bluebird": "^3.4.0",
"co-ware": "^1.6.0",
"debug": "^2.2.0",
"is-stream": "^1.1.0",
"lodash": "^4.13.1",
"multipart-stream": "^2.0.1",

@@ -49,0 +48,0 @@ "node-fetch": "^1.5.1"

@@ -27,11 +27,11 @@ [![npm](https://img.shields.io/npm/l/telegraf.svg?style=flat-square)](https://www.npmjs.com/package/telegraf)

```js
var Telegraf = require('telegraf');
var telegraf = new Telegraf(process.env.BOT_TOKEN);
const Telegraf = require('telegraf')
const app = new Telegraf(process.env.BOT_TOKEN)
// Message handling
telegraf.on('message', function * () {
this.reply('*42*', { parse_mode: 'Markdown' })
app.on('message', (ctx) => {
return ctx.reply('*42*', { parse_mode: 'Markdown' })
})
telegraf.startPolling()
app.startPolling()
```

@@ -42,22 +42,22 @@

```js
var Telegraf = require('telegraf');
var telegraf = new Telegraf(process.env.BOT_TOKEN);
const Telegraf = require('telegraf')
const app = new Telegraf(process.env.BOT_TOKEN)
// Look ma, middleware!
var sayYoMiddleware = function * (next) {
yield this.reply('yo')
yield next
const sayYoMiddleware = (ctx, next) => {
return ctx.reply('yo').then(next)
}
// Command handling
telegraf.hears('/command', sayYoMiddleware, function * () {
this.reply('Sure')
app.hears('/command', sayYoMiddleware, (ctx) => {
return ctx.reply('Sure')
})
// Wow! RegEx
telegraf.hears(/reverse (.+)/, sayYoMiddleware, function * () {
this.reply(this.match[1].split('').reverse().join(''))
app.hears(/reverse (.+)/, sayYoMiddleware, (ctx) => {
return ctx.reply(ctx.match[1].split('').reverse().join(''))
})
telegraf.startPolling()
app.startPolling()
```

@@ -71,83 +71,58 @@

A Telegraf application is an object containing an array of middleware generator functions
which are composed and executed in a stack-like manner upon request. Telegraf is similar to many
other middleware systems that you may have encountered such as Koa, Ruby's Rack, Connect, and so on -
however a key design decision was made to provide high level "sugar" at the otherwise low-level
middleware layer. This improves interoperability, robustness, and makes writing middleware much
more enjoyable.
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.
```js
var telegraf = new Telegraf(process.env.BOT_TOKEN)
const app = new Telegraf(process.env.BOT_TOKEN)
telegraf.on('text', function * (){
this.reply('Hello World')
app.on('text', (ctx) => {
return ctx.reply('Hello World')
})
telegraf.startPolling()
app.startPolling()
```
### Cascading
Telegraf middleware cascade in a more traditional way as you may be used to with similar tools -
this was previously difficult to make user friendly with node's use of callbacks.
However with generators we can achieve "true" middleware. Contrasting Connect's implementation which
simply passes control through series of functions until one returns, Telegraf yields "downstream", then
control flows back "upstream".
The following example bot will reply with "Hello World", however first the message flows through
the `logger` middleware to mark when the message has been received. When a middleware invokes `yield next`
the function suspends and passes control to the next middleware defined. After there are no more
middleware to execute downstream, the stack will unwind and each middleware is resumed to perform
its upstream behaviour.
```js
var telegraf = new Telegraf(process.env.BOT_TOKEN)
// Logger middleware
telegraf.use(function * (next){
var start = new Date
this.state.started = start
yield next
var ms = new Date - start
debug('response time %sms', ms)
})
telegraf.on('text', function * (){
this.reply('Hello World')
})
```
### Context
A Telegraf Context encapsulates telegram message.
Context is created per request, and is referenced in middleware as the receiver, or the this identifier, as shown in the following snippet:
Context is created per request and contains following props:
```js
telegraf.use(function * () {
this.telegraf // Telegraf instance
this.updateType // Update type(message, inline_query, etc.)
[this.updateSubType] // Update subtype(text, sticker, audio, etc.)
[this.message] // Received message
[this.editedMessage] // Edited message
[this.inlineQuery] // Received inline query
[this.chosenInlineResult] // Received inline query result
[this.callbackQuery] // Received callback query
[this.chat] // Current chat info
[this.from] // Sender info
[this.match] // Regex match (available only for `hears` handler)
app.use((ctx) => {
ctx.telegram // Telegram instance
ctx.updateType // Update type(message, inline_query, etc.)
[ctx.updateSubType] // Update subtype(text, sticker, audio, etc.)
[ctx.message] // Received message
[ctx.editedMessage] // Edited message
[ctx.inlineQuery] // Received inline query
[ctx.chosenInlineResult] // Received inline query result
[ctx.callbackQuery] // Received callback query
[ctx.chat] // Current chat info
[ctx.from] // Sender info
[ctx.match] // Regex match (available only for `hears` handler)
})
```
[Context api docs](/api.md#context)
The recommended way to extend application context.
### Cascading
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
var telegraf = new Telegraf(process.env.BOT_TOKEN)
const app = new Telegraf(process.env.BOT_TOKEN)
telegraf.context.db = {
getScores: function () { return 42 }
}
// Logger middleware
app.use((ctx, next) => {
const start = new Date()
return next().then(() => {
const ms = new Date() - start
console.log('response time %sms', ms)
})
})
telegraf.on('text', function * (){
var scores = this.db.getScores(this.message.from.username)
this.reply(`${this.message.from.username}: ${score}`)
app.on('text', (ctx) => {
return ctx.reply('Hello World')
})

@@ -161,11 +136,11 @@ ```

```js
var telegraf = new Telegraf(process.env.BOT_TOKEN)
const app = new Telegraf(process.env.BOT_TOKEN)
telegraf.use(function * (next) {
this.state.role = getUserRole(this.message)
yield next
app.use((ctx, next) => {
ctx.state.role = getUserRole(ctx.message)
return next()
})
telegraf.on('text', function * (){
this.reply(`Hello ${this.state.role}`)
app.on('text', (ctx) => {
return ctx.reply(`Hello ${ctx.state.role}`)
})

@@ -177,11 +152,11 @@ ```

```js
var telegraf = new Telegraf(process.env.BOT_TOKEN)
const app = new Telegraf(process.env.BOT_TOKEN)
// Session state will be lost on app restart
telegraf.use(Telegraf.memorySession())
app.use(Telegraf.memorySession())
telegraf.on('text', function * (){
this.session.counter = this.session.counter || 0
this.session.counter++
this.reply(`Message counter:${this.session.counter}`)
app.on('text', () => {
ctx.session.counter = ctx.session.counter || 0
ctx.session.counter++
return ctx.reply(`Message counter:${ctx.session.counter}`)
})

@@ -196,6 +171,6 @@ ```

var telegraf = new Telegraf(process.env.BOT_TOKEN)
const app = new Telegraf(process.env.BOT_TOKEN)
// TLS options
var tlsOptions = {
const tlsOptions = {
key: fs.readFileSync('server-key.pem'),

@@ -210,3 +185,3 @@ cert: fs.readFileSync('server-cert.pem'),

// Set telegram webhook
telegraf.setWebHook('https://server.tld:8443/secret-path', {
app.telegram.setWebHook('https://server.tld:8443/secret-path', {
content: 'server-cert.pem'

@@ -216,7 +191,7 @@ })

// Start https webhook
telegraf.startWebHook('/secret-path', tlsOptions, 8443)
app.startWebHook('/secret-path', tlsOptions, 8443)
// Http webhook, for nginx/heroku users.
telegraf.startWebHook('/secret-path', null, 5000)
app.startWebHook('/secret-path', null, 5000)

@@ -226,20 +201,20 @@

require('http')
.createServer(telegraf.webHookCallback('/secret-path'))
.createServer(app.webHookCallback('/secret-path'))
.listen(3000)
require('https')
.createServer(tlsOptions, telegraf.webHookCallback('/secret-path'))
.createServer(tlsOptions, app.webHookCallback('/secret-path'))
.listen(8443)
// Connect/Express.js integration
var express = require('express')
var app = express()
const express = require('express')
const expressApp = express()
app.use(telegraf.webHookCallback('/secret-path'))
expressApp.use(app.webHookCallback('/secret-path'))
app.get('/', function (req, res) {
expressApp.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000, function () {
expressApp.listen(3000, () => {
console.log('Example app listening on port 3000!')

@@ -256,3 +231,3 @@ })

```js
telegraf.onError = function(err){
telegraf.onError = (err) => {
log.error('server error', err)

@@ -259,0 +234,0 @@ throw err

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc