2
0
mirror of https://github.com/yagop/node-telegram-bot-api synced 2025-08-29 13:27:44 +00:00

src/telegram: Improve sending files (#471)

References:

  * PR: https://github.com/yagop/node-telegram-bot-api/pull/471
This commit is contained in:
GochoMugo 2017-12-20 11:03:00 +03:00
commit 1a08221174
No known key found for this signature in database
GPG Key ID: 7B6A01CB57AA39E4
6 changed files with 373 additions and 138 deletions

View File

@ -26,6 +26,13 @@ Changed:
1. Update *TelegramBot#answerCallbackQuery()* signature (by @GochoMugo) 1. Update *TelegramBot#answerCallbackQuery()* signature (by @GochoMugo)
1. Improve default error logging of `polling_error` and `webhook_error` 1. Improve default error logging of `polling_error` and `webhook_error`
Deprecated:
1. Sending files: *(See [usage guide][usage-sending-file])* (by @hufan-akari, @GochoMugo)
* Error will **not** be thrown if `Buffer` is used and file-type could **not** be detected.
* Filename will **not** be set to `data.${ext}` if `Buffer` is used
* Content type will **not** default to `null` or `undefined`
Fixed: Fixed:
1. (#265) Fix the offset infinite loop bug (#36) (by @GochoMugo) 1. (#265) Fix the offset infinite loop bug (#36) (by @GochoMugo)
@ -187,6 +194,8 @@ Fixed:
1. Fix typos (by oflisback) 1. Fix typos (by oflisback)
[usage-sending-files]:https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files-options
[0.25.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.25.0 [0.25.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.25.0
[0.26.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.26.0 [0.26.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.26.0
[0.27.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.27.0 [0.27.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.27.0

View File

@ -22,7 +22,7 @@ TelegramBot
* [.closeWebHook()](#TelegramBot+closeWebHook) ⇒ <code>Promise</code> * [.closeWebHook()](#TelegramBot+closeWebHook) ⇒ <code>Promise</code>
* [.hasOpenWebHook()](#TelegramBot+hasOpenWebHook) ⇒ <code>Boolean</code> * [.hasOpenWebHook()](#TelegramBot+hasOpenWebHook) ⇒ <code>Boolean</code>
* [.getMe([options])](#TelegramBot+getMe) ⇒ <code>Promise</code> * [.getMe([options])](#TelegramBot+getMe) ⇒ <code>Promise</code>
* [.setWebHook(url, [options])](#TelegramBot+setWebHook) ⇒ <code>Promise</code> * [.setWebHook(url, [options], [fileOptions])](#TelegramBot+setWebHook) ⇒ <code>Promise</code>
* [.deleteWebHook([options])](#TelegramBot+deleteWebHook) ⇒ <code>Promise</code> * [.deleteWebHook([options])](#TelegramBot+deleteWebHook) ⇒ <code>Promise</code>
* [.getWebHookInfo([options])](#TelegramBot+getWebHookInfo) ⇒ <code>Promise</code> * [.getWebHookInfo([options])](#TelegramBot+getWebHookInfo) ⇒ <code>Promise</code>
* [.getUpdates([options])](#TelegramBot+getUpdates) ⇒ <code>Promise</code> * [.getUpdates([options])](#TelegramBot+getUpdates) ⇒ <code>Promise</code>
@ -30,20 +30,20 @@ TelegramBot
* [.sendMessage(chatId, text, [options])](#TelegramBot+sendMessage) ⇒ <code>Promise</code> * [.sendMessage(chatId, text, [options])](#TelegramBot+sendMessage) ⇒ <code>Promise</code>
* [.answerInlineQuery(inlineQueryId, results, [options])](#TelegramBot+answerInlineQuery) ⇒ <code>Promise</code> * [.answerInlineQuery(inlineQueryId, results, [options])](#TelegramBot+answerInlineQuery) ⇒ <code>Promise</code>
* [.forwardMessage(chatId, fromChatId, messageId, [options])](#TelegramBot+forwardMessage) ⇒ <code>Promise</code> * [.forwardMessage(chatId, fromChatId, messageId, [options])](#TelegramBot+forwardMessage) ⇒ <code>Promise</code>
* [.sendPhoto(chatId, photo, [options])](#TelegramBot+sendPhoto) ⇒ <code>Promise</code> * [.sendPhoto(chatId, photo, [options], [fileOptions])](#TelegramBot+sendPhoto) ⇒ <code>Promise</code>
* [.sendAudio(chatId, audio, [options])](#TelegramBot+sendAudio) ⇒ <code>Promise</code> * [.sendAudio(chatId, audio, [options], [fileOptions])](#TelegramBot+sendAudio) ⇒ <code>Promise</code>
* [.sendDocument(chatId, doc, [options], [fileOpts])](#TelegramBot+sendDocument) ⇒ <code>Promise</code> * [.sendDocument(chatId, doc, [options], [fileOptions])](#TelegramBot+sendDocument) ⇒ <code>Promise</code>
* [.sendSticker(chatId, sticker, [options])](#TelegramBot+sendSticker) ⇒ <code>Promise</code> * [.sendSticker(chatId, sticker, [options], [fileOptions])](#TelegramBot+sendSticker) ⇒ <code>Promise</code>
* [.sendVideo(chatId, video, [options])](#TelegramBot+sendVideo) ⇒ <code>Promise</code> * [.sendVideo(chatId, video, [options], [fileOptions])](#TelegramBot+sendVideo) ⇒ <code>Promise</code>
* [.sendVideoNote(chatId, videoNote, [options])](#TelegramBot+sendVideoNote) ⇒ <code>Promise</code> * [.sendVideoNote(chatId, videoNote, [options], [fileOptions])](#TelegramBot+sendVideoNote) ⇒ <code>Promise</code>
* [.sendVoice(chatId, voice, [options])](#TelegramBot+sendVoice) ⇒ <code>Promise</code> * [.sendVoice(chatId, voice, [options], [fileOptions])](#TelegramBot+sendVoice) ⇒ <code>Promise</code>
* [.sendChatAction(chatId, action, [options])](#TelegramBot+sendChatAction) ⇒ <code>Promise</code> * [.sendChatAction(chatId, action, [options])](#TelegramBot+sendChatAction) ⇒ <code>Promise</code>
* [.kickChatMember(chatId, userId, [options])](#TelegramBot+kickChatMember) ⇒ <code>Promise</code> * [.kickChatMember(chatId, userId, [options])](#TelegramBot+kickChatMember) ⇒ <code>Promise</code>
* [.unbanChatMember(chatId, userId, [options])](#TelegramBot+unbanChatMember) ⇒ <code>Promise</code> * [.unbanChatMember(chatId, userId, [options])](#TelegramBot+unbanChatMember) ⇒ <code>Promise</code>
* [.restrictChatMember(chatId, userId, [options])](#TelegramBot+restrictChatMember) ⇒ <code>Promise</code> * [.restrictChatMember(chatId, userId, [options])](#TelegramBot+restrictChatMember) ⇒ <code>Promise</code>
* [.promoteChatMember(chatId, userId, [options])](#TelegramBot+promoteChatMember) ⇒ <code>Promise</code> * [.promoteChatMember(chatId, userId, [options])](#TelegramBot+promoteChatMember) ⇒ <code>Promise</code>
* [.exportChatInviteLink(chatId, [options])](#TelegramBot+exportChatInviteLink) ⇒ <code>Promise</code> * [.exportChatInviteLink(chatId, [options])](#TelegramBot+exportChatInviteLink) ⇒ <code>Promise</code>
* [.setChatPhoto(chatId, photo, [options])](#TelegramBot+setChatPhoto) ⇒ <code>Promise</code> * [.setChatPhoto(chatId, photo, [options], [fileOptions])](#TelegramBot+setChatPhoto) ⇒ <code>Promise</code>
* [.deleteChatPhoto(chatId, [options])](#TelegramBot+deleteChatPhoto) ⇒ <code>Promise</code> * [.deleteChatPhoto(chatId, [options])](#TelegramBot+deleteChatPhoto) ⇒ <code>Promise</code>
* [.setChatTitle(chatId, title, [options])](#TelegramBot+setChatTitle) ⇒ <code>Promise</code> * [.setChatTitle(chatId, title, [options])](#TelegramBot+setChatTitle) ⇒ <code>Promise</code>
* [.setChatDescription(chatId, description, [options])](#TelegramBot+setChatDescription) ⇒ <code>Promise</code> * [.setChatDescription(chatId, description, [options])](#TelegramBot+setChatDescription) ⇒ <code>Promise</code>
@ -82,9 +82,9 @@ TelegramBot
* [.answerShippingQuery(shippingQueryId, ok, [options])](#TelegramBot+answerShippingQuery) ⇒ <code>Promise</code> * [.answerShippingQuery(shippingQueryId, ok, [options])](#TelegramBot+answerShippingQuery) ⇒ <code>Promise</code>
* [.answerPreCheckoutQuery(preCheckoutQueryId, ok, [options])](#TelegramBot+answerPreCheckoutQuery) ⇒ <code>Promise</code> * [.answerPreCheckoutQuery(preCheckoutQueryId, ok, [options])](#TelegramBot+answerPreCheckoutQuery) ⇒ <code>Promise</code>
* [.getStickerSet(name, [options])](#TelegramBot+getStickerSet) ⇒ <code>Promise</code> * [.getStickerSet(name, [options])](#TelegramBot+getStickerSet) ⇒ <code>Promise</code>
* [.uploadStickerFile(userId, pngSticker, [options])](#TelegramBot+uploadStickerFile) ⇒ <code>Promise</code> * [.uploadStickerFile(userId, pngSticker, [options], [fileOptions])](#TelegramBot+uploadStickerFile) ⇒ <code>Promise</code>
* [.createNewStickerSet(userId, name, title, pngSticker, emojis, [options])](#TelegramBot+createNewStickerSet) ⇒ <code>Promise</code> * [.createNewStickerSet(userId, name, title, pngSticker, emojis, [options], [fileOptions])](#TelegramBot+createNewStickerSet) ⇒ <code>Promise</code>
* [.addStickerToSet(userId, name, pngSticker, emojis, [options])](#TelegramBot+addStickerToSet) ⇒ <code>Promise</code> * [.addStickerToSet(userId, name, pngSticker, emojis, [options], [fileOptions])](#TelegramBot+addStickerToSet) ⇒ <code>Promise</code>
* [.setStickerPositionInSet(sticker, position, [options])](#TelegramBot+setStickerPositionInSet) ⇒ <code>Promise</code> * [.setStickerPositionInSet(sticker, position, [options])](#TelegramBot+setStickerPositionInSet) ⇒ <code>Promise</code>
* [.deleteStickerFromSet(sticker, [options])](#TelegramBot+deleteStickerFromSet) ⇒ <code>Promise</code> * [.deleteStickerFromSet(sticker, [options])](#TelegramBot+deleteStickerFromSet) ⇒ <code>Promise</code>
* _static_ * _static_
@ -227,7 +227,7 @@ Returns basic information about the bot in form of a `User` object.
<a name="TelegramBot+setWebHook"></a> <a name="TelegramBot+setWebHook"></a>
### telegramBot.setWebHook(url, [options]) ⇒ <code>Promise</code> ### telegramBot.setWebHook(url, [options], [fileOptions]) ⇒ <code>Promise</code>
Specify an url to receive incoming updates via an outgoing webHook. Specify an url to receive incoming updates via an outgoing webHook.
This method has an [older, compatible signature][setWebHook-v0.25.0] This method has an [older, compatible signature][setWebHook-v0.25.0]
that is being deprecated. that is being deprecated.
@ -240,6 +240,7 @@ that is being deprecated.
| url | <code>String</code> | URL where Telegram will make HTTP Post. Leave empty to delete webHook. | | url | <code>String</code> | URL where Telegram will make HTTP Post. Leave empty to delete webHook. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [options.certificate] | <code>String</code> &#124; <code>stream.Stream</code> | PEM certificate key (public). | | [options.certificate] | <code>String</code> &#124; <code>stream.Stream</code> | PEM certificate key (public). |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+deleteWebHook"></a> <a name="TelegramBot+deleteWebHook"></a>
@ -341,50 +342,64 @@ Forward messages of any kind.
<a name="TelegramBot+sendPhoto"></a> <a name="TelegramBot+sendPhoto"></a>
### telegramBot.sendPhoto(chatId, photo, [options]) ⇒ <code>Promise</code> ### telegramBot.sendPhoto(chatId, photo, [options], [fileOptions]) ⇒ <code>Promise</code>
Send photo Send photo
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**See**: https://core.telegram.org/bots/api#sendphoto **See**
- https://core.telegram.org/bots/api#sendphoto
- https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
| Param | Type | Description | | Param | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| photo | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or a Stream. Can also be a `file_id` previously uploaded | | photo | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or a Stream. Can also be a `file_id` previously uploaded |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendAudio"></a> <a name="TelegramBot+sendAudio"></a>
### telegramBot.sendAudio(chatId, audio, [options]) ⇒ <code>Promise</code> ### telegramBot.sendAudio(chatId, audio, [options], [fileOptions]) ⇒ <code>Promise</code>
Send audio Send audio
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**See**: https://core.telegram.org/bots/api#sendaudio **See**
- https://core.telegram.org/bots/api#sendaudio
- https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
| Param | Type | Description | | Param | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| audio | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. | | audio | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendDocument"></a> <a name="TelegramBot+sendDocument"></a>
### telegramBot.sendDocument(chatId, doc, [options], [fileOpts]) ⇒ <code>Promise</code> ### telegramBot.sendDocument(chatId, doc, [options], [fileOptions]) ⇒ <code>Promise</code>
Send Document Send Document
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**See**: https://core.telegram.org/bots/api#sendDocument **See**
- https://core.telegram.org/bots/api#sendDocument
- https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
| Param | Type | Description | | Param | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| doc | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. | | doc | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOpts] | <code>Object</code> | Optional file related meta-data | | [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendSticker"></a> <a name="TelegramBot+sendSticker"></a>
### telegramBot.sendSticker(chatId, sticker, [options]) ⇒ <code>Promise</code> ### telegramBot.sendSticker(chatId, sticker, [options], [fileOptions]) ⇒ <code>Promise</code>
Send .webp stickers. Send .webp stickers.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
@ -395,49 +410,65 @@ Send .webp stickers.
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| sticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. Stickers are WebP format files. | | sticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. Stickers are WebP format files. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendVideo"></a> <a name="TelegramBot+sendVideo"></a>
### telegramBot.sendVideo(chatId, video, [options]) ⇒ <code>Promise</code> ### telegramBot.sendVideo(chatId, video, [options], [fileOptions]) ⇒ <code>Promise</code>
Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document).
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**See**: https://core.telegram.org/bots/api#sendvideo **See**
- https://core.telegram.org/bots/api#sendvideo
- https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
| Param | Type | Description | | Param | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| video | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or Stream. Can also be a `file_id` previously uploaded. | | video | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or Stream. Can also be a `file_id` previously uploaded. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendVideoNote"></a> <a name="TelegramBot+sendVideoNote"></a>
### telegramBot.sendVideoNote(chatId, videoNote, [options]) ⇒ <code>Promise</code> ### telegramBot.sendVideoNote(chatId, videoNote, [options], [fileOptions]) ⇒ <code>Promise</code>
Use this method to send rounded square videos of upto 1 minute long. Use this method to send rounded square videos of upto 1 minute long.
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**Info**: The length parameter is actually optional. However, the API (at time of writing) requires you to always provide it until it is fixed. **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 **See**
- https://core.telegram.org/bots/api#sendvideonote
- https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
| Param | Type | Description | | Param | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| videoNote | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or Stream. Can also be a `file_id` previously uploaded. | | videoNote | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or Stream. Can also be a `file_id` previously uploaded. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendVoice"></a> <a name="TelegramBot+sendVoice"></a>
### telegramBot.sendVoice(chatId, voice, [options]) ⇒ <code>Promise</code> ### telegramBot.sendVoice(chatId, voice, [options], [fileOptions]) ⇒ <code>Promise</code>
Send voice Send voice
**Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code> **Kind**: instance method of <code>[TelegramBot](#TelegramBot)</code>
**See**: https://core.telegram.org/bots/api#sendvoice **See**
- https://core.telegram.org/bots/api#sendvoice
- https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
| Param | Type | Description | | Param | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| voice | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. | | voice | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path, Stream or Buffer. Can also be a `file_id` previously uploaded. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+sendChatAction"></a> <a name="TelegramBot+sendChatAction"></a>
@ -543,7 +574,7 @@ Returns exported invite link as String on success.
<a name="TelegramBot+setChatPhoto"></a> <a name="TelegramBot+setChatPhoto"></a>
### telegramBot.setChatPhoto(chatId, photo, [options]) ⇒ <code>Promise</code> ### telegramBot.setChatPhoto(chatId, photo, [options], [fileOptions]) ⇒ <code>Promise</code>
Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. Use this method to set a new profile photo for the chat. 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. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
Returns True on success. Returns True on success.
@ -556,6 +587,7 @@ Returns True on success.
| chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient | | chatId | <code>Number</code> &#124; <code>String</code> | Unique identifier for the message recipient |
| photo | <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or a Stream. | | photo | <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or a Stream. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+deleteChatPhoto"></a> <a name="TelegramBot+deleteChatPhoto"></a>
@ -1150,7 +1182,7 @@ Use this method to get a sticker set. On success, a [StickerSet](https://core.te
<a name="TelegramBot+uploadStickerFile"></a> <a name="TelegramBot+uploadStickerFile"></a>
### telegramBot.uploadStickerFile(userId, pngSticker, [options]) ⇒ <code>Promise</code> ### telegramBot.uploadStickerFile(userId, pngSticker, [options], [fileOptions]) ⇒ <code>Promise</code>
Use this method to upload a .png file with a sticker for later use in *createNewStickerSet* and *addStickerToSet* methods (can be used multiple 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. times). Returns the uploaded [File](https://core.telegram.org/bots/api#file) on success.
@ -1162,10 +1194,11 @@ times). Returns the uploaded [File](https://core.telegram.org/bots/api#file) on
| userId | <code>Number</code> | User identifier of sticker file owner | | userId | <code>Number</code> | User identifier of sticker file owner |
| pngSticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or a Stream. Can also be a `file_id` previously uploaded. **Png** image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. | | pngSticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | A file path or a Stream. Can also be a `file_id` previously uploaded. **Png** image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+createNewStickerSet"></a> <a name="TelegramBot+createNewStickerSet"></a>
### telegramBot.createNewStickerSet(userId, name, title, pngSticker, emojis, [options]) ⇒ <code>Promise</code> ### telegramBot.createNewStickerSet(userId, name, title, pngSticker, emojis, [options], [fileOptions]) ⇒ <code>Promise</code>
Use this method to create new sticker set owned by a user. Use this method to create new sticker set owned by a user.
The bot will be able to edit the created sticker set. The bot will be able to edit the created sticker set.
Returns True on success. Returns True on success.
@ -1185,10 +1218,11 @@ Returns True on success.
| pngSticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. | | pngSticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. |
| emojis | <code>String</code> | One or more emoji corresponding to the sticker | | emojis | <code>String</code> | One or more emoji corresponding to the sticker |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+addStickerToSet"></a> <a name="TelegramBot+addStickerToSet"></a>
### telegramBot.addStickerToSet(userId, name, pngSticker, emojis, [options]) ⇒ <code>Promise</code> ### telegramBot.addStickerToSet(userId, name, pngSticker, emojis, [options], [fileOptions]) ⇒ <code>Promise</code>
Use this method to add a new sticker to a set created by the bot. Use this method to add a new sticker to a set created by the bot.
Returns True on success. Returns True on success.
@ -1206,6 +1240,7 @@ Returns True on success.
| pngSticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px | | pngSticker | <code>String</code> &#124; <code>stream.Stream</code> &#124; <code>Buffer</code> | Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px |
| emojis | <code>String</code> | One or more emoji corresponding to the sticker | | emojis | <code>String</code> | One or more emoji corresponding to the sticker |
| [options] | <code>Object</code> | Additional Telegram query options | | [options] | <code>Object</code> | Additional Telegram query options |
| [fileOptions] | <code>Object</code> | Optional file related meta-data |
<a name="TelegramBot+setStickerPositionInSet"></a> <a name="TelegramBot+setStickerPositionInSet"></a>

View File

@ -116,6 +116,63 @@ const url = 'https://telegram.org/img/t_logo.png';
bot.sendPhoto(chatId, url); bot.sendPhoto(chatId, url);
``` ```
If you wish to explicitly specify the filename or
[MIME type](http://en.wikipedia.org/wiki/Internet_media_type),
you may pass an additional argument as file options, like so:
```js
const fileOptions = {
// Explicitly specify the file name.
filename: 'customfilename',
// Explicitly specify the MIME type.
contentType: 'audio/mpeg',
};
bot.sendAudio(chatId, data, {}, fileOptions);
```
**NOTE:** You **MUST** provide an empty object (`{}`) in place of
*Additional Telegram query options*, if you have **no** query options
to specify. For example,
```js
// WRONG!
// 'fileOptions' will be taken as additional Telegram query options!!!
bot.sendAudio(chatId, data, fileOptions);
// RIGHT!
bot.sendAudio(chatId, data, {}, fileOptions);
```
<a name="sending-files-options"></a>
### File Options (metadata)
When sending files, the library automatically resolves
the `filename` and `contentType` properties.
**For now, this has to be manually activated using environment
variable `NTBA_FIX_350`.**
In order of highest-to-lowest precedence in searching for
a value, when resolving the `filename`:
*(`fileOptions` is the Object argument passed to the method.
The "file" argument passed to the method can be a `Stream`,
`Buffer` or `filepath`.)*
1. Is `fileOptions.filename` explictly defined?
1. Does `Stream#path` exist?
1. Is `filepath` provided?
1. Default to `"filename"`
And the `contentType`:
1. Is `fileOptions.contentType` explictly-defined?
1. Does `Stream#path` exist?
1. Try detecting file-type from the `Buffer`
1. Is `filepath` provided?
1. Is `fileOptions.filename` explicitly defined?
1. Default to `"application/octet-stream"`
<a name="sending-files-performance"></a> <a name="sending-files-performance"></a>
### Performance Issue ### Performance Issue

View File

@ -289,6 +289,9 @@ class TelegramBot extends EventEmitter {
* Format data to be uploaded; handles file paths, streams and buffers * Format data to be uploaded; handles file paths, streams and buffers
* @param {String} type * @param {String} type
* @param {String|stream.Stream|Buffer} data * @param {String|stream.Stream|Buffer} data
* @param {Object} fileOptions File options
* @param {String} [fileOptions.filename] File name
* @param {String} [fileOptions.contentType] Content type (i.e. MIME)
* @return {Array} formatted * @return {Array} formatted
* @return {Object} formatted[0] formData * @return {Object} formatted[0] formData
* @return {String} formatted[1] fileId * @return {String} formatted[1] fileId
@ -296,55 +299,70 @@ class TelegramBot extends EventEmitter {
* @see https://npmjs.com/package/file-type * @see https://npmjs.com/package/file-type
* @private * @private
*/ */
_formatSendData(type, data) { _formatSendData(type, data, fileOptions = {}) {
let formData; let filedata = data;
let fileName; let filename = fileOptions.filename;
let fileId; let contentType = fileOptions.contentType;
if (data instanceof stream.Stream) { if (data instanceof stream.Stream) {
// Will be 'null' if could not be parsed. Default to 'filename'. if (!filename && data.path) {
// Will be 'null' if could not be parsed.
// For example, 'data.path' === '/?id=123' from 'request("https://example.com/?id=123")' // For example, 'data.path' === '/?id=123' from 'request("https://example.com/?id=123")'
fileName = URL.parse(path.basename(data.path.toString())).pathname || 'filename'; const url = URL.parse(path.basename(data.path.toString()));
formData = {}; if (url.pathname) {
formData[type] = { filename = qs.unescape(url.pathname);
value: data, }
options: {
filename: qs.unescape(fileName),
contentType: mime.lookup(fileName)
} }
};
} else if (Buffer.isBuffer(data)) { } else if (Buffer.isBuffer(data)) {
if (!filename && !process.env.NTBA_FIX_350) {
deprecate('Buffers will have their filenames default to "filename" instead of "data".');
filename = 'data';
}
if (!contentType) {
const filetype = fileType(data); const filetype = fileType(data);
if (!filetype) { if (filetype) {
throw new errors.FatalError('Unsupported Buffer file type'); contentType = filetype.mime;
const ext = filetype.ext;
if (ext && !process.env.NTBA_FIX_350) {
filename = `${filename}.${ext}`;
} }
formData = {}; } else if (!process.env.NTBA_FIX_350) {
formData[type] = { deprecate('An error will no longer be thrown if file-type of buffer could not be detected.');
value: data, throw new errors.FatalError('Unsupported Buffer file-type');
options: {
filename: `data.${filetype.ext}`,
contentType: filetype.mime
} }
};
} else if (!this.options.filepath) {
/**
* When the constructor option 'filepath' is set to
* 'false', we do not support passing file-paths.
*/
fileId = data;
} else if (fs.existsSync(data)) {
fileName = path.basename(data);
formData = {};
formData[type] = {
value: fs.createReadStream(data),
options: {
filename: fileName,
contentType: mime.lookup(fileName)
} }
}; } else if (data) {
if (this.options.filepath && fs.existsSync(data)) {
filedata = fs.createReadStream(data);
if (!filename) {
filename = path.basename(data);
}
} else { } else {
fileId = data; return [null, data];
} }
return [formData, fileId]; } else {
return [null, data];
}
filename = filename || 'filename';
contentType = contentType || mime.lookup(filename);
if (process.env.NTBA_FIX_350) {
contentType = contentType || 'application/octet-stream';
} else {
deprecate('In the future, content-type of files you send will default to "application/octet-stream".');
}
// TODO: Add missing file extension.
return [{
[type]: {
value: filedata,
options: {
filename,
contentType,
},
},
}, null];
} }
/** /**
@ -456,10 +474,11 @@ class TelegramBot extends EventEmitter {
* delete webHook. * delete webHook.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {String|stream.Stream} [options.certificate] PEM certificate key (public). * @param {String|stream.Stream} [options.certificate] PEM certificate key (public).
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#setwebhook * @see https://core.telegram.org/bots/api#setwebhook
*/ */
setWebHook(url, options = {}) { setWebHook(url, options = {}, fileOptions = {}) {
/* The older method signature was setWebHook(url, cert). /* The older method signature was setWebHook(url, cert).
* We need to ensure backwards-compatibility while maintaining * We need to ensure backwards-compatibility while maintaining
* consistency of the method signatures throughout the library */ * consistency of the method signatures throughout the library */
@ -480,7 +499,7 @@ class TelegramBot extends EventEmitter {
if (cert) { if (cert) {
try { try {
const sendData = this._formatSendData('certificate', cert); const sendData = this._formatSendData('certificate', cert, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.certificate = sendData[1]; opts.qs.certificate = sendData[1];
} catch (ex) { } catch (ex) {
@ -690,16 +709,18 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} photo A file path or a Stream. Can * @param {String|stream.Stream|Buffer} photo A file path or a Stream. Can
* also be a `file_id` previously uploaded * also be a `file_id` previously uploaded
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendphoto * @see https://core.telegram.org/bots/api#sendphoto
* @see https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
*/ */
sendPhoto(chatId, photo, options = {}) { sendPhoto(chatId, photo, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options, qs: options,
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('photo', photo); const sendData = this._formatSendData('photo', photo, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.photo = sendData[1]; opts.qs.photo = sendData[1];
} catch (ex) { } catch (ex) {
@ -714,16 +735,18 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} audio A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} audio A file path, Stream or Buffer.
* Can also be a `file_id` previously uploaded. * Can also be a `file_id` previously uploaded.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendaudio * @see https://core.telegram.org/bots/api#sendaudio
* @see https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
*/ */
sendAudio(chatId, audio, options = {}) { sendAudio(chatId, audio, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('audio', audio); const sendData = this._formatSendData('audio', audio, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.audio = sendData[1]; opts.qs.audio = sendData[1];
} catch (ex) { } catch (ex) {
@ -738,25 +761,23 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} doc A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} doc A file path, Stream or Buffer.
* Can also be a `file_id` previously uploaded. * Can also be a `file_id` previously uploaded.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOpts] Optional file related meta-data * @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendDocument * @see https://core.telegram.org/bots/api#sendDocument
* @see https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
*/ */
sendDocument(chatId, doc, options = {}, fileOpts = {}) { sendDocument(chatId, doc, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('document', doc); const sendData = this._formatSendData('document', doc, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.document = sendData[1]; opts.qs.document = sendData[1];
} catch (ex) { } catch (ex) {
return Promise.reject(ex); return Promise.reject(ex);
} }
if (opts.formData && Object.keys(fileOpts).length) {
opts.formData.document.options = fileOpts;
}
return this._request('sendDocument', opts); return this._request('sendDocument', opts);
} }
@ -766,16 +787,17 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} sticker A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} sticker A file path, Stream or Buffer.
* Can also be a `file_id` previously uploaded. Stickers are WebP format files. * Can also be a `file_id` previously uploaded. Stickers are WebP format files.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendsticker * @see https://core.telegram.org/bots/api#sendsticker
*/ */
sendSticker(chatId, sticker, options = {}) { sendSticker(chatId, sticker, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('sticker', sticker); const sendData = this._formatSendData('sticker', sticker, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.sticker = sendData[1]; opts.qs.sticker = sendData[1];
} catch (ex) { } catch (ex) {
@ -790,16 +812,18 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} video A file path or Stream. * @param {String|stream.Stream|Buffer} video A file path or Stream.
* Can also be a `file_id` previously uploaded. * Can also be a `file_id` previously uploaded.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendvideo * @see https://core.telegram.org/bots/api#sendvideo
* @see https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
*/ */
sendVideo(chatId, video, options = {}) { sendVideo(chatId, video, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('video', video); const sendData = this._formatSendData('video', video, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.video = sendData[1]; opts.qs.video = sendData[1];
} catch (ex) { } catch (ex) {
@ -814,17 +838,19 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} videoNote A file path or Stream. * @param {String|stream.Stream|Buffer} videoNote A file path or Stream.
* Can also be a `file_id` previously uploaded. * Can also be a `file_id` previously uploaded.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @info The length parameter is actually optional. However, the API (at time of writing) requires you to always provide it until it is fixed. * @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 * @see https://core.telegram.org/bots/api#sendvideonote
* @see https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
*/ */
sendVideoNote(chatId, videoNote, options = {}) { sendVideoNote(chatId, videoNote, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('video_note', videoNote); const sendData = this._formatSendData('video_note', videoNote, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.video_note = sendData[1]; opts.qs.video_note = sendData[1];
} catch (ex) { } catch (ex) {
@ -839,16 +865,18 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} voice A file path, Stream or Buffer. * @param {String|stream.Stream|Buffer} voice A file path, Stream or Buffer.
* Can also be a `file_id` previously uploaded. * Can also be a `file_id` previously uploaded.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#sendvoice * @see https://core.telegram.org/bots/api#sendvoice
* @see https://github.com/yagop/node-telegram-bot-api/blob/master/doc/usage.md#sending-files
*/ */
sendVoice(chatId, voice, options = {}) { sendVoice(chatId, voice, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options qs: options
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('voice', voice); const sendData = this._formatSendData('voice', voice, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.voice = sendData[1]; opts.qs.voice = sendData[1];
} catch (ex) { } catch (ex) {
@ -973,16 +1001,17 @@ class TelegramBot extends EventEmitter {
* @param {Number|String} chatId Unique identifier for the message recipient * @param {Number|String} chatId Unique identifier for the message recipient
* @param {stream.Stream|Buffer} photo A file path or a Stream. * @param {stream.Stream|Buffer} photo A file path or a Stream.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#setchatphoto * @see https://core.telegram.org/bots/api#setchatphoto
*/ */
setChatPhoto(chatId, photo, options = {}) { setChatPhoto(chatId, photo, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options, qs: options,
}; };
opts.qs.chat_id = chatId; opts.qs.chat_id = chatId;
try { try {
const sendData = this._formatSendData('photo', photo); const sendData = this._formatSendData('photo', photo, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.photo = sendData[1]; opts.qs.photo = sendData[1];
} catch (ex) { } catch (ex) {
@ -1674,16 +1703,17 @@ class TelegramBot extends EventEmitter {
* @param {String|stream.Stream|Buffer} pngSticker A file path or a Stream. Can also be a `file_id` previously uploaded. **Png** image with the * @param {String|stream.Stream|Buffer} pngSticker A file path or a Stream. Can also be a `file_id` previously uploaded. **Png** image with the
* sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. * sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px.
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#uploadstickerfile * @see https://core.telegram.org/bots/api#uploadstickerfile
*/ */
uploadStickerFile(userId, pngSticker, options = {}) { uploadStickerFile(userId, pngSticker, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options, qs: options,
}; };
opts.qs.user_id = userId; opts.qs.user_id = userId;
try { try {
const sendData = this._formatSendData('png_sticker', pngSticker); const sendData = this._formatSendData('png_sticker', pngSticker, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.png_sticker = sendData[1]; opts.qs.png_sticker = sendData[1];
} catch (ex) { } catch (ex) {
@ -1704,11 +1734,12 @@ class TelegramBot extends EventEmitter {
* dimensions must not exceed 512px, and either width or height must be exactly 512px. * dimensions must not exceed 512px, and either width or height must be exactly 512px.
* @param {String} emojis One or more emoji corresponding to the sticker * @param {String} emojis One or more emoji corresponding to the sticker
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#createnewstickerset * @see https://core.telegram.org/bots/api#createnewstickerset
* @todo Add tests for this method! * @todo Add tests for this method!
*/ */
createNewStickerSet(userId, name, title, pngSticker, emojis, options = {}) { createNewStickerSet(userId, name, title, pngSticker, emojis, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options, qs: options,
}; };
@ -1718,7 +1749,7 @@ class TelegramBot extends EventEmitter {
opts.qs.emojis = emojis; opts.qs.emojis = emojis;
opts.qs.mask_position = stringify(options.mask_position); opts.qs.mask_position = stringify(options.mask_position);
try { try {
const sendData = this._formatSendData('png_sticker', pngSticker); const sendData = this._formatSendData('png_sticker', pngSticker, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.png_sticker = sendData[1]; opts.qs.png_sticker = sendData[1];
} catch (ex) { } catch (ex) {
@ -1737,11 +1768,12 @@ class TelegramBot extends EventEmitter {
* dimensions must not exceed 512px, and either width or height must be exactly 512px * dimensions must not exceed 512px, and either width or height must be exactly 512px
* @param {String} emojis One or more emoji corresponding to the sticker * @param {String} emojis One or more emoji corresponding to the sticker
* @param {Object} [options] Additional Telegram query options * @param {Object} [options] Additional Telegram query options
* @param {Object} [fileOptions] Optional file related meta-data
* @return {Promise} * @return {Promise}
* @see https://core.telegram.org/bots/api#addstickertoset * @see https://core.telegram.org/bots/api#addstickertoset
* @todo Add tests for this method! * @todo Add tests for this method!
*/ */
addStickerToSet(userId, name, pngSticker, emojis, options = {}) { addStickerToSet(userId, name, pngSticker, emojis, options = {}, fileOptions = {}) {
const opts = { const opts = {
qs: options, qs: options,
}; };
@ -1750,7 +1782,7 @@ class TelegramBot extends EventEmitter {
opts.qs.emojis = emojis; opts.qs.emojis = emojis;
opts.qs.mask_position = stringify(options.mask_position); opts.qs.mask_position = stringify(options.mask_position);
try { try {
const sendData = this._formatSendData('png_sticker', pngSticker); const sendData = this._formatSendData('png_sticker', pngSticker, fileOptions);
opts.formData = sendData[0]; opts.formData = sendData[0];
opts.qs.png_sticker = sendData[1]; opts.qs.png_sticker = sendData[1];
} catch (ex) { } catch (ex) {

View File

@ -633,13 +633,6 @@ describe('TelegramBot', function telegramSuite() {
assert.ok(is.object(resp.document)); assert.ok(is.object(resp.document));
}); });
}); });
it('should send a document with custom file options', function test() {
const document = fs.createReadStream(`${__dirname}/data/photo.gif`);
const fileOpts = { filename: 'customfilename.gif' };
return bot.sendDocument(USERID, document, {}, fileOpts).then(resp => {
assert.equal(resp.document.file_name, fileOpts.filename);
});
});
}); });
describe('#sendSticker', function sendStickerSuite() { describe('#sendSticker', function sendStickerSuite() {
@ -1361,36 +1354,6 @@ describe('TelegramBot', function telegramSuite() {
}); });
}); });
describe('#_formatSendData', function _formatSendDataSuite() {
it('should handle buffer path from fs.readStream', function test() {
let photo;
try {
photo = fs.createReadStream(Buffer.from(`${__dirname}/data/photo.gif`));
} catch (ex) {
// Older Node.js versions do not support passing a Buffer
// representation of the path to fs.createReadStream()
if (ex instanceof TypeError) return Promise.resolve();
}
return bot.sendPhoto(USERID, photo).then(resp => {
assert.ok(is.object(resp));
assert.ok(is.array(resp.photo));
});
});
it('should not accept file-paths if disallowed with constructor option', function test() {
const tgbot = new TelegramBot(TOKEN, { filepath: false });
const photo = `${__dirname}/data/photo.gif`;
return tgbot.sendPhoto(USERID, photo).catch(err => {
// TODO: check for error in a better way
assert.ok(err.response.body.description.indexOf('Bad Request') !== -1);
});
});
it('should allow stream.path that can not be parsed', function test() {
const fileStream = fs.createReadStream(`${__dirname}/data/photo.gif`);
fileStream.path = '/?id=123'; // for example, 'http://example.com/?id=666'
return bot.sendPhoto(USERID, fileStream);
});
});
describe('#sendInvoice', function sendInvoiceSuite() { describe('#sendInvoice', function sendInvoiceSuite() {
before(function before() { before(function before() {
utils.handleRatelimit(bot, 'sendInvoice', this); utils.handleRatelimit(bot, 'sendInvoice', this);

View File

@ -0,0 +1,139 @@
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const TelegramBot = require('..');
const paths = {
audio: path.join(__dirname, 'data/audio.mp3'),
};
describe('#_formatSendData', function sendfileSuite() {
const bot = new TelegramBot('token');
const type = 'file';
before(function beforeSuite() {
process.env.NTBA_FIX_350 = 1;
});
after(function afterSuite() {
delete process.env.NTBA_FIX_350;
});
describe('using fileOptions', function sendfileOptionsSuite() {
const stream = fs.createReadStream(paths.audio);
const nonPathStream = fs.createReadStream(paths.audio);
const buffer = fs.readFileSync(paths.audio);
const nonDetectableBuffer = fs.readFileSync(__filename);
const filepath = paths.audio;
const files = [stream, nonPathStream, buffer, nonDetectableBuffer, filepath];
delete nonPathStream.path;
describe('filename', function filenameSuite() {
it('(1) fileOptions.filename', function test() {
const filename = 'custom-filename';
files.forEach((file) => {
const [{ [type]: data }] = bot._formatSendData(type, file, { filename });
assert.equal(data.options.filename, filename);
});
});
it('(2) Stream#path', function test() {
if (!stream.path) {
this.skip('Stream#path unsupported');
return;
}
const [{ [type]: data }] = bot._formatSendData(type, stream);
assert.equal(data.options.filename, path.basename(paths.audio));
});
it('(3) filepath', function test() {
const [{ [type]: data }] = bot._formatSendData(type, filepath);
assert.equal(data.options.filename, path.basename(paths.audio));
});
it('(4) final default', function test() {
[nonPathStream, buffer, nonDetectableBuffer].forEach((file) => {
const [{ [type]: data }] = bot._formatSendData(type, file);
assert.equal(data.options.filename, 'filename');
});
});
});
describe('contentType', function contentTypeSuite() {
it('(1) fileOpts.contentType', function test() {
const contentType = 'application/custom-type';
files.forEach((file) => {
const [{ [type]: data }] = bot._formatSendData(type, file, { contentType });
assert.equal(data.options.contentType, contentType);
});
});
it('(2) Stream#path', function test() {
if (!stream.path) {
this.skip('Stream#path unsupported');
return;
}
const [{ [type]: data }] = bot._formatSendData(type, stream);
assert.equal(data.options.contentType, 'audio/mpeg');
});
it('(3) Buffer file-type', function test() {
const [{ [type]: data }] = bot._formatSendData(type, buffer);
assert.equal(data.options.contentType, 'audio/mpeg');
});
it('(4) filepath', function test() {
const [{ [type]: data }] = bot._formatSendData(type, filepath);
assert.equal(data.options.contentType, 'audio/mpeg');
});
it('(5) fileOptions.filename', function test() {
[nonPathStream, nonDetectableBuffer].forEach((file) => {
const [{ [type]: data }] = bot._formatSendData(type, file, {
filename: 'image.gif',
});
assert.equal(data.options.contentType, 'image/gif');
});
});
it('(6) Final default', function test() {
[nonPathStream, nonDetectableBuffer].forEach((file) => {
const [{ [type]: data }] = bot._formatSendData(type, file);
assert.equal(data.options.contentType, 'application/octet-stream');
});
});
});
});
it('should handle buffer path from fs.readStream', function test() {
let file;
try {
file = fs.createReadStream(Buffer.from(paths.audio));
} catch (ex) {
// Older Node.js versions do not support passing a Buffer
// representation of the path to fs.createReadStream()
if (ex instanceof TypeError) {
Promise.resolve();
return;
}
}
const [{ [type]: data }] = bot._formatSendData('file', file);
assert.equal(data.options.filename, path.basename(paths.audio));
});
it('should not accept file-paths if disallowed with constructor option', function test() {
const tgbot = new TelegramBot('token', { filepath: false });
const [formData, fileId] = tgbot._formatSendData('file', paths.audio);
assert.ok(fileId);
assert.ok(!formData);
});
it('should allow stream.path that can not be parsed', function test() {
const stream = fs.createReadStream(paths.audio);
stream.path = '/?id=123'; // for example, 'http://example.com/?id=666'
assert.doesNotThrow(function assertDoesNotThrow() {
bot._formatSendData('file', stream);
});
});
});