Compare commits

..

72 Commits
v1 ... master

Author SHA1 Message Date
Alexander Cerutti b585957a0a doc: Add telegram-keyboard-wrapper to community section (#529) 8 years ago
Daniel Pérez Fernández 8b7d10e01b doc: Add link to tutorial [ES] (#545) 8 years ago
Gocho Mugo 1224613fec
doc: Add link to tutorial (#533) 8 years ago
Gocho Mugo 0461c0bfe3
doc: Add missing full stop (#515) 8 years ago
Neetshin 71fbad31d9 Update tutorial articles link 8 years ago
Benny Neugebauer 091ef7a8a7
doc: Add missing full stop 8 years ago
Oleksandr Tryshchenko 435f06319e doc: Fixed type annotations for message id parameter (#491) 8 years ago
GochoMugo 119d892c34
release: v0.30.0 8 years ago
GochoMugo 1169f8e430
chore: Use npm script prepublishOnly instead of deprecated prepublish 8 years ago
GochoMugo 5cecffc34b
chore/deps: Downgrade eslint for Node v4 compatibility 8 years ago
GochoMugo 7e9e9b11b3
test: Fix previously-uncaught lint errors 8 years ago
GochoMugo 2bdd50fdc2
chore/deps: Update dependencies 8 years ago
GochoMugo 309696622d
doc: Showcase and update contributor list 8 years ago
GochoMugo 1f4c79ec8e
chore: Ignore package lock file 8 years ago
GochoMugo 8edf1fbc6d
doc: Update changelog 8 years ago
GochoMugo 55332c3c25
doc: Update changelog, version badge 8 years ago
GochoMugo 96c50ba1bd
doc: Improve deprecation messages 8 years ago
GochoMugo 4358f20dbb
doc: Minor fixes on documentation 8 years ago
GochoMugo 0781ae685d
src/telegram: Add TelegramBot#sendMediaGroup() 8 years ago
Oleg 584610baaf doc: Add tutorial [RUS] (#477) 8 years ago
GochoMugo 1a08221174
src/telegram: Improve sending files (#471) 8 years ago
GochoMugo d7197998dd
doc: Add note on specifying additional Telegram query options 8 years ago
GochoMugo 4051117ed0
src: Minor reorganisation, fixes 8 years ago
GochoMugo f28416fbaf
src/telegram: Implement downloadFile() in terms of getFileStream() 8 years ago
GochoMugo 04e8b892aa
src/telegram: Emit 'info' on stream from TelegramBot#getFileStream() 8 years ago
GochoMugo b968e893d3
src/telegram: Populate Stream#path from TelegramBot#getFileStream() 8 years ago
GochoMugo b91409a2b6
test: Fix path to ssl key, cert 8 years ago
GochoMugo 455a93cacb
examples: Add notice of openshift 2 shutdown 8 years ago
GochoMugo 17f839498e
chore: Re-organise examples 8 years ago
GochoMugo d9692f45a9
src/telegram: Add TelegramBot#getFileStream() 8 years ago
Gocho Mugo 0870684d83
src/polling: Fix the Offset Infinite Loop bug (#265) 8 years ago
GochoMugo 8edb687283
src: Add fileOptions to remaining file-sending methods 8 years ago
GochoMugo 3b603b1dbd
src: Minor fix, complete TODO 8 years ago
GochoMugo b774ff436f src: Minor fixes 8 years ago
GochoMugo d6083e4327 src: Support file options, defaults in sending files 8 years ago
GochoMugo fb1f4344b3
test: Disable tests on Node.js v0.12 8 years ago
GochoMugo b1f0ebaf17
src/polling: Add options to TelegramBot#stopPolling() 8 years ago
GochoMugo ce9ff57a63
src/telegram: Don't JSON-serialize parameter if already of String type 8 years ago
GochoMugo 012e7df35f
src: Support API v3.5 `provider_data` parameter 8 years ago
GochoMugo 57dec19bab
src: Support future additional Telegram parameters 8 years ago
GochoMugo fce9244dfd
doc: Update help information 8 years ago
GochoMugo 0008a39227 pr: Merge edited PR (#440) 8 years ago
GochoMugo 183b6bdb28
doc: Generate API reference, Update changelog 8 years ago
GochoMugo 816511b19f pr: Merge kamikazechaser/node-telegram-bot-api#feature/stickersets 8 years ago
GochoMugo cfde217488
test: Fix lint error 8 years ago
GochoMugo 13472899e4 pr: Merge edited PR (#439) 8 years ago
GochoMugo 59378d381b
test: Add tests 8 years ago
GochoMugo 79118b9fae
doc: Minor fixes, Update changelog 8 years ago
GochoMugo 65384a11d4
pr: Merge kamikazechaser/node-telegram-bot-api#feature/livelocations 8 years ago
GochoMugo 1f61b82aa8
doc: Fix documented types for params `chatId`, `userId` 8 years ago
GochoMugo 633bd83a0a
src/telegram: JSON-serialize 'mask_position's 8 years ago
drGOD 4586ebd10b src/telegram: JSON-serialize shipping_options in answerShippingQuery (#468) 8 years ago
Yago fd337e91f2
Merge pull request #463 from saeedhei/patch-1 8 years ago
Yago 20c5ab6710
Merge branch 'master' into patch-1 8 years ago
Yago 5510c07876
Merge branch 'master' into patch-1 8 years ago
Yago 3fbc6c85b0
Merge pull request #462 from Archakov06/patch-2 8 years ago
Sedric Heidarizarei 757ba2476a
Persian Language added 8 years ago
Archakov Dennis 16045fda6e
Add tutorial link RUS 8 years ago
GochoMugo ba4d207684
src: Improve performance when matching message types 8 years ago
GochoMugo 772609c334
doc: Update ParseError message; error might not be from Telegram 8 years ago
GochoMugo ea420edad9
doc/help: Add link to bug '502 Bad Gateway' 8 years ago
GochoMugo 8c965d3a14
src: Improve default error logging of `polling_error`, `webhook_error` 8 years ago
MCSH 6263dcb007
examples: Fix game to answer callback query correctly 8 years ago
Aaron Meese e03ffe5d04 doc: Update README.md (#457) 8 years ago
GochoMugo dc897d95e5
chore: Update npm script `gen-doc` to `doc` 8 years ago
GochoMugo bbac07ad2c
doc: Document TelegramBot.errors, TelegramBot.messageTypes 8 years ago
GochoMugo 49df0c6e02
src/telegram: Add metadata argument in `message` event (and friends) 8 years ago
GochoMugo 3722c7182c
src/telegram: Fix TelegramBot#answerCallbackQuery() signature 8 years ago
Mohammed Sohail 4d90529492
[API v3.4] Support sticker sets 8 years ago
Mohammed Sohail b25bc6eddb
[Doc] Generate documentation 8 years ago
Mohammed Sohail 7315fcff3e
[Fix] Minor copypasta typo 8 years ago
Mohammed Sohail 962ce2af3c
[API v3.4] Support live locations 8 years ago
  1. 2
      .github/PULL_REQUEST_TEMPLATE.md
  2. 1
      .gitignore
  3. 3
      .travis.yml
  4. 43
      CHANGELOG.md
  5. 4
      CONTRIBUTING.md
  6. 18
      README.md
  7. 1
      doc/api.hbs
  8. 647
      doc/api.md
  9. 24
      doc/help.md
  10. 5
      doc/tutorials.md
  11. 64
      doc/usage.md
  12. 2
      examples/game/game.js
  13. 0
      examples/ssl/crt.pem
  14. 0
      examples/ssl/key.pem
  15. 2
      examples/webhook/express.js
  16. 2
      examples/webhook/heroku.js
  17. 6
      examples/webhook/https.js
  18. 2
      examples/webhook/now.js
  19. 14
      examples/webhook/openshift2.js
  20. 14
      index.js
  21. 437
      package.json
  22. 6
      src/errors.js
  23. 570
      src/telegram.js
  24. 66
      src/telegramPolling.js
  25. 2
      src/telegramWebHook.js
  26. 149
      test/telegram.js
  27. 139
      test/test.format-send-data.js
  28. 12
      test/utils.js

@ -5,7 +5,7 @@ For example, if your PR passes all tests, you would mark the option as so:
Note the 'x' in between the square brackets '[]'
-->
- [ ] All tests pass
- [ ] I have run `npm run gen-doc`
- [ ] I have run `npm run doc`
### Description

1
.gitignore vendored

@ -2,6 +2,7 @@ node_modules
coverage/
npm-debug.log
.package.json
package-lock.json
output.md
output/
lib/

@ -4,6 +4,9 @@ node_js:
- "8"
- "7"
- "6"
- "5"
- "4"
# - "0.12"
after_success:
- bash <(curl -s https://codecov.io/bash)
cache:

@ -5,13 +5,45 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased][Unreleased]
* * *
## [0.30.0][0.30.0] - 2017-12-21
Added:
* Add support for Node.js v9
1. Support Bot API v3.5: (by @GochoMugo)
* Allow `provider_data` parameter in *TelegramBot#sendInvoice*
* Add method *TelegramBot#sendMediaGroup()*
1. Support Bot API v3.4: (by @kamikazechaser)
* Add methods *TelegramBot#editMessageLiveLocation*, *TelegramBot#stopMessageLiveLocation* (#439)
* Add methods *TelegramBot#setChatStickerSet*, *TelegramBot#deleteChatStickerSet* (#440)
1. Add methods:
* *TelegramBot#getFileStream* (#442) (by @GochoMugo, requested-by @Xaqron)
1. Add options to *TelegramBot#stopPolling()* (by @GochoMugo)
1. Add `metadata` argument in `message` event (and friends e.g. `text`, `audio`, etc.) (#409) (by @jlsjonas, @GochoMugo)
1. Add forward-compatibility i.e. support future additional Telegram options (by @GochoMugo)
1. Add support for Node.js v9 (by @GochoMugo)
1. Document *TelegramBot.errors*, *TelegramBot.messageTypes* (by @GochoMugo)
Changed:
1. Update *TelegramBot#answerCallbackQuery()* signature (by @GochoMugo)
1. Improve default error logging of `polling_error` and `webhook_error` (#377)
1. Update dependencies
Removed:
Deprecated:
* Drop support for Node.js v0.12, v4, v5
1. Sending files: *(See [usage guide][usage-sending-files])* (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:
1. Fix the offset infinite loop bug (#265, #36) (by @GochoMugo)
1. Fix game example (#449, #418) (by @MCSH)
* * *
@ -169,10 +201,13 @@ Fixed:
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.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.1]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.27.1
[0.28.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.28.0
[0.29.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.29.0
[Unreleased]:https://github.com/yagop/node-telegram-bot-api/compare/v0.29.0...master
[0.30.0]:https://github.com/yagop/node-telegram-bot-api/releases/tag/v0.30.0
[Unreleased]:https://github.com/yagop/node-telegram-bot-api/compare/v0.30.0...master

@ -24,13 +24,15 @@ Before proceeding any further, read the following documents:
Run:
```bash
$ npm run gen-doc
$ npm run doc
```
### Running tests
Please read `test/README.md` for more information.
### Transpiling ES2015 for older Node.js versions
We use babel to transpile the code:

@ -1,6 +1,6 @@
# Node.js Telegram Bot API
[![Bot API](https://img.shields.io/badge/Bot%20API-v.3.3.0-00aced.svg)](https://core.telegram.org/bots/api)
[![Bot API](https://img.shields.io/badge/Bot%20API-v.3.5.0-00aced.svg)](https://core.telegram.org/bots/api)
[![Build Status](https://travis-ci.org/yagop/node-telegram-bot-api.svg?branch=master)](https://travis-ci.org/yagop/node-telegram-bot-api)
[![Build status](https://ci.appveyor.com/api/projects/status/ujko6bsum3g5msjh/branch/master?svg=true)](https://ci.appveyor.com/project/yagop/node-telegram-bot-api/branch/master)
[![Coverage Status](https://coveralls.io/repos/yagop/node-telegram-bot-api/badge.svg?branch=master)](https://coveralls.io/r/yagop/node-telegram-bot-api?branch=master)
@ -8,7 +8,7 @@
[![https://telegram.me/node_telegram_bot_api](https://img.shields.io/badge/💬%20Telegram-node__telegram__bot__api-blue.svg)](https://telegram.me/node_telegram_bot_api)
[![https://telegram.me/Yago_Perez](https://img.shields.io/badge/💬%20Telegram-Yago__Perez-blue.svg)](https://telegram.me/Yago_Perez)
Node.js module to interact with official [Telegram Bot API](https://core.telegram.org/bots/api). A bot token is needed, to obtain one, talk to [@botfather](https://telegram.me/BotFather) and create a new bot.
Node.js module to interact with official [Telegram Bot API](https://core.telegram.org/bots/api). A bot token is **required** and can be obtained by talking to [@botfather](https://telegram.me/BotFather).
## Install
@ -61,28 +61,33 @@ bot.on('message', (msg) => {
* [Experimental Features][experimental]
_**Note**: Development is done against the **master** branch.
Code for the latest release resides on the **release** branch
Code for the latest release resides on the **release** branch.
Experimental features reside on the **experimental** branch._
## Community
We thank all the developers in the Open-Source community who continuously
take their time and effort in advancing this project.
See our [list of contributors][contributors].
We have a [Telegram channel][tg-channel] where we post updates on
the Project. Head over and subscribe!
Some things built using this library, and might interest you:
Some things built using this library that might interest you:
* [tgfancy](https://github.com/GochoMugo/tgfancy): A Fancy, Higher-Level Wrapper for Telegram Bot API
* [tgfancy](https://github.com/GochoMugo/tgfancy): A fancy, higher-level wrapper for Telegram Bot API
* [node-telegram-bot-api-middleware](https://github.com/idchlife/node-telegram-bot-api-middleware): Middleware for node-telegram-bot-api
* [teleirc](https://github.com/FruitieX/teleirc): A simple Telegram ↔ IRC gateway
* [bot-brother](https://github.com/SerjoPepper/bot-brother): Node.js library to help you easily create telegram bots
* [redbot](https://github.com/guidone/node-red-contrib-chatbot): A Node-RED plugin to create telegram bots visually
* [node-telegram-keyboard-wrapper](https://github.com/alexandercerutti/node-telegram-keyboard-wrapper): A wrapper to improve `reply_markup` structures creation in an easy way (supports Inline Keyboards, Reply Keyboard, Remove Keyboard and Force Reply)
## License
**The MIT License (MIT)**
Copyright (c) 2017 Yago
Copyright © 2017 Yago
[usage]:https://github.com/yagop/node-telegram-bot-api/tree/master/doc/usage.md
[examples]:https://github.com/yagop/node-telegram-bot-api/tree/master/examples
@ -92,5 +97,6 @@ Copyright (c) 2017 Yago
[api-release]:https://github.com/yagop/node-telegram-bot-api/tree/release/doc/api.md
[api-experimental]:https://github.com/yagop/node-telegram-bot-api/tree/experimental/doc/api.md
[contributing]:https://github.com/yagop/node-telegram-bot-api/tree/master/CONTRIBUTING.md
[contributors]:https://github.com/yagop/node-telegram-bot-api/graphs/contributors
[experimental]:https://github.com/yagop/node-telegram-bot-api/tree/master/doc/experimental.md
[tg-channel]:https://telegram.me/node_telegram_bot_api

@ -16,3 +16,4 @@
[getUpdates-v0.25.0]:https://github.com/yagop/node-telegram-bot-api/tree/4e5a493cadfaad5589a8d79e55d9e0d103000ce4#TelegramBot+getUpdates
[getUserProfilePhotos-v0.25.0]:https://github.com/yagop/node-telegram-bot-api/tree/4e5a493cadfaad5589a8d79e55d9e0d103000ce4#TelegramBot+getUserProfilePhotos
[answerCallbackQuery-v0.27.1]:https://github.com/yagop/node-telegram-bot-api/blob/v0.27.1/doc/api.md#TelegramBot+answerCallbackQuery
[answerCallbackQuery-v0.29.0]:https://github.com/yagop/node-telegram-bot-api/blob/v0.29.0/doc/api.md#TelegramBot+answerCallbackQuery

File diff suppressed because it is too large Load Diff

@ -29,6 +29,8 @@ Sources:
1. [How do I run my bot behind a proxy?](#proxy)
1. [Can you add feature X to the library?](#new-feature)
1. [Is this scalable?](#scalable)
1. [How do I listen for messages in a chat group?](#messages-in-chat)
1. [How do I know when a user blocks the bot?](#blocked-bot)
<a name="gifs"></a>
### How do I send GIFs?
@ -67,7 +69,9 @@ Sources:
<a name="error-meanings"></a>
### What does this error mean?
*Not done. PRs welcome!*
* [502 Bad Gateway](https://github.com/yagop/node-telegram-bot-api/issues/377)
*Not complete. PRs welcome!*
Sources:
@ -125,4 +129,22 @@ Sources:
* Issue [#219](https://github.com/yagop/node-telegram-bot-api/issues/219)
<a name="messages-in-chat"></a>
### How do I listen for messages in a chat group?
*Not done. PRs welcome!*
Sources:
* Issue [#304](https://github.com/yagop/node-telegram-bot-api/issues/304)
<a name="blocked-bot"></a>
### How do I know when a user blocks the bot?
*Not done. PRs welcome!*
Sources:
* Issue [#273](https://github.com/yagop/node-telegram-bot-api/issues/273)
[questions]:https://github.com/yagop/node-telegram-bot-api/issues?utf8=%E2%9C%93&q=is%3Aissue%20label%3Aquestion%20

@ -1,5 +1,10 @@
# Tutorials
* [node-telegram-bot-api-tutorial by @hosein2398](https://github.com/hosein2398/node-telegram-bot-api-tutorial)
* [node-telegram-bot-api-persian-language by @saeedhei](https://github.com/saeedhei/node-telegram-bot-api-persian-language)
* [Node.JS: Делаем своего Telegram бота [RUS]](https://archakov.im/post/telegram-bot-on-nodejs.html)
* [YouTube: Пишем Telegram бота на NodeJS [RUS]](https://www.youtube.com/watch?v=RS1nmDMf69U&list=PL6AOr-PZtK-mM2QC1ixyfa5CtJZGK61aN)
* [Node.jsでTelegramのチャットボットを作る - Qiita](https://qiita.com/neetshin/items/0e2f6fa3ade41adb77bc)
* [Guía: Creación de bots de Telegram en Nodejs [ES]](https://tecnonucleous.com/creacion-de-bots-de-telegram-en-nodejs/)
> Send a PR with useful links **not** listed above

@ -8,17 +8,19 @@
<a name="events"></a>
## Events
*TelegramBot* is an event-emitter that emits the following events:
*TelegramBot* is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
that emits the following events:
1. `message`: Received a new incoming [Message][message] of any kind
1. Depending on the properties of the [Message][message], one of these
events will **ALSO** be emitted: `text`, `audio`, `document`, `photo`,
events may **ALSO** be emitted: `text`, `audio`, `document`, `photo`,
`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`, `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 }`)
1. `new_chat_participant`, `left_chat_participant` are **deprecated**
1. `callback_query`: Received a new incoming [Callback Query][callback-query]
1. `inline_query`: Received a new incoming [Inline Query][inline-query]
@ -34,6 +36,7 @@
1. `pre_checkout_query`: Received a new incoming pre-checkout query
1. `polling_error`: Error occurred during polling. See [polling errors](#polling-errors).
1. `webhook_error`: Error occurred handling a webhook request. See [webhook errors](#webhook-errors).
1. `error`: Unexpected error occurred, usually fatal!
**Tip:** Its much better to listen a specific event rather than on
`message` in order to stay safe from the content.
@ -113,6 +116,63 @@ const url = 'https://telegram.org/img/t_logo.png';
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>
### Performance Issue

@ -39,7 +39,7 @@ bot.onText(/\/start/, function onPhotoText(msg) {
// Handle callback queries
bot.on('callback_query', function onCallbackQuery(callbackQuery) {
bot.answerCallbackQuery(callbackQuery.id, url, true, { url });
bot.answerCallbackQuery(callbackQuery.id, { url });
});
// Render the HTML game

@ -8,7 +8,7 @@ const TOKEN = process.env.TELEGRAM_TOKEN || 'YOUR_TELEGRAM_BOT_TOKEN';
const url = 'https://<PUBLIC-URL>';
const port = process.env.PORT;
const TelegramBot = require('..');
const TelegramBot = require('../..');
const express = require('express');
const bodyParser = require('body-parser');

@ -5,7 +5,7 @@
const TOKEN = process.env.TELEGRAM_TOKEN || 'YOUR_TELEGRAM_BOT_TOKEN';
const TelegramBot = require('..');
const TelegramBot = require('../..');
const options = {
webHook: {
// Port to which you should bind is assigned to $PORT variable

@ -5,12 +5,12 @@
const TOKEN = process.env.TELEGRAM_TOKEN || 'YOUR_TELEGRAM_BOT_TOKEN';
const TelegramBot = require('..');
const TelegramBot = require('../..');
const options = {
webHook: {
port: 443,
key: `${__dirname}/key.pem`, // Path to file with PEM private key
cert: `${__dirname}/crt.pem` // Path to file with PEM certificate
key: `${__dirname}/../ssl/key.pem`, // Path to file with PEM private key
cert: `${__dirname}/../ssl/crt.pem` // Path to file with PEM certificate
}
};
// This URL must route to the port set above (i.e. 443)

@ -6,7 +6,7 @@
const TOKEN = process.env.TELEGRAM_TOKEN || 'YOUR_TELEGRAM_BOT_TOKEN';
const TelegramBot = require('..');
const TelegramBot = require('../..');
const options = {
webHook: {
// Just use 443 directly

@ -1,11 +1,23 @@
/**
* This example demonstrates setting up webhook
* on the OpenShift platform.
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* NOTE:
*
* Openshift 2 has been shut down.
*
* This example is kept here for historical/educational purposes.
* No changes are expected to be made to the source code below.
*
* See https://github.com/yagop/node-telegram-bot-api/issues/426 for
* more information.
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
const TOKEN = process.env.TELEGRAM_TOKEN || 'YOUR_TELEGRAM_BOT_TOKEN';
const TelegramBot = require('..');
const TelegramBot = require('../..');
// See https://developers.openshift.com/en/node-js-environment-variables.html
const options = {
webHook: {

@ -1 +1,13 @@
module.exports = require('./src/telegram');
/**
* If running on Nodejs 5.x and below, we load the transpiled code.
* Otherwise, we use the ES6 code.
* We are deprecating support for Node.js v5.x and below.
*/
const majorVersion = parseInt(process.versions.node.split('.')[0], 10);
if (majorVersion <= 5) {
const deprecate = require('depd')('node-telegram-bot-api');
deprecate('Node.js v5.x and below will no longer be supported in the future');
module.exports = require('./lib/telegram');
} else {
module.exports = require('./src/telegram');
}

@ -1,6 +1,6 @@
{
"name": "node-telegram-bot-api",
"version": "0.29.0",
"version": "0.30.0",
"description": "Telegram Bot API",
"main": "./index.js",
"directories": {
@ -14,9 +14,10 @@
"bot"
],
"scripts": {
"gen-doc": "jsdoc2md --files src/telegram.js --template doc/api.hbs > doc/api.md",
"gen-doc": "echo 'WARNING: `npm run gen-doc` is deprecated. Use `npm run doc` instead.' && npm run doc",
"doc": "jsdoc2md --files src/telegram.js --template doc/api.hbs > doc/api.md",
"build": "babel -d ./lib src",
"prepublish": "npm run build && npm run gen-doc",
"prepublishOnly": "npm run build && npm run gen-doc",
"eslint": "eslint ./src ./test ./examples",
"mocha": "mocha",
"pretest": "npm run build",
@ -25,44 +26,45 @@
"author": "Yago Pérez <yagoperezs@gmail.com>",
"license": "MIT",
"engines": {
"node": ">=6"
"node": ">=0.12"
},
"dependencies": {
"array.prototype.findindex": "^2.0.0",
"bl": "^1.1.2",
"bluebird": "^3.3.4",
"debug": "^2.2.0",
"depd": "^1.1.0",
"eventemitter3": "^2.0.2",
"array.prototype.findindex": "^2.0.2",
"bl": "^1.2.1",
"bluebird": "^3.5.1",
"debug": "^3.1.0",
"depd": "^1.1.1",
"eventemitter3": "^3.0.0",
"file-type": "^3.9.0",
"mime": "^1.3.4",
"pump": "^1.0.1",
"request": "^2.69.0",
"request-promise": "^4.1.1"
"mime": "^1.6.0",
"pump": "^2.0.0",
"request": "^2.83.0",
"request-promise": "^4.2.2"
},
"devDependencies": {
"babel-cli": "^6.6.5",
"babel-eslint": "^6.1.2",
"babel-plugin-transform-class-properties": "^6.6.0",
"babel-plugin-transform-es2015-destructuring": "^6.6.5",
"babel-plugin-transform-es2015-parameters": "^6.7.0",
"babel-plugin-transform-es2015-shorthand-properties": "^6.5.0",
"babel-plugin-transform-es2015-spread": "^6.6.5",
"babel-plugin-transform-object-rest-spread": "^6.6.5",
"babel-plugin-transform-strict-mode": "^6.6.5",
"babel-preset-es2015": "^6.6.0",
"babel-register": "^6.7.2",
"babel-cli": "^6.26.0",
"babel-eslint": "^8.0.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-es2015-destructuring": "^6.23.0",
"babel-plugin-transform-es2015-parameters": "^6.24.1",
"babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
"babel-plugin-transform-es2015-spread": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-strict-mode": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"babel-register": "^6.26.0",
"concat-stream": "^1.6.0",
"contributor": "^0.1.25",
"eslint": "^2.13.1",
"eslint-config-airbnb": "^6.2.0",
"eslint-plugin-mocha": "^4.8.0",
"is": "^3.1.0",
"eslint-plugin-mocha": "^4.11.0",
"is": "^3.2.1",
"is-ci": "^1.0.10",
"istanbul": "^1.1.0-alpha.1",
"jsdoc-to-markdown": "^2.0.1",
"mocha": "^3.2.0",
"mocha-lcov-reporter": "^1.2.0",
"node-static": "^0.7.9"
"jsdoc-to-markdown": "^3.0.3",
"mocha": "^3.5.3",
"mocha-lcov-reporter": "^1.3.0",
"node-static": "^0.7.10"
},
"repository": {
"type": "git",
@ -74,59 +76,158 @@
"homepage": "https://github.com/yagop/node-telegram-bot-api",
"contributors": [
{
"name": "Anton Mironov",
"email": "ant.mironov@gmail.com",
"url": "https://github.com/mironov",
"name": "Oleg",
"email": null,
"url": "https://github.com/olegmdev",
"contributions": 1,
"additions": 51,
"deletions": 15,
"additions": 1,
"deletions": 0,
"hireable": true
},
{
"name": "Daniil Yastremskiy",
"email": "Catharsis@post.cz",
"url": "https://github.com/TheBeastOfCaerbannog",
"name": "Archakov Dennis",
"email": null,
"url": "https://github.com/Archakov06",
"contributions": 1,
"additions": 36,
"additions": 1,
"deletions": 0,
"hireable": true
},
{
"name": null,
"name": "drGOD",
"email": null,
"url": "https://github.com/Ni2c2k",
"url": "https://github.com/drGOD",
"contributions": 1,
"additions": 1,
"deletions": 0,
"hireable": null
},
{
"name": "MCSH",
"email": null,
"url": "https://github.com/MCSH",
"contributions": 1,
"additions": 2,
"deletions": 1,
"hireable": true
},
{
"name": "Aaron Meese",
"email": null,
"url": "https://github.com/ajmeese7",
"contributions": 1,
"additions": 4,
"deletions": 4,
"hireable": true
},
{
"name": "Misha",
"email": null,
"url": "https://github.com/mnb3000",
"contributions": 1,
"additions": 24,
"deletions": 12,
"hireable": null
},
{
"name": "Alexander Tarmolov",
"email": "tarmolov@gmail.com",
"url": "https://github.com/tarmolov",
"name": "Savely Krasovsky",
"email": null,
"url": "https://github.com/L11R",
"contributions": 1,
"additions": 5,
"deletions": 0,
"additions": 297,
"deletions": 1,
"hireable": null
},
{
"name": "Plusb Preco",
"email": "plusb21@gmail.com",
"url": "https://github.com/preco21",
"name": "Victor Le",
"email": null,
"url": "https://github.com/Coac",
"contributions": 1,
"additions": 1,
"deletions": 0,
"deletions": 1,
"hireable": null
},
{
"name": "Ola Flisbäck",
"name": null,
"email": null,
"url": "https://github.com/oflisback",
"url": "https://github.com/kucherenkovova",
"contributions": 1,
"additions": 1,
"deletions": 1,
"hireable": null
},
{
"name": "Guidone",
"email": null,
"url": "https://github.com/guidone",
"contributions": 1,
"additions": 1,
"deletions": 0,
"hireable": true
},
{
"name": "Jaakko Lipsanen",
"email": null,
"url": "https://github.com/JaakkoLipsanen",
"contributions": 1,
"additions": 3,
"deletions": 3,
"hireable": null
},
{
"name": "Fabio Zuber",
"email": null,
"url": "https://github.com/Sirius-A",
"contributions": 1,
"additions": 12,
"deletions": 0,
"hireable": null
},
{
"name": "Evgeny Bondarenko",
"email": null,
"url": "https://github.com/jehy",
"contributions": 1,
"additions": 8,
"deletions": 8,
"hireable": true
},
{
"name": "Anton Mironov",
"email": null,
"url": "https://github.com/mironov",
"contributions": 1,
"additions": 51,
"deletions": 15,
"hireable": null
},
{
"name": "Daniil Yastremskiy",
"email": null,
"url": "https://github.com/TheBeastOfCaerbannog",
"contributions": 1,
"additions": 36,
"deletions": 0,
"hireable": true
},
{
"name": "Nikolay Ershov",
"email": null,
"url": "https://github.com/Ni2c2k",
"contributions": 1,
"additions": 4,
"deletions": 4,
"hireable": null
},
{
"name": "Alexander Tarmolov",
"email": null,
"url": "https://github.com/tarmolov",
"contributions": 1,
"additions": 5,
"deletions": 0,
"hireable": null
},
{
"name": null,
"email": null,
@ -136,9 +237,18 @@
"deletions": 2,
"hireable": null
},
{
"name": "Mikhail Burshteyn",
"email": null,
"url": "https://github.com/m-burst",
"contributions": 1,
"additions": 12,
"deletions": 5,
"hireable": null
},
{
"name": "Sergey Bogdanov",
"email": "sergey.bogdanov@gmail.com",
"email": null,
"url": "https://github.com/desunit",
"contributions": 1,
"additions": 1,
@ -146,17 +256,17 @@
"hireable": null
},
{
"name": "Mikhail Burshteyn",
"name": "Ola Flisbäck",
"email": null,
"url": "https://github.com/m-burst",
"url": "https://github.com/oflisback",
"contributions": 1,
"additions": 12,
"deletions": 5,
"hireable": null
"additions": 3,
"deletions": 3,
"hireable": true
},
{
"name": "Horus Lugo",
"email": "horusgoul@gmail.com",
"email": null,
"url": "https://github.com/HorusGoul",
"contributions": 1,
"additions": 108,
@ -164,26 +274,26 @@
"hireable": true
},
{
"name": "Serhii Dmytruk",
"email": "dmitruksergey@gmail.com",
"url": "https://github.com/serhiidmytruk",
"name": "Conor Fennell",
"email": null,
"url": "https://github.com/conorfennell",
"contributions": 1,
"additions": 35,
"additions": 50,
"deletions": 1,
"hireable": null
},
{
"name": "Conor Fennell",
"name": "Serhii Dmytruk",
"email": null,
"url": "https://github.com/conorfennell",
"url": "https://github.com/imserhii",
"contributions": 1,
"additions": 50,
"additions": 35,
"deletions": 1,
"hireable": null
},
{
"name": "Aleksandr L.",
"email": "w.siteee@gmail.com",
"email": null,
"url": "https://github.com/w-site",
"contributions": 1,
"additions": 24,
@ -192,13 +302,22 @@
},
{
"name": "Matthew Brandly",
"email": "matt@brandly.me",
"email": null,
"url": "https://github.com/brandly",
"contributions": 1,
"additions": 1,
"deletions": 1,
"hireable": null
},
{
"name": "Patricio López Juri",
"email": null,
"url": "https://github.com/mrpatiwi",
"contributions": 1,
"additions": 49,
"deletions": 2,
"hireable": true
},
{
"name": "Anton",
"email": null,
@ -206,20 +325,11 @@
"contributions": 1,
"additions": 23,
"deletions": 5,
"hireable": null
},
{
"name": "Patricio López Juri",
"email": "patricio@lopezjuri.com",
"url": "https://github.com/mrpatiwi",
"contributions": 1,
"additions": 49,
"deletions": 2,
"hireable": true
},
{
"name": "Guido García",
"email": "palmerabollo@gmail.com",
"email": null,
"url": "https://github.com/palmerabollo",
"contributions": 1,
"additions": 1,
@ -228,7 +338,7 @@
},
{
"name": "Sebastian Troć",
"email": "sebastian.troc@gucman.pl",
"email": null,
"url": "https://github.com/SebastianTroc",
"contributions": 1,
"additions": 1,
@ -236,17 +346,26 @@
"hireable": null
},
{
"name": "Mohammed Sohail",
"email": "sohail@forfuture.tech",
"url": "https://github.com/kamikazechaser",
"name": "CapacitorSet",
"email": null,
"url": "https://github.com/CapacitorSet",
"contributions": 2,
"additions": 20,
"deletions": 5,
"additions": 110,
"deletions": 2,
"hireable": true
},
{
"name": "Plusb Preco",
"email": null,
"url": "https://github.com/preco21",
"contributions": 2,
"additions": 111,
"deletions": 200,
"hireable": null
},
{
"name": "Jishnu Mohan",
"email": "jishnu7@gmail.com",
"email": null,
"url": "https://github.com/jishnu7",
"contributions": 2,
"additions": 84,
@ -254,17 +373,17 @@
"hireable": true
},
{
"name": "Jérémy Gotteland",
"name": "TJ Horner",
"email": null,
"url": "https://github.com/Tketa",
"url": "https://github.com/tjhorner",
"contributions": 2,
"additions": 81,
"deletions": 3,
"additions": 223,
"deletions": 1,
"hireable": null
},
{
"name": "Alex Godko",
"email": "koloboid@gmail.com",
"email": null,
"url": "https://github.com/koloboid",
"contributions": 2,
"additions": 2,
@ -273,7 +392,7 @@
},
{
"name": "Dardan Neziri",
"email": "dard.ne@gmail.com",
"email": null,
"url": "https://github.com/knock-in",
"contributions": 2,
"additions": 22,
@ -281,26 +400,26 @@
"hireable": true
},
{
"name": "Cristian Baldi",
"email": "bld.cris.96@gmail.com",
"url": "https://github.com/crisbal",
"name": "Jérémy Gotteland",
"email": null,
"url": "https://github.com/Tketa",
"contributions": 2,
"additions": 26,
"deletions": 1,
"hireable": true
"additions": 81,
"deletions": 3,
"hireable": null
},
{
"name": "Vitaly Aminev",
"name": "Iiro Jäppinen",
"email": null,
"url": "https://github.com/AVVS",
"url": "https://github.com/iiroj",
"contributions": 2,
"additions": 1065,
"deletions": 1001,
"hireable": true
"additions": 40,
"deletions": 0,
"hireable": null
},
{
"name": null,
"email": "plo.cav@gmail.com",
"email": null,
"url": "https://github.com/evolun",
"contributions": 2,
"additions": 7,
@ -308,40 +427,31 @@
"hireable": null
},
{
"name": "Iiro Jäppinen",
"name": "Vitaly Aminev",
"email": null,
"url": "https://github.com/iiroj",
"url": "https://github.com/AVVS",
"contributions": 2,
"additions": 40,
"deletions": 0,
"hireable": null
"additions": 1065,
"deletions": 1001,
"hireable": true
},
{
"name": "TJ Horner",
"email": "me@tjhorner.com",
"url": "https://github.com/tjhorner",
"name": "Cristian Baldi",
"email": null,
"url": "https://github.com/crisbal",
"contributions": 2,
"additions": 223,
"additions": 26,
"deletions": 1,
"hireable": null
},
{
"name": "Rafael Kr",
"email": null,
"url": "https://github.com/RafaelKr",
"contributions": 3,
"additions": 3,
"deletions": 2,
"hireable": null
"hireable": true
},
{
"name": "Vítor Augusto da Silva Vasconcellos",
"email": "vasvas10@gmail.com",
"email": null,
"url": "https://github.com/HeavenVolkoff",
"contributions": 2,
"additions": 12,
"deletions": 0,
"hireable": true
"hireable": null
},
{
"name": "Rey",
@ -354,7 +464,7 @@
},
{
"name": "Ivan Skorokhodov",
"email": "iskorokhodov@gmail.com",
"email": null,
"url": "https://github.com/universome",
"contributions": 3,
"additions": 219,
@ -362,17 +472,17 @@
"hireable": null
},
{
"name": "Riddler",
"name": "Rafael Kr",
"email": null,
"url": "https://github.com/Waterloo",
"url": "https://github.com/RafaelKr",
"contributions": 3,
"additions": 64,
"additions": 3,
"deletions": 2,
"hireable": true
"hireable": null
},
{
"name": null,
"email": "exlmotodev@gmail.com",
"email": null,
"url": "https://github.com/EXL",
"contributions": 4,
"additions": 4,
@ -380,21 +490,12 @@
"hireable": true
},
{
"name": "Yago",
"email": "yago@yago.me",
"url": "https://github.com/yagop",
"contributions": 194,
"additions": 3014,
"deletions": 1173,
"hireable": true
},
{
"name": "Ilias Ismanalijev",
"email": "hello@illyism.com",
"url": "https://github.com/Illyism",
"contributions": 7,
"additions": 140,
"deletions": 10,
"name": "Riddler",
"email": null,
"url": "https://github.com/Waterloo",
"contributions": 3,
"additions": 64,
"deletions": 2,
"hireable": true
},
{
@ -406,14 +507,50 @@
"deletions": 6,
"hireable": null
},
{
"name": "Ilias Ismanalijev",
"email": null,
"url": "https://github.com/Illyism",
"contributions": 7,
"additions": 140,
"deletions": 10,
"hireable": true
},
{
"name": "Gocho Mugo",
"email": "mugo@forfuture.co.ke",
"email": null,
"url": "https://github.com/GochoMugo",
"contributions": 80,
"additions": 4590,
"deletions": 2377,
"contributions": 152,
"additions": 7186,
"deletions": 3367,
"hireable": true
},
{
"name": "Mohammed Sohail",
"email": null,
"url": "https://github.com/kamikazechaser",
"contributions": 12,
"additions": 523,
"deletions": 127,
"hireable": true
},
{
"name": "Yago",
"email": null,
"url": "https://github.com/yagop",
"contributions": 197,
"additions": 3023,
"deletions": 1177,
"hireable": true
},
{
"name": "Sedric Heidarizarei",
"email": null,
"url": "https://github.com/saeedhei",
"contributions": 1,
"additions": 1,
"deletions": 0,
"hireable": null
}
]
}

@ -10,6 +10,12 @@ exports.BaseError = class BaseError extends Error {
super(`${code}: ${message}`);
this.code = code;
}
toJSON() {
return {
code: this.code,
message: this.message,
};
}
};

File diff suppressed because it is too large Load Diff

@ -1,3 +1,4 @@
const errors = require('./errors');
const debug = require('debug')('node-telegram-bot-api');
const deprecate = require('depd')('node-telegram-bot-api');
const ANOTHER_WEB_HOOK_USED = 409;
@ -49,7 +50,7 @@ class TelegramBotPolling {
/**
* Stop polling
* @param {Object} [options]
* @param {Object} [options] Options
* @param {Boolean} [options.cancel] Cancel current request
* @param {String} [options.reason] Reason for stopping polling
* @return {Promise}
@ -79,6 +80,18 @@ class TelegramBotPolling {
return !!this._lastRequest;
}
/**
* Handle error thrown during polling.
* @private
* @param {Error} error
*/
_error(error) {
if (!this.bot.listeners('polling_error').length) {
return console.error('error: [polling_error] %j', error); // eslint-disable-line no-console
}
return this.bot.emit('polling_error', error);
}
/**
* Invokes polling (with recursion!)
* @return {Promise} promise of the current request
@ -93,18 +106,59 @@ class TelegramBotPolling {
updates.forEach(update => {
this.options.params.offset = update.update_id + 1;
debug('updated offset: %s', this.options.params.offset);
try {
this.bot.processUpdate(update);
} catch (err) {
err._processing = true;
throw err;
}
});
return null;
})
.catch(err => {
debug('polling error: %s', err.message);
if (this.bot.listeners('polling_error').length) {
this.bot.emit('polling_error', err);
} else {
console.error(err); // eslint-disable-line no-console
if (!err._processing) {
return this._error(err);
}
return null;
delete err._processing;
/*
* An error occured while processing the items,
* i.e. in `this.bot.processUpdate()` above.
* We need to mark the already-processed items
* to avoid fetching them again once the application
* is restarted, or moves to next polling interval
* (in cases where unhandled rejections do not terminate
* the process).
* See https://github.com/yagop/node-telegram-bot-api/issues/36#issuecomment-268532067
*/
if (!this.bot.options.badRejection) {
return this._error(err);
}
const opts = {
offset: this.options.params.offset,
limit: 1,
timeout: 0,
};
return this.bot.getUpdates(opts).then(() => {
return this._error(err);
}).catch(requestErr => {
/*
* We have been unable to handle this error.
* We have to log this to stderr to ensure devops
* understands that they may receive already-processed items
* on app restart.
* We simply can not rescue this situation, emit "error"
* event, with the hope that the application exits.
*/
/* eslint-disable no-console */
const bugUrl = 'https://github.com/yagop/node-telegram-bot-api/issues/36#issuecomment-268532067';
console.error('error: Internal handling of The Offset Infinite Loop failed');
console.error(`error: Due to error '${requestErr}'`);
console.error('error: You may receive already-processed updates on app restart');
console.error(`error: Please see ${bugUrl} for more information`);
/* eslint-enable no-console */
return this.bot.emit('error', new errors.FatalError(err));
});
})
.finally(() => {
if (this._abort) {

@ -97,7 +97,7 @@ class TelegramBotWebHook {
*/
_error(error) {
if (!this.bot.listeners('webhook_error').length) {
return console.error(error); // eslint-disable-line no-console
return console.error('error: [webhook_error] %j', error); // eslint-disable-line no-console
}
return this.bot.emit('webhook_error', error);
}

@ -5,9 +5,11 @@ const assert = require('assert');
const fs = require('fs');
const os = require('os');
const path = require('path');
const stream = require('stream');
const is = require('is');
const utils = require('./utils');
const isCI = require('is-ci');
const concat = require('concat-stream');
// Allows self-signed certificates to be used in our tests
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
@ -36,9 +38,12 @@ const pollingPort2 = portindex++;
const webHookPort2 = portindex++;
const badTgServerPort = portindex++;
const staticUrl = `http://127.0.0.1:${staticPort}`;
const key = `${__dirname}/../examples/key.pem`;
const key = `${__dirname}/../examples/ssl/key.pem`;
const cert = `${__dirname}/../examples/ssl/crt.pem`;
const ip = '216.58.210.174'; // Google IP ¯\_(ツ)_/¯
const cert = `${__dirname}/../examples/crt.pem`;
const lat = 47.5351072;
const long = -52.7508537;
const FILE_PATH = `${__dirname}/data/photo.gif`;
let FILE_ID;
let GAME_CHAT_ID;
let GAME_MSG_ID;
@ -55,9 +60,15 @@ before(function beforeAll() {
describe('module.exports', function moduleExportsSuite() {
it('is loaded from src', function test() {
const nodeVersion = parseInt(process.versions.node.split('.')[0], 10);
it('is loaded from src/ on Node.js v6+ and above', function test() {
if (nodeVersion <= 5) this.skip(); // skip on Node.js v5 and below
assert.equal(TelegramBot, require('../src/telegram'));
});
it('is loaded from lib/ on Node.js v5 and below', function test() {
if (nodeVersion > 5) this.skip(); // skip on newer versions
assert.equal(TelegramBot, require('../lib/telegram'));
});
});
@ -93,7 +104,7 @@ describe('TelegramBot', function telegramSuite() {
utils.handleRatelimit(bot, 'sendPhoto', this);
utils.handleRatelimit(bot, 'sendMessage', this);
utils.handleRatelimit(bot, 'sendGame', this);
return bot.sendPhoto(USERID, `${__dirname}/data/photo.gif`).then(resp => {
return bot.sendPhoto(USERID, FILE_PATH).then(resp => {
FILE_ID = resp.photo[0].file_id;
return bot.sendMessage(USERID, 'chat');
}).then(resp => {
@ -622,13 +633,6 @@ describe('TelegramBot', function telegramSuite() {
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() {
@ -1036,8 +1040,6 @@ describe('TelegramBot', function telegramSuite() {
utils.handleRatelimit(bot, 'sendLocation', this);
});
it('should send a location', function test() {
const lat = 47.5351072;
const long = -52.7508537;
return bot.sendLocation(USERID, lat, long).then(resp => {
assert.ok(is.object(resp));
assert.ok(is.object(resp.location));
@ -1047,13 +1049,51 @@ describe('TelegramBot', function telegramSuite() {
});
});
describe('#editMessageLiveLocation', function editMessageLiveLocationSuite() {
let message;
before(function before() {
utils.handleRatelimit(bot, 'editMessageLiveLocation', this);
const opts = { live_period: 86400 };
return bot.sendLocation(USERID, lat, long, opts).then(resp => { message = resp; });
});
it('edits live location', function test() {
const opts = { chat_id: USERID, message_id: message.message_id };
return bot.editMessageLiveLocation(lat + 1, long + 1, opts).then(resp => {
assert.ok(is.object(resp));
assert.ok(is.object(resp.location));
assert.ok(is.number(resp.location.latitude));
assert.ok(is.number(resp.location.longitude));
});
});
});
describe('#stopMessageLiveLocation', function editMessageLiveLocationSuite() {
let message;
before(function before() {
utils.handleRatelimit(bot, 'stopMessageLiveLocation', this);
return bot.sendLocation(USERID, lat, long, { live_period: 86400 })
.then((resp) => {
message = resp;
const opts = { chat_id: USERID, message_id: message.message_id };
return bot.editMessageLiveLocation(lat + 1, long + 1, opts);
});
});
it('stops location updates', function test() {
const opts = { chat_id: USERID, message_id: message.message_id };
return bot.stopMessageLiveLocation(opts).then(resp => {
assert.ok(is.object(resp));
assert.ok(is.object(resp.location));
assert.ok(is.number(resp.location.latitude));
assert.ok(is.number(resp.location.longitude));
});
});
});
describe('#sendVenue', function sendVenueSuite() {
before(function before() {
utils.handleRatelimit(bot, 'sendVenue', this);
});
it('should send a venue', function test() {
const lat = 47.5351072;
const long = -52.7508537;
const title = 'The Village Shopping Centre';
const address = '430 Topsail Rd,St. John\'s, NL A1E 4N1, Canada';
return bot.sendVenue(USERID, lat, long, title, address).then(resp => {
@ -1113,7 +1153,27 @@ describe('TelegramBot', function telegramSuite() {
return bot.getFileLink(FILE_ID)
.then(fileURI => {
assert.ok(is.string(fileURI));
assert.ok(/https?:\/\/.*\/file\/bot.*\/.*/.test(fileURI));
assert.ok(utils.isTelegramFileURI(fileURI));
});
});
});
describe('#getFileStream', function getFileStreamSuite() {
this.timeout(timeout);
before(function before() {
// utils.handleRatelimit(bot, 'getFileStream', this);
});
it('should get a file stream', function test(done) {
const fileStream = bot.getFileStream(FILE_ID);
assert.ok(fileStream instanceof stream.Readable);
assert.equal(fileStream.path, FILE_ID);
fileStream.on('info', (info) => {
assert.ok(info);
assert.ok(utils.isTelegramFileURI(info.uri), `${info.uri} is not a file URI`);
fileStream.pipe(concat(function readFile(buffer) {
buffer.equals(fs.readFileSync(FILE_PATH)); // sync :(
return done();
}));
});
});
});
@ -1294,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 stream = fs.createReadStream(`${__dirname}/data/photo.gif`);
stream.path = '/?id=123'; // for example, 'http://example.com/?id=666'
return bot.sendPhoto(USERID, stream);
});
});
describe('#sendInvoice', function sendInvoiceSuite() {
before(function before() {
utils.handleRatelimit(bot, 'sendInvoice', this);
@ -1379,4 +1409,31 @@ describe('TelegramBot', function telegramSuite() {
});
// Other tests (eg. Buffer, URL) are skipped, because they rely on the same features as sendPhoto.
});
describe('#sendMediaGroup', function sendMediaGroupSuite() {
before(function before() {
utils.handleRatelimit(bot, 'sendMediaGroup', this);
});
it('should send group of photos/videos as album', function test() {
return bot.sendMediaGroup(USERID, [
{
type: 'photo',
media: `${__dirname}/data/photo.gif`,
},
{
type: 'video',
media: `${__dirname}/data/video.mp4`,
},
{
type: 'photo',
media: FILE_ID,
},
], {
disable_notification: true,
}).then(resp => {
assert.ok(is.array(resp));
assert.equal(resp.length, 3);
});
});
});
}); // End Telegram

@ -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);
});
});
});

@ -30,6 +30,13 @@ exports = module.exports = {
* @return {Promise}
*/
isPollingMockServer,
/**
* Return true if the string is a URI to a file
* on Telegram servers.
* @param {String} uri
* @return {Boolean}
*/
isTelegramFileURI,
/**
* Send a message to the webhook at the specified port and path.
* @param {Number} port
@ -217,3 +224,8 @@ function handleRatelimit(bot, methodName, suite) {
};
return bot;
}
function isTelegramFileURI(uri) {
return /https?:\/\/.*\/file\/bot.*\/.*/.test(uri);
}

Loading…
Cancel
Save