From 1bae9c2964b9927ef2cd72a79105b65902bc9441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=C3=A9rez=20Fern=C3=A1ndez?= Date: Tue, 12 May 2020 06:01:30 +0200 Subject: [PATCH] Add new method sendDice, getMyCommands, setMyCommands and more (#796) * Add new method sendPoll * getMyCommands * setMyCommands * Update doc/api * 1# Fix Test sendPhoto The sendPhoto method does not support .gif files, use sendAnimation. This fix remplace .gif file by .png * CustomTitle and ChatPermissions support setChatAdministratorCustomTitle setChatPermissions * Update Readme Update Badge Telegram API Version * Minor Fix and Fix setChatPhoto The Telegram Bots api has a bug that they are fixing and gives problems with the previous image. While they don't fix it, the image replacement is the fastest solution * Minor Fix and Add Test Fixed setChatPermissions Test: - sendDice - getMyCommands - setMyCommands - setChatAdministratorCustomTitle - setChatPermissions * Update Changelog and Package.json version * Fix typos in Changelog * Add support for poll_answer From: https://github.com/yagop/node-telegram-bot-api/pull/777 * Add JieJiSS contribution in Changelog * Add sendPoll Test --- CHANGELOG.md | 24 ++- README.md | 2 +- doc/api.md | 384 +++++++++++++++++++++++---------------- doc/usage.md | 2 +- package.json | 2 +- src/telegram.js | 86 +++++++++ test/data/chat_photo.png | Bin 12399 -> 14399 bytes test/data/photo.png | Bin 0 -> 14399 bytes test/telegram.js | 124 +++++++++++-- 9 files changed, 447 insertions(+), 177 deletions(-) create mode 100644 test/data/photo.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 059b4b4..848ec0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,29 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [0.40.0][0.40.0] - 2019-10-15 +## [0.50.0][0.50.0] - 2020-05-2020 +1. Support Bot API v4.8: (by @danielperez9430) + * Add methods: *sendDice()* +1. Support Bot API v4.7: (by @danielperez9430) + * Add methods: *getMyCommands()*,*setMyCommands()* +1. Support Bot API v4.5: (by @danielperez9430) + * Add methods: *setChatAdministratorCustomTitle()* +1. Support Bot API v4.4: (by @danielperez9430) + * Add methods: *setChatPermissions()* +1. Support for poll_answer (by @JieJiSS) + +Changed: (by @danielperez9430) + * New message type: *dice* + * Fix Bugs in tests + +New Test: (by @danielperez9430) + * sendDice + * getMyCommands + * setMyCommands + * setChatAdministratorCustomTitle + * setChatPermissions + +## [0.40.0][0.40.0] - 2019-05-04 Added: diff --git a/README.md b/README.md index a9ddb40..b27e1d6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Node.js module to interact with the official [Telegram Bot API](https://core.telegram.org/bots/api). -[![Bot API](https://img.shields.io/badge/Bot%20API-v.4.4.0-00aced.svg?style=flat-square&logo=telegram)](https://core.telegram.org/bots/api) +[![Bot API](https://img.shields.io/badge/Bot%20API-v.4.8.0-00aced.svg?style=flat-square&logo=telegram)](https://core.telegram.org/bots/api) [![npm package](https://img.shields.io/npm/v/node-telegram-bot-api?logo=npm&style=flat-square)](https://www.npmjs.org/package/node-telegram-bot-api) [![Build Status](https://img.shields.io/travis/yagop/node-telegram-bot-api/master?style=flat-square&logo=travis)](https://travis-ci.org/yagop/node-telegram-bot-api) [![Coverage Status](https://img.shields.io/codecov/c/github/yagop/node-telegram-bot-api?style=flat-square&logo=codecov)](https://codecov.io/gh/yagop/node-telegram-bot-api) diff --git a/doc/api.md b/doc/api.md index ea9bd69..c79b9a5 100644 --- a/doc/api.md +++ b/doc/api.md @@ -7,8 +7,8 @@ ## TelegramBot TelegramBot -**Kind**: global class -**See**: https://core.telegram.org/bots/api +**Kind**: global class +**See**: https://core.telegram.org/bots/api * [TelegramBot](#TelegramBot) * [new TelegramBot(token, [options])](#new_TelegramBot_new) @@ -43,6 +43,8 @@ TelegramBot * [.unbanChatMember(chatId, userId, [options])](#TelegramBot+unbanChatMember) ⇒ Promise * [.restrictChatMember(chatId, userId, [options])](#TelegramBot+restrictChatMember) ⇒ Promise * [.promoteChatMember(chatId, userId, [options])](#TelegramBot+promoteChatMember) ⇒ Promise + * [.setChatAdministratorCustomTitle(chatId, userId, customTitle, [options])](#TelegramBot+setChatAdministratorCustomTitle) ⇒ Promise + * [.setChatPermissions(chatId, ChatPermissions, [options])](#TelegramBot+setChatPermissions) ⇒ Promise * [.exportChatInviteLink(chatId, [options])](#TelegramBot+exportChatInviteLink) ⇒ Promise * [.setChatPhoto(chatId, photo, [options], [fileOptions])](#TelegramBot+setChatPhoto) ⇒ Promise * [.deleteChatPhoto(chatId, [options])](#TelegramBot+deleteChatPhoto) ⇒ Promise @@ -51,6 +53,8 @@ TelegramBot * [.pinChatMessage(chatId, messageId, [options])](#TelegramBot+pinChatMessage) ⇒ Promise * [.unpinChatMessage(chatId, [options])](#TelegramBot+unpinChatMessage) ⇒ Promise * [.answerCallbackQuery(callbackQueryId, [options])](#TelegramBot+answerCallbackQuery) ⇒ Promise + * [.setMyCommands(commands, [options])](#TelegramBot+setMyCommands) ⇒ Promise + * [.getMyCommands([options])](#TelegramBot+getMyCommands) ⇒ Promise * [.editMessageText(text, [options])](#TelegramBot+editMessageText) ⇒ Promise * [.editMessageCaption(caption, [options])](#TelegramBot+editMessageCaption) ⇒ Promise * [.editMessageMedia(media, [options])](#TelegramBot+editMessageMedia) ⇒ Promise @@ -63,6 +67,7 @@ TelegramBot * [.sendContact(chatId, phoneNumber, firstName, [options])](#TelegramBot+sendContact) ⇒ Promise * [.sendPoll(chatId, question, pollOptions, [options])](#TelegramBot+sendPoll) ⇒ Promise * [.stopPoll(chatId, pollId, [options])](#TelegramBot+stopPoll) ⇒ Promise + * [.sendDice(chatId, [options])](#TelegramBot+sendDice) ⇒ Promise * [.getFile(fileId, [options])](#TelegramBot+getFile) ⇒ Promise * [.getFileLink(fileId, [options])](#TelegramBot+getFileLink) ⇒ Promise * [.getFileStream(fileId, [options])](#TelegramBot+getFileStream) ⇒ stream.Readable @@ -136,7 +141,7 @@ Emits `message` when a message arrives. Add listener for the specified [event](https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#events). This is the usual `emitter.on()` method. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - [Available events](https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#events) @@ -145,8 +150,8 @@ This is the usual `emitter.on()` method. | Param | Type | | --- | --- | -| event | String | -| listener | function | +| event | String | +| listener | function | @@ -154,7 +159,7 @@ This is the usual `emitter.on()` method. Start polling. Rejects returned promise if a WebHook is being used by this instance. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) | Param | Type | Default | Description | | --- | --- | --- | --- | @@ -168,11 +173,11 @@ Rejects returned promise if a WebHook is being used by this instance. Alias of `TelegramBot#startPolling()`. This is **deprecated**. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) | Param | Type | | --- | --- | -| [options] | Object | +| [options] | Object | @@ -181,7 +186,7 @@ Stops polling after the last polling request resolves. Multiple invocations do nothing if polling is already stopped. Returning the promise of the last polling request is **deprecated**. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) | Param | Type | Description | | --- | --- | --- | @@ -194,7 +199,7 @@ Returning the promise of the last polling request is **deprecated**. ### telegramBot.isPolling() ⇒ Boolean Return true if polling. Otherwise, false. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) ### telegramBot.openWebHook() ⇒ Promise @@ -202,29 +207,29 @@ Open webhook. Multiple invocations do nothing if webhook is already open. Rejects returned promise if Polling is being used by this instance. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) ### telegramBot.closeWebHook() ⇒ Promise Close webhook after closing all current connections. Multiple invocations do nothing if webhook is already closed. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**Returns**: Promise - promise +**Kind**: instance method of [TelegramBot](#TelegramBot) +**Returns**: Promise - promise ### telegramBot.hasOpenWebHook() ⇒ Boolean Return true if using webhook and it is open i.e. accepts connections. Otherwise, false. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) ### telegramBot.getMe([options]) ⇒ Promise Returns basic information about the bot in form of a `User` object. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getme +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getme | Param | Type | Description | | --- | --- | --- | @@ -237,7 +242,7 @@ Specify an url to receive incoming updates via an outgoing webHook. This method has an [older, compatible signature][setWebHook-v0.25.0] that is being deprecated. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#setwebhook @@ -257,8 +262,8 @@ that is being deprecated. Use this method to remove webhook integration if you decide to switch back to getUpdates. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#deletewebhook +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#deletewebhook | Param | Type | Description | | --- | --- | --- | @@ -272,8 +277,8 @@ On success, returns a [WebhookInfo](https://core.telegram.org/bots/api#webhookin If the bot is using getUpdates, will return an object with the url field empty. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getwebhookinfo +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getwebhookinfo | Param | Type | Description | | --- | --- | --- | @@ -286,8 +291,8 @@ Use this method to receive incoming updates using long polling. This method has an [older, compatible signature][getUpdates-v0.25.0] that is being deprecated. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getupdates +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getupdates | Param | Type | Description | | --- | --- | --- | @@ -300,20 +305,20 @@ Process an update; emitting the proper events and executing regexp callbacks. This method is useful should you be using a different way to fetch updates, other than those provided by TelegramBot. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#update +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#update | Param | Type | | --- | --- | -| update | Object | +| update | Object | ### telegramBot.sendMessage(chatId, text, [options]) ⇒ Promise Send text message. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendmessage +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendmessage | Param | Type | Description | | --- | --- | --- | @@ -326,8 +331,8 @@ Send text message. ### telegramBot.answerInlineQuery(inlineQueryId, results, [options]) ⇒ Promise Send answers to an inline query. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#answerinlinequery +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#answerinlinequery | Param | Type | Description | | --- | --- | --- | @@ -340,7 +345,7 @@ Send answers to an inline query. ### telegramBot.forwardMessage(chatId, fromChatId, messageId, [options]) ⇒ Promise Forward messages of any kind. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) | Param | Type | Description | | --- | --- | --- | @@ -354,7 +359,7 @@ Forward messages of any kind. ### telegramBot.sendPhoto(chatId, photo, [options], [fileOptions]) ⇒ Promise Send photo -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendphoto @@ -373,7 +378,7 @@ Send photo ### telegramBot.sendAudio(chatId, audio, [options], [fileOptions]) ⇒ Promise Send audio -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendaudio @@ -392,7 +397,7 @@ Send audio ### telegramBot.sendDocument(chatId, doc, [options], [fileOptions]) ⇒ Promise Send Document -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendDocument @@ -411,8 +416,8 @@ Send Document ### telegramBot.sendSticker(chatId, sticker, [options], [fileOptions]) ⇒ Promise Send .webp stickers. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendsticker +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendsticker | Param | Type | Description | | --- | --- | --- | @@ -426,7 +431,7 @@ Send .webp stickers. ### telegramBot.sendVideo(chatId, video, [options], [fileOptions]) ⇒ Promise Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendvideo @@ -445,7 +450,7 @@ Use this method to send video files, Telegram clients support mp4 videos (other ### telegramBot.sendAnimation(chatId, animation, [options], [fileOptions]) ⇒ Promise Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendanimation @@ -464,8 +469,8 @@ Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without s ### telegramBot.sendVideoNote(chatId, videoNote, [options], [fileOptions]) ⇒ Promise Use this method to send rounded square videos of upto 1 minute long. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**Info**: The length parameter is actually optional. However, the API (at time of writing) requires you to always provide it until it is fixed. +**Kind**: instance method of [TelegramBot](#TelegramBot) +**Info**: The length parameter is actually optional. However, the API (at time of writing) requires you to always provide it until it is fixed. **See** - https://core.telegram.org/bots/api#sendvideonote @@ -484,7 +489,7 @@ Use this method to send rounded square videos of upto 1 minute long. ### telegramBot.sendVoice(chatId, voice, [options], [fileOptions]) ⇒ Promise Send voice -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendvoice @@ -507,8 +512,8 @@ Send chat action. `record_audio` or `upload_audio` for audio files, `upload_document` for general files, `find_location` for location data. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendchataction +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendchataction | Param | Type | Description | | --- | --- | --- | @@ -525,8 +530,8 @@ to the group on their own using invite links, etc., unless unbanned first. The bot must be an administrator in the group for this to work. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#kickchatmember +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#kickchatmember | Param | Type | Description | | --- | --- | --- | @@ -542,8 +547,8 @@ The user will not return to the group automatically, but will be able to join via link, etc. The bot must be an administrator in the group for this to work. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#unbanchatmember +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#unbanchatmember | Param | Type | Description | | --- | --- | --- | @@ -559,8 +564,8 @@ 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. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#restrictchatmember +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#restrictchatmember | Param | Type | Description | | --- | --- | --- | @@ -576,8 +581,8 @@ 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. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#promotechatmember +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#promotechatmember | Param | Type | Description | | --- | --- | --- | @@ -585,6 +590,38 @@ Returns True on success. | userId | Number | | | [options] | Object | Additional Telegram query options | + + +### telegramBot.setChatAdministratorCustomTitle(chatId, userId, customTitle, [options]) ⇒ Promise +Use this method to set a custom title for an administrator in a supergroup promoted by the bot. +Returns True on success. + +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setchatadministratorcustomtitle + +| Param | Type | Description | +| --- | --- | --- | +| chatId | Integer or String \| String | Unique identifier for the target chat or username of the target supergroup | +| userId | Integer | Unique identifier of the target user | +| customTitle | String | New custom title for the administrator; 0-16 characters, emoji are not allowed | +| [options] | Object | Additional Telegram query options | + + + +### telegramBot.setChatPermissions(chatId, ChatPermissions, [options]) ⇒ Promise +Use this method to set default chat permissions for all members. The bot must be an administrator +in the group or a supergroup for this to work and must have the can_restrict_members admin rights. +Returns True on success. + +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setchatpermissions + +| Param | Type | Description | +| --- | --- | --- | +| chatId | Integer or String \| String | Unique identifier for the target chat or username of the target supergroup | +| ChatPermissions | Object | New default chat permissions | +| [options] | Object | Additional Telegram query options | + ### telegramBot.exportChatInviteLink(chatId, [options]) ⇒ Promise @@ -592,8 +629,8 @@ Use this method to export an invite link to 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. Returns exported invite link as String on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#exportchatinvitelink +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#exportchatinvitelink | Param | Type | Description | | --- | --- | --- | @@ -607,8 +644,8 @@ Use this method to set a new profile photo for the chat. Photos can't be changed The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#setchatphoto +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setchatphoto | Param | Type | Description | | --- | --- | --- | @@ -624,8 +661,8 @@ Use this method to delete a chat photo. Photos can't be changed for private chat The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#deletechatphoto +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#deletechatphoto | Param | Type | Description | | --- | --- | --- | @@ -639,8 +676,8 @@ Use this method to change the title of a chat. Titles can't be changed for priva The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#setchattitle +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setchattitle | Param | Type | Description | | --- | --- | --- | @@ -655,8 +692,8 @@ Use this method to change the description of 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. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#setchatdescription +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setchatdescription | Param | Type | Description | | --- | --- | --- | @@ -671,8 +708,8 @@ Use this method to pin a message in a supergroup. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#pinchatmessage +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#pinchatmessage | Param | Type | Description | | --- | --- | --- | @@ -687,8 +724,8 @@ Use this method to unpin a message in a supergroup chat. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#unpinchatmessage +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#unpinchatmessage | Param | Type | Description | | --- | --- | --- | @@ -706,14 +743,41 @@ On success, True is returned. This method has **older, compatible signatures ([1][answerCallbackQuery-v0.27.1])([2][answerCallbackQuery-v0.29.0])** that are being deprecated. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#answercallbackquery +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#answercallbackquery | Param | Type | Description | | --- | --- | --- | | callbackQueryId | String | Unique identifier for the query to be answered | | [options] | Object | Additional Telegram query options | + + +### telegramBot.getMyCommands([options]) ⇒ Promise +Use this method to get the current list of the bot's commands +Returns True on success.Returns Array of BotCommand on success. + +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getmycommands + +| Param | Type | Description | +| --- | --- | --- | +| [options] | Object | Additional Telegram query options | + + + +### telegramBot.setMyCommands(commands, [options]) ⇒ Promise +Use this method to change the list of the bot's commands. +Returns True on success. + +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setmycommands + +| Param | Type | Description | +| --- | --- | --- | +| commands | Array of BotCommand | A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified. | +| [options] | Object | Additional Telegram query options | + ### telegramBot.editMessageText(text, [options]) ⇒ Promise @@ -724,8 +788,8 @@ returned. Note that you must provide one of chat_id, message_id, or inline_message_id in your request. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#editmessagetext +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#editmessagetext | Param | Type | Description | | --- | --- | --- | @@ -742,8 +806,8 @@ edited Message is returned. Note that you must provide one of chat_id, message_id, or inline_message_id in your request. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#editmessagecaption +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#editmessagecaption | Param | Type | Description | | --- | --- | --- | @@ -762,8 +826,8 @@ On success, the edited Message is returned. Note that you must provide one of chat_id, message_id, or inline_message_id in your request. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#editmessagemedia +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#editmessagemedia | Param | Type | Description | | --- | --- | --- | @@ -780,8 +844,8 @@ On success, the edited Message is returned. Note that you must provide one of chat_id, message_id, or inline_message_id in your request. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#editmessagetext +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#editmessagetext | Param | Type | Description | | --- | --- | --- | @@ -796,8 +860,8 @@ Returns a [UserProfilePhotos](https://core.telegram.org/bots/api#userprofilephot This method has an [older, compatible signature][getUserProfilePhotos-v0.25.0] that is being deprecated. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getuserprofilephotos +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getuserprofilephotos | Param | Type | Description | | --- | --- | --- | @@ -810,8 +874,8 @@ that is being deprecated. Send location. Use this method to send point on the map. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendlocation +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendlocation | Param | Type | Description | | --- | --- | --- | @@ -829,8 +893,8 @@ the bot or via the bot (for inline bots). Note that you must provide one of chat_id, message_id, or inline_message_id in your request. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#editmessagelivelocation +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#editmessagelivelocation | Param | Type | Description | | --- | --- | --- | @@ -847,8 +911,8 @@ the bot or via the bot (for inline bots) before live_period expires. Note that you must provide one of chat_id, message_id, or inline_message_id in your request. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#stopmessagelivelocation +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#stopmessagelivelocation | Param | Type | Description | | --- | --- | --- | @@ -860,8 +924,8 @@ inline_message_id in your request. Send venue. Use this method to send information about a venue. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendvenue +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendvenue | Param | Type | Description | | --- | --- | --- | @@ -878,8 +942,8 @@ Use this method to send information about a venue. Send contact. Use this method to send phone contacts. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendcontact +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendcontact | Param | Type | Description | | --- | --- | --- | @@ -894,8 +958,8 @@ Use this method to send phone contacts. Send poll. Use this method to send a native poll. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendpoll +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendpoll | Param | Type | Description | | --- | --- | --- | @@ -910,8 +974,8 @@ Use this method to send a native poll. Stop poll. Use this method to stop a native poll. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#stoppoll +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#stoppoll | Param | Type | Description | | --- | --- | --- | @@ -919,6 +983,20 @@ Use this method to stop a native poll. | pollId | Number | Identifier of the original message with the poll | | [options] | Object | Additional Telegram query options | + + +### telegramBot.sendDice(chatId, [options]) ⇒ Promise +Send Dice. +Use this method to send a dice. + +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#senddice + +| Param | Type | Description | +| --- | --- | --- | +| chatId | Number \| String | Unique identifier for the group/channel | +| [options] | Object | Additional Telegram query options | + ### telegramBot.getFile(fileId, [options]) ⇒ Promise @@ -926,8 +1004,8 @@ Get file. Use this method to get basic info about a file and prepare it for downloading. Attention: link will be valid for 1 hour. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getfile +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getfile | Param | Type | Description | | --- | --- | --- | @@ -944,9 +1022,9 @@ Attention: link will be valid for 1 hour. This method is a sugar extension of the (getFile)[#getfilefileid] method, which returns just path to file on remote server (you will have to manually build full uri after that). -**Kind**: instance method of [TelegramBot](#TelegramBot) -**Returns**: Promise - promise Promise which will have *fileURI* in resolve callback -**See**: https://core.telegram.org/bots/api#getfile +**Kind**: instance method of [TelegramBot](#TelegramBot) +**Returns**: Promise - promise Promise which will have *fileURI* in resolve callback +**See**: https://core.telegram.org/bots/api#getfile | Param | Type | Description | | --- | --- | --- | @@ -966,8 +1044,8 @@ file on Telegram servers. This method is a sugar extension of the [getFileLink](#TelegramBot+getFileLink) method, which returns the full URI to the file on remote server. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**Returns**: stream.Readable - fileStream +**Kind**: instance method of [TelegramBot](#TelegramBot) +**Returns**: stream.Readable - fileStream | Param | Type | Description | | --- | --- | --- | @@ -982,8 +1060,8 @@ Downloads file in the specified folder. This method is a sugar extension of the [getFileStream](#TelegramBot+getFileStream) method, which returns a readable file stream. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**Returns**: Promise - promise Promise, which will have *filePath* of downloaded file in resolve callback +**Kind**: instance method of [TelegramBot](#TelegramBot) +**Returns**: Promise - promise Promise, which will have *filePath* of downloaded file in resolve callback | Param | Type | Description | | --- | --- | --- | @@ -996,7 +1074,7 @@ which returns a readable file stream. ### telegramBot.onText(regexp, callback) Register a RegExp to test against an incomming text message. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) | Param | Type | Description | | --- | --- | --- | @@ -1008,10 +1086,10 @@ Register a RegExp to test against an incomming text message. ### telegramBot.removeTextListener(regexp) ⇒ Object Remove a listener registered with `onText()`. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **Returns**: Object - deletedListener The removed reply listener if found. This object has `regexp` and `callback` - properties. If not found, returns `null`. + properties. If not found, returns `null`. | Param | Type | Description | | --- | --- | --- | @@ -1022,8 +1100,8 @@ Remove a listener registered with `onText()`. ### telegramBot.onReplyToMessage(chatId, messageId, callback) ⇒ Number Register a reply to wait for a message response. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**Returns**: Number - id The ID of the inserted reply listener. +**Kind**: instance method of [TelegramBot](#TelegramBot) +**Returns**: Number - id The ID of the inserted reply listener. | Param | Type | Description | | --- | --- | --- | @@ -1036,10 +1114,10 @@ Register a reply to wait for a message response. ### telegramBot.removeReplyListener(replyListenerId) ⇒ Object Removes a reply that has been prev. registered for a message response. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **Returns**: Object - deletedListener The removed reply listener if found. This object has `id`, `chatId`, `messageId` and `callback` - properties. If not found, returns `null`. + properties. If not found, returns `null`. | Param | Type | Description | | --- | --- | --- | @@ -1052,8 +1130,8 @@ Use this method to get up to date information about the chat (current name of the user for one-on-one conversations, current username of a user, group or channel, etc.). -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getchat +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getchat | Param | Type | Description | | --- | --- | --- | @@ -1065,8 +1143,8 @@ username of a user, group or channel, etc.). ### telegramBot.getChatAdministrators(chatId, [options]) ⇒ Promise Returns the administrators in a chat in form of an Array of `ChatMember` objects. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getchatadministrators +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getchatadministrators | Param | Type | Description | | --- | --- | --- | @@ -1078,8 +1156,8 @@ Returns the administrators in a chat in form of an Array of `ChatMember` objects ### telegramBot.getChatMembersCount(chatId, [options]) ⇒ Promise Use this method to get the number of members in a chat. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getchatmemberscount +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getchatmemberscount | Param | Type | Description | | --- | --- | --- | @@ -1091,8 +1169,8 @@ Use this method to get the number of members in a chat. ### telegramBot.getChatMember(chatId, userId, [options]) ⇒ Promise Use this method to get information about a member of a chat. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getchatmember +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getchatmember | Param | Type | Description | | --- | --- | --- | @@ -1105,8 +1183,8 @@ Use this method to get information about a member of a chat. ### telegramBot.leaveChat(chatId, [options]) ⇒ Promise Leave a group, supergroup or channel. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#leavechat +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#leavechat | Param | Type | Description | | --- | --- | --- | @@ -1118,8 +1196,8 @@ Leave a group, supergroup or channel. ### telegramBot.setChatStickerSet(chatId, stickerSetName, [options]) ⇒ Promise Use this method to set a new group sticker set for a supergroup. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#setchatstickerset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setchatstickerset | Param | Type | Description | | --- | --- | --- | @@ -1132,8 +1210,8 @@ Use this method to set a new group sticker set for a supergroup. ### telegramBot.deleteChatStickerSet(chatId, [options]) ⇒ Promise Use this method to delete a group sticker set from a supergroup. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#deletechatstickerset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#deletechatstickerset | Param | Type | Description | | --- | --- | --- | @@ -1145,8 +1223,8 @@ Use this method to delete a group sticker set from a supergroup. ### telegramBot.sendGame(chatId, gameShortName, [options]) ⇒ Promise Use this method to send a game. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendgame +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendgame | Param | Type | Description | | --- | --- | --- | @@ -1159,8 +1237,8 @@ Use this method to send a game. ### telegramBot.setGameScore(userId, score, [options]) ⇒ Promise Use this method to set the score of the specified user in a game. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#setgamescore +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setgamescore | Param | Type | Description | | --- | --- | --- | @@ -1173,8 +1251,8 @@ Use this method to set the score of the specified user in a game. ### telegramBot.getGameHighScores(userId, [options]) ⇒ Promise Use this method to get data for high score table. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getgamehighscores +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getgamehighscores | Param | Type | Description | | --- | --- | --- | @@ -1186,8 +1264,8 @@ Use this method to get data for high score table. ### telegramBot.deleteMessage(chatId, messageId, [options]) ⇒ Promise Use this method to delete a message. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#deletemessage +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#deletemessage | Param | Type | Description | | --- | --- | --- | @@ -1201,8 +1279,8 @@ Use this method to delete a message. Send invoice. Use this method to send an invoice. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#sendinvoice +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#sendinvoice | Param | Type | Description | | --- | --- | --- | @@ -1222,8 +1300,8 @@ Use this method to send an invoice. Answer shipping query.. Use this method to reply to shipping queries. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#answershippingquery +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#answershippingquery | Param | Type | Description | | --- | --- | --- | @@ -1237,8 +1315,8 @@ Use this method to reply to shipping queries. Answer pre-checkout query. Use this method to confirm shipping of a product. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#answerprecheckoutquery +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#answerprecheckoutquery | Param | Type | Description | | --- | --- | --- | @@ -1251,8 +1329,8 @@ Use this method to confirm shipping of a product. ### telegramBot.getStickerSet(name, [options]) ⇒ Promise Use this method to get a sticker set. On success, a [StickerSet](https://core.telegram.org/bots/api#stickerset) object is returned. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#getstickerset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#getstickerset | Param | Type | Description | | --- | --- | --- | @@ -1265,8 +1343,8 @@ Use this method to get a sticker set. On success, a [StickerSet](https://core.te Use this method to upload a .png file with a sticker for later use in *createNewStickerSet* and *addStickerToSet* methods (can be used multiple times). Returns the uploaded [File](https://core.telegram.org/bots/api#file) on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#uploadstickerfile +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#uploadstickerfile | Param | Type | Description | | --- | --- | --- | @@ -1282,8 +1360,8 @@ Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#createnewstickerset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#createnewstickerset **Todo** - [ ] Add tests for this method! @@ -1305,8 +1383,8 @@ Returns True on success. Use this method to add a new sticker to a set created by the bot. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#addstickertoset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#addstickertoset **Todo** - [ ] Add tests for this method! @@ -1327,8 +1405,8 @@ Returns True on success. Use this method to move a sticker in a set created by the bot to a specific position. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#setstickerpositioninset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#setstickerpositioninset **Todo** - [ ] Add tests for this method! @@ -1346,8 +1424,8 @@ Returns True on success. Use this method to delete a sticker from a set created by the bot. Returns True on success. -**Kind**: instance method of [TelegramBot](#TelegramBot) -**See**: https://core.telegram.org/bots/api#deletestickerfromset +**Kind**: instance method of [TelegramBot](#TelegramBot) +**See**: https://core.telegram.org/bots/api#deletestickerfromset **Todo** - [ ] Add tests for this method! @@ -1368,7 +1446,7 @@ is returned. If you wish to [specify file options](https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files), add a `fileOptions` property to the target input in `media`. -**Kind**: instance method of [TelegramBot](#TelegramBot) +**Kind**: instance method of [TelegramBot](#TelegramBot) **See** - https://core.telegram.org/bots/api#sendmediagroup @@ -1386,26 +1464,26 @@ add a `fileOptions` property to the target input in `media`. ### TelegramBot.errors : Object The different errors the library uses. -**Kind**: static property of [TelegramBot](#TelegramBot) +**Kind**: static property of [TelegramBot](#TelegramBot) ### TelegramBot.messageTypes : Array.<String> The types of message updates the library handles. -**Kind**: static property of [TelegramBot](#TelegramBot) +**Kind**: static property of [TelegramBot](#TelegramBot) ### TelegramBot.Promise Change Promise library used internally, for all existing and new instances. -**Kind**: static property of [TelegramBot](#TelegramBot) +**Kind**: static property of [TelegramBot](#TelegramBot) | Param | Type | | --- | --- | -| customPromise | function | +| customPromise | function | -**Example** +**Example** ```js const TelegramBot = require('node-telegram-bot-api'); TelegramBot.Promise = myPromise; diff --git a/doc/usage.md b/doc/usage.md index b3d3048..49c0042 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -17,7 +17,7 @@ that emits the following events: `sticker`, `video`, `voice`, `contact`, `location`, `new_chat_members`, `left_chat_member`, `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, - `game`, `pinned_message`, `poll`, `migrate_from_chat_id`, `migrate_to_chat_id`, + `game`, `pinned_message`, `poll`, `dice`, `migrate_from_chat_id`, `migrate_to_chat_id`, `channel_chat_created`, `supergroup_chat_created`, `successful_payment`, `invoice`, `video_note` 1. **Arguments**: `message` ([Message][message]), `metadata` (`{ type?:string }`) diff --git a/package.json b/package.json index 81489b6..587becb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-telegram-bot-api", - "version": "0.40.0", + "version": "0.50.0", "description": "Telegram Bot API", "main": "./index.js", "directories": { diff --git a/src/telegram.js b/src/telegram.js index f3a12e4..0885989 100644 --- a/src/telegram.js +++ b/src/telegram.js @@ -26,6 +26,7 @@ const _messageTypes = [ 'channel_chat_created', 'contact', 'delete_chat_photo', + 'dice', 'document', 'game', 'group_chat_created', @@ -588,6 +589,7 @@ class TelegramBot extends EventEmitter { const shippingQuery = update.shipping_query; const preCheckoutQuery = update.pre_checkout_query; const poll = update.poll; + const pollAnswer = update.poll_answer; if (message) { debug('Process Update message %j', message); @@ -668,6 +670,9 @@ class TelegramBot extends EventEmitter { } else if (poll) { debug('Process Update poll %j', poll); this.emit('poll', poll); + } else if (pollAnswer) { + debug('Process Update poll_answer %j', pollAnswer); + this.emit('poll_answer', pollAnswer); } } @@ -767,6 +772,28 @@ class TelegramBot extends EventEmitter { return this._request('sendAudio', opts); } + /** + * Send Dice + * Use this method to send a dice. + * @param {Number|String} chatId Unique identifier for the message recipient + * @param {Object} [options] Additional Telegram query options + * @return {Promise} + * @see https://core.telegram.org/bots/api#senddice + */ + sendDice(chatId, options = {}) { + const opts = { + qs: options, + }; + opts.qs.chat_id = chatId; + try { + const sendData = this._formatSendData('dice'); + opts.formData = sendData[0]; + } catch (ex) { + return Promise.reject(ex); + } + return this._request('sendDice', opts); + } + /** * Send Document * @param {Number|String} chatId Unique identifier for the message recipient @@ -1016,6 +1043,42 @@ class TelegramBot extends EventEmitter { return this._request('promoteChatMember', { form }); } + /** + * Use this method to set a custom title for an administrator in a supergroup promoted by the bot. + * Returns True on success. + * + * @param {Number|String} chatId Unique identifier for the message recipient + * @param {Number} userId Unique identifier of the target user + * @param {String} customTitle New custom title for the administrator; 0-16 characters, emoji are not allowed + * @param {Object} [options] Additional Telegram query options + * @return {Promise} + * @see https://core.telegram.org/bots/api#setchatadministratorcustomtitle + */ + setChatAdministratorCustomTitle(chatId, userId, customTitle, form = {}) { + form.chat_id = chatId; + form.user_id = userId; + form.custom_title = customTitle; + return this._request('setChatAdministratorCustomTitle', { form }); + } + + /** + * Use this method to set default chat permissions for all members. + * The bot must be an administrator in the group or a supergroup for this to + * work and must have the can_restrict_members admin rights. + * Returns True on success. + * + * @param {Number|String} chatId Unique identifier for the message recipient + * @param {Array} chatPermissions New default chat permissions + * @param {Object} [options] Additional Telegram query options + * @return {Promise} + * @see https://core.telegram.org/bots/api#setchatpermissions + */ + setChatPermissions(chatId, chatPermissions, form = {}) { + form.chat_id = chatId; + form.permissions = JSON.stringify(chatPermissions); + return this._request('setChatPermissions', { form }); + } + /** * Use this method to export an invite link to 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. @@ -1181,6 +1244,29 @@ class TelegramBot extends EventEmitter { return this._request('answerCallbackQuery', { form }); } + /** + * Returns True on success. + * Use this method to change the list of the bot's commands. + * @param {Array} commands Poll options, between 2-10 options + * @param {Object} [options] Additional Telegram query options + * @return {Promise} + * @see https://core.telegram.org/bots/api#setmycommands + */ + setMyCommands(commands, form = {}) { + form.commands = stringify(commands); + return this._request('setMyCommands', { form }); + } + + /** + * Returns Array of BotCommand on success. + * @param {Object} [options] Additional Telegram query options + * @return {Promise} + * @see https://core.telegram.org/bots/api#getmycommands + */ + getMyCommands(form = {}) { + return this._request('getMyCommands', { form }); + } + /** * Use this method to edit text messages sent by the bot or via * the bot (for inline bots). On success, the edited Message is diff --git a/test/data/chat_photo.png b/test/data/chat_photo.png index ee0756db5e5f4ab4742c125e3e72bf41e2c246b3..df5c81da9b26a8d8ad17c2bd3603186718657c88 100644 GIT binary patch literal 14399 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 FV1mOX03!eZ literal 12399 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 FV1mOX03!eZ literal 0 HcmV?d00001 diff --git a/test/telegram.js b/test/telegram.js index a0179c7..5be83a1 100644 --- a/test/telegram.js +++ b/test/telegram.js @@ -43,7 +43,7 @@ const cert = `${__dirname}/../examples/ssl/crt.pem`; const ip = '216.58.210.174'; // Google IP ¯\_(ツ)_/¯ const lat = 47.5351072; const long = -52.7508537; -const FILE_PATH = `${__dirname}/data/photo.gif`; +const FILE_PATH = `${__dirname}/data/photo.png`; let FILE_ID; let GAME_CHAT_ID; let GAME_MSG_ID; @@ -481,7 +481,7 @@ describe('TelegramBot', function telegramSuite() { }); }); - describe.skip('#answerInlineQuery', function answerInlineQuerySuite() {}); + describe.skip('#answerInlineQuery', function answerInlineQuerySuite() { }); describe('#forwardMessage', function forwardMessageSuite() { before(function before() { @@ -507,7 +507,7 @@ describe('TelegramBot', function telegramSuite() { utils.handleRatelimit(bot, 'sendPhoto', this); }); it('should send a photo from file', function test() { - const photo = `${__dirname}/data/photo.gif`; + const photo = `${__dirname}/data/photo.png`; return bot.sendPhoto(USERID, photo).then(resp => { assert.ok(is.object(resp)); assert.ok(is.array(resp.photo)); @@ -523,21 +523,21 @@ describe('TelegramBot', function telegramSuite() { }); }); it('should send a photo from fs.readStream', function test() { - const photo = fs.createReadStream(`${__dirname}/data/photo.gif`); + const photo = fs.createReadStream(`${__dirname}/data/photo.png`); return bot.sendPhoto(USERID, photo).then(resp => { assert.ok(is.object(resp)); assert.ok(is.array(resp.photo)); }); }); it('should send a photo from request Stream', function test() { - const photo = request(`${staticUrl}/photo.gif`); + const photo = request(`${staticUrl}/photo.png`); return bot.sendPhoto(USERID, photo).then(resp => { assert.ok(is.object(resp)); assert.ok(is.array(resp.photo)); }); }); it('should send a photo from a Buffer', function test() { - const photo = fs.readFileSync(`${__dirname}/data/photo.gif`); + const photo = fs.readFileSync(`${__dirname}/data/photo.png`); return bot.sendPhoto(USERID, photo).then(resp => { assert.ok(is.object(resp)); assert.ok(is.array(resp.photo)); @@ -817,15 +817,61 @@ describe('TelegramBot', function telegramSuite() { }); }); - describe.skip('#kickChatMember', function kickChatMemberSuite() {}); + describe.skip('#kickChatMember', function kickChatMemberSuite() { }); - describe.skip('#unbanChatMember', function unbanChatMemberSuite() {}); + describe.skip('#unbanChatMember', function unbanChatMemberSuite() { }); - describe.skip('#restrictChatMember', function restrictChatMemberSuite() {}); + describe.skip('#restrictChatMember', function restrictChatMemberSuite() { }); - describe.skip('#promoteChatMember', function promoteChatMemberSuite() {}); + describe.skip('#promoteChatMember', function promoteChatMemberSuite() { }); - describe.skip('#answerCallbackQuery', function answerCallbackQuerySuite() {}); + describe.skip('#answerCallbackQuery', function answerCallbackQuerySuite() { }); + + describe('#setMyCommands', function setMyCommandsSuite() { + it('should set bot commands', function test() { + const opts = [ + { command: 'eat', description: 'Command for eat' }, + { command: 'run', description: 'Command for run' } + ]; + return bot.setMyCommands(opts).then(resp => { + assert.ok(is.boolean(resp)); + }); + }); + }); + + describe('#getMyCommands ', function getMyCommandsSuite() { + it('should get bot commands', function test() { + return bot.getMyCommands().then(resp => { + assert.ok(is.array(resp)); + }); + }); + }); + + describe.skip('#setChatAdministratorCustomTitle ', function setChatAdministratorCustomTitleSuite() { + it('should set chat permissions', function test() { + return bot.setChatAdministratorCustomTitle(GROUPID, USERID, 'Custom Name').then(resp => { + assert.ok(is.boolean(resp)); + }); + }); + }); + + describe('#setChatPermissions ', function setChatPermissionsSuite() { + it('should set chat permissions', function test() { + const ChatPermissions = { + can_send_messages: true, + can_send_media_messages: true, + can_send_polls: false, + can_send_other_messages: false, + can_add_web_page_previews: true, + can_change_info: false, + can_invite_users: false, + can_pin_messages: true + }; + return bot.setChatPermissions(GROUPID, ChatPermissions).then(resp => { + assert.ok(is.boolean(resp)); + }); + }); + }); describe('#exportChatInviteLink', function exportChatInviteLinkSuite() { before(function before() { @@ -885,7 +931,8 @@ describe('TelegramBot', function telegramSuite() { utils.handleRatelimit(bot, 'setChatTitle', this); }); it('should set the chat title', function test() { - return bot.setChatTitle(GROUPID, 'ntba test group').then(resp => { + const random = Math.floor(Math.random() * 1000); + return bot.setChatTitle(GROUPID, `ntba test group (random: ${random})`).then(resp => { assert.equal(resp, true); }); }); @@ -956,7 +1003,7 @@ describe('TelegramBot', function telegramSuite() { utils.handleRatelimit(bot, 'editMessageCaption', this); }); it('should edit a caption sent by the bot', function test() { - const photo = `${__dirname}/data/photo.gif`; + const photo = `${__dirname}/data/photo.png`; const options = { caption: 'test caption' }; return bot.sendPhoto(USERID, photo, options).then(resp => { assert.equal(resp.caption, 'test caption'); @@ -1128,6 +1175,43 @@ describe('TelegramBot', function telegramSuite() { }); }); + describe('#sendPoll', function sendPollSuite() { + it('should send a Poll', function test() { + const question = '¿Are you okey?'; + const answers = ['Yes', 'No']; + const opts = { is_anonymous: true }; + return bot.sendPoll(GROUPID, question, answers, opts).then(resp => { + assert.ok(is.object(resp)); + }); + }); + it('should send a Quiz', function test() { + const question = '¿Are you okey?'; + const answers = ['Yes', 'No']; + const opts = { + is_anonymous: true, + type: 'quiz', + correct_option_id: 0 + }; + return bot.sendPoll(GROUPID, question, answers, opts).then(resp => { + assert.ok(is.object(resp)); + }); + }); + }); + + describe('#sendDice', function sendDiceSuite() { + it('should send a Dice', function test() { + return bot.sendDice(GROUPID).then(resp => { + assert.ok(is.object(resp)); + }); + }); + it('should send a Dart', function test() { + const opts = { emoji: '🎯' }; + return bot.sendDice(GROUPID, opts).then(resp => { + assert.ok(is.object(resp)); + }); + }); + }); + describe('#getFile', function getFileSuite() { this.timeout(timeout); before(function before() { @@ -1221,7 +1305,7 @@ describe('TelegramBot', function telegramSuite() { describe('#removeTextListener', function removeTextListenerSuite() { const regexp = /\/onText/; const regexp2 = /\/onText/; - const callback = function noop() {}; + const callback = function noop() { }; after(function after() { bot.removeTextListener(regexp); bot.removeTextListener(regexp2); @@ -1240,12 +1324,12 @@ describe('TelegramBot', function telegramSuite() { }); }); - describe.skip('#onReplyToMessage', function onReplyToMessageSuite() {}); + describe.skip('#onReplyToMessage', function onReplyToMessageSuite() { }); describe('#removeReplyListener', function removeReplyListenerSuite() { const chatId = -1234; const messageId = 1; - const callback = function noop() {}; + const callback = function noop() { }; it('returns the right reply-listener', function test() { const id = bot.onReplyToMessage(chatId, messageId, callback); const replyListener = bot.removeReplyListener(id); @@ -1306,7 +1390,7 @@ describe('TelegramBot', function telegramSuite() { }); }); - describe.skip('#leaveChat', function leaveChatSuite() {}); + describe.skip('#leaveChat', function leaveChatSuite() { }); describe('#sendGame', function sendGameSuite() { before(function before() { @@ -1375,9 +1459,9 @@ describe('TelegramBot', function telegramSuite() { }); }); - describe.skip('#answerShippingQuery', function answerShippingQuerySuite() {}); + describe.skip('#answerShippingQuery', function answerShippingQuerySuite() { }); - describe.skip('#answerPreCheckoutQuery', function answerPreCheckoutQuerySuite() {}); + describe.skip('#answerPreCheckoutQuery', function answerPreCheckoutQuerySuite() { }); describe('#getStickerSet', function getStickerSetSuite() { before(function before() { @@ -1416,7 +1500,7 @@ describe('TelegramBot', function telegramSuite() { return bot.sendMediaGroup(USERID, [ { type: 'photo', - media: `${__dirname}/data/photo.gif`, + media: `${__dirname}/data/photo.png`, }, { type: 'video',