diff --git a/LICENSE b/LICENSE index 43cf7f141..d4ada101a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016-2019 Vitaly Domnikov +Copyright (c) 2016-2021 Vitaly Domnikov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/context.js b/context.js index 02f421079..154deed72 100644 --- a/context.js +++ b/context.js @@ -272,24 +272,24 @@ class TelegrafContext { ) } - editMessageLiveLocation (latitude, longitude, markup) { + editMessageLiveLocation (latitude, longitude, extra) { this.assert(this.callbackQuery || this.inlineMessageId, 'editMessageLiveLocation') return this.inlineMessageId ? this.telegram.editMessageLiveLocation( - latitude, - longitude, undefined, undefined, this.inlineMessageId, - markup - ) - : this.telegram.editMessageLiveLocation( latitude, longitude, + extra + ) + : this.telegram.editMessageLiveLocation( this.chat.id, this.callbackQuery.message.message_id, undefined, - markup + latitude, + longitude, + extra ) } @@ -380,6 +380,11 @@ class TelegrafContext { return this.telegram.unpinChatMessage(this.chat.id, ...args) } + unpinAllChatMessages () { + this.assert(this.chat, 'unpinAllChatMessages') + return this.telegram.unpinAllChatMessages(this.chat.id) + } + leaveChat (...args) { this.assert(this.chat, 'leaveChat') return this.telegram.leaveChat(this.chat.id, ...args) @@ -590,6 +595,16 @@ class TelegrafContext { this.assert(message, 'forwardMessage') return this.telegram.forwardMessage(chatId, this.chat.id, message.message_id, extra) } + + copyMessage (chatId, extra) { + const message = this.message || + this.editedMessage || + this.channelPost || + this.editedChannelPost || + (this.callbackQuery && this.callbackQuery.message) + this.assert(message, 'copyMessage') + return this.telegram.copyMessage(chatId, message.chat.id, message.message_id, extra) + } } module.exports = TelegrafContext diff --git a/docs/CNAME b/docs/CNAME index a4944683c..91def4306 100644 --- a/docs/CNAME +++ b/docs/CNAME @@ -1 +1 @@ -telegraf.js.org \ No newline at end of file +v3.telegrafjs.org diff --git a/docs/README.md b/docs/README.md index 6d0af7c7a..b5b71982e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,14 +1,12 @@ -![Telegraf](header.png) +![Telegraf](media/header.png) -## Introduction +# Introduction -Bots are special [Telegram](https://telegram.org) accounts designed to handle messages automatically. -Users can interact with bots by sending them command messages in private or group chats. -These accounts serve as an interface for code running somewhere on your server. +Bots are special [Telegram](https://telegram.org) accounts designed to handle messages automatically. Users can interact with bots by sending them command messages in private or group chats. These accounts serve as an interface for code running somewhere on your server. -#### Features +## Features -- Full [Telegram Bot API 4.8](https://core.telegram.org/bots/api) support +- Full [Telegram Bot API 5.0](https://core.telegram.org/bots/api) support - [Telegram Payment Platform](https://telegram.org/blog/payments) - [HTML5 Games](https://core.telegram.org/bots/api#games) - [Inline mode](https://core.telegram.org/bots/api#inline-mode) @@ -18,19 +16,19 @@ These accounts serve as an interface for code running somewhere on your server. - Easy to extend - `TypeScript` typings -#### Installation +## Installation ```bash -$ npm install telegraf --save +npm install telegraf --save ``` or using yarn ```bash -$ yarn add telegraf +yarn add telegraf ``` -#### Example +## Example ```js const { Telegraf } = require('telegraf') @@ -107,2088 +105,3 @@ For additional bot examples see [`examples`](https://github.com/telegraf/telegra | [BibleBot](https://github.com/Kriv-Art/BibleBot) | Bot to get bible verses | | [BitcoinDogBot](https://github.com/jibital/bitcoin-dog-bot) | Bitcoin prices, Technical analysis and Alerts! | | Send PR to add link to your bot | | - -## Getting started - -#### Telegram token - -To use the [Telegram Bot API](https://core.telegram.org/bots/api), -you first have to [get a bot account](https://core.telegram.org/bots) -by [chatting with BotFather](https://core.telegram.org/bots#6-botfather). - -BotFather will give you a *token*, something like `123456789:AbCdfGhIJKlmNoQQRsTUVwxyZ`. - -#### Bot - -A Telegraf bot 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 update, -`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 bot = new Telegraf(process.env.BOT_TOKEN) - -bot.use(async (ctx, next) => { - const start = new Date() - await next() - const ms = new Date() - start - console.log('Response time: %sms', ms) -}) - -bot.on('text', (ctx) => ctx.reply('Hello World')) -bot.launch() -``` - -##### 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) -- [Rate-limiting](https://github.com/telegraf/telegraf-ratelimit) -- [Menus via inline keyboards](https://github.com/EdJoPaTo/telegraf-inline-menu) -- [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 bot = new Telegraf(process.env.BOT_TOKEN) -bot.catch((err, ctx) => { - console.log(`Ooops, encountered an error for ${ctx.updateType}`, err) -}) -bot.start((ctx) => { - throw new Error('Example error') -}) -bot.launch() -``` - -#### Context - -A Telegraf Context encapsulates telegram update. -Context is created per request and contains following props: - -| Property | Description | -| --- | --- | -| ` ctx.telegram ` | Telegram client instance | -| ` ctx.updateType ` | Update type (message, inline_query, etc.) | -| `[ctx.updateSubTypes]` | Update subtypes (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.shippingQuery]` | Shipping query | -| `[ctx.preCheckoutQuery]` | Precheckout query | -| `[ctx.channelPost]` | New incoming channel post of any kind β€” text, photo, sticker, etc. | -| `[ctx.editedChannelPost]` | New version of a channel post that is known to the bot and was edited | -| `[ctx.poll]` | New version of a anonymous poll that is known to the bot and was changed | -| `[ctx.pollAnswer]` | This object represents an answer of a user in a non-anonymous poll. | -| `[ctx.chat]` | Current chat info | -| `[ctx.from]` | Sender info | -| `[ctx.match]` | Regex match (available only for `hears`, `command`, `action`, `inlineQuery` handlers) | -| ` ctx.webhookReply ` | Shortcut to `ctx.telegram.webhookReply` | - -```js -bot.use((ctx) => { - console.log(ctx.message) -}) -``` - -##### Extending context - -The recommended way to extend bot context: - -```js -const bot = new Telegraf(process.env.BOT_TOKEN) - -bot.context.db = { - getScores: () => { return 42 } -} - -bot.on('text', (ctx) => { - const scores = ctx.db.getScores(ctx.message.from.username) - return ctx.reply(`${ctx.message.from.username}: ${scores}`) -}) - -bot.launch() -``` - -##### Shortcuts - -Context shortcuts for **message** update: - -| Shortcut | Bound to | -| --- | --- | -| `addStickerToSet` | [`telegram.addStickerToSet`](#addstickertoset) | -| `createNewStickerSet` | [`telegram.createNewStickerSet`](#createnewstickerset) | -| `deleteChatPhoto` | [`telegram.deleteChatPhoto`](#deletechatphoto) | -| `deleteMessage` | [`telegram.deleteMessage`](#deletemessage) | -| `deleteStickerFromSet` | [`telegram.deleteStickerFromSet`](#deletestickerfromset) | -| `exportChatInviteLink` | [`telegram.exportChatInviteLink`](#exportchatinvitelink) | -| `forwardMessage` | [`telegram.forwardMessage`](#forwardmessage) | -| `getChat` | [`telegram.getChat`](#getchat) | -| `getChatAdministrators` | [`telegram.getChatAdministrators`](#getchatadministrators) | -| `getChatMember` | [`telegram.getChatMember`](#getchatmember) | -| `getChatMembersCount` | [`telegram.getChatMembersCount`](#getchatmemberscount) | -| `getMyCommands` | [`telegram.getMyCommands`](#getmycommands) | -| `getStickerSet` | [`telegram.getStickerSet`](#getstickerset) | -| `leaveChat` | [`telegram.leaveChat`](#leavechat) | -| `pinChatMessage` | [`telegram.pinChatMessage`](#pinchatmessage) | -| `reply` | [`telegram.sendMessage`](#sendmessage) | -| `replyWithAudio` | [`telegram.sendAudio`](#sendaudio) | -| `replyWithChatAction` | [`telegram.sendChatAction`](#sendchataction) | -| `replyWithDice` | [`telegram.sendDice`](#senddice) | -| `replyWithDocument` | [`telegram.sendDocument`](#senddocument) | -| `replyWithGame` | [`telegram.sendGame`](#sendgame) | -| `replyWithHTML` | [`telegram.sendMessage`](#sendmessage) | -| `replyWithInvoice` | [`telegram.sendInvoice`](#sendinvoice) | -| `replyWithLocation` | [`telegram.sendLocation`](#sendlocation) | -| `replyWithMarkdown` | [`telegram.sendMessage`](#sendmessage) | -| `replyWithMediaGroup` | [`telegram.sendMediaGroup`](#sendmediagroup) | -| `replyWithPhoto` | [`telegram.sendPhoto`](#sendphoto) | -| `replyWithPoll` | [`telegram.sendPoll`](#sendpoll) | -| `replyWithQuiz` | [`telegram.sendQuiz`](#sendquiz) | -| `replyWithSticker` | [`telegram.sendSticker`](#sendsticker) | -| `replyWithVideo` | [`telegram.sendVideo`](#sendvideo) | -| `replyWithVideoNote` | [`telegram.sendVideoNote`](#sendvideonote) | -| `replyWithVoice` | [`telegram.sendVoice`](#sendvoice) | -| `setChatDescription` | [`telegram.setChatDescription`](#setchatdescription) | -| `setChatPhoto` | [`telegram.setChatPhoto`](#setchatphoto) | -| `setChatTitle` | [`telegram.setChatTitle`](#setchattitle) | -| `setMyCommands` | [`telegram.setMyCommands`](#setmycommands) | -| `setPassportDataErrors` | [`telegram.setPassportDataErrors`](#setpassportdataerrors) | -| `setStickerPositionInSet` | [`telegram.setStickerPositionInSet`](#setstickerpositioninset) | -| `setStickerSetThumb` | [`telegram.setStickerSetThumb`](#setstickersetthumb) | -| `setStickerSetThumb` | [`telegram.setStickerSetThumb`](#setstickersetthumb) | -| `stopPoll` | [`telegram.stopPoll`](#stoppoll) | -| `unpinChatMessage` | [`telegram.unpinChatMessage`](#unpinchatmessage) | -| `uploadStickerFile` | [`telegram.uploadStickerFile`](#uploadstickerfile) | -| `unbanChatMember` | [`telegram.unbanChatMember`](#unbanchatmember) | - -Context shortcuts for **callback_query** update: - -| Shortcut | Bound to | -| --- | --- | -| `addStickerToSet` | [`telegram.addStickerToSet`](#addstickertoset) | -| `answerCbQuery` | [`telegram.answerCbQuery`](#answercbquery) | -| `answerGameQuery` | [`telegram.answerGameQuery`](#answergamequery) | -| `createNewStickerSet` | [`telegram.createNewStickerSet`](#createnewstickerset) | -| `deleteChatPhoto` | [`telegram.deleteChatPhoto`](#deletechatphoto) | -| `deleteMessage` | [`telegram.deleteMessage`](#deletemessage) | -| `deleteStickerFromSet` | [`telegram.deleteStickerFromSet`](#deletestickerfromset) | -| `editMessageCaption` | [`telegram.editMessageCaption`](#editmessagecaption) | -| `editMessageMedia` | [`telegram.editMessageMedia`](#editmessagemedia) | -| `editMessageReplyMarkup` | [`telegram.editMessageReplyMarkup`](#editmessagereplymarkup) | -| `editMessageText` | [`telegram.editMessageText`](#editmessagetext) | -| `exportChatInviteLink` | [`telegram.exportChatInviteLink`](#exportchatinvitelink) | -| `forwardMessage` | [`telegram.forwardMessage`](#forwardmessage) | -| `getChat` | [`telegram.getChat`](#getchat) | -| `getChatAdministrators` | [`telegram.getChatAdministrators`](#getchatadministrators) | -| `getChatMember` | [`telegram.getChatMember`](#getchatmember) | -| `getChatMembersCount` | [`telegram.getChatMembersCount`](#getchatmemberscount) | -| `getStickerSet` | [`telegram.getStickerSet`](#getstickerset) | -| `leaveChat` | [`telegram.leaveChat`](#leavechat) | -| `pinChatMessage` | [`telegram.pinChatMessage`](#pinchatmessage) | -| `reply` | [`telegram.sendMessage`](#sendmessage) | -| `replyWithAnimation` | [`telegram.sendAnimation`](#sendanimation) | -| `replyWithAudio` | [`telegram.sendAudio`](#sendaudio) | -| `replyWithChatAction` | [`telegram.sendChatAction`](#sendchataction) | -| `replyWithDice` | [`telegram.sendDice`](#senddice) | -| `replyWithDocument` | [`telegram.sendDocument`](#senddocument) | -| `replyWithGame` | [`telegram.sendGame`](#sendgame) | -| `replyWithHTML` | [`telegram.sendMessage`](#sendmessage) | -| `replyWithInvoice` | [`telegram.sendInvoice`](#sendinvoice) | -| `replyWithLocation` | [`telegram.sendLocation`](#sendlocation) | -| `replyWithMarkdown` | [`telegram.sendMessage`](#sendmessage) | -| `replyWithMediaGroup` | [`telegram.sendMediaGroup`](#sendmediagroup) | -| `replyWithPhoto` | [`telegram.sendPhoto`](#sendphoto) | -| `replyWithPoll` | [`telegram.sendPoll`](#sendpoll) | -| `replyWithSticker` | [`telegram.sendSticker`](#sendsticker) | -| `replyWithVideo` | [`telegram.sendVideo`](#sendvideo) | -| `replyWithVideoNote` | [`telegram.sendVideoNote`](#sendvideonote) | -| `replyWithVoice` | [`telegram.sendVoice`](#sendvoice) | -| `setChatDescription` | [`telegram.setChatDescription`](#setchatdescription) | -| `setChatPhoto` | [`telegram.setChatPhoto`](#setchatphoto) | -| `setChatTitle` | [`telegram.setChatTitle`](#setchattitle) | -| `setStickerPositionInSet` | [`telegram.setStickerPositionInSet`](#setstickerpositioninset) | -| `setStickerSetThumb` | [`telegram.setStickerSetThumb`](#setstickersetthumb) | -| `stopPoll` | [`telegram.stopPoll`](#stoppoll) | -| `unpinChatMessage` | [`telegram.unpinChatMessage`](#unpinchatmessage) | -| `uploadStickerFile` | [`telegram.uploadStickerFile`](#uploadstickerfile) | -| `unbanChatMember` | [`telegram.unbanChatMember`](#unbanchatmember) | - -Context shortcuts for **inline_query** update: - -| Shortcut | Bound to | -| --- | --- | -| `answerInlineQuery` | [`telegram.answerInlineQuery`](#answerinlinequery) | - -Context shortcuts for **shipping_query** update: - -| Shortcut | Bound to | -| --- | --- | -| `answerShippingQuery` | [`telegram.answerShippingQuery`](#answershippingquery) | - -Context shortcuts for **pre_checkout_query** update: - -| Shortcut | Bound to | -| --- | --- | -| `answerPreCheckoutQuery` | [`telegram.answerPreCheckoutQuery`](#answerprecheckoutquery) | - -##### Shortcuts usage example - -```js -const bot = new Telegraf(process.env.BOT_TOKEN) - -bot.command('quit', (ctx) => { - // Explicit usage - ctx.telegram.leaveChat(ctx.message.chat.id) - - // Using context shortcut - ctx.leaveChat() -}) - -bot.on('text', (ctx) => { - // Explicit usage - ctx.telegram.sendMessage(ctx.message.chat.id, `Hello ${ctx.state.role}`) - - // Using context shortcut - ctx.reply(`Hello ${ctx.state.role}`) -}) - -bot.on('callback_query', (ctx) => { - // Explicit usage - ctx.telegram.answerCbQuery(ctx.callbackQuery.id) - - // Using context shortcut - ctx.answerCbQuery() -}) - -bot.on('inline_query', (ctx) => { - const result = [] - // Explicit usage - ctx.telegram.answerInlineQuery(ctx.inlineQuery.id, result) - - // Using context shortcut - ctx.answerInlineQuery(result) -}) - -bot.launch() -``` - -#### State - -The recommended namespace to share information between middlewares. - -```js -const bot = new Telegraf(process.env.BOT_TOKEN) - -// Naive authorization middleware -bot.use((ctx, next) => { - ctx.state.role = getUserRole(ctx.message) - return next() -}) - -bot.on('text', (ctx) => { - return ctx.reply(`Hello ${ctx.state.role}`) -}) - -bot.launch() -``` - -#### Session - -```js -const session = require('telegraf/session') - -const bot = new Telegraf(process.env.BOT_TOKEN) -bot.use(session()) -bot.on('text', (ctx) => { - ctx.session.counter = ctx.session.counter || 0 - ctx.session.counter++ - return ctx.reply(`Message counter:${ctx.session.counter}`) -}) - -bot.launch() -``` - -**Note: For persistent sessions you can use any of [`telegraf-session-*`](https://www.npmjs.com/search?q=telegraf-session) middleware.** - -**Tip: To use same session in private chat with bot and in inline mode, use following session key resolver:** - -```js -{ - getSessionKey: (ctx) => { - if (ctx.from && ctx.chat) { - return `${ctx.from.id}:${ctx.chat.id}` - } else if (ctx.from && ctx.inlineQuery) { - return `${ctx.from.id}:${ctx.from.id}` - } - return null - } -} -``` - -#### 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` -- `dice` -- `document` -- `photo` -- `sticker` -- `video` -- `voice` -- `contact` -- `location` -- `venue` -- `forward` -- `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` -- `connected_website` -- `passport_data` -- `poll` - -```js -// Handle message update -bot.on('message', (ctx) => { - return ctx.reply('Hello') -}) - -// Handle sticker or photo update -bot.on(['sticker', 'photo'], (ctx) => { - console.log(ctx.message) - return ctx.reply('Cool!') -}) -``` -[Official Docs](https://core.telegram.org/bots/api#message) - -#### Webhooks - -```js -require('dotenv') - -const bot = 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 a self-signed certificate. - fs.readFileSync('client-cert.pem') - ] -} - -// Set telegram webhook -// The second argument is necessary only if the client uses a self-signed -// certificate. Including it for a verified certificate may cause things to break. -bot.telegram.setWebhook('https://server.tld:8443/secret-path', { - source: 'server-cert.pem' -}) - -// Start https webhook -bot.startWebhook('/secret-path', tlsOptions, 8443) - -// Http webhook, for nginx/heroku users. -bot.startWebhook('/secret-path', null, 5000) -``` - -Use webhookCallback() if you want to attach telegraf to existing http server - -```js -require('http') - .createServer(bot.webhookCallback('/secret-path')) - .listen(3000) - -require('https') - .createServer(tlsOptions, bot.webhookCallback('/secret-path')) - .listen(8443) -``` - -Express.js example integration - -```js -const { Telegraf } = require('telegraf') -const express = require('express') -const expressApp = express() - -const bot = new Telegraf(process.env.BOT_TOKEN) -expressApp.use(bot.webhookCallback('/secret-path')) -bot.telegram.setWebhook('https://server.tld:8443/secret-path') - -expressApp.get('/', (req, res) => { - res.send('Hello World!') -}) - -expressApp.listen(3000, () => { - console.log('Example app listening on port 3000!') -}) -``` - -Fastify example integration - -```js -const { Telegraf } = require('telegraf') -const fastifyApp = require('fastify')() - -const bot = new Telegraf(process.env.BOT_TOKEN) - -bot.on('text', ({ reply }) => reply('Hello')) -fastifyApp.use(bot.webhookCallback('/secret-path')) -// Set telegram webhook -// npm install -g localtunnel && lt --port 3000 -bot.telegram.setWebhook('https://------.localtunnel.me/secret-path') - -fastifyApp.listen(3000, () => { - console.log('Example app listening on port 3000!') -}) -``` - -Koa.js example integration - -```js -const { Telegraf } = require('telegraf') -const Koa = require('koa') -const koaBody = require('koa-body') - -const bot = new Telegraf(process.env.BOT_TOKEN) -bot.telegram.setWebhook('https://server.tld:8443/secret-path') - -const app = new Koa() -app.use(koaBody()) -app.use(async (ctx, next) => { - if (ctx.method !== 'POST' || ctx.url !== '/secret-path') { - return next() - } - await bot.handleUpdate(ctx.request.body, ctx.response) - ctx.status = 200 -}) -app.use(async (ctx) => { - ctx.body = 'Hello World' -}) - -app.listen(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('message', (ctx) => { - // resend existing file by file_id - ctx.replyWithSticker('123123jkbhj6b') - - // send file - ctx.replyWithVideo({ source: '/path/to/video.mp4' }) - - // send stream - ctx.replyWithVideo({ - source: fs.createReadStream('/path/to/video.mp4') - }) - - // send buffer - ctx.replyWithVoice({ - source: Buffer.alloc() - }) - - // send url via Telegram server - ctx.replyWithPhoto('https://picsum.photos/200/300/') - - // pipe url content - ctx.replyWithPhoto({ - url: 'https://picsum.photos/200/300/?random', - filename: 'kitten.jpg' - }) -}) -``` - -#### Telegram Passport - -To enable Telegram Passport support you can use [`telegram-passport`](https://www.npmjs.com/package/telegram-passport) package: - -```js -const { Telegraf } = require('telegraf') -const TelegramPassport = require('telegram-passport') - -const bot = new Telegraf(process.env.BOT_TOKEN) -const passport = new TelegramPassport("PRIVATE_KEY_IN_PEM_FORMAT") - -bot.on('passport_data', (ctx) => { - const decryptedPasswordData = passport.decrypt(ctx.passportData) - console.log(decryptedPasswordData) - return ctx.setPassportDataErrors([ - { source: 'selfie', type: 'driver_license', file_hash: 'file-hash', message: 'Selfie photo is too low quality'} - ]) -}) -``` - -#### Telegraf Modules - -Telegraf Modules is higher level abstraction for writing modular Telegram bots. - -Module is simple js file with exported Telegraf middleware: - -```js -module.exports = (ctx) => ctx.reply('Hello from Telegraf Module!') -``` - -```js -const Composer = require('telegraf/composer') - -module.exports = Composer.mount( - 'sticker', - (ctx) => ctx.reply('Wow, sticker') -) -``` - -To run modules you can use `telegraf` module runner, it allows you to start Telegraf module easily from the command line. - -```bash -$ npm install telegraf -g -``` - -#### Telegraf CLI usage - -``` -telegraf [opts] - -t Bot token [$BOT_TOKEN] - -d Webhook domain - -H Webhook host [0.0.0.0] - -p Webhook port [$PORT or 3000] - -s Stop on error - -l Enable logs - -h Show this help message -``` - -##### Telegraf Module example - -Create module with name `bot.js` and following content: - -```js -const Composer = require('telegraf/composer') -const PhotoURL = 'https://picsum.photos/200/300/?random' - -const bot = new Composer() -bot.start((ctx) => ctx.reply('Hello there!')) -bot.help((ctx) => ctx.reply('Help message')) -bot.command('photo', (ctx) => ctx.replyWithPhoto({ url: PhotoURL })) - -module.exports = bot -``` - -then run it: - -```bash -$ telegraf -t "bot token" bot.js -``` - -## API reference - -#### Telegraf - -Telegraf API reference - -```js -const { Telegraf } = require('telegraf') -``` - -##### Constructor - -Initialize new Telegraf bot. - -`const telegraf = new Telegraf(token, [options])` - -| Param | Type | Description | -| --- | --- | --- | -| token | `string` | [Bot Token](https://core.telegram.org/bots#3-how-do-i-create-a-bot) | -| [options] | `object` | Telegraf options | - -Telegraf options: - -```js -{ - telegram: { // Telegram options - agent: null, // https.Agent instance, allows custom proxy, certificate, keep alive, etc. - webhookReply: true // Reply via webhook - }, - username: '' // Bot username (optional) - channelMode: false // Handle `channel_post` updates as messages (optional) -} -``` - -##### token - -Use this property to get/set bot token. - -`telegraf.token = [string]` - -##### webhookReply - -Use this property to control `reply via webhook` feature. - -`telegraf.webhookReply = [bool]` - -##### use - -Registers a middleware. - -`telegraf.use(...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| middleware | `function` | Middleware function | - -##### on - -Registers middleware for provided update type. - -`telegraf.on(updateTypes, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| updateTypes | `string/string[]` | Update type | -| middleware | `function` | Middleware | - -##### hears - -Registers middleware for handling `text` messages. - -`telegraf.hears(triggers, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function` | Triggers | -| middleware | `function` | Middleware | - -##### command - -Command handling. - -`telegraf.command(commands, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| commands | `string/string[]` | Commands | -| middleware | `function` | Middleware | - -##### start - -Handler for /start command. - -`telegraf.start(...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| middleware | `function` | Middleware | - -##### help - -Handler for /help command. - -`telegraf.help(...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| middleware | `function` | Middleware | - -##### settings - -Handler for /settings command. - -`telegraf.settings(...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| middleware | `function` | Middleware | - -##### entity - -Entity handling. - -`telegraf.entity(entity, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| entity | `string/string[]/RegEx/RegEx[]/Function` | Entity name | -| middleware | `function` | Middleware | - -##### mention - -Mention handling. - -`telegraf.mention(username, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| username | `string/string[]` | Username | -| middleware | `function` | Middleware | - -##### phone - -Phone number handling. - -`telegraf.phone(number, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| number | `string/string[]` | Phone number | -| middleware | `function` | Middleware | - -##### hashtag - -Hashtag handling. - -`telegraf.hashtag(hashtag, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| hashtag | `string/string[]` | Hashtag | -| middleware | `function` | Middleware | - -##### cashtag - -Cashtag handling. - -`telegraf.cashtag(cashtag, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| cashtag | `string/string[]` | Cashtag | -| middleware | `function` | Middleware | - -##### action - -Registers middleware for handling `callback_data` actions with regular expressions. - -`telegraf.action(triggers, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]` | Triggers | -| middleware | `function` | Middleware | - - -##### inlineQuery - -Registers middleware for handling `inline_query` actions with regular expressions. - -`telegraf.inlineQuery(triggers, ...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]` | Triggers | -| middleware | `function` | Middleware | - - -##### gameQuery - -Registers middleware for handling `callback_data` actions with game query. - -`telegraf.gameQuery(...middleware)` - -| Param | Type | Description | -| --- | --- | --- | -| middleware | `function` | Middleware | - -##### launch - -Launch bot in long-polling or webhook mode. - -`telegraf.launch(options) => Promise` - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| [options] | `object` | Launch options | - -Launch options: - -```js -{ - // Start bot in polling mode (Default) - // See startPolling reference - polling: { timeout, limit, allowedUpdates, stopCallback }, - - // Start bot in webhook mode - // See startWebhook reference - webhook: { domain, hookPath, port, host, tlsOptions, cb } -} -``` - -##### startPolling - -Start poll updates. - -`telegraf.startPolling([timeout], [limit], [allowedUpdates], [stopCallback])` - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| [timeout] | `number` | 30 | Poll timeout in seconds | -| [limit] | `number` | 100 | Limits the number of updates to be retrieved | -| [allowedUpdates] | `string[]/string/null` | null | List the types of updates you want your bot to receive | -| [stopCallback] | `function` | null | Polling stop callback | - -##### startWebhook - -Start listening @ `https://host:port/webhookPath` for Telegram calls. - -`telegraf.startWebhook(hookPath, [tlsOptions], port, [host])` - -| Param | Type | Description | -| --- | --- | --- | -| hookPath | `string` | Webhook url path (see Telegraf.setWebhook) | -| [tlsOptions] | `object` | [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` | Hostname | - -##### stop - -Stop Webhook and polling - -`telegraf.stop([callback]) => Promise` - -| Param | Type | -| --- | --- | -| [callback] | function | - -##### webhookCallback - -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 Connect/Express app. - -`telegraf.webhookCallback(webhookPath) => Function` - -| Param | Type | Description | -| --- | --- | --- | -| webhookPath | `string` | Webhook url path (see Telegraf.setWebhook) | - -##### handleUpdate - -Handle raw Telegram update. -In case you use centralized webhook server, queue, etc. - -`telegraf.handleUpdate(rawUpdate, [webhookResponse])` - -| Param | Type | Description | -| --- | --- | --- | -| rawUpdate | `object` | Telegram update payload | -| [webhookResponse] | `object` | [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) | - -##### Telegraf.compose - -Compose `middlewares` returning a fully valid middleware comprised of all those which are passed. - -`Telegraf.compose(middlewares) => function` - -| Param | Type | Description | -| --- | --- | --- | -| middlewares | `function[]` | Array of middlewares | - -##### Telegraf.mount - -Generates middleware for handling provided update types. - -`Telegraf.mount(updateTypes, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| updateTypes | `string/string[]` | Update type | -| middleware | `function` | middleware | - -##### Telegraf.hears - -Generates middleware for handling `text` messages with regular expressions. - -`Telegraf.hears(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.action - -Generates middleware for handling `callbackQuery` data with regular expressions. - -`Telegraf.action(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.inlineQuery - -Generates middleware for handling `inlineQuery` data with regular expressions. - -`Telegraf.inlineQuery(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.passThru - -Generates pass thru middleware. - -`Telegraf.passThru() => function` - -##### Telegraf.safePassThru - -Generates safe version of pass thru middleware. - -`Telegraf.safePassThru() => function` - -##### Telegraf.optional - -Generates optional middleware. - -`Telegraf.optional(test, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| test | `truthy/function` | Value or predicate `(ctx) => bool` | -| middleware | `function` | middleware | - -##### Telegraf.acl - -Generates middleware for provided users only. - -`Telegraf.acl(userId, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| userId | `string/string[]` | User id | -| middleware | `function` | middleware | - -##### Telegraf.drop - -Generates drop middleware. - -`Telegraf.drop(test) => function` - -| Param | Type | Description | -| --- | --- | --- | -| test | `truthy/function` | Value or predicate `(ctx) => bool` | - -##### Telegraf.filter - -Generates filter middleware. - -`Telegraf.filter(test) => function` - -| Param | Type | Description | -| --- | --- | --- | -| test | `truthy/function` | Value or predicate `(ctx) => bool` | - -##### Telegraf.branch - -Generates branch middleware. - -`Telegraf.branch(test, trueMiddleware, falseMiddleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| test | `truthy/function` | Value or predicate `(ctx) => bool` | -| trueMiddleware | `function` | true action middleware | -| falseMiddleware | `function` | false action middleware | - - -##### Telegraf.email - -Generates middleware for handling messages with `email` entity. - -`Telegraf.email(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.hashtag - -Generates middleware for handling messages with `hashtag` entity. - -`Telegraf.hashtag(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.cashtag - -Generates middleware for handling messages with `cashtag` entity. - -`Telegraf.cashtag(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.url - -Generates middleware for handling messages with `url` entity. - -`Telegraf.url(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.phone - -Generates middleware for handling messages with `phone` entity. - -`Telegraf.phone(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.textLink - -Generates middleware for handling messages with `text_link` entity. - -`Telegraf.textLink(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -##### Telegraf.textMention - -Generates middleware for handling messages with `text_mention` entity. - -`Telegraf.textMention(triggers, ...middleware) => function` - -| Param | Type | Description | -| --- | --- | --- | -| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | -| handler | `function` | Handler | - -#### Telegram - -Telegram client API reference. - -```js -const Telegram = require('telegraf/telegram') -``` - -##### Constructor - -Initialize new Telegram client. - -`const telegram = new Telegram(token, [options])` - -| Param | Type | Description | -| --- | --- | --- | -| token | `string` | [Bot Token](https://core.telegram.org/bots#3-how-do-i-create-a-bot) | -| [options] | `object` | Telegram options | - -Telegram options: - -```js -{ - agent: null, // https.Agent instance, allows custom proxy, certificate, keep alive, etc. - webhookReply: true // Reply via webhook -} -``` - -##### webhookReply - -Use this property to control `reply via webhook` feature. - -`telegram.webhookReply = [bool]` - -##### addStickerToSet - -Use this method to add a new sticker to a set created by the bot. - -`telegram.addStickerToSet(ownerId, name, stickerData) => Promise` -[Official documentation](https://core.telegram.org/bots/api#addstickertoset) - -| Param | Type | Description | -| --- | --- | --- | -| ownerId | `string` | User identifier of sticker set owner | -| name | `string` | Sticker set name | -| stickerData | `Object` | Sticker data({png_sticker: 'stiker file', emojis: 'πŸ˜‰', mask__position: '' }) | - -##### answerCbQuery - -Use this method to send answers to callback queries. - -`telegram.answerCbQuery(callbackQueryId, text, [showAlert], [extra]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#answercallbackquery) - -| Param | Type | Description | -| --- | --- | --- | -| callbackQueryId | `string` | Query id | -| [text] | `string` | Notification text | -| [showAlert] | `bool` | Show alert instead of notification | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#answercallbackquery) | - -##### answerGameQuery - -Use this method to send answers to game query. - -`telegram.answerGameQuery(callbackQueryId, url) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| callbackQueryId | `string` | Query id | -| url | `string` | Notification text | - -##### answerShippingQuery - -Use this method to send answers to shipping query. - -`telegram.answerShippingQuery(shippingQueryId, ok, shippingOptions, [errorMessage]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| shippingQueryId | `string` | Shipping Query id | -| ok | `bool` | Specify True if delivery to the specified address is possible | -| shippingOptions | `object` | [Shipping Options](https://core.telegram.org/bots/api#answershippingquery) | -| [errorMessage] | `string` | Error message in human readable form | - -##### answerPreCheckoutQuery - -Use this method to send answers to shipping query. - -`telegram.answerPreCheckoutQuery(preCheckoutQueryId, ok, [errorMessage]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| preCheckoutQueryId | `string` | Shipping Query id | -| ok | `bool` | Specify True if everything is alright (goods are available, etc.) | -| [errorMessage] | `string` | Error message in human readable form | - -##### answerInlineQuery - -Use this method to send answers to an inline query. - -`telegram.answerInlineQuery(inlineQueryId, results, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| inlineQueryId | `string` | Query id | -| results | `object[]` | Results | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#answerinlinequery)| - -##### createNewStickerSet - -Use this method to create new sticker set owned by a user. - -`telegram.createNewStickerSet(ownerId, name, title, stickerData, [isMasks]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#createnewstickerset) - -| Param | Type | Description | -| --- | --- | --- | -| ownerId | `string` | User identifier of sticker set owner | -| name | `string` | Sticker set name | -| title | `string` | Sticker set title | -| stickerData | `object` | Sticker data({png_sticker: 'stiker file', emojis: 'πŸ˜‰', mask__position: '' }) | -| [isMasks] | `bool` | Pass True, if a set of mask stickers should be created | - -##### deleteChatStickerSet - -Use this method to delete a group sticker set from a supergroup. - -`telegram.deleteChatStickerSet(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#deletechatstickerset) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### deleteMessage - -Use this method to delete bot messages. - -`telegram.deleteMessage(chatId, messageId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#deletemessage) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | - -##### setStickerSetThumb - -Use this method to set the thumbnail of a sticker set. - -`telegram.setStickerSetThumb(name, userId, [thumb]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setstickersetthumb) - -| Param | Type | Description | -| --- | --- | --- | -| name | `string` | Sticker set name | -| userId | `string` | User identifier of the sticker set owner | -| thumb | `File` | A PNG image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a TGS animation with the thumbnail up to 32 kilobytes in size | - -##### deleteStickerFromSet - -Use this method to delete a sticker from a set created by the bot. - -`telegram.deleteStickerFromSet(stickerId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#deletestickerfromset) - -| Param | Type | Description | -| --- | --- | --- | -| stickerId | `string` | File identifier of the sticker | - -##### editMessageCaption - -Use this method to edit captions of messages sent by the bot or via the bot. - -`telegram.editMessageCaption(chatId, messageId, inlineMessageId, caption, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | -| inlineMessageId | `string` | Inline message id | -| caption | `string` | Caption | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagecaption)| - -##### editMessageMedia - -Use this method to edit media of messages sent by the bot or via the bot. - -`telegram.editMessageMedia(chatId, messageId, inlineMessageId, media, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | -| inlineMessageId | `string` | Inline message id | -| media | `InputMedia` | [InputMedia](https://core.telegram.org/bots/api#inputmedia) | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagemedia)| - -##### editMessageLiveLocation - -Use this method to edit live location messages sent by the bot or via the bot. - -`telegram.editMessageLiveLocation(latitude, longitude, chatId, messageId, inlineMessageId, [markup]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#editmessagelivelocation) - -| Param | Type | Description | -| --- | --- | --- | -| latitude | `string` | Latitude of new location | -| longitude | `string` | Longitude of new location | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | -| inlineMessageId | `string` | Inline message id | -| [markup] | `object` | Keyboard markup | - -##### editMessageReplyMarkup - -Use this method to edit only the reply markup of messages sent by the bot or via the bot. - -`telegram.editMessageReplyMarkup(chatId, messageId, inlineMessageId, markup, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | -| inlineMessageId | `string` | Inline message id | -| markup | `object` | Keyboard markup | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagereplymarkup)| - -##### editMessageText - -Use this method to edit text messages sent by the bot or via the bot. - -`telegram.editMessageText(chatId, messageId, inlineMessageId, text, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | -| inlineMessageId | `string` | Inline message id | -| text | `string` | Message | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagetext)| - -##### forwardMessage - -Forwards message. - -`telegram.forwardMessage(chatId, fromChatId, messageId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Target Chat id | -| fromChatId | `number/string` | Source Chat id | -| messageId | `number` | Message id | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#forwardmessage)| - - -##### sendCopy - -Sends message copy. - -`telegram.sendCopy(chatId, message, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Target Chat id | -| message | `object` | Message | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendmessage)| - -##### getWebhookInfo - -Use this method to get current webhook status. Requires no parameters. On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty. - -`telegram.getWebhookInfo() => Promise` - -##### getChat - -Use this method to get up to date information about the chat (current name of the user for one-on-one conversatio -ns, current username of a user, group or channel, etc.). - -`telegram.getChat(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getchat) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### getChatAdministrators - -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. - -`telegram.getChatAdministrators(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getchatadministrators) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### setGameScore - -Use this method to set the score of the specified user in a game. On success, if the message was sent by the bot, returns the edited Message, otherwise returns True. Returns an error, if the new score is not greater than the user's current score in the chat. - -`telegram.setGameScore(userId, score, inlineMessageId, chatId, messageId, [editMessage], [force]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setgamescore) - -| Param | Type | Description | -| --- | --- | --- | -| userId | `number` | Target User id | -| score | `number` | Target User id | -| inlineMessageId | `string` | Inline message id | -| chatId | `number/string` | Target Chat id | -| messageId | `number/string` | Message id | -| [editMessage] | `boolean` | edit target message, default value is True | -| [force] | `boolean` | Pass True, if the high score is allowed to decrease. This can be useful when fixing mistakes or banning cheaters | - -##### getGameHighScores - -Use this method to get data for high score tables. Will return the score of the specified user and several of his neighbors in a game. On success, returns an Array of GameHighScore objects. - -`telegram.getGameHighScores(userId, inlineMessageId, chatId, messageId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getgamehighscores) - -| Param | Type | Description | -| --- | --- | --- | -| userId | `number`\ | Target User id | -| inlineMessageId | `string` | Inline message id | -| chatId | `number/string` | Target Chat id | -| messageId | `number/string` | Message id | - -##### getChatMember - -Use this method to get information about a member of a chat. - -`telegram.getChatMember(chatId, userId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getchatmember) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| userId | `number` | User identifier | - -##### getChatMembersCount - -Use this method to get the number of members in a chat. - -`telegram.getChatMembersCount(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getchatmemberscount) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### getFile - -Returns basic info about a file and prepare it for downloading. - -`telegram.getFile(fileId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getfile) - -| Param | Type | Description | -| --- | --- | --- | -| fileId | `string` | File id | - -##### getFileLink - -Returns link to file. - -`telegram.getFileLink(fileId) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| fileId | `string/object` | File id or file object | - -##### getMe - -Returns basic information about the bot. - -`telegram.getMe() => Promise` -[Official documentation](https://core.telegram.org/bots/api#getme) - -##### getMyCommands - -Use this method to get the current list of the bot's commands. -Requires no parameters. Returns Array of BotCommand on success. - -`telegram.getMyCommands() => Promise` -[Official documentation](https://core.telegram.org/bots/api#getmycommands) - -##### getStickerSet - -Use this method to get a sticker set. - -`telegram.getStickerSet(name) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| name | `string` | Short name of the sticker set | -[Official documentation](https://core.telegram.org/bots/api#getstickerset) - -##### getUserProfilePhotos - -Returns profiles photos for provided user. - -`telegram.getUserProfilePhotos(userId, [offset], [limit]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#getuserprofilephotos) - -| Param | Type | Description | -| --- | --- | --- | -| userId | `number` | Chat id | -| [offset] | `number` | Offset | -| [limit] | `number` | Limit | - -##### setChatPermissions - -Use this method to set default chat permissions for all members. - -`telegram.setChatPermissions(chatId, permissions) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| permissions | `object` | [New default chat permissions](https://core.telegram.org/bots/api#chatpermissions)| - -##### kickChatMember - -Use this method to kick a user from a group or a supergroup. - -`telegram.kickChatMember(chatId, userId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| userId | `number` | User id | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#kickchatmember)| - -##### restrictChatMember - -Use this method to restrict a user in a supergroup. - -`telegram.restrictChatMember(chatId, userId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| userId | `number` | User id | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#restrictchatmember)| - -##### promoteChatMember - -Use this method to promote or demote a user in a supergroup or a channel. - -`telegram.promoteChatMember(chatId, userId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| userId | `number` | User id | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#promotechatmember)| - -##### setChatAdministratorCustomTitle - -New custom title for the administrator; 0-16 characters, emoji are not allowed - -`telegram.setChatAdministratorCustomTitle(chatId, userId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| userId | `number` | User id | -| title | `string` | Custom title | - -##### exportChatInviteLink - -Use this method to export an invite link to a supergroup or a channel. - -`telegram.exportChatInviteLink(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#exportchatinvitelink) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### setChatPhoto - -Use this method to set a new profile photo for the chat. - -`telegram.setChatPhoto(chatId, photo) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setchatphoto) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| photo | `File` | New chat photo | - -##### deleteChatPhoto - -Use this method to delete a chat photo. - -`telegram.deleteChatPhoto(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#deletechatphoto) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### setChatTitle - -Use this method to change the title of a chat. - -`telegram.setChatTitle(chatId, title) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setchattitle) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| title | `string` | New chat title, 1-255 characters | - -##### setChatDescription - -Use this method to change the description of a supergroup or a channel. - -`telegram.setChatDescription(chatId, description) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setchattitle) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| description | `string` | New chat description, 0-255 characters | - -##### setChatStickerSet - -Use this method to set a new group sticker set for a supergroup. - -`telegram.setChatStickerSet(chatId, stickerSetName) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setchatstickerset) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| stickerSetName | `string` | Name of the sticker set | - -##### pinChatMessage - -Use this method to pin a message in a supergroup. - -`telegram.pinChatMessage(chatId, messageId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `number` | Message id | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#pinchatmessage)| - -##### unpinChatMessage - -Use this method to unpin a message in a supergroup chat. - -`telegram.unpinChatMessage(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#unpinchatmessage) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### leaveChat - -Use this method for your bot to leave a group, supergroup or channel. - -`telegram.leaveChat(chatId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#leavechat) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | - -##### deleteWebhook - -Removes webhook integration. - -`telegram.deleteWebhook() => Promise` -[Official documentation](https://core.telegram.org/bots/api#deletewebhook) - -##### sendAudio - -Sends audio. - -`telegram.sendAudio(chatId, audio, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| audio | `File` | Document | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendaudio)| - - -##### sendGame - -Sends game. - -`telegram.sendGame(chatId, gameName, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| gameName | `String` | Game short name | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendgame)| - -##### sendChatAction - -Sends chat action. - -`telegram.sendChatAction(chatId, action) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| action | `string` | [Chat action](https://core.telegram.org/bots/api#sendchataction) | - -##### sendContact - -Sends document. - -`telegram.sendContact(chatId, phoneNumber, firstName, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| phoneNumber | `string` | Contact phone number | -| firstName | `string` | Contact first name | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendcontact)| - -##### sendDice - -Sends dice. - -`telegram.sendDice(chatId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#senddice)| - -##### sendDocument - -Sends document. - -`telegram.sendDocument(chatId, doc, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| doc | `File` | Document | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#senddocument)| - -##### sendLocation - -Sends location. - -`telegram.sendLocation(chatId, latitude, longitude, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| latitude | `number` | Latitude | -| longitude | `number` | Longitude | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendlocation)| - -##### sendMessage - -Sends text message. - -`telegram.sendMessage(chatId, text, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| text | `string` | Message | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendmessage)| - -##### sendPhoto - -Sends photo. - -`telegram.sendPhoto(chatId, photo, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| photo | `File` | Photo | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendphoto)| - -##### sendMediaGroup - -Sends media album. - -`telegram.sendMediaGroup(chatId, media, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| media | `InputMedia[]` | Media array | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendmediagroup)| - -##### sendSticker - -Sends sticker. - -`telegram.sendSticker(chatId, sticker, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| sticker | `File` | Document | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendsticker)| - -##### setStickerPositionInSet - -Use this method to move a sticker in a set created by the bot to a specific position. - -`telegram.setStickerPositionInSet(sticker, position) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| sticker | `string` | File identifier of the sticker | -| position | `number` | New sticker position in the set, zero-based | - -##### sendVenue - -Sends venue information. - -`telegram.sendVenue(chatId, latitude, longitude, title, address, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| latitude | `number` | Latitude | -| longitude | `number` | Longitude | -| title | `string` | Venue title | -| address | `string` | Venue address | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvenue)| - -##### sendInvoice - -Sends invoice. - -`telegram.sendInvoice(chatId, invoice) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| invoice | `object` | [Invoice object](https://core.telegram.org/bots/api#sendinvoice) | - -##### sendVideo - -Sends video. - -`telegram.sendVideo(chatId, video, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| video | `File` | Document | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvideo)| - -##### sendAnimation - -Sends video. - -`telegram.sendAnimation(chatId, animation, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| animation | `File` | Document | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendanimation)| - -##### sendVideoNote - -Sends round video. - -`telegram.sendVideoNote(chatId, video, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| video | `File` | Video note file | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvideonote)| - -##### sendVoice - -Sends voice. - -`telegram.sendVoice(chatId, voice, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| voice | `File/string` | File, file id or HTTP URL | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvoice)| - -##### sendPoll - -Sends anonymous poll. - -`telegram.sendPoll(chatId, question, options, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| question | `string` | Poll question | -| options | `string[]` | Answer options | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendpoll)| - -##### setMyCommands - -Use this method to change the list of the bot's commands - -`telegram.setMyCommands(commands) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| commands | `object[]` | [List of bot commands](https://core.telegram.org/bots/api#setmycommands) | - -##### sendQuiz - -Sends quiz. - -`telegram.sendQuiz(chatId, question, options, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| question | `string` | Poll question | -| options | `string[]` | Answer options | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendpoll)| - - -##### stopPoll - -Stops anonymous poll. - -`telegram.stopPoll(chatId, messageId, [extra]) => Promise` - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Poll message id | -| options| `string[]` | Answer options | -| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#stoppoll)| - -##### stopMessageLiveLocation - -Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before live_period expires. - -`telegram.stopMessageLiveLocation(chatId, messageId, inlineMessageId, [markup]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#stopmessagelivelocation) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| messageId | `string` | Message id | -| inlineMessageId | `string` | Inline message id | -| [markup] | `object` | Keyboard markup | - -##### uploadStickerFile - -Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods. - -`telegram.uploadStickerFile(ownerId, stickerFile) => Promise` -[Official documentation](https://core.telegram.org/bots/api#uploadstickerfile) - -| Param | Type | Description | -| --- | --- | --- | -| ownerId | `string` | User identifier of sticker file owner | -| stickerFile | `File` | Png image with the sticker | - -##### setWebhook - -Specifies an url to receive incoming updates via an outgoing webhook. - -`telegram.setWebhook(url, [cert], [maxConnections], [allowedUpdates]) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setwebhook) - -| Param | Type | Description | -| --- | --- | --- | -| url | `string` | Public url for webhook | -| [cert] | `File` | SSL public certificate | -| [maxConnections] | `number` | Maximum allowed number of simultaneous HTTPS connections to the webhook | -| [allowedUpdates] | `string[]` | List the types of updates you want your bot to receive | - -##### unbanChatMember - -Use this method to unban a previously kicked user in a supergroup. - -`telegram.unbanChatMember(chatId, userId) => Promise` -[Official documentation](https://core.telegram.org/bots/api#unbanchatmember) - -| Param | Type | Description | -| --- | --- | --- | -| chatId | `number/string` | Chat id | -| userId | `number` | User id | - - -##### setPassportDataErrors - -Informs a user that some of the Telegram Passport elements they provided contains errors. -The user will not be able to re-submit their Passport to you -until the errors are fixed (the contents of the field for which you returned the error must change). - -`telegram.setPassportDataErrors(errors) => Promise` -[Official documentation](https://core.telegram.org/bots/api#setpassportdataerrors) - -| Param | Type | Description | -| --- | --- | --- | -| [errors] | `PassportElementError[]` | An array describing the errors | - -#### Extra - -Telegram message options helper, [see examples](https://github.com/telegraf/telegraf/tree/develop/docs/examples/). - -#### Markup - -Telegram markup helper, [see examples](https://github.com/telegraf/telegraf/tree/develop/docs/examples/). - -#### Stage - -Simple scene-based control flow middleware. - -```js -const { Telegraf } = require('telegraf') -const session = require('telegraf/session') -const Stage = require('telegraf/stage') -const Scene = require('telegraf/scenes/base') -const { leave } = Stage - -// Greeter scene -const greeter = new Scene('greeter') -greeter.enter((ctx) => ctx.reply('Hi')) -greeter.leave((ctx) => ctx.reply('Bye')) -greeter.hears(/hi/gi, leave()) -greeter.on('message', (ctx) => ctx.reply('Send `hi`')) - -// Create scene manager -const stage = new Stage() -stage.command('cancel', leave()) - -// Scene registration -stage.register(greeter) - -const bot = new Telegraf(process.env.BOT_TOKEN) -bot.use(session()) -bot.use(stage.middleware()) -bot.command('greeter', (ctx) => ctx.scene.enter('greeter')) -bot.startPolling() -``` - -Scenes related context props and functions: - -```js -bot.on('message', (ctx) => { - ctx.scene.state // Current scene state (persistent) - ctx.scene.enter(sceneId, [defaultState, silent]) // Enter scene - ctx.scene.reenter() // Reenter current scene - ctx.scene.leave() // Leave scene -}) -``` diff --git a/docs/_sidebar.md b/docs/_sidebar.md new file mode 100644 index 000000000..cdfb6091d --- /dev/null +++ b/docs/_sidebar.md @@ -0,0 +1,9 @@ +- [Introduction](/) +- [Getting started](getting-started.md) +- API reference + - [Telegraf](telegraf.md) + - [Telegram](telegram.md) + - [Extra](extra.md) + - [Markup](markup.md) + - [Router](router.md) + - [Stage](stage.md) diff --git a/docs/examples/custom-context-bot.js b/docs/examples/custom-context-bot.js index 1a614f1b1..c3225ef7f 100644 --- a/docs/examples/custom-context-bot.js +++ b/docs/examples/custom-context-bot.js @@ -1,6 +1,6 @@ -const Telegraf = require('telegraf') +const { Telegraf, Context } = require('telegraf') -class CustomContext extends Telegraf.Context { +class CustomContext extends Context { constructor (update, telegram, options) { console.log('Creating contexy for %j', update) super(update, telegram, options) diff --git a/docs/examples/custom-router-bot.js b/docs/examples/custom-router-bot.js new file mode 100644 index 000000000..7f70960be --- /dev/null +++ b/docs/examples/custom-router-bot.js @@ -0,0 +1,61 @@ +const { Telegraf, Router, Extra, session } = require('telegraf') + +const markup = Extra + .HTML() + .markup((m) => m.inlineKeyboard([ + m.callbackButton('Add 1', 'add:1'), + m.callbackButton('Add 10', 'add:10'), + m.callbackButton('Add 100', 'add:100'), + m.callbackButton('Subtract 1', 'sub:1'), + m.callbackButton('Subtract 10', 'sub:10'), + m.callbackButton('Subtract 100', 'sub:100'), + m.callbackButton('🐈', Math.random().toString(36).slice(2)), + m.callbackButton('Clear', 'clear') + ], { columns: 3 })) + +const calculator = new Router(({ callbackQuery }) => { + if (!callbackQuery.data) { + return + } + const parts = callbackQuery.data.split(':') + return { + route: parts[0], + state: { + amount: parseInt(parts[1], 10) || 0 + } + } +}) + +calculator.on('add', (ctx) => { + ctx.session.value = (ctx.session.value || 0) + ctx.state.amount + return editText(ctx) +}) + +calculator.on('sub', (ctx) => { + ctx.session.value = (ctx.session.value || 0) - ctx.state.amount + return editText(ctx) +}) + +calculator.on('clear', (ctx) => { + ctx.session.value = 0 + return editText(ctx) +}) + +calculator.otherwise((ctx) => ctx.reply('🌯')) + +function editText (ctx) { + if (ctx.session.value === 42) { + return ctx.answerCbQuery('Answer to the Ultimate Question of Life, the Universe, and Everything', true) + .then(() => ctx.editMessageText('πŸŽ†')) + } + return ctx.editMessageText(`Value: ${ctx.session.value}`, markup).catch(() => undefined) +} + +const bot = new Telegraf(process.env.BOT_TOKEN) +bot.use(session({ ttl: 10 })) +bot.start((ctx) => { + ctx.session.value = 0 + return ctx.reply(`Value: ${ctx.session.value}`, markup) +}) +bot.on('callback_query', calculator) +bot.launch() diff --git a/docs/examples/deeplink-bot.js b/docs/examples/deeplink-bot.js index a95ec7d67..e1d59d7b0 100644 --- a/docs/examples/deeplink-bot.js +++ b/docs/examples/deeplink-bot.js @@ -1,5 +1,5 @@ // https://core.telegram.org/bots#deep-linking -const Telegraf = require('telegraf') +const { Telegraf } = require('telegraf') const bot = new Telegraf(process.env.BOT_TOKEN) bot.start((ctx) => ctx.reply(`Deep link payload: ${ctx.startPayload}`)) diff --git a/docs/examples/echo-bot-module.js b/docs/examples/echo-bot-module.js index 56c5971c3..65b395070 100644 --- a/docs/examples/echo-bot-module.js +++ b/docs/examples/echo-bot-module.js @@ -1,8 +1,6 @@ // Modules documentation: https://telegraf.js.org/#/?id=telegraf-modules // $> telegraf -t `BOT TOKEN` echo-bot-module.js -const Composer = require('telegraf/composer') -const Extra = require('telegraf/extra') -const Markup = require('telegraf/markup') +const { Composer, Extra, Markup } = require('telegraf') const keyboard = Markup.inlineKeyboard([ Markup.urlButton('❀️', 'http://telegraf.js.org'), @@ -35,6 +33,6 @@ bot.help(async (ctx) => { }) bot.action('delete', ({ deleteMessage }) => deleteMessage()) bot.on('dice', (ctx) => ctx.reply(`Value: ${ctx.message.dice.value}`)) -bot.on('message', (ctx) => ctx.telegram.sendCopy(ctx.chat.id, ctx.message, Extra.markup(keyboard))) +bot.on('message', (ctx) => ctx.copyMessage(ctx.chat.id, Extra.markup(keyboard))) module.exports = bot diff --git a/docs/examples/echo-bot.js b/docs/examples/echo-bot.js index e2475a652..be7a0ed8e 100644 --- a/docs/examples/echo-bot.js +++ b/docs/examples/echo-bot.js @@ -1,6 +1,4 @@ -const Telegraf = require('telegraf') -const Extra = require('telegraf/extra') -const Markup = require('telegraf/markup') +const { Telegraf, Extra, Markup } = require('telegraf') const keyboard = Markup.inlineKeyboard([ Markup.urlButton('❀️', 'http://telegraf.js.org'), @@ -10,6 +8,6 @@ const keyboard = Markup.inlineKeyboard([ const bot = new Telegraf(process.env.BOT_TOKEN) bot.start((ctx) => ctx.reply('Hello')) bot.help((ctx) => ctx.reply('Help message')) -bot.on('message', (ctx) => ctx.telegram.sendCopy(ctx.chat.id, ctx.message, Extra.markup(keyboard))) +bot.on('message', (ctx) => ctx.copyMessage(ctx.chat.id, Extra.markup(keyboard))) bot.action('delete', ({ deleteMessage }) => deleteMessage()) bot.launch() diff --git a/docs/examples/example-bot.js b/docs/examples/example-bot.js index 777bd454a..dc51a2b3b 100644 --- a/docs/examples/example-bot.js +++ b/docs/examples/example-bot.js @@ -1,6 +1,4 @@ -const Telegraf = require('telegraf') -const Extra = require('telegraf/extra') -const session = require('telegraf/session') +const { Telegraf, Extra, session } = require('telegraf') const { reply, fork } = Telegraf const randomPhoto = 'https://picsum.photos/200/300/?random' diff --git a/docs/examples/game-bot.js b/docs/examples/game-bot.js index 0caff23cb..749afd8c5 100644 --- a/docs/examples/game-bot.js +++ b/docs/examples/game-bot.js @@ -1,6 +1,4 @@ -const Telegraf = require('telegraf') -const Extra = require('telegraf/extra') -const Markup = require('telegraf/markup') +const { Telegraf, Markup } = require('telegraf') const gameShortName = 'your-game' const gameUrl = 'https://your-game.tld' diff --git a/docs/examples/inline-bot.js b/docs/examples/inline-bot.js index befa22949..9aee7299c 100644 --- a/docs/examples/inline-bot.js +++ b/docs/examples/inline-bot.js @@ -1,5 +1,4 @@ -const Telegraf = require('telegraf') -const Markup = require('telegraf/markup') +const { Telegraf, Markup } = require('telegraf') const fetch = require('node-fetch') const bot = new Telegraf(process.env.BOT_TOKEN) diff --git a/docs/examples/keyboard-bot.js b/docs/examples/keyboard-bot.js index 29b44bcac..6d5c453ba 100644 --- a/docs/examples/keyboard-bot.js +++ b/docs/examples/keyboard-bot.js @@ -1,6 +1,4 @@ -const Telegraf = require('telegraf') -const Extra = require('telegraf/extra') -const Markup = require('telegraf/markup') +const { Telegraf, Extra, Markup } = require('telegraf') const bot = new Telegraf(process.env.BOT_TOKEN) diff --git a/docs/extra.md b/docs/extra.md new file mode 100644 index 000000000..3b9da27be --- /dev/null +++ b/docs/extra.md @@ -0,0 +1,3 @@ +# Extra + +Telegram message options helper, [see examples](https://github.com/telegraf/telegraf/tree/develop/docs/examples/). diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 000000000..13338fdfc --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,625 @@ +# Getting started + +## Telegram token + +To use the [Telegram Bot API](https://core.telegram.org/bots/api), you first have to [get a bot account](https://core.telegram.org/bots) by [chatting with BotFather](https://core.telegram.org/bots#6-botfather). + +BotFather will give you a *token*, something like `123456789:AbCdfGhIJKlmNoQQRsTUVwxyZ`. + +## Bot + +A Telegraf bot 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 a 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 update, `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 bot = new Telegraf(process.env.BOT_TOKEN) + +bot.use(async (ctx, next) => { + const start = new Date() + await next() + const ms = new Date() - start + console.log('Response time: %sms', ms) +}) + +bot.on('text', (ctx) => ctx.reply('Hello World')) +bot.launch() +``` + +### 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) +- [Rate-limiting](https://github.com/telegraf/telegraf-ratelimit) +- [Menus via inline keyboards](https://github.com/EdJoPaTo/telegraf-inline-menu) +- [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) +- [Powerful 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 bot = new Telegraf(process.env.BOT_TOKEN) +bot.catch((err, ctx) => { + console.log(`Ooops, encountered an error for ${ctx.updateType}`, err) +}) +bot.start((ctx) => { + throw new Error('Example error') +}) +bot.launch() +``` + +## Context + +A Telegraf Context encapsulates telegram update. +Context is created per request and contains following props: + +| Property | Description | +| --- | --- | +| ` ctx.telegram ` | Telegram client instance | +| ` ctx.updateType ` | Update type (message, inline_query, etc.) | +| `[ctx.updateSubTypes]` | Update subtypes (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.shippingQuery]` | Shipping query | +| `[ctx.preCheckoutQuery]` | Pre-checkout query | +| `[ctx.channelPost]` | New incoming channel post of any kind β€” text, photo, sticker, etc. | +| `[ctx.editedChannelPost]` | New version of a channel post that is known to the bot and was edited | +| `[ctx.poll]` | New version of a anonymous poll that is known to the bot and was changed | +| `[ctx.pollAnswer]` | This object represents an answer of a user in a non-anonymous poll. | +| `[ctx.chat]` | Current chat info | +| `[ctx.from]` | Sender info | +| `[ctx.match]` | Regex match (available only for `hears`, `command`, `action`, `inlineQuery` handlers) | +| ` ctx.webhookReply ` | Shortcut to `ctx.telegram.webhookReply` | + +```js +bot.use((ctx) => { + console.log(ctx.message) +}) +``` + +### Extending context + +The recommended way to extend bot context: + +```js +const bot = new Telegraf(process.env.BOT_TOKEN) + +bot.context.db = { + getScores: () => { return 42 } +} + +bot.on('text', (ctx) => { + const scores = ctx.db.getScores(ctx.message.from.username) + return ctx.reply(`${ctx.message.from.username}: ${scores}`) +}) + +bot.launch() +``` + +### Shortcuts + +Context shortcuts for **message** update: + +| Shortcut | Bound to | +| --- | --- | +| `addStickerToSet` | [`telegram.addStickerToSet`](telegram.md#addstickertoset) | +| `createNewStickerSet` | [`telegram.createNewStickerSet`](telegram.md#createnewstickerset) | +| `deleteChatPhoto` | [`telegram.deleteChatPhoto`](telegram.md#deletechatphoto) | +| `deleteMessage` | [`telegram.deleteMessage`](telegram.md#deletemessage) | +| `deleteStickerFromSet` | [`telegram.deleteStickerFromSet`](telegram.md#deletestickerfromset) | +| `exportChatInviteLink` | [`telegram.exportChatInviteLink`](telegram.md#exportchatinvitelink) | +| `forwardMessage` | [`telegram.forwardMessage`](telegram.md#forwardmessage) | +| `getChat` | [`telegram.getChat`](telegram.md#getchat) | +| `getChatAdministrators` | [`telegram.getChatAdministrators`](telegram.md#getchatadministrators) | +| `getChatMember` | [`telegram.getChatMember`](telegram.md#getchatmember) | +| `getChatMembersCount` | [`telegram.getChatMembersCount`](telegram.md#getchatmemberscount) | +| `getMyCommands` | [`telegram.getMyCommands`](telegram.md#getmycommands) | +| `getStickerSet` | [`telegram.getStickerSet`](telegram.md#getstickerset) | +| `leaveChat` | [`telegram.leaveChat`](telegram.md#leavechat) | +| `pinChatMessage` | [`telegram.pinChatMessage`](telegram.md#pinchatmessage) | +| `reply` | [`telegram.sendMessage`](telegram.md#sendmessage) | +| `replyWithAudio` | [`telegram.sendAudio`](telegram.md#sendaudio) | +| `replyWithChatAction` | [`telegram.sendChatAction`](telegram.md#sendchataction) | +| `replyWithDice` | [`telegram.sendDice`](telegram.md#senddice) | +| `replyWithDocument` | [`telegram.sendDocument`](telegram.md#senddocument) | +| `replyWithGame` | [`telegram.sendGame`](telegram.md#sendgame) | +| `replyWithHTML` | [`telegram.sendMessage`](telegram.md#sendmessage) | +| `replyWithInvoice` | [`telegram.sendInvoice`](telegram.md#sendinvoice) | +| `replyWithLocation` | [`telegram.sendLocation`](telegram.md#sendlocation) | +| `replyWithMarkdown` | [`telegram.sendMessage`](telegram.md#sendmessage) | +| `replyWithMediaGroup` | [`telegram.sendMediaGroup`](telegram.md#sendmediagroup) | +| `replyWithPhoto` | [`telegram.sendPhoto`](telegram.md#sendphoto) | +| `replyWithPoll` | [`telegram.sendPoll`](telegram.md#sendpoll) | +| `replyWithQuiz` | [`telegram.sendQuiz`](telegram.md#sendquiz) | +| `replyWithSticker` | [`telegram.sendSticker`](telegram.md#sendsticker) | +| `replyWithVideo` | [`telegram.sendVideo`](telegram.md#sendvideo) | +| `replyWithVideoNote` | [`telegram.sendVideoNote`](telegram.md#sendvideonote) | +| `replyWithVoice` | [`telegram.sendVoice`](telegram.md#sendvoice) | +| `setChatDescription` | [`telegram.setChatDescription`](telegram.md#setchatdescription) | +| `setChatPhoto` | [`telegram.setChatPhoto`](telegram.md#setchatphoto) | +| `setChatTitle` | [`telegram.setChatTitle`](telegram.md#setchattitle) | +| `setMyCommands` | [`telegram.setMyCommands`](telegram.md#setmycommands) | +| `setPassportDataErrors` | [`telegram.setPassportDataErrors`](telegram.md#setpassportdataerrors) | +| `setStickerPositionInSet` | [`telegram.setStickerPositionInSet`](telegram.md#setstickerpositioninset) | +| `setStickerSetThumb` | [`telegram.setStickerSetThumb`](telegram.md#setstickersetthumb) | +| `setStickerSetThumb` | [`telegram.setStickerSetThumb`](telegram.md#setstickersetthumb) | +| `stopPoll` | [`telegram.stopPoll`](telegram.md#stoppoll) | +| `unpinChatMessage` | [`telegram.unpinChatMessage`](telegram.md#unpinchatmessage) | +| `unpinAllChatMessages` | [`telegram.unpinAllChatMessages`](telegram.md#unpinallchatmessages) | +| `uploadStickerFile` | [`telegram.uploadStickerFile`](telegram.md#uploadstickerfile) | +| `unbanChatMember` | [`telegram.unbanChatMember`](telegram.md#unbanchatmember) | + +Context shortcuts for **callback_query** update: + +| Shortcut | Bound to | +| --- | --- | +| `addStickerToSet` | [`telegram.addStickerToSet`](telegram.md#addstickertoset) | +| `answerCbQuery` | [`telegram.answerCbQuery`](telegram.md#answercbquery) | +| `answerGameQuery` | [`telegram.answerGameQuery`](telegram.md#answergamequery) | +| `createNewStickerSet` | [`telegram.createNewStickerSet`](telegram.md#createnewstickerset) | +| `deleteChatPhoto` | [`telegram.deleteChatPhoto`](telegram.md#deletechatphoto) | +| `deleteMessage` | [`telegram.deleteMessage`](telegram.md#deletemessage) | +| `deleteStickerFromSet` | [`telegram.deleteStickerFromSet`](telegram.md#deletestickerfromset) | +| `editMessageCaption` | [`telegram.editMessageCaption`](telegram.md#editmessagecaption) | +| `editMessageMedia` | [`telegram.editMessageMedia`](telegram.md#editmessagemedia) | +| `editMessageReplyMarkup` | [`telegram.editMessageReplyMarkup`](telegram.md#editmessagereplymarkup) | +| `editMessageText` | [`telegram.editMessageText`](telegram.md#editmessagetext) | +| `exportChatInviteLink` | [`telegram.exportChatInviteLink`](telegram.md#exportchatinvitelink) | +| `forwardMessage` | [`telegram.forwardMessage`](telegram.md#forwardmessage) | +| `getChat` | [`telegram.getChat`](telegram.md#getchat) | +| `getChatAdministrators` | [`telegram.getChatAdministrators`](telegram.md#getchatadministrators) | +| `getChatMember` | [`telegram.getChatMember`](telegram.md#getchatmember) | +| `getChatMembersCount` | [`telegram.getChatMembersCount`](telegram.md#getchatmemberscount) | +| `getStickerSet` | [`telegram.getStickerSet`](telegram.md#getstickerset) | +| `leaveChat` | [`telegram.leaveChat`](telegram.md#leavechat) | +| `pinChatMessage` | [`telegram.pinChatMessage`](telegram.md#pinchatmessage) | +| `reply` | [`telegram.sendMessage`](telegram.md#sendmessage) | +| `replyWithAnimation` | [`telegram.sendAnimation`](telegram.md#sendanimation) | +| `replyWithAudio` | [`telegram.sendAudio`](telegram.md#sendaudio) | +| `replyWithChatAction` | [`telegram.sendChatAction`](telegram.md#sendchataction) | +| `replyWithDice` | [`telegram.sendDice`](telegram.md#senddice) | +| `replyWithDocument` | [`telegram.sendDocument`](telegram.md#senddocument) | +| `replyWithGame` | [`telegram.sendGame`](telegram.md#sendgame) | +| `replyWithHTML` | [`telegram.sendMessage`](telegram.md#sendmessage) | +| `replyWithInvoice` | [`telegram.sendInvoice`](telegram.md#sendinvoice) | +| `replyWithLocation` | [`telegram.sendLocation`](telegram.md#sendlocation) | +| `replyWithMarkdown` | [`telegram.sendMessage`](telegram.md#sendmessage) | +| `replyWithMediaGroup` | [`telegram.sendMediaGroup`](telegram.md#sendmediagroup) | +| `replyWithPhoto` | [`telegram.sendPhoto`](telegram.md#sendphoto) | +| `replyWithPoll` | [`telegram.sendPoll`](telegram.md#sendpoll) | +| `replyWithSticker` | [`telegram.sendSticker`](telegram.md#sendsticker) | +| `replyWithVideo` | [`telegram.sendVideo`](telegram.md#sendvideo) | +| `replyWithVideoNote` | [`telegram.sendVideoNote`](telegram.md#sendvideonote) | +| `replyWithVoice` | [`telegram.sendVoice`](telegram.md#sendvoice) | +| `setChatDescription` | [`telegram.setChatDescription`](telegram.md#setchatdescription) | +| `setChatPhoto` | [`telegram.setChatPhoto`](telegram.md#setchatphoto) | +| `setChatTitle` | [`telegram.setChatTitle`](telegram.md#setchattitle) | +| `setStickerPositionInSet` | [`telegram.setStickerPositionInSet`](telegram.md#setstickerpositioninset) | +| `setStickerSetThumb` | [`telegram.setStickerSetThumb`](telegram.md#setstickersetthumb) | +| `stopPoll` | [`telegram.stopPoll`](telegram.md#stoppoll) | +| `unpinChatMessage` | [`telegram.unpinChatMessage`](telegram.md#unpinchatmessage) | +| `unpinAllChatMessages` | [`telegram.unpinAllChatMessages`](telegram.md#unpinallchatmessages) | +| `uploadStickerFile` | [`telegram.uploadStickerFile`](telegram.md#uploadstickerfile) | +| `unbanChatMember` | [`telegram.unbanChatMember`](telegram.md#unbanchatmember) | + +Context shortcuts for **inline_query** update: + +| Shortcut | Bound to | +| --- | --- | +| `answerInlineQuery` | [`telegram.answerInlineQuery`](telegram.md#answerinlinequery) | + +Context shortcuts for **shipping_query** update: + +| Shortcut | Bound to | +| --- | --- | +| `answerShippingQuery` | [`telegram.answerShippingQuery`](telegram.md#answershippingquery) | + +Context shortcuts for **pre_checkout_query** update: + +| Shortcut | Bound to | +| --- | --- | +| `answerPreCheckoutQuery` | [`telegram.answerPreCheckoutQuery`](telegram.md#answerprecheckoutquery) | + +#### Shortcuts usage example + +```js +const bot = new Telegraf(process.env.BOT_TOKEN) + +bot.command('quit', async (ctx) => { + // Explicit usage + await ctx.telegram.leaveChat(ctx.message.chat.id) + + // Using context shortcut + await ctx.leaveChat() +}) + +bot.on('text', async (ctx) => { + // Explicit usage + await ctx.telegram.sendMessage(ctx.message.chat.id, `Hello ${ctx.state.role}`) + + // Using context shortcut + await ctx.reply(`Hello ${ctx.state.role}`) +}) + +bot.on('callback_query', async (ctx) => { + // Explicit usage + await ctx.telegram.answerCbQuery(ctx.callbackQuery.id) + + // Using context shortcut + await ctx.answerCbQuery() +}) + +bot.on('inline_query', async (ctx) => { + const result = [] + // Explicit usage + await ctx.telegram.answerInlineQuery(ctx.inlineQuery.id, result) + + // Using context shortcut + await ctx.answerInlineQuery(result) +}) + +bot.launch() +``` + +## State + +The recommended namespace to share information between middlewares. + +```js +const bot = new Telegraf(process.env.BOT_TOKEN) + +// Naive authorization middleware +bot.use((ctx, next) => { + ctx.state.role = getUserRole(ctx.message) + return next() +}) + +bot.on('text', (ctx) => { + return ctx.reply(`Hello ${ctx.state.role}`) +}) + +bot.launch() +``` + +## Session + +```js +const session = require('telegraf/session') + +const bot = new Telegraf(process.env.BOT_TOKEN) +bot.use(session()) +bot.on('text', (ctx) => { + ctx.session.counter = ctx.session.counter || 0 + ctx.session.counter++ + return ctx.reply(`Message counter:${ctx.session.counter}`) +}) + +bot.launch() +``` + +**Note: For persistent sessions you can use any of [`telegraf-session-*`](https://www.npmjs.com/search?q=telegraf-session) middleware.** + +**Tip: To use same session in private chat with the bot and in inline mode, use following session key resolver:** + +```js +{ + getSessionKey: (ctx) => { + if (ctx.from && ctx.chat) { + return `${ctx.from.id}:${ctx.chat.id}` + } else if (ctx.from && ctx.inlineQuery) { + return `${ctx.from.id}:${ctx.from.id}` + } + return null + } +} +``` + +## 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` +- `dice` +- `document` +- `photo` +- `sticker` +- `video` +- `voice` +- `contact` +- `location` +- `venue` +- `forward` +- `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` +- `connected_website` +- `passport_data` +- `poll` + +```js +// Handle message update +bot.on('message', (ctx) => { + return ctx.reply('Hello') +}) + +// Handle sticker or photo update +bot.on(['sticker', 'photo'], (ctx) => { + console.log(ctx.message) + return ctx.reply('Cool!') +}) +``` + +[Official Docs](https://core.telegram.org/bots/api#message) + +## Webhooks + +```js +require('dotenv') + +const bot = 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 a self-signed certificate. + fs.readFileSync('client-cert.pem') + ] +} + +// Set telegram webhook +// The second argument is necessary only if the client uses a self-signed +// certificate. Including it for a verified certificate may cause things to break. +bot.telegram.setWebhook('https://server.tld:8443/secret-path', { + source: 'server-cert.pem' +}) + +// Start https webhook +bot.startWebhook('/secret-path', tlsOptions, 8443) + +// Http webhook, for nginx/heroku users. +bot.startWebhook('/secret-path', null, 5000) +``` + +Use webhookCallback() if you want to attach telegraf to existing http server + +```js +require('http') + .createServer(bot.webhookCallback('/secret-path')) + .listen(3000) + +require('https') + .createServer(tlsOptions, bot.webhookCallback('/secret-path')) + .listen(8443) +``` + +Express.js example integration + +```js +const { Telegraf } = require('telegraf') +const express = require('express') +const expressApp = express() + +const bot = new Telegraf(process.env.BOT_TOKEN) +expressApp.use(bot.webhookCallback('/secret-path')) +bot.telegram.setWebhook('https://server.tld:8443/secret-path') + +expressApp.get('/', (req, res) => { + res.send('Hello World!') +}) + +expressApp.listen(3000, () => { + console.log('Example app listening on port 3000!') +}) +``` + +Fastify example integration + +```js +const { Telegraf } = require('telegraf') +const fastifyApp = require('fastify')() + +const bot = new Telegraf(process.env.BOT_TOKEN) + +bot.on('text', ({ reply }) => reply('Hello')) +fastifyApp.use(bot.webhookCallback('/secret-path')) +// Set telegram webhook +// npm install -g localtunnel && lt --port 3000 +bot.telegram.setWebhook('https://------.localtunnel.me/secret-path') + +fastifyApp.listen(3000, () => { + console.log('Example app listening on port 3000!') +}) +``` + +Koa.js example integration + +```js +const { Telegraf } = require('telegraf') +const Koa = require('koa') +const koaBody = require('koa-body') + +const bot = new Telegraf(process.env.BOT_TOKEN) +bot.telegram.setWebhook('https://server.tld:8443/secret-path') + +const app = new Koa() +app.use(koaBody()) +app.use(async (ctx, next) => { + if (ctx.method !== 'POST' || ctx.url !== '/secret-path') { + return next() + } + await bot.handleUpdate(ctx.request.body, ctx.response) + ctx.status = 200 +}) +app.use(async (ctx) => { + ctx.body = 'Hello World' +}) + +app.listen(3000) +``` + +## Working with files + +Supported file sources: + +- `Existing file_id` +- `File path` +- `Url` +- `Buffer` +- `ReadStream` + +Also, you can provide an optional name of file as `filename`. + +```js +bot.on('message', async (ctx) => { + // resend existing file by file_id + await ctx.replyWithSticker('123123jkbhj6b') + + // send file + await ctx.replyWithVideo({ source: '/path/to/video.mp4' }) + + // send stream + await ctx.replyWithVideo({ + source: fs.createReadStream('/path/to/video.mp4') + }) + + // send buffer + await ctx.replyWithVoice({ + source: Buffer.alloc() + }) + + // send url via Telegram server + await ctx.replyWithPhoto('https://picsum.photos/200/300/') + + // pipe url content + await ctx.replyWithPhoto({ + url: 'https://picsum.photos/200/300/?random', + filename: 'kitten.jpg' + }) +}) +``` + +## Telegram Passport + +To enable Telegram Passport support you can use [`telegram-passport`](https://www.npmjs.com/package/telegram-passport) package: + +```js +const { Telegraf } = require('telegraf') +const TelegramPassport = require('telegram-passport') + +const bot = new Telegraf(process.env.BOT_TOKEN) +const passport = new TelegramPassport("PRIVATE_KEY_IN_PEM_FORMAT") + +bot.on('passport_data', (ctx) => { + const decryptedPasswordData = passport.decrypt(ctx.passportData) + console.log(decryptedPasswordData) + return ctx.setPassportDataErrors([ + { source: 'selfie', type: 'driver_license', file_hash: 'file-hash', message: 'Selfie photo is too low quality'} + ]) +}) +``` + +## Telegraf Modules + +Telegraf Modules is higher level abstraction for writing modular Telegram bots. + +Module is simple js file with exported Telegraf middleware: + +```js +module.exports = (ctx) => ctx.reply('Hello from Telegraf Module!') +``` + +```js +const Composer = require('telegraf/composer') + +module.exports = Composer.mount( + 'sticker', + (ctx) => ctx.reply('Wow, sticker') +) +``` + +To run modules you can use `telegraf` module runner, it allows you to start Telegraf module easily from the command line. + +```bash +npm install telegraf -g +``` + +## Telegraf CLI usage + +```bash +telegraf [opts] + -t Bot token [$BOT_TOKEN] + -d Webhook domain + -H Webhook host [0.0.0.0] + -p Webhook port [$PORT or 3000] + -s Stop on error + -l Enable logs + -h Show this help message +``` + +### Telegraf Module example + +Create a module with name `bot.js` and following content: + +```js +const Composer = require('telegraf/composer') +const PhotoURL = 'https://picsum.photos/200/300/?random' + +const bot = new Composer() +bot.start((ctx) => ctx.reply('Hello there!')) +bot.help((ctx) => ctx.reply('Help message')) +bot.command('photo', (ctx) => ctx.replyWithPhoto({ url: PhotoURL })) + +module.exports = bot +``` + +then run it: + +```bash +telegraf -t "bot token" bot.js +``` diff --git a/docs/index.html b/docs/index.html index da6abfb71..e179fed16 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,47 +6,39 @@ - - + + +
- + + diff --git a/docs/markup.md b/docs/markup.md new file mode 100644 index 000000000..5d03a4fc3 --- /dev/null +++ b/docs/markup.md @@ -0,0 +1,3 @@ +# Markup + +Telegram markup helper, [see examples](https://github.com/telegraf/telegraf/tree/develop/docs/examples/). diff --git a/docs/header.png b/docs/media/header.png similarity index 100% rename from docs/header.png rename to docs/media/header.png diff --git a/docs/telegraf.png b/docs/media/telegraf.png similarity index 100% rename from docs/telegraf.png rename to docs/media/telegraf.png diff --git a/docs/router.md b/docs/router.md new file mode 100644 index 000000000..65239c1da --- /dev/null +++ b/docs/router.md @@ -0,0 +1,30 @@ +# Router + +Router is used to direct the flow of update. It accepts as arguments a routing function and, optionally, a Map with predefined routes and handlers. Routing function accepts [context](getting-started.md#context) and return object with route property set to String value. Handler for a specific route is just another middleware. + +Basic usage: + +```js +const Router = require('telegraf/router') + +// can be any function that returns { route: String } +function routeFn(ctx) { + return { route: ctx.updateType } +} + +const router = new Router(routeFn) + +// registering 'callback_query' route +const middlewareCb = function (ctx, next) { ... } +router.on('callback_query', middlewareCb) + +// registering 'message' route +const middlewareMessage = new Composer(...) +router.on('message', middlewareMessage) + +// setting handler for routes that are not registered +const middlewareDefault = someOtherRouter +router.otherwise(middlewareDefault) +``` + +As `Router` object is itself a middleware, routers can be nested, e.g., `router1.on('yo', router2)`. Thus, they allow for very deep, well-structured and flexible logic of updates processing. Possible usecases include multilevel menus, setting different levels of access for bot users and much much more. diff --git a/docs/stage.md b/docs/stage.md new file mode 100644 index 000000000..c3bdc8ad8 --- /dev/null +++ b/docs/stage.md @@ -0,0 +1,42 @@ +# Stage + +Simple scene-based control flow middleware. + +```js +const { Telegraf } = require('telegraf') +const session = require('telegraf/session') +const Stage = require('telegraf/stage') +const Scene = require('telegraf/scenes/base') +const { leave } = Stage + +// Greeter scene +const greeter = new Scene('greeter') +greeter.enter((ctx) => ctx.reply('Hi')) +greeter.leave((ctx) => ctx.reply('Bye')) +greeter.hears(/hi/gi, leave()) +greeter.on('message', (ctx) => ctx.reply('Send `hi`')) + +// Create scene manager +const stage = new Stage() +stage.command('cancel', leave()) + +// Scene registration +stage.register(greeter) + +const bot = new Telegraf(process.env.BOT_TOKEN) +bot.use(session()) +bot.use(stage.middleware()) +bot.command('greeter', (ctx) => ctx.scene.enter('greeter')) +bot.startPolling() +``` + +Scenes related context props and functions: + +```js +bot.on('message', (ctx) => { + ctx.scene.state // Current scene state (persistent) + ctx.scene.enter(sceneId, [defaultState, silent]) // Enter scene + ctx.scene.reenter() // Reenter current scene + ctx.scene.leave() // Leave scene +}) +``` diff --git a/docs/sw.js b/docs/sw.js new file mode 100644 index 000000000..6fed32c4e --- /dev/null +++ b/docs/sw.js @@ -0,0 +1,83 @@ +/* =========================================================== + * docsify sw.js + * =========================================================== + * Copyright 2016 @huxpro + * Licensed under Apache 2.0 + * Register service worker. + * ========================================================== */ + +const RUNTIME = 'docsify' +const HOSTNAME_WHITELIST = [ + self.location.hostname, + 'fonts.gstatic.com', + 'fonts.googleapis.com', + 'cdn.jsdelivr.net' +] + +// The Util Function to hack URLs of intercepted requests +const getFixedUrl = (req) => { + var now = Date.now() + var url = new URL(req.url) + + // 1. fixed http URL + // Just keep syncing with location.protocol + // fetch(httpURL) belongs to active mixed content. + // And fetch(httpRequest) is not supported yet. + url.protocol = self.location.protocol + + // 2. add query for caching-busting. + // Github Pages served with Cache-Control: max-age=600 + // max-age on mutable content is error-prone, with SW life of bugs can even extend. + // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string. + // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190 + if (url.hostname === self.location.hostname) { + url.search += (url.search ? '&' : '?') + 'cache-bust=' + now + } + return url.href +} + +/** + * @Lifecycle Activate + * New one activated when old isnt being used. + * + * waitUntil(): activating ====> activated + */ +self.addEventListener('activate', event => { + event.waitUntil(self.clients.claim()) +}) + +/** + * @Functional Fetch + * All network requests are being intercepted here. + * + * void respondWith(Promise r) + */ +self.addEventListener('fetch', event => { + // Skip some of cross-origin requests, like those for Google Analytics. + if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) { + // Stale-while-revalidate + // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale + // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1 + const cached = caches.match(event.request) + const fixedUrl = getFixedUrl(event.request) + const fetched = fetch(fixedUrl, { cache: 'no-store' }) + const fetchedCopy = fetched.then(resp => resp.clone()) + + // Call respondWith() with whatever we get first. + // If the fetch fails (e.g disconnected), wait for the cache. + // If there’s nothing in cache, wait for the fetch. + // If neither yields a response, return offline pages. + event.respondWith( + Promise.race([fetched.catch(_ => cached), cached]) + .then(resp => resp || fetched) + .catch(_ => { /* eat any errors */ }) + ) + + // Update the cache with the version we fetched (only for ok status) + event.waitUntil( + Promise.all([fetchedCopy, caches.open(RUNTIME)]) + .then(([response, cache]) => response.ok && cache.put(event.request, response)) + .catch(_ => { /* eat any errors */ }) + ) + } +}) diff --git a/docs/telegraf.md b/docs/telegraf.md new file mode 100644 index 000000000..9e1f75d24 --- /dev/null +++ b/docs/telegraf.md @@ -0,0 +1,481 @@ +# Telegraf + +Telegraf API reference + +```js +const { Telegraf } = require('telegraf') +``` + +## Constructor + +Initialize new Telegraf bot. + +`const telegraf = new Telegraf(token, [options])` + +| Param | Type | Description | +| --- | --- | --- | +| token | `string` | [Bot Token](https://core.telegram.org/bots#3-how-do-i-create-a-bot) | +| [options] | `object` | Telegraf options | + +Telegraf options: + +```js +{ + telegram: { // Telegram options + agent: null, // https.Agent instance, allows custom proxy, certificate, keep alive, etc. + webhookReply: true // Reply via webhook + }, + username: '' // Bot username (optional) + channelMode: false // Handle `channel_post` updates as messages (optional) +} +``` + +## token + +Use this property to get/set bot token. + +`telegraf.token = [string]` + +## webhookReply + +Use this property to control `reply via webhook` feature. + +`telegraf.webhookReply = [bool]` + +## use + +Registers a middleware. + +`telegraf.use(...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| middleware | `function` | Middleware function | + +## on + +Registers middleware for provided update type. + +`telegraf.on(updateTypes, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| updateTypes | `string/string[]` | Update type | +| middleware | `function` | Middleware | + +## hears + +Registers middleware for handling `text` messages. + +`telegraf.hears(triggers, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function` | Triggers | +| middleware | `function` | Middleware | + +## command + +Command handling. + +`telegraf.command(commands, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| commands | `string/string[]` | Commands | +| middleware | `function` | Middleware | + +## start + +Handler for /start command. + +`telegraf.start(...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| middleware | `function` | Middleware | + +## help + +Handler for /help command. + +`telegraf.help(...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| middleware | `function` | Middleware | + +## settings + +Handler for /settings command. + +`telegraf.settings(...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| middleware | `function` | Middleware | + +## entity + +Entity handling. + +`telegraf.entity(entity, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| entity | `string/string[]/RegEx/RegEx[]/Function` | Entity name | +| middleware | `function` | Middleware | + +## mention + +Mention handling. + +`telegraf.mention(username, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| username | `string/string[]` | Username | +| middleware | `function` | Middleware | + +## phone + +Phone number handling. + +`telegraf.phone(number, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| number | `string/string[]` | Phone number | +| middleware | `function` | Middleware | + +## hashtag + +Hashtag handling. + +`telegraf.hashtag(hashtag, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| hashtag | `string/string[]` | Hashtag | +| middleware | `function` | Middleware | + +## cashtag + +Cashtag handling. + +`telegraf.cashtag(cashtag, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| cashtag | `string/string[]` | Cashtag | +| middleware | `function` | Middleware | + +## action + +Registers middleware for handling `callback_data` actions with regular expressions. + +`telegraf.action(triggers, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]` | Triggers | +| middleware | `function` | Middleware | + +## inlineQuery + +Registers middleware for handling `inline_query` actions with regular expressions. + +`telegraf.inlineQuery(triggers, ...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]` | Triggers | +| middleware | `function` | Middleware | + +## gameQuery + +Registers middleware for handling `callback_data` actions with game query. + +`telegraf.gameQuery(...middleware)` + +| Param | Type | Description | +| --- | --- | --- | +| middleware | `function` | Middleware | + +## launch + +Launch bot in long-polling or webhook mode. + +`telegraf.launch(options) => Promise` + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [options] | `object` | Launch options | + +Launch options: + +```js +{ + // Start bot in polling mode (Default) + // See startPolling reference + polling: { timeout, limit, allowedUpdates, stopCallback }, + + // Start bot in webhook mode + // See startWebhook reference + webhook: { domain, hookPath, port, host, tlsOptions, cb } +} +``` + +## startPolling + +Start poll updates. + +`telegraf.startPolling([timeout], [limit], [allowedUpdates], [stopCallback])` + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| [timeout] | `number` | 30 | Poll timeout in seconds | +| [limit] | `number` | 100 | Limits the number of updates to be retrieved | +| [allowedUpdates] | `string[]/string/null` | null | List the types of updates you want your bot to receive | +| [stopCallback] | `function` | null | Polling stop callback | + +## startWebhook + +Start listening @ `https://host:port/webhookPath` for Telegram calls. + +`telegraf.startWebhook(hookPath, [tlsOptions], port, [host])` + +| Param | Type | Description | +| --- | --- | --- | +| hookPath | `string` | Webhook url path (see Telegraf.setWebhook) | +| [tlsOptions] | `object` | [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` | Hostname | + +## stop + +Stop Webhook and polling + +`telegraf.stop([callback]) => Promise` + +| Param | Type | +| --- | --- | +| [callback] | function | + +## webhookCallback + +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 Connect/Express app. + +`telegraf.webhookCallback(webhookPath) => Function` + +| Param | Type | Description | +| --- | --- | --- | +| webhookPath | `string` | Webhook url path (see Telegraf.setWebhook) | + +## handleUpdate + +Handle raw Telegram update. In case you use centralized webhook server, queue, etc. + +`telegraf.handleUpdate(rawUpdate, [webhookResponse])` + +| Param | Type | Description | +| --- | --- | --- | +| rawUpdate | `object` | Telegram update payload | +| [webhookResponse] | `object` | [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) | + +## compose + +Compose `middlewares` returning a fully valid middleware comprised of all those which are passed. + +`Telegraf.compose(middlewares) => function` + +| Param | Type | Description | +| --- | --- | --- | +| middlewares | `function[]` | Array of middlewares | + +## mount + +Generates a middleware for handling provided update types. + +`Telegraf.mount(updateTypes, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| updateTypes | `string/string[]` | Update type | +| middleware | `function` | middleware | + +## hears + +Generates a middleware for handling `text` messages with regular expressions. + +`Telegraf.hears(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## action + +Generates a middleware for handling `callbackQuery` data with regular expressions. + +`Telegraf.action(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## inlineQuery + +Generates a middleware for handling `inlineQuery` data with regular expressions. + +`Telegraf.inlineQuery(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## passThru + +Generates pass thru middleware. + +`Telegraf.passThru() => function` + +## safePassThru + +Generates a safe version of pass thru middleware. + +`Telegraf.safePassThru() => function` + +## optional + +Generates an optional middleware. + +`Telegraf.optional(test, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| test | `truthy/function` | Value or predicate `(ctx) => bool` | +| middleware | `function` | middleware | + +## acl + +Generates a middleware for provided users only. + +`Telegraf.acl(userId, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| userId | `string/string[]` | User id | +| middleware | `function` | middleware | + +## drop + +Generates drop middleware. + +`Telegraf.drop(test) => function` + +| Param | Type | Description | +| --- | --- | --- | +| test | `truthy/function` | Value or predicate `(ctx) => bool` | + +## filter + +Generates filter middleware. + +`Telegraf.filter(test) => function` + +| Param | Type | Description | +| --- | --- | --- | +| test | `truthy/function` | Value or predicate `(ctx) => bool` | + +## branch + +Generates branch middleware. + +`Telegraf.branch(test, trueMiddleware, falseMiddleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| test | `truthy/function` | Value or predicate `(ctx) => bool` | +| trueMiddleware | `function` | true action middleware | +| falseMiddleware | `function` | false action middleware | + +## email + +Generates a middleware for handling messages with `email` entity. + +`Telegraf.email(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## hashtag + +Generates a middleware for handling messages with `hashtag` entity. + +`Telegraf.hashtag(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## cashtag + +Generates a middleware for handling messages with `cashtag` entity. + +`Telegraf.cashtag(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## url + +Generates a middleware for handling messages with `url` entity. + +`Telegraf.url(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## phone + +Generates a middleware for handling messages with `phone` entity. + +`Telegraf.phone(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## textLink + +Generates a middleware for handling messages with `text_link` entity. + +`Telegraf.textLink(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | + +## textMention + +Generates a middleware for handling messages with `text_mention` entity. + +`Telegraf.textMention(triggers, ...middleware) => function` + +| Param | Type | Description | +| --- | --- | --- | +| triggers | `string/string[]/RegEx/RegEx[]/Function/Function[]` | Triggers | +| handler | `function` | Handler | diff --git a/docs/telegram.md b/docs/telegram.md new file mode 100644 index 000000000..83ccb4b86 --- /dev/null +++ b/docs/telegram.md @@ -0,0 +1,937 @@ +# Telegram + +Telegram client API reference. + +```js +const Telegram = require('telegraf/telegram') +``` + +## Constructor + +Initialize new Telegram client. + +`const telegram = new Telegram(token, [options])` + +| Param | Type | Description | +| --- | --- | --- | +| token | `string` | [Bot Token](https://core.telegram.org/bots#3-how-do-i-create-a-bot) | +| [options] | `object` | Telegram options | + +Telegram options: + +```js +{ + agent: null, // https.Agent instance, allows custom proxy, certificate, keep alive, etc. + webhookReply: true // Reply via webhook +} +``` + +## webhookReply + +Use this property to control `reply via webhook` feature. + +`telegram.webhookReply = [bool]` + +## addStickerToSet + +Use this method to add a new sticker to a set created by the bot. + +`telegram.addStickerToSet(ownerId, name, stickerData) => Promise` +[Official documentation](https://core.telegram.org/bots/api#addstickertoset) + +| Param | Type | Description | +| --- | --- | --- | +| ownerId | `string` | User identifier of sticker set owner | +| name | `string` | Sticker set name | +| stickerData | `Object` | Sticker data({png_sticker: 'stiker file', emojis: 'πŸ˜‰', mask__position: '' }) | + +## answerCbQuery + +Use this method to send answers to callback queries. + +`telegram.answerCbQuery(callbackQueryId, text, [showAlert], [extra]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#answercallbackquery) + +| Param | Type | Description | +| --- | --- | --- | +| callbackQueryId | `string` | Query id | +| [text] | `string` | Notification text | +| [showAlert] | `bool` | Show alert instead of notification | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#answercallbackquery) | + +## answerGameQuery + +Use this method to send answers to game query. + +`telegram.answerGameQuery(callbackQueryId, url) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| callbackQueryId | `string` | Query id | +| url | `string` | Notification text | + +## answerShippingQuery + +Use this method to send answers to shipping query. + +`telegram.answerShippingQuery(shippingQueryId, ok, shippingOptions, [errorMessage]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| shippingQueryId | `string` | Shipping Query id | +| ok | `bool` | Specify True if delivery to the specified address is possible | +| shippingOptions | `object` | [Shipping Options](https://core.telegram.org/bots/api#answershippingquery) | +| [errorMessage] | `string` | Error message in human readable form | + +## answerPreCheckoutQuery + +Use this method to send answers to shipping query. + +`telegram.answerPreCheckoutQuery(preCheckoutQueryId, ok, [errorMessage]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| preCheckoutQueryId | `string` | Shipping Query id | +| ok | `bool` | Specify True if everything is alright (goods are available, etc.) | +| [errorMessage] | `string` | Error message in human readable form | + +## answerInlineQuery + +Use this method to send answers to an inline query. + +`telegram.answerInlineQuery(inlineQueryId, results, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| inlineQueryId | `string` | Query id | +| results | `object[]` | Results | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#answerinlinequery)| + +## createNewStickerSet + +Use this method to create new sticker set owned by a user. + +`telegram.createNewStickerSet(ownerId, name, title, stickerData, [isMasks]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#createnewstickerset) + +| Param | Type | Description | +| --- | --- | --- | +| ownerId | `string` | User identifier of sticker set owner | +| name | `string` | Sticker set name | +| title | `string` | Sticker set title | +| stickerData | `object` | Sticker data({png_sticker: 'stiker file', emojis: 'πŸ˜‰', mask__position: '' }) | +| [isMasks] | `bool` | Pass True, if a set of mask stickers should be created | + +## deleteChatStickerSet + +Use this method to delete a group sticker set from a supergroup. + +`telegram.deleteChatStickerSet(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#deletechatstickerset) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## deleteMessage + +Use this method to delete bot messages. + +`telegram.deleteMessage(chatId, messageId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#deletemessage) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | + +## setStickerSetThumb + +Use this method to set the thumbnail of a sticker set. + +`telegram.setStickerSetThumb(name, userId, [thumb]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setstickersetthumb) + +| Param | Type | Description | +| --- | --- | --- | +| name | `string` | Sticker set name | +| userId | `string` | User identifier of the sticker set owner | +| thumb | `File` | A PNG image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a TGS animation with the thumbnail up to 32 kilobytes in size | + +## deleteStickerFromSet + +Use this method to delete a sticker from a set created by the bot. + +`telegram.deleteStickerFromSet(stickerId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#deletestickerfromset) + +| Param | Type | Description | +| --- | --- | --- | +| stickerId | `string` | File identifier of the sticker | + +## editMessageCaption + +Use this method to edit captions of messages sent by the bot or via the bot. + +`telegram.editMessageCaption(chatId, messageId, inlineMessageId, caption, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | +| inlineMessageId | `string` | Inline message id | +| caption | `string` | Caption | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagecaption)| + +## editMessageMedia + +Use this method to edit media of messages sent by the bot or via the bot. + +`telegram.editMessageMedia(chatId, messageId, inlineMessageId, media, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | +| inlineMessageId | `string` | Inline message id | +| media | `InputMedia` | [InputMedia](https://core.telegram.org/bots/api#inputmedia) | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagemedia)| + +## editMessageLiveLocation + +Use this method to edit live location messages sent by the bot or via the bot. + +`telegram.editMessageLiveLocation(latitude, longitude, chatId, messageId, inlineMessageId, [markup]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#editmessagelivelocation) + +| Param | Type | Description | +| --- | --- | --- | +| latitude | `string` | Latitude of new location | +| longitude | `string` | Longitude of new location | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | +| inlineMessageId | `string` | Inline message id | +| [markup] | `object` | Keyboard markup | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagelivelocation)| + +## editMessageReplyMarkup + +Use this method to edit only the reply markup of messages sent by the bot or via the bot. + +`telegram.editMessageReplyMarkup(chatId, messageId, inlineMessageId, markup, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | +| inlineMessageId | `string` | Inline message id | +| markup | `object` | Keyboard markup | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagereplymarkup)| + +## editMessageText + +Use this method to edit text messages sent by the bot or via the bot. + +`telegram.editMessageText(chatId, messageId, inlineMessageId, text, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | +| inlineMessageId | `string` | Inline message id | +| text | `string` | Message | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#editmessagetext)| + +## forwardMessage + +Forwards message. + +`telegram.forwardMessage(chatId, fromChatId, messageId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Target Chat id | +| fromChatId | `number/string` | Source Chat id | +| messageId | `number` | Message id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#forwardmessage)| + +## sendCopy + +Sends message copy. + +`telegram.sendCopy(chatId, message, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Target Chat id | +| message | `object` | Message | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendmessage)| + +## copyMessage + +Use this method to copy messages of any kind. + +`telegram.copyMessage(chatId, message, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Target Chat id | +| fromChatId | `number/string` | Source Chat id | +| messageId | `number` | Message id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#copymessage)| + +## getWebhookInfo + +Use this method to get current webhook status. Requires no parameters. On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty. + +`telegram.getWebhookInfo() => Promise` + +## getChat + +Use this method to get up to date information about the chat (current name of the user for one-on-one conversatio +ns, current username of a user, group or channel, etc.). + +`telegram.getChat(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getchat) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## getChatAdministrators + +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. + +`telegram.getChatAdministrators(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getchatadministrators) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## setGameScore + +Use this method to set the score of the specified user in a game. On success, if the message was sent by the bot, returns the edited Message, otherwise returns True. Returns an error, if the new score is not greater than the user's current score in the chat. + +`telegram.setGameScore(userId, score, inlineMessageId, chatId, messageId, [editMessage], [force]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setgamescore) + +| Param | Type | Description | +| --- | --- | --- | +| userId | `number` | Target User id | +| score | `number` | Target User id | +| inlineMessageId | `string` | Inline message id | +| chatId | `number/string` | Target Chat id | +| messageId | `number/string` | Message id | +| [editMessage] | `boolean` | edit target message, default value is True | +| [force] | `boolean` | Pass True, if the high score is allowed to decrease. This can be useful when fixing mistakes or banning cheaters | + +## getGameHighScores + +Use this method to get data for high score tables. Will return the score of the specified user and several of his neighbors in a game. On success, returns an Array of GameHighScore objects. + +`telegram.getGameHighScores(userId, inlineMessageId, chatId, messageId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getgamehighscores) + +| Param | Type | Description | +| --- | --- | --- | +| userId | `number`\ | Target User id | +| inlineMessageId | `string` | Inline message id | +| chatId | `number/string` | Target Chat id | +| messageId | `number/string` | Message id | + +## getChatMember + +Use this method to get information about a member of a chat. + +`telegram.getChatMember(chatId, userId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getchatmember) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| userId | `number` | User identifier | + +## getChatMembersCount + +Use this method to get the number of members in a chat. + +`telegram.getChatMembersCount(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getchatmemberscount) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## getFile + +Returns basic info about a file and prepare it for downloading. + +`telegram.getFile(fileId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getfile) + +| Param | Type | Description | +| --- | --- | --- | +| fileId | `string` | File id | + +## getFileLink + +Returns link to file. + +`telegram.getFileLink(fileId) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| fileId | `string/object` | File id or file object | + +## getMe + +Returns basic information about the bot. + +`telegram.getMe() => Promise` +[Official documentation](https://core.telegram.org/bots/api#getme) + +## getMyCommands + +Use this method to get the current list of the bot's commands. Requires no parameters. Returns Array of BotCommand on success. + +`telegram.getMyCommands() => Promise` +[Official documentation](https://core.telegram.org/bots/api#getmycommands) + +## getStickerSet + +Use this method to get a sticker set. + +`telegram.getStickerSet(name) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| name | `string` | Short name of the sticker set | +[Official documentation](https://core.telegram.org/bots/api#getstickerset) + +## getUserProfilePhotos + +Returns profiles photos for provided user. + +`telegram.getUserProfilePhotos(userId, [offset], [limit]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#getuserprofilephotos) + +| Param | Type | Description | +| --- | --- | --- | +| userId | `number` | Chat id | +| [offset] | `number` | Offset | +| [limit] | `number` | Limit | + +## setChatPermissions + +Use this method to set default chat permissions for all members. + +`telegram.setChatPermissions(chatId, permissions) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| permissions | `object` | [New default chat permissions](https://core.telegram.org/bots/api#chatpermissions)| + +## kickChatMember + +Use this method to kick a user from a group or a supergroup. + +`telegram.kickChatMember(chatId, userId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| userId | `number` | User id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#kickchatmember)| + +## restrictChatMember + +Use this method to restrict a user in a supergroup. + +`telegram.restrictChatMember(chatId, userId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| userId | `number` | User id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#restrictchatmember)| + +## promoteChatMember + +Use this method to promote or demote a user in a supergroup or a channel. + +`telegram.promoteChatMember(chatId, userId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| userId | `number` | User id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#promotechatmember)| + +## setChatAdministratorCustomTitle + +New custom title for the administrator; 0-16 characters, emoji are not allowed + +`telegram.setChatAdministratorCustomTitle(chatId, userId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| userId | `number` | User id | +| title | `string` | Custom title | + +## exportChatInviteLink + +Use this method to export an invite link to a supergroup or a channel. + +`telegram.exportChatInviteLink(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#exportchatinvitelink) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## setChatPhoto + +Use this method to set a new profile photo for the chat. + +`telegram.setChatPhoto(chatId, photo) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setchatphoto) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| photo | `File` | New chat photo | + +## deleteChatPhoto + +Use this method to delete a chat photo. + +`telegram.deleteChatPhoto(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#deletechatphoto) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## setChatTitle + +Use this method to change the title of a chat. + +`telegram.setChatTitle(chatId, title) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setchattitle) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| title | `string` | New chat title, 1-255 characters | + +## setChatDescription + +Use this method to change the description of a supergroup or a channel. + +`telegram.setChatDescription(chatId, description) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setchattitle) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| description | `string` | New chat description, 0-255 characters | + +## setChatStickerSet + +Use this method to set a new group sticker set for a supergroup. + +`telegram.setChatStickerSet(chatId, stickerSetName) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setchatstickerset) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| stickerSetName | `string` | Name of the sticker set | + +## pinChatMessage + +Use this method to pin a message in a supergroup. + +`telegram.pinChatMessage(chatId, messageId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `number` | Message id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#pinchatmessage)| + +## unpinChatMessage + +Use this method to unpin a message in a supergroup chat. + +`telegram.unpinChatMessage(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#unpinchatmessage) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#unpinchatmessage)| + +## unpinAllChatMessages + +Use this method to clear the list of pinned messages in a chat + +`telegram.unpinAllChatMessages(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#unpinallchatmessages) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## leaveChat + +Use this method for your bot to leave a group, supergroup or channel. + +`telegram.leaveChat(chatId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#leavechat) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | + +## deleteWebhook + +Removes webhook integration. + +`telegram.deleteWebhook() => Promise` +[Official documentation](https://core.telegram.org/bots/api#deletewebhook) + +| Param | Type | Description | +| --- | --- | --- | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#deletewebhook) | + +## sendAudio + +Sends audio. + +`telegram.sendAudio(chatId, audio, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| audio | `File` | Document | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendaudio)| + +## sendGame + +Sends game. + +`telegram.sendGame(chatId, gameName, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| gameName | `String` | Game short name | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendgame)| + +## sendChatAction + +Sends chat action. + +`telegram.sendChatAction(chatId, action) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| action | `string` | [Chat action](https://core.telegram.org/bots/api#sendchataction) | + +## sendContact + +Sends document. + +`telegram.sendContact(chatId, phoneNumber, firstName, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| phoneNumber | `string` | Contact phone number | +| firstName | `string` | Contact first name | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendcontact)| + +## sendDice + +Sends dice. + +`telegram.sendDice(chatId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#senddice)| + +## sendDocument + +Sends document. + +`telegram.sendDocument(chatId, doc, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| doc | `File` | Document | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#senddocument)| + +## sendLocation + +Sends location. + +`telegram.sendLocation(chatId, latitude, longitude, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| latitude | `number` | Latitude | +| longitude | `number` | Longitude | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendlocation)| + +## sendMessage + +Sends text message. + +`telegram.sendMessage(chatId, text, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| text | `string` | Message | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendmessage)| + +## sendPhoto + +Sends a photo. + +`telegram.sendPhoto(chatId, photo, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| photo | `File` | Photo | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendphoto)| + +## sendMediaGroup + +Sends media album. + +`telegram.sendMediaGroup(chatId, media, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| media | `InputMedia[]` | Media array | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendmediagroup)| + +## sendSticker + +Sends sticker. + +`telegram.sendSticker(chatId, sticker, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| sticker | `File` | Document | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendsticker)| + +## setStickerPositionInSet + +Use this method to move a sticker in a set created by the bot to a specific position. + +`telegram.setStickerPositionInSet(sticker, position) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| sticker | `string` | File identifier of the sticker | +| position | `number` | New sticker position in the set, zero-based | + +## sendVenue + +Sends venue information. + +`telegram.sendVenue(chatId, latitude, longitude, title, address, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| latitude | `number` | Latitude | +| longitude | `number` | Longitude | +| title | `string` | Venue title | +| address | `string` | Venue address | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvenue)| + +## sendInvoice + +Sends invoice. + +`telegram.sendInvoice(chatId, invoice) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| invoice | `object` | [Invoice object](https://core.telegram.org/bots/api#sendinvoice) | + +## sendVideo + +Sends video. + +`telegram.sendVideo(chatId, video, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| video | `File` | Document | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvideo)| + +## sendAnimation + +Sends video. + +`telegram.sendAnimation(chatId, animation, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| animation | `File` | Document | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendanimation)| + +## sendVideoNote + +Sends round video. + +`telegram.sendVideoNote(chatId, video, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| video | `File` | Video note file | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvideonote)| + +## sendVoice + +Sends voice. + +`telegram.sendVoice(chatId, voice, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| voice | `File/string` | File, file id or HTTP URL | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendvoice)| + +## sendPoll + +Sends a poll. + +`telegram.sendPoll(chatId, question, options, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| question | `string` | Poll question | +| options | `string[]` | Answer options | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendpoll)| + +## setMyCommands + +Use this method to change the list of the bot's commands + +`telegram.setMyCommands(commands) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| commands | `object[]` | [List of bot commands](https://core.telegram.org/bots/api#setmycommands) | + +## sendQuiz + +Sends quiz. + +`telegram.sendQuiz(chatId, question, options, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| question | `string` | Poll question | +| options | `string[]` | Answer options | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#sendpoll)| + +## stopPoll + +Stops anonymous poll. + +`telegram.stopPoll(chatId, messageId, [extra]) => Promise` + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Poll message id | +| options| `string[]` | Answer options | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#stoppoll)| + +## stopMessageLiveLocation + +Use this method to stop updating a live location message sent by the bot or via the bot (for inline bots) before live_period expires. + +`telegram.stopMessageLiveLocation(chatId, messageId, inlineMessageId, [markup]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#stopmessagelivelocation) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| messageId | `string` | Message id | +| inlineMessageId | `string` | Inline message id | +| [markup] | `object` | Keyboard markup | + +## uploadStickerFile + +Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods. + +`telegram.uploadStickerFile(ownerId, stickerFile) => Promise` +[Official documentation](https://core.telegram.org/bots/api#uploadstickerfile) + +| Param | Type | Description | +| --- | --- | --- | +| ownerId | `string` | User identifier of sticker file owner | +| stickerFile | `File` | Png image with the sticker | + +## setWebhook + +Specifies an url to receive incoming updates via an outgoing webhook. + +`telegram.setWebhook(url, [extra]) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setwebhook) + +| Param | Type | Description | +| --- | --- | --- | +| url | `string` | Public url for webhook | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#setwebhook) | + +## unbanChatMember + +Use this method to unban a previously kicked user in a supergroup. + +`telegram.unbanChatMember(chatId, userId) => Promise` +[Official documentation](https://core.telegram.org/bots/api#unbanchatmember) + +| Param | Type | Description | +| --- | --- | --- | +| chatId | `number/string` | Chat id | +| userId | `number` | User id | +| [extra] | `object` | [Extra parameters](https://core.telegram.org/bots/api#unbanchatmember) | + +## setPassportDataErrors + +Informs a user that some Telegram Passport elements they provided contains errors. The user will not be able to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned the error must change). + +`telegram.setPassportDataErrors(errors) => Promise` +[Official documentation](https://core.telegram.org/bots/api#setpassportdataerrors) + +| Param | Type | Description | +| --- | --- | --- | +| [errors] | `PassportElementError[]` | An array describing the errors | diff --git a/extra.js b/extra.js index 61fea593f..de2c132b7 100644 --- a/extra.js +++ b/extra.js @@ -42,6 +42,11 @@ class Extra { return this } + markdownV2 (value = true) { + this.parse_mode = value ? 'MarkdownV2' : undefined + return this + } + caption (caption = '') { this.caption = caption return this @@ -75,6 +80,10 @@ class Extra { return new Extra().markdown(value) } + static markdownV2 (value) { + return new Extra().markdownV2(value) + } + static caption (caption) { return new Extra().caption(caption) } diff --git a/markup.js b/markup.js index ca0683c0c..df50ec1ed 100644 --- a/markup.js +++ b/markup.js @@ -59,6 +59,10 @@ class Markup { return Markup.locationRequestButton(text, hide) } + pollRequestButton (text, type, hide) { + return Markup.pollRequestButton(text, type, hide) + } + urlButton (text, url, hide) { return Markup.urlButton(text, url, hide) } diff --git a/package.json b/package.json index bee6b14da..5bd7f1271 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "module-alias": "^2.2.2", "node-fetch": "^2.2.0", "sandwich-stream": "^2.0.1", - "telegram-typings": "^3.6.0" + "typegram": "^3.1.5" }, "devDependencies": { "@types/node": "^13.1.0", diff --git a/readme.md b/readme.md index ee9dcf222..87437fb9f 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ -![Telegraf](docs/header.png) -[![Bot API Version](https://img.shields.io/badge/Bot%20API-v4.8-f36caf.svg?style=flat-square)](https://core.telegram.org/bots/api) +![Telegraf](docs/media/header.png) +[![Bot API Version](https://img.shields.io/badge/Bot%20API-v5.0-f36caf.svg?style=flat-square)](https://core.telegram.org/bots/api) [![NPM Version](https://img.shields.io/npm/v/telegraf.svg?style=flat-square)](https://www.npmjs.com/package/telegraf) [![node](https://img.shields.io/node/v/telegraf.svg?style=flat-square)](https://www.npmjs.com/package/telegraf) [![Build Status](https://img.shields.io/travis/telegraf/telegraf.svg?branch=master&style=flat-square)](https://travis-ci.org/telegraf/telegraf) @@ -8,13 +8,11 @@ ## Introduction -Bots are special [Telegram](https://telegram.org) accounts designed to handle messages automatically. -Users can interact with bots by sending them command messages in private or group chats. -These accounts serve as an interface for code running somewhere on your server. +Bots are special [Telegram](https://telegram.org) accounts designed to handle messages automatically. Users can interact with bots by sending them command messages in private or group chats. These accounts serve as an interface for code running somewhere on your server. ### Features -- Full [Telegram Bot API 4.8](https://core.telegram.org/bots/api) support +- Full [Telegram Bot API 5.0](https://core.telegram.org/bots/api) support - [Telegram Payment Platform](https://telegram.org/blog/payments) - [HTML5 Games](https://core.telegram.org/bots/api#games) - [Inline mode](https://core.telegram.org/bots/api#inline-mode) @@ -26,12 +24,14 @@ These accounts serve as an interface for code running somewhere on your server. ### Installation +```bash +npm install telegraf ``` -$ npm install telegraf -``` + or using `yarn`: -``` -$ yarn add telegraf + +```bash +yarn add telegraf ``` ### Documentation diff --git a/telegram.js b/telegram.js index 1224b766e..ce2758672 100644 --- a/telegram.js +++ b/telegram.js @@ -54,17 +54,12 @@ class Telegram extends ApiClient { }) } - setWebhook (url, certificate, maxConnections, allowedUpdates) { - return this.callApi('setWebhook', { - url, - certificate, - max_connections: maxConnections, - allowed_updates: allowedUpdates - }) + setWebhook (url, extra) { + return this.callApi('setWebhook', { url, ...extra }) } - deleteWebhook () { - return this.callApi('deleteWebhook') + deleteWebhook (extra) { + return this.callApi('deleteWebhook', extra) } sendMessage (chatId, text, extra) { @@ -231,16 +226,20 @@ class Telegram extends ApiClient { return this.callApi('pinChatMessage', { chat_id: chatId, message_id: messageId, ...extra }) } - unpinChatMessage (chatId) { - return this.callApi('unpinChatMessage', { chat_id: chatId }) + unpinChatMessage (chatId, extra) { + return this.callApi('unpinChatMessage', { chat_id: chatId, ...extra }) + } + + unpinAllChatMessages (chatId) { + return this.callApi('unpinAllChatMessages', { chat_id: chatId }) } leaveChat (chatId) { return this.callApi('leaveChat', { chat_id: chatId }) } - unbanChatMember (chatId, userId) { - return this.callApi('unbanChatMember', { chat_id: chatId, user_id: userId }) + unbanChatMember (chatId, userId, extra) { + return this.callApi('unbanChatMember', { chat_id: chatId, user_id: userId, ...extra }) } answerCbQuery (callbackQueryId, text, showAlert, extra) { @@ -287,22 +286,30 @@ class Telegram extends ApiClient { } editMessageCaption (chatId, messageId, inlineMessageId, caption, extra = {}) { + // todo: deprecation warning about Markup being passed instead of extra return this.callApi('editMessageCaption', { caption, chat_id: chatId, message_id: messageId, inline_message_id: inlineMessageId, - parse_mode: extra.parse_mode, + ...extra.parse_mode && { parse_mode: extra.parse_mode }, + ...extra.caption_entities && { caption_entities: extra.caption_entities }, reply_markup: extra.parse_mode || extra.reply_markup ? extra.reply_markup : extra }) } editMessageMedia (chatId, messageId, inlineMessageId, media, extra = {}) { + // todo: deprecation warning about Markup being passed instead of extra return this.callApi('editMessageMedia', { chat_id: chatId, message_id: messageId, inline_message_id: inlineMessageId, - media: { ...media, parse_mode: extra.parse_mode }, + media: { + ...media, + parse_mode: extra.parse_mode, + caption: extra.caption, + caption_entities: extra.caption_entities + }, reply_markup: extra.reply_markup ? extra.reply_markup : extra }) } @@ -316,14 +323,14 @@ class Telegram extends ApiClient { }) } - editMessageLiveLocation (latitude, longitude, chatId, messageId, inlineMessageId, markup) { + editMessageLiveLocation (chatId, messageId, inlineMessageId, latitude, longitude, extra) { return this.callApi('editMessageLiveLocation', { - latitude, - longitude, chat_id: chatId, message_id: messageId, inline_message_id: inlineMessageId, - reply_markup: markup + latitude, + longitude, + ...extra }) } @@ -417,6 +424,9 @@ class Telegram extends ApiClient { if (!message) { throw new Error('Message is required') } + if (message.chat && message.chat.id && message.message_id) { + return this.copyMessage(chatId, message.chat.id, message.message_id, extra) + } const type = Object.keys(replicators.copyMethods).find((type) => message[type]) if (!type) { throw new Error('Unsupported message type') @@ -428,6 +438,15 @@ class Telegram extends ApiClient { } return this.callApi(replicators.copyMethods[type], opts) } + + copyMessage (chatId, fromChatId, messageId, extra) { + return this.callApi('copyMessage', { + chat_id: chatId, + from_chat_id: fromChatId, + message_id: messageId, + ...extra + }) + } } module.exports = Telegram diff --git a/test/telegraf.js b/test/telegraf.js index 92d894009..f48e7e944 100644 --- a/test/telegraf.js +++ b/test/telegraf.js @@ -86,6 +86,7 @@ test.cb('should provide shortcuts for `message` update', (t) => { t.true('setChatDescription' in ctx) t.true('pinChatMessage' in ctx) t.true('unpinChatMessage' in ctx) + t.true('unpinAllChatMessages' in ctx) t.true('leaveChat' in ctx) t.true('getChatAdministrators' in ctx) t.true('getChatMember' in ctx) @@ -102,6 +103,7 @@ test.cb('should provide shortcuts for `message` update', (t) => { t.true('editMessageLiveLocation' in ctx) t.true('stopMessageLiveLocation' in ctx) t.true('forwardMessage' in ctx) + t.true('copyMessage' in ctx) t.end() }) bot.handleUpdate({ message: BaseTextMessage }) @@ -141,6 +143,7 @@ test.cb('should provide shortcuts for `callback_query` update', (t) => { t.true('setChatDescription' in ctx) t.true('pinChatMessage' in ctx) t.true('unpinChatMessage' in ctx) + t.true('unpinAllChatMessages' in ctx) t.true('leaveChat' in ctx) t.true('getChatAdministrators' in ctx) t.true('getChatMember' in ctx) @@ -156,6 +159,7 @@ test.cb('should provide shortcuts for `callback_query` update', (t) => { t.true('editMessageLiveLocation' in ctx) t.true('stopMessageLiveLocation' in ctx) t.true('forwardMessage' in ctx) + t.true('copyMessage' in ctx) t.end() }) bot.handleUpdate({ callback_query: BaseTextMessage }) diff --git a/typings/composer.d.ts b/typings/composer.d.ts index 9212add6e..a0438b15a 100644 --- a/typings/composer.d.ts +++ b/typings/composer.d.ts @@ -169,7 +169,7 @@ export declare class Composer static reply( text: string, - extra?: tt.ExtraReplyMessage + extra?: tt.ExtraSendMessage ): MiddlewareFn /** diff --git a/typings/context.d.ts b/typings/context.d.ts index 7021badde..35b316670 100644 --- a/typings/context.d.ts +++ b/typings/context.d.ts @@ -21,7 +21,7 @@ export declare class TelegrafContext { inlineQuery?: tt.InlineQuery match?: RegExpExecArray | null me?: string - message?: tt.IncomingMessage + message?: tt.Message poll?: tt.Poll pollAnswer?: tt.PollAnswer preCheckoutQuery?: tt.PreCheckoutQuery @@ -145,8 +145,15 @@ export declare class TelegrafContext { /** * Use this method to unpin a message in a group, a supergroup, or a channel. * @returns True on success + * @param extra Extra params + */ + unpinChatMessage(extra?: tt.ExtraUnpinMessage): Promise + + /** + * Use this method to clear the list of pinned messages in a chat + * @returns True on success */ - unpinChatMessage(): Promise + unpinAllChatMessages(): Promise /** * Use this method to reply on messages in the same chat. @@ -154,7 +161,7 @@ export declare class TelegrafContext { * @param extra SendMessage additional params * @returns sent Message if Success */ - reply(text: string, extra?: tt.ExtraReplyMessage): Promise + reply(text: string, extra?: tt.ExtraSendMessage): Promise /** * Use this method to send audio files to the same chat, if you want Telegram clients to display them in the music player. @@ -213,7 +220,7 @@ export declare class TelegrafContext { * @param extra Additional params to send message * @returns a Message on success */ - replyWithHTML(html: string, extra?: tt.ExtraReplyMessage): Promise + replyWithHTML(html: string, extra?: tt.ExtraSendMessage): Promise /** * Use this method to send invoices @@ -247,7 +254,7 @@ export declare class TelegrafContext { */ replyWithMarkdown( markdown: string, - extra?: tt.ExtraReplyMessage + extra?: tt.ExtraSendMessage ): Promise /** @@ -295,7 +302,7 @@ export declare class TelegrafContext { replyWithQuiz( question: string, options: string[], - extra: tt.ExtraPoll + extra: tt.ExtraQuiz ): Promise /** @@ -348,6 +355,17 @@ export declare class TelegrafContext { */ replyWithDice(extra?: tt.ExtraDice): Promise + /** + * Use this method to send copy of exists message. + * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param extra Additional params to send modified copy of message + * @returns the MessageId of the sent message on success + */ + copyMessage( + chatId: number | string, + extra?: object + ): Promise + // ------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------ // @@ -410,11 +428,11 @@ export declare class TelegrafContext { * Use this method to edit captions of messages sent by the bot or via the bot (for inline bots). * On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. * @param caption New caption of the message - * @param markup Markup of inline keyboard + * @param extra Extra params */ editMessageCaption( caption?: string, - markup?: tt.InlineKeyboardMarkup + extra?: tt.ExtraEditCaption ): Promise /** @@ -430,23 +448,33 @@ export declare class TelegrafContext { * Use this method to edit animation, audio, document, photo, or video messages. * @returns On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. * @param media New media of message - * @param markup Markup of inline keyboard + * @param extra Extra params */ editMessageMedia( media: tt.MessageMedia, - extra?: tt.ExtraEditMessage + extra?: tt.ExtraEditMessageMedia ): Promise /** - * Use this method to edit live location messages. + * Use this method to edit live location messages * @returns On success, if the edited message was sent by the bot, the edited message is returned, otherwise True is returned. - * @param lat New latitude - * @param lon New longitude + * @param latitude New latitude + * @param longitude New longitude + * @param extra Extra params */ editMessageLiveLocation( - lat: number, - lon: number, - extra?: tt.ExtraLocation + latitude: number, + longitude: number, + extra?: tt.ExtraEditLocation + ): Promise + + /** + * Use this method to stop updating a live location message before live_period expires. + * @param extra Extra params + * @returns On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. + */ + stopMessageLiveLocation( + extra?: tt.ExtraStopLiveLocation ): Promise /** @@ -460,14 +488,15 @@ export declare class TelegrafContext { /** * Use this method to unban a user from a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights * @param userId Unique identifier of the target user + * @param extra Extra params * @returns True on success */ - unbanChatMember(userId: number): Promise + unbanChatMember(userId: number, extra?: tt.ExtraUnban): Promise /** * Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote a user. - * @param chatId Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) * @param userId Unique identifier of the target user + * @param extra Extra parameters for promoteChatMember * @returns True on success */ promoteChatMember( @@ -475,15 +504,6 @@ export declare class TelegrafContext { extra: tt.ExtraPromoteChatMember ): Promise - /** - * Use this method to stop updating a live location message before live_period expires. - * @returns On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. - * @param extra Extra params - */ - stopMessageLiveLocation( - extra?: tt.ExtraLocation - ): Promise - /** * Use this method to delete a message, including service messages, with the following limitations: * - A message can only be deleted if it was sent less than 48 hours ago. diff --git a/typings/extra.d.ts b/typings/extra.d.ts index f05a0161b..d1186f88d 100644 --- a/typings/extra.d.ts +++ b/typings/extra.d.ts @@ -13,12 +13,14 @@ export declare class Extra { webPreview(value?: boolean): this - markup(markup: any): tt.ExtraEditMessage & this + markup(markup: any): tt.ExtraReplyMarkup & this HTML(value?: boolean): this markdown(value?: boolean): this + markdownV2(value?: boolean): this + caption(caption: string): this static load(opts: object): Extra @@ -29,7 +31,7 @@ export declare class Extra { static webPreview(value?: boolean): Extra - static markup(markup: any): tt.ExtraEditMessage + static markup(markup: any): tt.ExtraReplyMarkup static HTML(value?: boolean): Extra diff --git a/typings/markup.d.ts b/typings/markup.d.ts index b38508a4c..f616c0642 100644 --- a/typings/markup.d.ts +++ b/typings/markup.d.ts @@ -4,25 +4,24 @@ import * as tt from './telegram-types.d' export interface Button { text: string - hide: boolean + + /** + * Keyboard builder sugar + */ + hide?: boolean } -export interface ContactRequestButton { - text: string - hide: boolean +export interface ContactRequestButton extends Button { request_contact: boolean } -export interface LocationRequestButton { - text: string - hide: boolean +export interface LocationRequestButton extends Button { request_location: boolean } type PollType = 'poll' | 'quiz' -export interface PollRequestButton { - text: string +export interface PollRequestButton extends Button { request_poll: { type?: PollType } } @@ -33,40 +32,28 @@ export type KeyboardButton = | PollRequestButton | string -export interface UrlButton { +export interface UrlButton extends Button { url: string - text: string - hide?: boolean } -export interface CallbackButton { - text: string - hide: boolean +export interface CallbackButton extends Button { callback_data: string } -export interface SwitchToChatButton { - text: string - hide: boolean +export interface SwitchToChatButton extends Button { switch_inline_query: string } -export interface SwitchToCurrentChatButton { - text: string - hide: boolean +export interface SwitchToCurrentChatButton extends Button { switch_inline_query_current_chat: string } -export interface GameButton { - text: string - hide: boolean +export interface GameButton extends Button { callback_game: tt.CallbackGame } -export interface PayButton { +export interface PayButton extends Button { pay: boolean - text: string - hide: boolean } export interface LoginUrl { @@ -76,10 +63,8 @@ export interface LoginUrl { request_write_access?: boolean } -export interface LoginButton { - text: string +export interface LoginButton extends Button { login_url: LoginUrl - hide: boolean } export type InlineKeyboardButton = @@ -103,7 +88,7 @@ export declare class Markup { selective(value?: boolean): this - extra(options?: tt.ExtraReplyMessage): tt.ExtraReplyMessage + extra(options?: tt.Extra): tt.Extra keyboard( buttons: KeyboardButton[] | KeyboardButton[][], diff --git a/typings/telegraf.d.ts b/typings/telegraf.d.ts index 09e4921da..8b3914fec 100644 --- a/typings/telegraf.d.ts +++ b/typings/telegraf.d.ts @@ -13,16 +13,21 @@ import { TelegrafContext } from './context' import { Composer } from './composer' import { Telegram, TelegramOptions } from './telegram' -export interface TelegrafOptions { +export interface TelegrafOptions extends TOptions { /** * Telegram options */ telegram?: TelegramOptions /** - * Bot username + * Custom context */ - username?: string + contextType?: TelegrafContext + + /** + * Autoset after launch by botInfo method + */ + username?: never } export interface LaunchPollingOptions { @@ -189,17 +194,7 @@ export interface TOptions { /** * Telegram options */ - telegram?: { - /** - * https.Agent or http.Agent instance, allows custom proxy, certificate, keep alive, etc. - */ - agent: https.Agent | http.Agent - - /** - * Reply via webhook - */ - webhookReply: boolean - } + telegram?: TelegramOptions /** * Bot username @@ -211,7 +206,13 @@ export interface TOptions { */ channelMode?: boolean + /** + * Delay (in seconds) before making a follow-up request to get updates + */ retryAfter?: number + /** + * Maximum amount of time (in microseconds) for which middlewares execution can pause updates fetching + */ handlerTimeout?: number } diff --git a/typings/telegram-types.d.ts b/typings/telegram-types.d.ts index decfa226b..22ccb8833 100644 --- a/typings/telegram-types.d.ts +++ b/typings/telegram-types.d.ts @@ -1,5 +1,5 @@ -import * as TT from "telegram-typings"; -export * from "telegram-typings"; +import * as TT from 'typegram' +export * from 'typegram' export type ParseMode = 'Markdown' | 'MarkdownV2' | 'HTML' @@ -64,6 +64,12 @@ export type MessageSubTypes = 'connected_website' | 'animation' +export type InputMediaTypes = 'photo' + | 'video' + | 'animation' + | 'audio' + | 'document' + export type InlineQueryResult = TT.InlineQueryResultCachedAudio | TT.InlineQueryResultCachedDocument | @@ -93,55 +99,45 @@ export type MessageMedia = InputMediaAudio | InputMediaDocument -export interface InputMediaPhoto { - type: string +export interface InputMediaPhoto extends ExtraCaption { + type: InputMediaTypes media: InputFile - caption?: string - parse_mode?: string } -export interface InputMediaVideo { - type: string +export interface InputMediaVideo extends ExtraCaption { + type: InputMediaTypes media: InputFile thumb?: string | InputFile - caption?: string - parse_mode?: string width?: number height?: number duration?: number supports_streaming?: boolean } -export interface InputMediaAnimation { - type: string +export interface InputMediaAnimation extends ExtraCaption { + type: InputMediaTypes media: InputFile thumb?: string | InputFile - caption?: string - parse_mode?: string width?: number height?: number duration?: number supports_streaming?: boolean } -export interface InputMediaAudio { - type: string +export interface InputMediaAudio extends ExtraCaption { + type: InputMediaTypes media: InputFile thumb?: string | InputFile - caption?: string - parse_mode?: string performer?: string title?: string duration?: number supports_streaming?: boolean } -export interface InputMediaDocument { - type: string +export interface InputMediaDocument extends ExtraCaption { + type: InputMediaTypes media: InputFile thumb?: string | InputFile - caption?: string - parse_mode?: string } export interface StickerData { @@ -207,6 +203,28 @@ export interface ChatPermissions { can_pin_messages?: boolean } +export interface ExtraSetWebhook { + /** SSL public certificate */ + certificate?: InputFile + + /** The fixed IP address which will be used to send webhook requests instead of the IP address resolved through DNS */ + ip_address?: string + + /** Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100. Defaults to 40. */ + max_connections?: number + + /** List the types of updates you want your bot to receive */ + allowed_updates?: UpdateType[] + + /** Pass True to drop all pending updates */ + drop_pending_updates?: boolean +} + +export interface ExtraDeleteWebhook { + /** Pass True to drop all pending updates */ + drop_pending_updates?: boolean +} + export interface ExtraRestrictChatMember { /** New user permissions */ permissions: ChatPermissions @@ -241,43 +259,89 @@ export interface ExtraPromoteChatMember { can_promote_members?: boolean } -export interface ExtraReplyMessage { +export interface ExtraReplyMarkup { + /** + * Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + */ + reply_markup?: TT.InlineKeyboardMarkup | TT.ReplyKeyboardMarkup | TT.ReplyKeyboardRemove | TT.ForceReply +} + +interface ExtraReplyMarkupInlineKeyboard { + /** A JSON-serialized object for a new message inline keyboard. */ + reply_markup?: TT.InlineKeyboardMarkup +} +interface ExtraFormatting { /** - * Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message. + * Mode for parsing entities in the message text. See formatting options for more details. */ parse_mode?: ParseMode + /** + * List of special entities that appear in message text, which can be specified instead of parse_mode + */ + entities?: TT.MessageEntity[] +} + +interface ExtraCaptionFormatting { + /** + * Mode for parsing entities in the photo caption. See formatting options for more details. + */ + parse_mode?: ParseMode + + /** + * List of special entities that appear in message text, which can be specified instead of parse_mode + */ + caption_entities?: TT.MessageEntity[] +} + +interface ExtraCaption extends ExtraCaptionFormatting { + /** + * Media caption, 0-1024 characters + */ + caption?: string +} + +interface ExtraDisableWebPagePreview { /** * Disables link previews for links in this message */ disable_web_page_preview?: boolean +} +interface ExtraDisableNotifications { /** * Sends the message silently. Users will receive a notification with no sound. */ disable_notification?: boolean +} +interface ExtraReplyMessage { /** * If the message is a reply, ID of the original message */ reply_to_message_id?: number /** - * Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + * Pass True, if the message should be sent even if the specified replied-to message is not found */ - reply_markup?: TT.InlineKeyboardMarkup | TT.ReplyKeyboardMarkup | TT.ReplyKeyboardRemove | TT.ForceReply + allow_sending_without_reply?: boolean } -export interface ExtraEditMessage extends ExtraReplyMessage { - // no specified properties -} +export interface ExtraSendMessage extends ExtraFormatting, ExtraDisableWebPagePreview, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup {} + +export interface ExtraEditMessage extends ExtraFormatting, ExtraDisableWebPagePreview, ExtraReplyMarkupInlineKeyboard {} -export interface ExtraAudio extends ExtraReplyMessage { +export interface ExtraEditMessageMedia extends ExtraReplyMarkupInlineKeyboard {} + +export interface ExtraUnpinMessage { /** - * Audio caption, 0-1024 characters + * Identifier of a message to unpin. If not specified, the most recent pinned message (by sending date) will be unpinned. */ - caption?: string + message_id?: number +} + +export interface ExtraAudio extends ExtraCaption, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** * Duration of the audio in seconds @@ -301,14 +365,9 @@ export interface ExtraAudio extends ExtraReplyMessage { * so you can pass β€œattach://” if the thumbnail was uploaded using multipart/form-data under . */ thumb?: InputFile - - /** - * Does not exist, see https://core.telegram.org/bots/api#sendaudio - */ - disable_web_page_preview?: never } -export interface ExtraDocument extends ExtraReplyMessage { +export interface ExtraDocument extends ExtraCaption, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** * Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. * The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnailβ€˜s width and height should not exceed 320. @@ -318,116 +377,70 @@ export interface ExtraDocument extends ExtraReplyMessage { thumb?: InputFile /** - * Document caption (may also be used when resending documents by file_id), 0-1024 characters - */ - caption?: string - - /** - * Does not exist, see https://core.telegram.org/bots/api#senddocument - */ - disable_web_page_preview?: never -} - -export interface ExtraGame extends ExtraReplyMessage { - /** - * Inline keyboard. If empty, one β€˜Play game_title’ button will be shown. If not empty, the first button must launch the game. - */ - reply_markup?: TT.InlineKeyboardMarkup - - /** - * Does not exist, see https://core.telegram.org/bots/api#sendgame - */ - disable_web_page_preview?: never - - /** - * Does not exist, see https://core.telegram.org/bots/api#sendgame + * Disables automatic server-side content type detection for files uploaded using multipart/form-data */ - parse_mode?: never + disable_content_type_detection?: Boolean } -export interface ExtraInvoice extends ExtraReplyMessage { - /** - * Inline keyboard. If empty, one 'Pay total price' button will be shown. If not empty, the first button must be a Pay button. - */ - reply_markup?: TT.InlineKeyboardMarkup +export interface ExtraGame extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkupInlineKeyboard {} - /** - * Does not exist, see https://core.telegram.org/bots/api#sendinvoice - */ - disable_web_page_preview?: never +export interface ExtraInvoice extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkupInlineKeyboard {} +export interface ExtraLocation extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** - * Does not exist, see https://core.telegram.org/bots/api#sendinvoice + * The radius of uncertainty for the location, measured in meters; 0-1500 */ - parse_mode?: never -} + horizontal_accuracy?: number -export interface ExtraLocation extends ExtraReplyMessage { /** * Period in seconds for which the location will be updated (should be between 60 and 86400) */ live_period?: number /** - * Does not exist, see https://core.telegram.org/bots/api#sendlocation + * For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. */ - disable_web_page_preview?: never + heading?: number /** - * Does not exist, see https://core.telegram.org/bots/api#sendlocation + * For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. */ - parse_mode?: never + proximity_alert_radius?: number } -export interface ExtraPhoto extends ExtraReplyMessage { +export interface ExtraEditLocation extends ExtraReplyMarkupInlineKeyboard { /** - * Photo caption (may also be used when resending photos by file_id), 0-1024 characters + * The radius of uncertainty for the location, measured in meters; 0-1500 */ - caption?: string + horizontal_accuracy?: number /** - * Does not exist, see https://core.telegram.org/bots/api#sendphoto - */ - disable_web_page_preview?: never -} - -export interface ExtraMediaGroup extends ExtraReplyMessage { - /** - * Does not exist, see https://core.telegram.org/bots/api#sendmediagroup + * Period in seconds for which the location will be updated (should be between 60 and 86400) */ - disable_web_page_preview?: never + live_period?: number /** - * Does not exist, see https://core.telegram.org/bots/api#sendmediagroup + * For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. */ - parse_mode?: never + heading?: number /** - * Does not exist, see https://core.telegram.org/bots/api#sendmediagroup + * For live locations, a maximum distance for proximity alerts about approaching another chat member, in meters. Must be between 1 and 100000 if specified. */ - reply_markup?: never + proximity_alert_radius?: number } -export interface ExtraAnimation extends ExtraReplyMessage { - /** - * Animation caption (may also be used when resending animation by file_id), 0-200 characters - */ - caption?: string -} +export interface ExtraStopLiveLocation extends ExtraReplyMarkupInlineKeyboard {} -export interface ExtraSticker extends ExtraReplyMessage { - /** - * Does not exist, see https://core.telegram.org/bots/api#sendsticker - */ - disable_web_page_preview?: never +export interface ExtraPhoto extends ExtraCaption, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup {} - /** - * Does not exist, see https://core.telegram.org/bots/api#sendsticker - */ - parse_mode?: never -} +export interface ExtraMediaGroup extends ExtraDisableNotifications, ExtraReplyMessage {} + +export interface ExtraAnimation extends ExtraCaption, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup {} -export interface ExtraVideo extends ExtraReplyMessage { +export interface ExtraSticker extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup {} + +export interface ExtraVideo extends ExtraCaption, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** * Duration of sent video in seconds */ @@ -451,23 +464,13 @@ export interface ExtraVideo extends ExtraReplyMessage { */ thumb?: InputFile - /** - * Video caption (may also be used when resending videos by file_id), 0-1024 characters - */ - caption?: string - /** * Pass True, if the uploaded video is suitable for streaming */ supports_streaming?: boolean - - /** - * Does not exist, see https://core.telegram.org/bots/api#sendvideo - */ - disable_web_page_preview?: never } -export interface ExtraVideoNote extends ExtraReplyMessage { +export interface ExtraVideoNote extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** * Duration of sent video in seconds */ @@ -487,138 +490,99 @@ export interface ExtraVideoNote extends ExtraReplyMessage { thumb?: InputFile } -export interface ExtraVoice extends ExtraReplyMessage { - /** - * Voice message caption, 0-1024 characters - */ - caption?: string - +export interface ExtraVoice extends ExtraCaption, ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** * Duration of the voice message in seconds */ duration?: number - - /** - * Does not exist, see https://core.telegram.org/bots/api#sendvoice - */ - disable_web_page_preview?: never } -export interface ExtraDice extends ExtraReplyMessage { - /** - * Does not exist, see https://core.telegram.org/bots/api#senddice - */ - parse_mode?: never - +export interface ExtraDice extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** - * Does not exist, see https://core.telegram.org/bots/api#senddice - */ - disable_web_page_preview?: never + * Emoji on which the dice throw animation is based. + * Currently, must be one of β€œπŸŽ²β€, β€œπŸŽ―β€, β€œπŸ€β€, β€œβš½β€, or β€œπŸŽ°β€. + * Dice can have values 1-6 for β€œπŸŽ²β€ and β€œπŸŽ―β€, values 1-5 for β€œπŸ€β€ and β€œβš½β€, and values 1-64 for β€œπŸŽ°β€. + * Defaults to β€œπŸŽ²β€ + * */ + emoji?: string } -export interface ExtraPoll { +export interface ExtraPoll extends ExtraDisableNotifications, ExtraReplyMessage, ExtraReplyMarkup { /** True, if the poll needs to be anonymous, defaults to True */ is_anonymous?: boolean /** True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False */ allows_multiple_answers?: boolean - /** 0-based identifier of the correct answer option, required for polls in quiz mode */ - correct_option_id?: number - /** Pass True, if the poll needs to be immediately closed. This can be useful for poll preview. */ is_closed?: boolean - /** Sends the message silently. Users will receive a notification with no sound. */ - disable_notification?: boolean - - /** If the message is a reply, ID of the original message */ - reply_to_message_id?: number - - /** Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. */ - reply_markup?: - | TT.InlineKeyboardMarkup - | TT.ReplyKeyboardMarkup - | TT.ReplyKeyboardRemove - | TT.ForceReply -} - -export interface ExtraStopPoll { - /** A JSON-serialized object for a new message inline keyboard. */ - reply_markup?: TT.InlineKeyboardMarkup -} - -export interface IncomingMessage extends TT.Message { - audio?: TT.Audio - entities?: TT.MessageEntity[] - caption?: string - document?: TT.Document - game?: TT.Game - photo?: TT.PhotoSize[] - animation?: TT.Animation - sticker?: TT.Sticker - video?: TT.Video - video_note?: TT.VideoNote - contact?: TT.Contact - location?: TT.Location - venue?: TT.Venue - pinned_message?: TT.Message - invoice?: TT.Invoice - successful_payment?: TT.SuccessfulPayment - dice?: Dice -} - -export interface MessageAudio extends TT.Message { - audio: TT.Audio -} - -export interface MessageDocument extends TT.Message { - document: TT.Document -} - -export interface MessageGame extends TT.Message { - game: TT.Game -} - -export interface MessageInvoice extends TT.Message { - invoice: TT.Invoice -} - -export interface MessageLocation extends TT.Message { - location: TT.Location -} - -export interface MessagePhoto extends TT.Message { - photo: TT.PhotoSize[] -} - -export interface MessageAnimation extends TT.Message { - animation: TT.Animation -} - -export interface MessageSticker extends TT.Message { - sticker: TT.Sticker -} + /** Amount of time in seconds the poll will be active after creation, 5-600. Can't be used together with close_date. */ + open_period?: number -export interface MessageVideo extends TT.Message { - video: TT.Video + /** Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 600 seconds in the future. Can't be used together with open_period. */ + close_date?: number } -export interface MessageVideoNote extends TT.Message { - video_note: TT.VideoNote -} - -export interface MessageVoice extends TT.Message { - voice: TT.Voice -} - -export interface MessageDice extends TT.Message { - dice: Dice -} - -export interface MessagePoll extends TT.Message { - poll: Poll -} +export interface ExtraQuiz extends ExtraPoll { + /** 0-based identifier of the correct answer option, required for polls in quiz mode */ + correct_option_id: number + + /** Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing */ + explanation?: string + + /** List of special entities that appear in the poll explanation, which can be specified instead of parse_mode */ + explanation_entities?: TT.MessageEntity[] + + /** Mode for parsing entities in the explanation. See formatting options for more details. */ + explanation_parse_mode?: ParseMode +} + +export interface ExtraStopPoll extends ExtraReplyMarkupInlineKeyboard {} + +export interface ExtraEditCaption extends ExtraCaptionFormatting, ExtraReplyMarkupInlineKeyboard {} + +export type Extra = ExtraSendMessage + | ExtraEditMessage + | ExtraEditMessageMedia + | ExtraUnpinMessage + | ExtraAudio + | ExtraDocument + | ExtraGame + | ExtraInvoice + | ExtraLocation + | ExtraEditLocation + | ExtraPhoto + | ExtraMediaGroup + | ExtraAnimation + | ExtraSticker + | ExtraVideo + | ExtraVideoNote + | ExtraVoice + | ExtraDice + | ExtraPoll + | ExtraQuiz + | ExtraStopPoll + | ExtraEditCaption + +export interface ExtraUnban { + /** Do nothing if the user is not banned */ + only_if_banned?: Boolean +} + +export type MessageAudio = TT.Message.AudioMessage +export type MessageDocument = TT.Message.DocumentMessage +export type MessageGame = TT.Message.GameMessage +export type MessageInvoice = TT.Message.InvoiceMessage +export type MessageLocation = TT.Message.LocationMessage +export type MessagePhoto = TT.Message.PhotoMessage +export type MessageAnimation = TT.Message.AnimationMessage +export type MessageSticker = TT.Message.StickerMessage +export type MessageVideo = TT.Message.VideoMessage +export type MessageVideoNote = TT.Message.VideoNoteMessage +export type MessageVoice = TT.Message.VoiceMessage +export type MessageDice = TT.Message.DiceMessage +export type MessagePoll = TT.Message.PollMessage export interface NewInvoiceParameters { /** @@ -743,61 +707,3 @@ export interface BotCommand { */ description: string } - -/** - * This object represents a dice with random value from 1 to 6. (Yes, we're aware of the β€œproper” singular of die. But it's awkward, and we decided to help it change. One dice at a time!) - */ -export interface Dice { - /** - * Value of the dice, 1-6 - */ - value: number -} - -export interface PollOption { - /** Option text, 1-100 characters */ - text: string - - /** Number of users that voted for this option */ - voter_count: number -} - -export interface PollAnswer { - /** Unique poll identifier */ - poll_id: string - - /** The user, who changed the answer to the poll */ - user: TT.User - - /** 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote. */ - option_ids: number[] -} - -export interface Poll { - /** Unique poll identifier */ - id: string - - /** Poll question, 1-255 characters */ - question: string - - /** List of poll options */ - options: PollOption[] - - /** Total number of users that voted in the poll */ - total_voter_count: number - - /** True, if the poll is closed */ - is_closed: boolean - - /** True, if the poll is anonymous */ - is_anonymous: boolean - - /** Poll type, currently can be β€œregular” or β€œquiz” */ - type: 'regular' | 'quiz' - - /** True, if the poll allows multiple answers */ - allows_multiple_answers: boolean - - /** 0-based identifier of the correct answer option. Available only for polls in the quiz mode, which are closed, or was sent (not forwarded) by the bot or to the private chat with the bot. */ - correct_option_id?: number -} diff --git a/typings/telegram.d.ts b/typings/telegram.d.ts index 4d7a20699..12066c703 100644 --- a/typings/telegram.d.ts +++ b/typings/telegram.d.ts @@ -131,14 +131,14 @@ export declare class Telegram extends ApiClient { * @param messageId Required if inlineMessageId is not specified. Identifier of the sent message * @param inlineMessageId Required if chatId and messageId are not specified. Identifier of the inline message * @param caption New caption of the message - * @param markup A JSON-serialized object for an inline keyboard. + * @param extra Extra params */ editMessageCaption( chatId?: number | string, messageId?: number, inlineMessageId?: string, caption?: string, - markup?: string + extra?: tt.ExtraEditCaption ): Promise /** @@ -147,15 +147,66 @@ export declare class Telegram extends ApiClient { * @param chatId Required if inlineMessageId is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername) * @param messageId Required if inlineMessageId is not specified. Identifier of the sent message * @param inlineMessageId Required if chatId and messageId are not specified. Identifier of the inline message - * @param markup A JSON-serialized object for an inline keyboard. + * @param markup Markup of inline keyboard */ editMessageReplyMarkup( chatId?: number | string, messageId?: number, inlineMessageId?: string, - markup?: string + markup?: tt.InlineKeyboardMarkup ): Promise + /** + * Use this method to edit animation, audio, document, photo, or video messages. + * @returns On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. + * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageId Required if inlineMessageId is not specified. Identifier of the sent message + * @param inlineMessageId Required if chatId and messageId are not specified. Identifier of the inline message + * @param media New media of message + * @param extra Extra params + */ + editMessageMedia( + chatId: number | string | void, + messageId: number | void, + inlineMessageId: string | void, + media: tt.MessageMedia, + extra?: tt.ExtraEditMessageMedia + ): Promise + + /** + * Use this method to edit live location messages + * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageId Required if inlineMessageId is not specified. Identifier of the sent message + * @param inlineMessageId Required if chatId and messageId are not specified. Identifier of the inline message + * @param latitude Latitude of location + * @param longitude Longitude of location + * @param extra Extra params + * @returns On success, if the edited message is not an inline message, the edited Message is returned, otherwise True is returned. + */ + editMessageLiveLocation( + chatId: number | string | void, + messageId: number | void, + inlineMessageId: string | void, + latitude: number, + longitude: number, + extra?: tt.ExtraEditLocation + ): Promise + + /** + * Use this method to stop updating a live location message before live_period expires. + * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param messageId Required if inlineMessageId is not specified. Identifier of the sent message + * @param inlineMessageId Required if chatId and messageId are not specified. Identifier of the inline message + * @param extra Extra params + * @returns On success, if the message was sent by the bot, the sent Message is returned, otherwise True is returned. + */ + stopMessageLiveLocation( + chatId: number | string | void, + messageId: number | void, + inlineMessageId: string | void, + extra?: tt.ExtraStopLiveLocation + ): Promise + /** * Use this method to delete a message, including service messages, with the following limitations: * - A message can only be deleted if it was sent less than 48 hours ago. @@ -246,6 +297,21 @@ export declare class Telegram extends ApiClient { extra?: object ): Promise + /** + * Use this method to send copy of exists message. + * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param fromChatId Unique identifier for the chat where the original message was sent (or channel username in the format @channelusername) + * @param messageId Message identifier in the chat specified in from_chat_id + * @param extra Additional params to send modified copy of message + * @returns the MessageId of the sent message on success + */ + copyMessage( + chatId: number | string, + fromChatId: number | string, + messageId: number, + extra?: object + ): Promise + /** * Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -298,7 +364,7 @@ export declare class Telegram extends ApiClient { /** * Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights. Pass True for all boolean parameters to lift restrictions from a user. Returns True on success. * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) - * @param user_id Unique identifier of the target user + * @param userId Unique identifier of the target user * @param extra Additional params for restrict chat member * @returns True on success */ @@ -331,9 +397,17 @@ export declare class Telegram extends ApiClient { /** * Use this method to unpin a message in a group, a supergroup, or a channel. * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) + * @param extra Extra params + * @returns True on success + */ + unpinChatMessage(chatId: number | string, extra?: tt.ExtraUnpinMessage): Promise + + /** + * Use this method to clear the list of pinned messages in a chat + * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) * @returns True on success */ - unpinChatMessage(chatId: number | string): Promise + unpinAllChatMessages(chatId: number | string): Promise /** * Use this method to send text messages @@ -459,14 +533,14 @@ export declare class Telegram extends ApiClient { */ sendMediaGroup( chatId: number | string, - media: tt.MessageMedia[], + media: (tt.InputMediaAudio | tt.InputMediaDocument | tt.InputMediaPhoto | tt.InputMediaVideo)[], extra?: tt.ExtraMediaGroup ): Promise> /** * Use this method to send a native poll. * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) - * @param question Poll question, 1-255 characters + * @param question Poll question, 1-300 characters * @param options A JSON-serialized list of answer options, 2-10 strings 1-100 characters each * @param extra Additional params to send poll * @returns On success, the sent Message is returned. @@ -490,7 +564,7 @@ export declare class Telegram extends ApiClient { chatId: number | string, question: string, options: string[], - extra: tt.ExtraPoll + extra: tt.ExtraQuiz ): Promise /** @@ -586,23 +660,22 @@ export declare class Telegram extends ApiClient { /** * Use this method to specify a url and receive incoming updates via an outgoing webhook * @param url HTTPS url to send updates to. Use an empty string to remove webhook integration - * @param cert Upload your public key certificate so that the root certificate in use can be checked - * @param maxConnections Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery, 1-100 - * @param allowedUpdates List the types of updates you want your bot to receive + * @param extra Additional params to set webhook * @returns True on success */ setWebhook( url: string, - cert?: tt.InputFile, - maxConnections?: number, - allowedUpdates?: string[] + extra?: tt.ExtraSetWebhook ): Promise /** * Use this method to delete webhook + * @param extra Additional params to delete webhook * @returns True on success */ - deleteWebhook(): Promise + deleteWebhook( + extra?: tt.ExtraDeleteWebhook + ): Promise /** * Use this method to get information about set webhook @@ -641,14 +714,16 @@ export declare class Telegram extends ApiClient { * Use this method to unban a user from a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights * @param chatId Unique identifier for the target group or username of the target supergroup or channel (in the format @username) * @param userId Unique identifier of the target user + * @param extra Extra params * @returns True on success */ - unbanChatMember(chatId: number | string, userId: number): Promise + unbanChatMember(chatId: number | string, userId: number, extra?: tt.ExtraUnban): Promise /** * Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote a user. * @param chatId Unique identifier for the target chat or username of the target channel (in the format `@channelusername`) * @param userId Unique identifier of the target user + * @param extra Extra parameters for promoteChatMember * @returns True on success */ promoteChatMember( diff --git a/typings/test.ts b/typings/test.ts index 6eb0d387c..50919296b 100644 --- a/typings/test.ts +++ b/typings/test.ts @@ -108,8 +108,9 @@ bot.hears('something', async (ctx) => { reply_markup: Markup.inlineKeyboard([]) }) - ctx.editMessageLiveLocation(90,90, { - reply_markup: Markup.inlineKeyboard([]) + ctx.editMessageLiveLocation(90, 90, { + heading: 1, + reply_markup: Markup.inlineKeyboard([]) }) ctx.stopMessageLiveLocation({ @@ -166,9 +167,7 @@ bot.hears('something', async (ctx) => { duration: 0, length: 0, thumb: '', - parse_mode: "HTML", disable_notification: false, - disable_web_page_preview: false, reply_markup: Markup.inlineKeyboard([]), reply_to_message_id: 0, })