Initial commit
This commit is contained in:
commit
dfbb21800b
5220 files changed
+368059
No files matched your search
+68
@@ -0,0 +1,68 @@
|
||||
<!--
|
||||
This template includes three sections:
|
||||
1. Bug reporting
|
||||
2. Feature request
|
||||
3. Question
|
||||
|
||||
Please remove sections that do not apply to your issue
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<!--********************************************************************
|
||||
Reporting a Bug.
|
||||
*********************************************************************-->
|
||||
|
||||
> Bug Report
|
||||
|
||||
I have read:
|
||||
|
||||
* [Usage information](https://github.com/yagop/node-telegram-bot-api/tree/master/doc/usage.md)
|
||||
* [Help information](https://github.com/yagop/node-telegram-bot-api/tree/master/doc/help.md)
|
||||
|
||||
I am using the latest version of the library.
|
||||
|
||||
### Expected Behavior
|
||||
|
||||
<!-- Explain what you are trying to achieve -->
|
||||
|
||||
### Actual Behavior
|
||||
|
||||
<!-- Explain what happens, contrary to what you expected -->
|
||||
|
||||
### Steps to reproduce the Behavior
|
||||
|
||||
<!-- Explain how we can reproduce the bug -->
|
||||
|
||||
|
||||
|
||||
<!--********************************************************************
|
||||
Feature Request.
|
||||
*********************************************************************-->
|
||||
|
||||
> Feature Request
|
||||
|
||||
I have:
|
||||
|
||||
* searched for such a feature request (https://github.com/yagop/node-telegram-bot-api/labels/enhancement) and found none
|
||||
|
||||
### Introduction
|
||||
|
||||
<!-- Describe what value this feature would add, and in which use case,
|
||||
or scenario -->
|
||||
|
||||
### Example
|
||||
|
||||
<!-- A code snippet of how this feature would work, were it already
|
||||
implemented -->
|
||||
|
||||
|
||||
|
||||
<!--********************************************************************
|
||||
Question.
|
||||
*********************************************************************-->
|
||||
|
||||
> Question
|
||||
|
||||
<!-- Ask your question here. Please be precise, adding as much detail
|
||||
as necessary. Also, add a code snippet(s) if possible. -->
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<!--
|
||||
Mark whichever option below applies to this PR.
|
||||
For example, if your PR passes all tests, you would mark the option as so:
|
||||
- [x] All tests pass
|
||||
Note the 'x' in between the square brackets '[]'
|
||||
-->
|
||||
- [ ] All tests pass
|
||||
- [ ] I have run `npm run doc`
|
||||
|
||||
### Description
|
||||
|
||||
<!-- Explain what you are trying to achieve with this PR -->
|
||||
|
||||
### References
|
||||
|
||||
<!--
|
||||
Add references to other documents/pages that are relevant to this
|
||||
PR, such as related issues, documentation, etc.
|
||||
|
||||
For example,
|
||||
* Issue #1: https://github.com/yagop/node-telegram-bot-api/issues/1
|
||||
* Telegram Bot API - Getting updates: https://core.telegram.org/bots/api#getting-updates
|
||||
-->
|
||||
+515
@@ -0,0 +1,515 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.66.0][0.66.0] - 2024-05-03
|
||||
|
||||
1. Support Telegram Bot API 7.2 & 7.3 (@danielperez9430)
|
||||
* getBusinessConnection
|
||||
* replaceStickerInSet
|
||||
|
||||
2. Support for updates: (@danielperez9430)
|
||||
* business_connection
|
||||
* business_message
|
||||
* edited_business_message
|
||||
* deleted_business_messages
|
||||
|
||||
3. Minor fixes: (@danielperez9430)
|
||||
* getUserChatBoosts
|
||||
|
||||
## [0.65.1][0.65.1] - 2024-03-09
|
||||
|
||||
1. Support for updates (@danielperez9430)
|
||||
* message_reaction
|
||||
* message_reaction_count
|
||||
* chat_boost
|
||||
* removed_chat_boost
|
||||
|
||||
## [0.65.0][0.65.0] - 2024-02-20
|
||||
|
||||
1. Support Telegram Bot API v7.1
|
||||
* deleteMessages (@Sp3ricka)
|
||||
* copyMessages (@xjx0106 & @Sp3ricka)
|
||||
* setMessageReaction (@Sp3ricka)
|
||||
* forwardMessages (@danielperez9430)
|
||||
* getUserChatBoosts (@danielperez9430)
|
||||
|
||||
2. Minor changes: (@danielperez9430)
|
||||
* Refactor methods order
|
||||
* Fix copyMessages & setMessageReaction methods
|
||||
* Added missing tests
|
||||
* Fix tests for methods copyMessages & getMyDefaulAdministratorRights
|
||||
|
||||
## [0.64.0][0.64.0] - 2023-10-25
|
||||
|
||||
1. Replace `request` with a maintained version (@danielperez9430)
|
||||
* Change `request` to `@cypress/request`
|
||||
* Change `request-promise` to `@cypress/request-promise`
|
||||
|
||||
## [0.63.0][0.63.0] - 2023-08-23
|
||||
|
||||
1. Support Telegram Bot API v6.8 (@danielperez9430)
|
||||
* unpinAllGeneralForumTopicMessages
|
||||
|
||||
## [0.62.0][0.62.0] - 2023-03-19
|
||||
|
||||
1. Support Telegram Bot API v6.6 & v6.7 (@danielperez9430)
|
||||
* setMyDescription
|
||||
* getMyDescription
|
||||
* setMyShortDescription
|
||||
* getMyShortDescription
|
||||
* setCustomEmojiStickerSetThumbnail
|
||||
* setStickerSetTitle
|
||||
* deleteStickerSet
|
||||
* setStickerEmojiList
|
||||
* setStickerKeywords
|
||||
* setStickerMaskPosition
|
||||
|
||||
## [0.61.0][0.61.0] - 2022-12-30
|
||||
|
||||
1. Support Telegram Bot API v6.4 (@danielperez9430)
|
||||
* editGeneralForumTopic
|
||||
* closeGeneralForumTopic
|
||||
* reopenGeneralForumTopic
|
||||
* hideGeneralForumTopic
|
||||
* unhideGeneralForumTopic
|
||||
|
||||
2. Minor changes: (@danielperez9430)
|
||||
* The parameters `name` and `icon_custom_emoji_id` of the method `editForumTopic` are now optional.
|
||||
* Fix add thumb in sendAudio, sendVideo and sendVideoNote
|
||||
* Fix getMyCommands and setMyCommands
|
||||
* Suggested tip amounts stringify in sendInvoice
|
||||
|
||||
## [0.60.0][0.60.0] - 2022-10-06
|
||||
|
||||
1. Support Telegram Bot API v6.3 (@danielperez9430)
|
||||
* createForumTopic
|
||||
* closeForumTopic
|
||||
* reopenForumTopic
|
||||
* deleteForumTopic
|
||||
* unpinAllForumTopicMessages
|
||||
* getForumTopicIconStickers
|
||||
|
||||
2. Fix test getMyDefaultAdministratorRights (@danielperez9430)
|
||||
|
||||
3. Fix parse entities - (@toniop99)
|
||||
|
||||
## [0.59.0][0.59.0] - 2022-08-15
|
||||
|
||||
1. Support Telegram Bot API v6.2 (@danielperez9430)
|
||||
* getCustomEmojiStickers
|
||||
|
||||
2. Support test enviroment (@tinsaeDev & @kamikazechaser)
|
||||
|
||||
3. Remove dependencies: (@danielperez9430)
|
||||
* Remove *bluebird* => Use NodeJS Native Promises
|
||||
* Remove *depd* => Use node native deprecate util for warnings
|
||||
* Remove contributor dev dependency and add list of contributors in the readme
|
||||
|
||||
4. Remove legacy methods: (@danielperez9430)
|
||||
* getChatMembersCount
|
||||
* kickChatMember
|
||||
|
||||
5. Docs: (@danielperez9430)
|
||||
* Update the docs of the methods
|
||||
* Order methods follow the Telegram bot API docs in src/telegram.js
|
||||
* Update README
|
||||
|
||||
6. Fix: (@danielperez9430)
|
||||
* addStickerToSet() -> Allow to send tgs_sticker + webm_sticker
|
||||
* Remove mandatory param “start_parameter” from sendInvoice, because in the docs is a optional param
|
||||
* getStickerSet test fix deprecated response value "contains_masks" change to "sticker_type"
|
||||
* Fix some other tests
|
||||
|
||||
7. New Test: (@danielperez9430)
|
||||
* deleteStickerFromSet
|
||||
* setStickerPositionInSet
|
||||
* getCustomEmojiStickers
|
||||
|
||||
## [0.58.0][0.58.0] - 2022-06-22
|
||||
|
||||
1. Support Bot API v6.1: (@danielperez9430)
|
||||
* Add method *createInvoiceLink()*
|
||||
|
||||
2. Support for setStickerSetThumb (@elihaidv)
|
||||
|
||||
3. Add new test (@danielperez9430)
|
||||
* createInvoiceLink
|
||||
|
||||
4. Test fixes (@danielperez9430)
|
||||
* sendVideoNote
|
||||
* createNewStickerSet
|
||||
* setStickerSetThumb
|
||||
* getChatMenuButton
|
||||
* setWebHook
|
||||
|
||||
5. Bug fixes (@danielperez9430)
|
||||
* answerWebAppQuery
|
||||
* Support for send thumb in sendAudio
|
||||
|
||||
## [0.57.0][0.57.0] - 2022-04-23
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v6: (@danielperez9430)
|
||||
|
||||
* Add method *setChatMenuButton()*
|
||||
* Add method *getChatMenuButton()*
|
||||
* Add method *setMyDefaultAdministratorRights()*
|
||||
* Add method *getMyDefaultAdministratorRights()*
|
||||
* Add method *answerWebAppQuery()*
|
||||
* Renamed the fields voice_chat_scheduled, voice_chat_started, voice_chat_ended, and voice_chat_participants_invited to video_chat_scheduled, video_chat_started, video_chat_ended, and video_chat_participants_invited
|
||||
|
||||
|
||||
Tests:
|
||||
|
||||
* answerWebAppQuery
|
||||
* setChatMenuButton
|
||||
* getChatMenuButton
|
||||
* setMyDefaultAdministratorRights
|
||||
* getMyDefaultAdministratorRights
|
||||
|
||||
## [0.56.0][0.56.0] - 2021-12-07
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v5.5: (@danielperez9430)
|
||||
|
||||
* Add method *banChatSenderChat()*
|
||||
* Add method *unbanChatSenderChat()*
|
||||
|
||||
Fixes:
|
||||
|
||||
* Tests for support with new invite link format
|
||||
|
||||
## [0.55.0][0.55.0] - 2021-11-06
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v5.4: (@danielperez9430)
|
||||
|
||||
* Add method *approveChatJoinRequest()*
|
||||
* Add method *declineChatJoinRequest()*
|
||||
* Add support for new updates:
|
||||
* *chat_join_request*
|
||||
|
||||
Fixes:
|
||||
|
||||
* Method *editMessageMedia*: Now you can send a local file (`"attach://" + filePatch`)
|
||||
|
||||
## [0.54.0][0.54.0] - 2021-06-29
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v5.3: (@danielperez9430)
|
||||
|
||||
* Add method *deleteMyCommands()*
|
||||
* Add method *banChatMember()*
|
||||
* Add method *getChatMemberCount()*
|
||||
|
||||
New Test:
|
||||
|
||||
* deleteMyCommands
|
||||
* banChatMember
|
||||
* getChatMemberCount
|
||||
|
||||
Deprecated:
|
||||
* Method *kickChatMember()*
|
||||
* Method *getChatMembersCount()*
|
||||
|
||||
## [0.53.0][0.53.0] - 2021-04-26
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v5.2:(@danielperez9430)
|
||||
|
||||
* Add support for new messageTypes:
|
||||
* *voice_chat_scheduled*
|
||||
|
||||
## [0.52.0][0.52.0] - 2021-03-20
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v5.1: (by @danielperez9430)
|
||||
|
||||
* Add method *createChatInviteLink()*
|
||||
* Add method *editChatInviteLink()*
|
||||
* Add method *revokeChatInviteLink()*
|
||||
* Add support for new messageTypes:
|
||||
* *voice_chat_started*
|
||||
* *voice_chat_ended*
|
||||
* *voice_chat_participants_invited*
|
||||
* *message_auto_delete_timer_changed*
|
||||
* *chat_invite_link*
|
||||
* *chat_member_updated*
|
||||
* Add support for new updates:
|
||||
* *my_chat_member*
|
||||
* *chat_member*
|
||||
|
||||
New Test: (by @danielperez9430)
|
||||
|
||||
* createChatInviteLink
|
||||
* editChatInviteLink
|
||||
* revokeChatInviteLink
|
||||
|
||||
## [0.51.0][0.51.0] - 2020-11-04
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v5.0: (by @danielperez9430)
|
||||
|
||||
* Add method *copyMessage()*
|
||||
* Add method *unpinAllChatMessages()*
|
||||
* Add method *close()*
|
||||
* Add method *logOut()*
|
||||
|
||||
Changed: (by @danielperez9430)
|
||||
|
||||
* Remove trailing-spaces
|
||||
* Fix Bugs in Test
|
||||
|
||||
New Test: (by @danielperez9430)
|
||||
|
||||
* copyMessage
|
||||
* unpinAllChatMessages
|
||||
|
||||
## [0.50.0][0.50.0] - 2020-05-2020
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v4.8: (by @danielperez9430)
|
||||
* Add methods: *sendDice()*
|
||||
2. Support Bot API v4.7: (by @danielperez9430)
|
||||
* Add methods: *getMyCommands()*,*setMyCommands()*
|
||||
3. Support Bot API v4.5: (by @danielperez9430)
|
||||
* Add methods: *setChatAdministratorCustomTitle()*
|
||||
4. Support Bot API v4.4: (by @danielperez9430)
|
||||
* Add methods: *setChatPermissions()*
|
||||
5. Support for poll_answer (by @JieJiSS)
|
||||
6. Add request options in file stream (by @zhangpanyi )
|
||||
|
||||
Changed: (by @danielperez9430)
|
||||
|
||||
* New message type: *dice*
|
||||
* Fix Bugs in tests
|
||||
* Fix regex compare (by @ledamint)
|
||||
* Fix listening for error events when downloading files (by @Kraigo)
|
||||
|
||||
New Test: (by @danielperez9430)
|
||||
|
||||
* sendDice
|
||||
* getMyCommands
|
||||
* setMyCommands
|
||||
* setChatAdministratorCustomTitle
|
||||
* setChatPermissions
|
||||
|
||||
## [0.40.0][0.40.0] - 2019-05-04
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v4.2: (by @kamikazechaser)
|
||||
* Add methods: *TelegramBot#sendPoll()*, *TelegramBot#stopPoll()*
|
||||
* Support events: *poll*
|
||||
2. Support Bot API v4.0: (by @kamikazechaser)
|
||||
* Add methods: *TelegramBot#editMessageMedia()*, *TelegramBot#sendAnimation()*
|
||||
* Support new message types: *passport_data*, *animation*
|
||||
|
||||
* * *
|
||||
|
||||
## [0.30.0][0.30.0] - 2017-12-21
|
||||
|
||||
Added:
|
||||
|
||||
1. Support Bot API v3.5: (by @GochoMugo)
|
||||
* Allow `provider_data` parameter in *TelegramBot#sendInvoice*
|
||||
* Add method *TelegramBot#sendMediaGroup()*
|
||||
2. Support Bot API v3.4: (by @kamikazechaser)
|
||||
* Add methods *TelegramBot#editMessageLiveLocation*, *TelegramBot#stopMessageLiveLocation* (#439)
|
||||
* Add methods *TelegramBot#setChatStickerSet*, *TelegramBot#deleteChatStickerSet* (#440)
|
||||
3. Add methods:
|
||||
* *TelegramBot#getFileStream* (#442) (by @GochoMugo, requested-by @Xaqron)
|
||||
4. Add options to *TelegramBot#stopPolling()* (by @GochoMugo)
|
||||
5. Add `metadata` argument in `message` event (and friends e.g. `text`, `audio`, etc.) (#409) (by @jlsjonas, @GochoMugo)
|
||||
6. Add forward-compatibility i.e. support future additional Telegram options (by @GochoMugo)
|
||||
7. Add support for Node.js v9 (by @GochoMugo)
|
||||
8. Document *TelegramBot.errors*, *TelegramBot.messageTypes* (by @GochoMugo)
|
||||
|
||||
Changed:
|
||||
|
||||
1. Update *TelegramBot#answerCallbackQuery()* signature (by @GochoMugo)
|
||||
2. Improve default error logging of `polling_error` and `webhook_error` (#377)
|
||||
3. Update dependencies
|
||||
|
||||
Deprecated:
|
||||
|
||||
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)
|
||||
2. Fix game example (#449, #418) (by @MCSH)
|
||||
|
||||
* * *
|
||||
|
||||
## [0.29.0][0.29.0] - 2017-10-22
|
||||
|
||||
Added:
|
||||
|
||||
1. Add Bot API v3.2 methods:
|
||||
* (#429) *TelegramBot#getStickerSet* (by @CapacitorSet, @LibertyLocked)
|
||||
* (#430) *TelegramBot#uploadStickerFile* (by @CapacitorSet)
|
||||
* *TelegramBot#createNewStickerSet*, *TelegramBot#addStickerToSet*, *TelegramBot#setStickerPositionInSet*, *TelegramBot#deleteStickerFromSet* (by @GochoMugo)
|
||||
2. Supports API v3.3
|
||||
|
||||
Deprecated:
|
||||
|
||||
1. Auto-enabling Promise cancellation (#319) (by @GochoMugo)
|
||||
|
||||
* * *
|
||||
|
||||
## [0.28.0][0.28.0] - 2017-08-06
|
||||
|
||||
Added:
|
||||
|
||||
1. (#361) Support Bot API v3.1 (by @Lord-Protector, @kamikazechaser)
|
||||
2. (#332) Support Bot API v3.0 (by @kamikazechaser, @GochoMugo)
|
||||
3. Add *TelegramBot#removeTextListener()* (by @GochoMugo)
|
||||
4. (#342) Add game example (by @MCSH)
|
||||
5. (#315) List 'bot-brother' project in community section in README (by @saeedhei)
|
||||
|
||||
Changed:
|
||||
|
||||
1. (#367) Update *TelegramBot#answerCallbackQuery()* signature (by @mnb3000)
|
||||
|
||||
Fixed:
|
||||
|
||||
1. (#325) Fix global regexp state reset (by @Sirius-A)
|
||||
2. (#363) Fix download file path on windows (by @kucherenkovova)
|
||||
3. (#346) Fix anchor webhook link in docs (by @Coac)
|
||||
|
||||
* * *
|
||||
|
||||
## [0.27.1][0.27.1] - 2017-04-07
|
||||
|
||||
Added:
|
||||
|
||||
1. (#287) Add Express WebHook example (by @kamikazechaser)
|
||||
|
||||
Fixed:
|
||||
|
||||
1. (#291) Improve docs (by @preco21)
|
||||
2. (#298) Fix running on Node v5 (by @jehy)
|
||||
3. (#307) Fix badge links in README (by @JaakkoLipsanen)
|
||||
4. Fix defaulting value of `options.polling.params.timeout` (by @GochoMugo)
|
||||
5. Fix typos in Github issue template (by @GochoMugo, requested-by @GingerPlusPlus)
|
||||
|
||||
* * *
|
||||
|
||||
## [0.27.0][0.27.0] - 2017-02-10
|
||||
|
||||
Added:
|
||||
|
||||
1. Add constructor options:
|
||||
* (#243) `options.polling.params` (by @GochoMugo, requested-by @sidelux)
|
||||
2. Add methods:
|
||||
* (#74) *TelegramBot#removeReplyListener()* (by @githugger)
|
||||
3. (#283) Add proper error handling (by @GochoMugo)
|
||||
4. (#272) Add health-check endpoint (by @mironov)
|
||||
* `options.webHook.healthEndpoint`
|
||||
5. (#152) Add test for TelegramBot#sendDocument() using 'fileOpts'
|
||||
param (by @evolun)
|
||||
6. Document `options.webHook.host` (by @GochoMugo)
|
||||
7. (#264) Add Bot API version to README (by @kamikazechaser)
|
||||
8. Add examples:
|
||||
- (#271) WebHook on Heroku (by @TheBeastOfCaerbannog)
|
||||
- (#274) WebHook on Zeit Now (by @Ferrari)
|
||||
|
||||
Changed:
|
||||
|
||||
1. (#147) Use *String#indexOf()*, instead of *RegExp#test()*, to
|
||||
find token in webhook request (by @AVVS)
|
||||
|
||||
Fixed:
|
||||
|
||||
* Fix bug:
|
||||
- (#275, #280) fix es6 syntax error on Node.js v4.x (by @crazyabdul)
|
||||
- (#276) promise.warning from `request-promise` (by @GochoMugo,
|
||||
reported-by @preco21)
|
||||
- (#281) fix handling error during polling (by @GochoMugo,
|
||||
reported-by @dimawebmaker)
|
||||
- (#284) fix error during deletion of already-set webhook, during
|
||||
polling (by @GochoMugo, reported-by @dcparga)
|
||||
1. Fix links in documentation (by @Ni2c2k)
|
||||
|
||||
* * *
|
||||
|
||||
## [0.26.0][0.26.0] - 2017-01-20
|
||||
|
||||
Added:
|
||||
|
||||
1. Add *TelegramBot* constructor options:
|
||||
* `options.https`
|
||||
* `options.baseApiUrl`
|
||||
* `options.filepath`
|
||||
2. Add methods:
|
||||
* *TelegramBot#stopPolling()*
|
||||
* *TelegramBot#isPolling()*
|
||||
* *TelegramBot#openWebHook()*
|
||||
* *TelegramBot#closeWebHook()*
|
||||
* *TelegramBot#hasOpenWebHook()*
|
||||
* *TelegramBot#deleteWebHook()*
|
||||
* *TelegramBot#getWebHookInfo()*
|
||||
|
||||
Changed:
|
||||
|
||||
1. Use POST requests by default
|
||||
2. Ensure all relevant methods return Promises
|
||||
3. Document auto-deletion of webhook during polling
|
||||
4. Deprecate support for Node.js v0.12
|
||||
5. Fix consistency of methods signatures
|
||||
6. Rename *TelegramBot#initPolling()* to *TelegramBot#startPolling()*
|
||||
* Deprecate *TelegramBot#initPolling()*
|
||||
|
||||
Fixed:
|
||||
|
||||
1. Handle error during formatting `formData`
|
||||
2. Fix ES6 syntax
|
||||
|
||||
*Credits/Blames: Unless explicitly stated otherwise, above work was
|
||||
done by @GochoMugo*
|
||||
|
||||
* * *
|
||||
|
||||
## [0.25.0][0.25.0] - 2016-12-21
|
||||
|
||||
Added:
|
||||
|
||||
1. Supports the API v2.3 updates (by @kamikazechaser)
|
||||
2. Add *TelegramBot* constructor option:
|
||||
* `options.request`: proxy extra request options (by @tarmolov)
|
||||
* `options.onlyFirstMatch` (by @GingerPlusPlus)
|
||||
3. Add methods:
|
||||
* *TelegramBot#sendVenue()* (by Tketa)
|
||||
* *TelegramBot#sendContact()* (by @GochoMugo)
|
||||
* *TelegramBot#getGameHighScores()* (by @jishnu7)
|
||||
|
||||
Fixed:
|
||||
|
||||
1. Fix request performance issue (by @preco21)
|
||||
2. 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
|
||||
[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
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at mugo@forfuture.co.ke. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
# Contributing
|
||||
|
||||
> If you are willing to contribute, first you should know that
|
||||
> I will love you and so will the Telegram Bot community.
|
||||
|
||||
Before proceeding any further, read the following documents:
|
||||
|
||||
1. [Code of Conduct][coc]
|
||||
1. [License][license]
|
||||
|
||||
## General Information
|
||||
|
||||
### Creating a Github issue:
|
||||
|
||||
1. Ensure that your issue does **not** already exist. [Do a search](https://github.com/yagop/node-telegram-bot-api/issues).
|
||||
2. Browse through [StackOverflow](https://stackoverflow.com/search?q=telegram+nodejs) and other similar platforms.
|
||||
3. Should you open your issue, ensure you use the English language for
|
||||
the wider target audience.
|
||||
4. Be patient please.
|
||||
|
||||
|
||||
### Updating API Reference i.e. generating `doc/api.md`
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
$ 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:
|
||||
|
||||
```bash
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
[coc]:https://github.com/yagop/node-telegram-bot-api/blob/master/CODE_OF_CONDUCT.md
|
||||
[license]:https://github.com/yagop/node-telegram-bot-api/blob/master/LICENSE.md
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Yago
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
<h1 align="center">Node.js Telegram Bot API</h1>
|
||||
|
||||
<div align="center">
|
||||
|
||||
Node.js module to interact with the official [Telegram Bot API](https://core.telegram.org/bots/api).
|
||||
|
||||
|
||||
[](https://core.telegram.org/bots/api)
|
||||
[](https://www.npmjs.org/package/node-telegram-bot-api)
|
||||
[](https://travis-ci.org/yagop/node-telegram-bot-api)
|
||||
[](https://codecov.io/gh/yagop/node-telegram-bot-api)
|
||||
|
||||
[](https://telegram.me/node_telegram_bot_api)
|
||||
[](https://t.me/+nc3A9Hs1S81mYzdk)
|
||||
[](https://telegram.me/Yago_Perez)
|
||||
|
||||
</div>
|
||||
|
||||
## 📦 Install
|
||||
|
||||
```sh
|
||||
npm i node-telegram-bot-api
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
> ✍️ **Note:** If you use Typescript you can install this package that contains type definitions for this library
|
||||
>```sh
|
||||
>npm install --save-dev @types/node-telegram-bot-api
|
||||
>```
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
```js
|
||||
const TelegramBot = require('node-telegram-bot-api');
|
||||
|
||||
// replace the value below with the Telegram token you receive from @BotFather
|
||||
const token = 'YOUR_TELEGRAM_BOT_TOKEN';
|
||||
|
||||
// Create a bot that uses 'polling' to fetch new updates
|
||||
const bot = new TelegramBot(token, {polling: true});
|
||||
|
||||
// Matches "/echo [whatever]"
|
||||
bot.onText(/\/echo (.+)/, (msg, match) => {
|
||||
// 'msg' is the received Message from Telegram
|
||||
// 'match' is the result of executing the regexp above on the text content
|
||||
// of the message
|
||||
|
||||
const chatId = msg.chat.id;
|
||||
const resp = match[1]; // the captured "whatever"
|
||||
|
||||
// send back the matched "whatever" to the chat
|
||||
bot.sendMessage(chatId, resp);
|
||||
});
|
||||
|
||||
// Listen for any kind of message. There are different kinds of
|
||||
// messages.
|
||||
bot.on('message', (msg) => {
|
||||
const chatId = msg.chat.id;
|
||||
|
||||
// send a message to the chat acknowledging receipt of their message
|
||||
bot.sendMessage(chatId, 'Received your message');
|
||||
});
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
* [Usage][usage]
|
||||
* [Examples][examples]
|
||||
* [Tutorials][tutorials]
|
||||
* [Help Information][help]
|
||||
* API Reference: ([api-release](../master/doc/api.md) / [development][api-dev] / [experimental][api-experimental])
|
||||
* [Contributing to the Project][contributing]
|
||||
* [Experimental Features][experimental]
|
||||
|
||||
_**Note**: Development is done against the **development** branch.
|
||||
Code for the latest release resides on the **master** 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!
|
||||
|
||||
We also have a [Telegram group][tg-group] to discuss issues related to this library.
|
||||
|
||||
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
|
||||
* [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 keyboards structures creation through a more easy-to-see way (supports Inline Keyboards, Reply Keyboard, Remove Keyboard and Force Reply)
|
||||
* [beetube-bot](https://github.com/kodjunkie/beetube-bot): A telegram bot for music, videos, movies, EDM tracks, torrent downloads, files and more.
|
||||
* [telegram-inline-calendar](https://github.com/VDS13/telegram-inline-calendar): Date and time picker and inline calendar for Node.js telegram bots.
|
||||
* [telegram-captcha](https://github.com/VDS13/telegram-captcha): Telegram bot to protect Telegram groups from automatic bots.
|
||||
|
||||
|
||||
## 👥 Contributors
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/yagop/node-telegram-bot-api/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=yagop/node-telegram-bot-api" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## License
|
||||
|
||||
**The MIT License (MIT)**
|
||||
|
||||
Copyright © 2019 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
|
||||
[help]:https://github.com/yagop/node-telegram-bot-api/tree/master/doc/help.md
|
||||
[tutorials]:https://github.com/yagop/node-telegram-bot-api/tree/master/doc/tutorials.md
|
||||
[api-dev]:https://github.com/yagop/node-telegram-bot-api/tree/master/doc/api.md
|
||||
[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
|
||||
[tg-group]:https://t.me/+nc3A9Hs1S81mYzdk
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# API Reference
|
||||
|
||||
**Note:** If you are looking for available [events](usage.md#events) or usage of api, please refer [`usage.md`](usage.md).
|
||||
|
||||
{{#class name="TelegramBot"~}}
|
||||
{{>header~}}
|
||||
{{>body~}}
|
||||
{{>member-index~}}
|
||||
{{>members~}}
|
||||
{{/class}}
|
||||
* * *
|
||||
|
||||
|
||||
[usage-sending-files-performance]:https://github.com/yagop/node-telegram-bot-api/tree/master/doc/usage.md#sending-files-performance
|
||||
[setWebHook-v0.25.0]:https://github.com/yagop/node-telegram-bot-api/tree/4e5a493cadfaad5589a8d79e55d9e0d103000ce4#telegrambotsetwebhookurl-cert
|
||||
[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
|
||||
+2470
File diff suppressed because it is too large.
Load diff
+28
@@ -0,0 +1,28 @@
|
||||
# Experimental
|
||||
|
||||
Experimental features are things we are trying out. We are **not** sure
|
||||
if they'll become stable and move into the `master` branch.
|
||||
Try them out and give feedback to support stabilizing them.
|
||||
|
||||
* [Features](#features)
|
||||
* [API Reference][api-experimental]
|
||||
* [Installation](#installation)
|
||||
|
||||
|
||||
<a name="features"></a>
|
||||
## features:
|
||||
|
||||
* Support API method `deleteMessage`
|
||||
|
||||
Open issues tagged `experimental`: [link](https://github.com/yagop/node-telegram-bot-api/issues?q=is%3Apr+is%3Aopen+label%3Aexperimental)
|
||||
|
||||
|
||||
<a name="installation"></a>
|
||||
## installation:
|
||||
|
||||
```bash
|
||||
$ npm install yagop/node-telegram-bot-api#experimental
|
||||
```
|
||||
|
||||
|
||||
[api-experimental]:https://github.com/yagop/node-telegram-bot-api/tree/experimental/doc/api.md
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
# Help Information
|
||||
|
||||
* [Common Pitfalls](#pitfalls)
|
||||
* [FAQs](#faqs)
|
||||
|
||||
<a name="pitfalls"></a>
|
||||
## Common Pitfalls
|
||||
|
||||
<a name="reply-to-message"></a>
|
||||
### Failing to receive reply with `ReplyToMessage`
|
||||
|
||||
The user has to **manually reply** to your message, by tapping on the bot's message and select *Reply*.
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#113](https://github.com/yagop/node-telegram-bot-api/issues/113)
|
||||
|
||||
<a name="faqs"></a>
|
||||
## Frequently Asked Questions
|
||||
|
||||
> Check out [all questions ever asked][questions] on our Github Issues.
|
||||
|
||||
1. [How do I send GIFs?](#gifs)
|
||||
1. [Why and When do I need a certificate when using WebHooks?](#webhook-cert)
|
||||
1. [How do I know when a user leaves a chat?](#leave-chat)
|
||||
1. [What does this error mean?](#error-meanings)
|
||||
1. [How do I know the selected option in reply keyboard?](#reply-keyboard)
|
||||
1. [How do I send multiple message in correct sequence?](#ordered-sending)
|
||||
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?
|
||||
|
||||
You might be trying to send your animated GIFs using *TelegramBot#sendPhoto()*.
|
||||
The method mostly supports static images. As noted by the community,
|
||||
it seems you need to send them as documents, using *TelegramBot#sendDocument()*.
|
||||
|
||||
```js
|
||||
bot.sendDocument(chatId, 'cat.gif');
|
||||
```
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#11](https://github.com/yagop/node-telegram-bot-api/issues/11)
|
||||
|
||||
<a name="webhook-cert"></a>
|
||||
### Why and When do I need a certificate when using WebHooks?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#63](https://github.com/yagop/node-telegram-bot-api/issues/63)
|
||||
* Issue [#125](https://github.com/yagop/node-telegram-bot-api/issues/125)
|
||||
|
||||
<a name="leave-chat"></a>
|
||||
### How do I know when a user leaves a chat?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#248](https://github.com/yagop/node-telegram-bot-api/issues/248)
|
||||
|
||||
<a name="error-meanings"></a>
|
||||
### What does this error mean?
|
||||
|
||||
* [502 Bad Gateway](https://github.com/yagop/node-telegram-bot-api/issues/377)
|
||||
|
||||
*Not complete. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#73](https://github.com/yagop/node-telegram-bot-api/issues/73)
|
||||
* Issue [#99](https://github.com/yagop/node-telegram-bot-api/issues/99)
|
||||
* Issue [#101](https://github.com/yagop/node-telegram-bot-api/issues/101)
|
||||
* Issue [#107](https://github.com/yagop/node-telegram-bot-api/issues/107)
|
||||
* Issue [#156](https://github.com/yagop/node-telegram-bot-api/issues/156)
|
||||
* Issue [#170](https://github.com/yagop/node-telegram-bot-api/issues/170)
|
||||
* Issue [#244](https://github.com/yagop/node-telegram-bot-api/issues/244)
|
||||
|
||||
<a name="reply-keyboard"></a>
|
||||
### How do I know the selected option in reply keyboard?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#108](https://github.com/yagop/node-telegram-bot-api/issues/108)
|
||||
|
||||
<a name="ordered-sending"></a>
|
||||
### How do I send multiple message in correct sequence?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#240](https://github.com/yagop/node-telegram-bot-api/issues/240)
|
||||
|
||||
<a name="proxy"></a>
|
||||
### How do I run my bot behind a proxy?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#122](https://github.com/yagop/node-telegram-bot-api/issues/122)
|
||||
* Issue [#253](https://github.com/yagop/node-telegram-bot-api/issues/253)
|
||||
* Issue [#766](https://github.com/yagop/node-telegram-bot-api/issues/766)
|
||||
|
||||
<a name="new-feature"></a>
|
||||
### Can you add feature X to the library?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
Sources:
|
||||
|
||||
* Issue [#238](https://github.com/yagop/node-telegram-bot-api/issues/238)
|
||||
|
||||
<a name="scalable"></a>
|
||||
### Is this scalable?
|
||||
|
||||
*Not done. PRs welcome!*
|
||||
|
||||
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
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
# 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)
|
||||
* [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/)
|
||||
* [node-telegram-bot-api-tutorial:a telegram bot helper to send templates by sms](https://github.com/vito2005/chatManagerTelegramBot)
|
||||
* [Telegram bot using blockchain services](https://ilanolkies.com/post/Telegram-bot-using-blockchain-services)
|
||||
* [How to set webhooks using express local server and NGROK](https://github.com/leobloise/node-telegram-bot-api-wb-tutorial)
|
||||
> Send a PR with useful links **not** listed above
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
# Usage
|
||||
|
||||
- [Usage](#usage)
|
||||
- [Events](#events)
|
||||
- [WebHooks](#webhooks)
|
||||
- [Sending files](#sending-files)
|
||||
- [File Options (metadata)](#file-options-metadata)
|
||||
- [Performance Issue](#performance-issue)
|
||||
- [Error handling](#error-handling)
|
||||
- [Polling errors](#polling-errors)
|
||||
- [WebHook errors](#webhook-errors)
|
||||
|
||||
<a name="events"></a>
|
||||
## 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 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`, `poll`, `dice`, `migrate_from_chat_id`, `migrate_to_chat_id`,
|
||||
`channel_chat_created`, `supergroup_chat_created`,
|
||||
`successful_payment`, `invoice`, `video_note`
|
||||
1. **Arguments**: `message` ([Message][message]), `metadata` (`{ type?:string }`)
|
||||
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]
|
||||
1. `chosen_inline_result`: Received result of an inline query i.e. [ChosenInlineResult][chosen-inline-result]
|
||||
1. `channel_post`: Received a new incoming channel post of any kind
|
||||
1. `edited_message`: Received a new version of a message that is known to the bot and was edited
|
||||
1. `edited_message_text`
|
||||
1. `edited_message_caption`
|
||||
1. `edited_channel_post`: Received a new version of a channel post that is known to the bot and was edited
|
||||
1. `edited_channel_post_text`
|
||||
1. `edited_channel_post_caption`
|
||||
1. `shipping_query`: Received a new incoming shipping query
|
||||
1. `pre_checkout_query`: Received a new incoming pre-checkout query
|
||||
1. `poll`: Received a new incoming poll
|
||||
2. `poll_answer`: A user has changed their answer in a non-anonymous poll (Only polls sent by the bot)
|
||||
3. `chat_member`: A chat member's status was updated in a chat
|
||||
4. `my_chat_member`: The bot's chat member status was updated in a chat
|
||||
5. `chat_join_request`: A request to join the chat has been sent (The bot must have the can_invite_users administrator right)
|
||||
5. `polling_error`: Error occurred during polling. See [polling errors](#polling-errors).
|
||||
6. `webhook_error`: Error occurred handling a webhook request. See [webhook errors](#webhook-errors).
|
||||
7. `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.
|
||||
|
||||
**Tip:** Bot must be enabled on [inline mode][inline-mode] for receive some
|
||||
messages.
|
||||
|
||||
<a name="webhooks"></a>
|
||||
## WebHooks
|
||||
|
||||
Telegram only supports HTTPS connections to WebHooks.
|
||||
Therefore, in order to set a WebHook, you will need a SSL certificate.
|
||||
Since August 29, 2015 Telegram supports self-signed ones, thus, you can
|
||||
generate them:
|
||||
|
||||
```bash
|
||||
# Our private cert will be key.pem, keep this file private
|
||||
$ openssl genrsa -out key.pem 2048
|
||||
|
||||
# Our public certificate will be crt.pem
|
||||
$ openssl req -new -sha256 -key key.pem -out crt.pem
|
||||
```
|
||||
|
||||
Once they are generated, the `crt.pem` should be uploaded, when setting up
|
||||
your webhook. For example,
|
||||
|
||||
```js
|
||||
bot.setWebHook('public-url.com', {
|
||||
certificate: 'path/to/crt.pem', // Path to your crt.pem
|
||||
});
|
||||
```
|
||||
|
||||
**Note:** If you encounter an error, like
|
||||
`Error: error:0906D06C:PEM routines:PEM_read_bio:no start line`,
|
||||
you may want to proceed to [this issue][issue-63] for more information.
|
||||
|
||||
<a name="sending-files"></a>
|
||||
## Sending files
|
||||
|
||||
The library makes it easy to get started sending files. *By default*, you
|
||||
may provide a **file-path** and the library will handle reading it for you.
|
||||
For example,
|
||||
|
||||
```js
|
||||
bot.sendAudio(chatId, 'path/to/audio.mp3');
|
||||
```
|
||||
|
||||
You may also pass in a **Readable Stream** from which data will be piped.
|
||||
For example,
|
||||
|
||||
```js
|
||||
const stream = fs.createReadStream('path/to/audio.mp3');
|
||||
bot.sendAudio(chatId, stream);
|
||||
```
|
||||
|
||||
You may also pass in a **Buffer** containing the contents of your file.
|
||||
For example,
|
||||
|
||||
```js
|
||||
const buffer = fs.readFileSync('path/to/audio.mp3'); // sync! that's sad! :-( Just making a point!
|
||||
bot.sendAudio(chatId, buffer);
|
||||
```
|
||||
|
||||
If you already have a **File ID**, you earlier retrieved from Telegram,
|
||||
you may pass it in, for example:
|
||||
|
||||
```js
|
||||
const fileId = getFileIdSomehow();
|
||||
bot.sendAudio(chatId, fileId);
|
||||
```
|
||||
|
||||
Some API methods, such as *SendPhoto*, allow passing a **HTTP URL**, that
|
||||
the Telegram servers will use to download the file. For example,
|
||||
|
||||
```js
|
||||
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
|
||||
|
||||
To support providing file-paths to methods that send files involves
|
||||
performing a file operation, i.e. *fs.existsSync()*, that checks for
|
||||
the existence of the file at the provided path. While the cost of
|
||||
this operation *might* be negligible in most use cases, if you want
|
||||
to squeeze the best performance out of this library, you may wish to
|
||||
disable this behavior.
|
||||
|
||||
This will mean that you will **NOT** be able to pass in file-paths.
|
||||
You will have to use Streams or Buffers to provide the file contents.
|
||||
|
||||
Disabling this behavior:
|
||||
|
||||
```js
|
||||
const bot = new TelegramBot(token, {
|
||||
filepath: false,
|
||||
});
|
||||
```
|
||||
|
||||
<a name="error-handling"></a>
|
||||
## Error handling
|
||||
|
||||
Every `Error` object we pass back has the properties:
|
||||
|
||||
* `code` (String):
|
||||
* value is `EFATAL` if error was fatal e.g. network error
|
||||
* value is `EPARSE` if response body could **not** be parsed
|
||||
* value is `ETELEGRAM` if error was returned from Telegram servers
|
||||
* `response` ([http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)):
|
||||
* available if `error.code` is **not** `EFATAL`
|
||||
* `response.body` (String|Object): Error response from Telegram
|
||||
* type is `String` if `error.code` is `EPARSE`
|
||||
* type is `Object` if `error.code` is `ETELEGRAM`
|
||||
|
||||
For example, sending message to a non-existent user:
|
||||
|
||||
```js
|
||||
bot.sendMessage(nonExistentUserId, 'text').catch((error) => {
|
||||
console.log(error.code); // => 'ETELEGRAM'
|
||||
console.log(error.response.body); // => { ok: false, error_code: 400, description: 'Bad Request: chat not found' }
|
||||
});
|
||||
```
|
||||
|
||||
<a name="polling-errors"></a>
|
||||
## Polling errors
|
||||
|
||||
An error may occur during polling. It is up to you to handle it
|
||||
as you see fit. You may decide to crash your bot after a maximum number
|
||||
of polling errors occurring. **It is all up to you.**
|
||||
|
||||
By default, the polling error is just logged to stderr, if you do
|
||||
**not** handle this event yourself.
|
||||
|
||||
Listen on the `'polling_error'` event. For example,
|
||||
|
||||
```js
|
||||
bot.on('polling_error', (error) => {
|
||||
console.log(error.code); // => 'EFATAL'
|
||||
});
|
||||
```
|
||||
|
||||
<a name="webhook-errors"></a>
|
||||
## WebHook errors
|
||||
|
||||
Just like with [polling errors](#polling-errors), you decide on how to
|
||||
handle it. By default, the error is logged to stderr.
|
||||
|
||||
Listen on the `'webhook_error'` event. For example,
|
||||
|
||||
```js
|
||||
bot.on('webhook_error', (error) => {
|
||||
console.log(error.code); // => 'EPARSE'
|
||||
});
|
||||
```
|
||||
|
||||
[update]:https://core.telegram.org/bots/api#update
|
||||
[message]:https://core.telegram.org/bots/api#message
|
||||
[callback-query]:https://core.telegram.org/bots/api#callbackquery
|
||||
[inline-query]:https://core.telegram.org/bots/api#inlinequery
|
||||
[chosen-inline-result]:https://core.telegram.org/bots/api#choseninlineresult
|
||||
[inline-mode]:https://core.telegram.org/bots/api#inline-mode
|
||||
[issue-63]:https://github.com/yagop/node-telegram-bot-api/issues/63
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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('./src/utils').deprecate;
|
||||
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');
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
'use strict';
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||||
|
||||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||||
|
||||
exports.BaseError = function (_Error) {
|
||||
_inherits(BaseError, _Error);
|
||||
|
||||
/**
|
||||
* @class BaseError
|
||||
* @constructor
|
||||
* @private
|
||||
* @param {String} code Error code
|
||||
* @param {String} message Error message
|
||||
*/
|
||||
function BaseError(code, message) {
|
||||
_classCallCheck(this, BaseError);
|
||||
|
||||
var _this = _possibleConstructorReturn(this, (BaseError.__proto__ || Object.getPrototypeOf(BaseError)).call(this, code + ': ' + message));
|
||||
|
||||
_this.code = code;
|
||||
return _this;
|
||||
}
|
||||
|
||||
_createClass(BaseError, [{
|
||||
key: 'toJSON',
|
||||
value: function toJSON() {
|
||||
return {
|
||||
code: this.code,
|
||||
message: this.message
|
||||
};
|
||||
}
|
||||
}]);
|
||||
|
||||
return BaseError;
|
||||
}(Error);
|
||||
|
||||
exports.FatalError = function (_exports$BaseError) {
|
||||
_inherits(FatalError, _exports$BaseError);
|
||||
|
||||
/**
|
||||
* Fatal Error. Error code is `"EFATAL"`.
|
||||
* @class FatalError
|
||||
* @constructor
|
||||
* @param {String|Error} data Error object or message
|
||||
*/
|
||||
function FatalError(data) {
|
||||
_classCallCheck(this, FatalError);
|
||||
|
||||
var error = typeof data === 'string' ? null : data;
|
||||
var message = error ? error.message : data;
|
||||
|
||||
var _this2 = _possibleConstructorReturn(this, (FatalError.__proto__ || Object.getPrototypeOf(FatalError)).call(this, 'EFATAL', message));
|
||||
|
||||
if (error) _this2.stack = error.stack;
|
||||
return _this2;
|
||||
}
|
||||
|
||||
return FatalError;
|
||||
}(exports.BaseError);
|
||||
|
||||
exports.ParseError = function (_exports$BaseError2) {
|
||||
_inherits(ParseError, _exports$BaseError2);
|
||||
|
||||
/**
|
||||
* Error during parsing. Error code is `"EPARSE"`.
|
||||
* @class ParseError
|
||||
* @constructor
|
||||
* @param {String} message Error message
|
||||
* @param {http.IncomingMessage} response Server response
|
||||
*/
|
||||
function ParseError(message, response) {
|
||||
_classCallCheck(this, ParseError);
|
||||
|
||||
var _this3 = _possibleConstructorReturn(this, (ParseError.__proto__ || Object.getPrototypeOf(ParseError)).call(this, 'EPARSE', message));
|
||||
|
||||
_this3.response = response;
|
||||
return _this3;
|
||||
}
|
||||
|
||||
return ParseError;
|
||||
}(exports.BaseError);
|
||||
|
||||
exports.TelegramError = function (_exports$BaseError3) {
|
||||
_inherits(TelegramError, _exports$BaseError3);
|
||||
|
||||
/**
|
||||
* Error returned from Telegram. Error code is `"ETELEGRAM"`.
|
||||
* @class TelegramError
|
||||
* @constructor
|
||||
* @param {String} message Error message
|
||||
* @param {http.IncomingMessage} response Server response
|
||||
*/
|
||||
function TelegramError(message, response) {
|
||||
_classCallCheck(this, TelegramError);
|
||||
|
||||
var _this4 = _possibleConstructorReturn(this, (TelegramError.__proto__ || Object.getPrototypeOf(TelegramError)).call(this, 'ETELEGRAM', message));
|
||||
|
||||
_this4.response = response;
|
||||
return _this4;
|
||||
}
|
||||
|
||||
return TelegramError;
|
||||
}(exports.BaseError);
|
||||
+3830
File diff suppressed because it is too large.
Load diff
+245
@@ -0,0 +1,245 @@
|
||||
'use strict';
|
||||
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var errors = require('./errors');
|
||||
var debug = require('debug')('node-telegram-bot-api');
|
||||
var deprecate = require('./utils').deprecate;
|
||||
var ANOTHER_WEB_HOOK_USED = 409;
|
||||
|
||||
var TelegramBotPolling = function () {
|
||||
/**
|
||||
* Handles polling against the Telegram servers.
|
||||
* @param {TelegramBot} bot
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
*/
|
||||
function TelegramBotPolling(bot) {
|
||||
_classCallCheck(this, TelegramBotPolling);
|
||||
|
||||
this.bot = bot;
|
||||
this.options = typeof bot.options.polling === 'boolean' ? {} : bot.options.polling;
|
||||
this.options.interval = typeof this.options.interval === 'number' ? this.options.interval : 300;
|
||||
this.options.params = _typeof(this.options.params) === 'object' ? this.options.params : {};
|
||||
this.options.params.offset = typeof this.options.params.offset === 'number' ? this.options.params.offset : 0;
|
||||
this.options.params.timeout = typeof this.options.params.timeout === 'number' ? this.options.params.timeout : 10;
|
||||
if (typeof this.options.timeout === 'number') {
|
||||
deprecate('`options.polling.timeout` is deprecated. Use `options.polling.params` instead.');
|
||||
this.options.params.timeout = this.options.timeout;
|
||||
}
|
||||
this._lastUpdate = 0;
|
||||
this._lastRequest = null;
|
||||
this._abort = false;
|
||||
this._pollingTimeout = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start polling
|
||||
* @param {Object} [options]
|
||||
* @param {Object} [options.restart]
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
|
||||
_createClass(TelegramBotPolling, [{
|
||||
key: 'start',
|
||||
value: function start() {
|
||||
var _this = this;
|
||||
|
||||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
|
||||
if (this._lastRequest) {
|
||||
if (!options.restart) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this.stop({
|
||||
cancel: true,
|
||||
reason: 'Polling restart'
|
||||
}).then(function () {
|
||||
return _this._polling();
|
||||
});
|
||||
}
|
||||
return this._polling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop polling
|
||||
* @param {Object} [options] Options
|
||||
* @param {Boolean} [options.cancel] Cancel current request
|
||||
* @param {String} [options.reason] Reason for stopping polling
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'stop',
|
||||
value: function stop() {
|
||||
var _this2 = this;
|
||||
|
||||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
|
||||
if (!this._lastRequest) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
var lastRequest = this._lastRequest;
|
||||
this._lastRequest = null;
|
||||
clearTimeout(this._pollingTimeout);
|
||||
if (options.cancel) {
|
||||
var reason = options.reason || 'Polling stop';
|
||||
lastRequest.cancel(reason);
|
||||
return Promise.resolve();
|
||||
}
|
||||
this._abort = true;
|
||||
return lastRequest.finally(function () {
|
||||
_this2._abort = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if is polling. Otherwise, `false`.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'isPolling',
|
||||
value: function isPolling() {
|
||||
return !!this._lastRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle error thrown during polling.
|
||||
* @private
|
||||
* @param {Error} error
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_error',
|
||||
value: function _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
|
||||
* @private
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_polling',
|
||||
value: function _polling() {
|
||||
var _this3 = this;
|
||||
|
||||
this._lastRequest = this._getUpdates().then(function (updates) {
|
||||
_this3._lastUpdate = Date.now();
|
||||
debug('polling data %j', updates);
|
||||
updates.forEach(function (update) {
|
||||
_this3.options.params.offset = update.update_id + 1;
|
||||
debug('updated offset: %s', _this3.options.params.offset);
|
||||
try {
|
||||
_this3.bot.processUpdate(update);
|
||||
} catch (err) {
|
||||
err._processing = true;
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}).catch(function (err) {
|
||||
debug('polling error: %s', err.message);
|
||||
if (!err._processing) {
|
||||
return _this3._error(err);
|
||||
}
|
||||
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 (!_this3.bot.options.badRejection) {
|
||||
return _this3._error(err);
|
||||
}
|
||||
var opts = {
|
||||
offset: _this3.options.params.offset,
|
||||
limit: 1,
|
||||
timeout: 0
|
||||
};
|
||||
return _this3.bot.getUpdates(opts).then(function () {
|
||||
return _this3._error(err);
|
||||
}).catch(function (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 */
|
||||
var 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 _this3.bot.emit('error', new errors.FatalError(err));
|
||||
});
|
||||
}).finally(function () {
|
||||
if (_this3._abort) {
|
||||
debug('Polling is aborted!');
|
||||
} else {
|
||||
debug('setTimeout for %s miliseconds', _this3.options.interval);
|
||||
_this3._pollingTimeout = setTimeout(function () {
|
||||
return _this3._polling();
|
||||
}, _this3.options.interval);
|
||||
}
|
||||
});
|
||||
return this._lastRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset current webhook. Used when we detect that a webhook has been set
|
||||
* and we are trying to poll. Polling and WebHook are mutually exclusive.
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
* @private
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_unsetWebHook',
|
||||
value: function _unsetWebHook() {
|
||||
debug('unsetting webhook');
|
||||
return this.bot._request('setWebHook');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve updates
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_getUpdates',
|
||||
value: function _getUpdates() {
|
||||
var _this4 = this;
|
||||
|
||||
debug('polling with options: %j', this.options.params);
|
||||
return this.bot.getUpdates(this.options.params).catch(function (err) {
|
||||
if (err.response && err.response.statusCode === ANOTHER_WEB_HOOK_USED) {
|
||||
return _this4._unsetWebHook().then(function () {
|
||||
return _this4.bot.getUpdates(_this4.options.params);
|
||||
});
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}]);
|
||||
|
||||
return TelegramBotPolling;
|
||||
}();
|
||||
|
||||
module.exports = TelegramBotPolling;
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
'use strict';
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var errors = require('./errors');
|
||||
var debug = require('debug')('node-telegram-bot-api');
|
||||
var https = require('https');
|
||||
var http = require('http');
|
||||
var fs = require('fs');
|
||||
var bl = require('bl');
|
||||
|
||||
var TelegramBotWebHook = function () {
|
||||
/**
|
||||
* Sets up a webhook to receive updates
|
||||
* @param {TelegramBot} bot
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
*/
|
||||
function TelegramBotWebHook(bot) {
|
||||
_classCallCheck(this, TelegramBotWebHook);
|
||||
|
||||
this.bot = bot;
|
||||
this.options = typeof bot.options.webHook === 'boolean' ? {} : bot.options.webHook;
|
||||
this.options.host = this.options.host || '0.0.0.0';
|
||||
this.options.port = this.options.port || 8443;
|
||||
this.options.https = this.options.https || {};
|
||||
this.options.healthEndpoint = this.options.healthEndpoint || '/healthz';
|
||||
this._healthRegex = new RegExp(this.options.healthEndpoint);
|
||||
this._webServer = null;
|
||||
this._open = false;
|
||||
this._requestListener = this._requestListener.bind(this);
|
||||
this._parseBody = this._parseBody.bind(this);
|
||||
|
||||
if (this.options.key && this.options.cert) {
|
||||
debug('HTTPS WebHook enabled (by key/cert)');
|
||||
this.options.https.key = fs.readFileSync(this.options.key);
|
||||
this.options.https.cert = fs.readFileSync(this.options.cert);
|
||||
this._webServer = https.createServer(this.options.https, this._requestListener);
|
||||
} else if (this.options.pfx) {
|
||||
debug('HTTPS WebHook enabled (by pfx)');
|
||||
this.options.https.pfx = fs.readFileSync(this.options.pfx);
|
||||
this._webServer = https.createServer(this.options.https, this._requestListener);
|
||||
} else if (Object.keys(this.options.https).length) {
|
||||
debug('HTTPS WebHook enabled by (https)');
|
||||
this._webServer = https.createServer(this.options.https, this._requestListener);
|
||||
} else {
|
||||
debug('HTTP WebHook enabled');
|
||||
this._webServer = http.createServer(this._requestListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open WebHook by listening on the port
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
|
||||
_createClass(TelegramBotWebHook, [{
|
||||
key: 'open',
|
||||
value: function open() {
|
||||
var _this = this;
|
||||
|
||||
if (this.isOpen()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
_this._webServer.listen(_this.options.port, _this.options.host, function () {
|
||||
debug('WebHook listening on port %s', _this.options.port);
|
||||
_this._open = true;
|
||||
return resolve();
|
||||
});
|
||||
|
||||
_this._webServer.once('error', function (err) {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the webHook
|
||||
* @return {Promise}
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'close',
|
||||
value: function close() {
|
||||
var _this2 = this;
|
||||
|
||||
if (!this.isOpen()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
_this2._webServer.close(function (error) {
|
||||
if (error) return reject(error);
|
||||
_this2._open = false;
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if server is listening. Otherwise, `false`.
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: 'isOpen',
|
||||
value: function isOpen() {
|
||||
// NOTE: Since `http.Server.listening` was added in v5.7.0
|
||||
// and we still need to support Node v4,
|
||||
// we are going to fallback to 'this._open'.
|
||||
// The following LOC would suffice for newer versions of Node.js
|
||||
// return this._webServer.listening;
|
||||
return this._open;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle error thrown during processing of webhook request.
|
||||
* @private
|
||||
* @param {Error} error
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_error',
|
||||
value: function _error(error) {
|
||||
if (!this.bot.listeners('webhook_error').length) {
|
||||
return console.error('error: [webhook_error] %j', error); // eslint-disable-line no-console
|
||||
}
|
||||
return this.bot.emit('webhook_error', error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request body by passing it to 'callback'
|
||||
* @private
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_parseBody',
|
||||
value: function _parseBody(error, body) {
|
||||
if (error) {
|
||||
return this._error(new errors.FatalError(error));
|
||||
}
|
||||
|
||||
var data = void 0;
|
||||
try {
|
||||
data = JSON.parse(body.toString());
|
||||
} catch (parseError) {
|
||||
return this._error(new errors.ParseError(parseError.message));
|
||||
}
|
||||
|
||||
return this.bot.processUpdate(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for 'request' event on server
|
||||
* @private
|
||||
* @see https://nodejs.org/docs/latest/api/http.html#http_http_createserver_requestlistener
|
||||
* @see https://nodejs.org/docs/latest/api/https.html#https_https_createserver_options_requestlistener
|
||||
*/
|
||||
|
||||
}, {
|
||||
key: '_requestListener',
|
||||
value: function _requestListener(req, res) {
|
||||
debug('WebHook request URL: %s', req.url);
|
||||
debug('WebHook request headers: %j', req.headers);
|
||||
|
||||
if (req.url.indexOf(this.bot.token) !== -1) {
|
||||
if (req.method !== 'POST') {
|
||||
debug('WebHook request isn\'t a POST');
|
||||
res.statusCode = 418; // I'm a teabot!
|
||||
res.end();
|
||||
} else {
|
||||
req.pipe(bl(this._parseBody)).on('finish', function () {
|
||||
return res.end('OK');
|
||||
});
|
||||
}
|
||||
} else if (this._healthRegex.test(req.url)) {
|
||||
debug('WebHook health check passed');
|
||||
res.statusCode = 200;
|
||||
res.end('OK');
|
||||
} else {
|
||||
debug('WebHook request unauthorized');
|
||||
res.statusCode = 401;
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
}]);
|
||||
|
||||
return TelegramBotWebHook;
|
||||
}();
|
||||
|
||||
module.exports = TelegramBotWebHook;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var util = require('util');
|
||||
// Native deprecation warning
|
||||
exports.deprecate = function (msg) {
|
||||
return util.deprecate(function () {}, msg, 'node-telegram-bot-api')();
|
||||
};
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"name": "node-telegram-bot-api",
|
||||
"version": "0.66.0",
|
||||
"description": "Telegram Bot API",
|
||||
"main": "./index.js",
|
||||
"directories": {
|
||||
"example": "examples",
|
||||
"test": "test"
|
||||
},
|
||||
"keywords": [
|
||||
"telegram",
|
||||
"telegram bot",
|
||||
"telegram bot api",
|
||||
"bot"
|
||||
],
|
||||
"scripts": {
|
||||
"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",
|
||||
"prepublishOnly": "npm run build && npm run gen-doc",
|
||||
"eslint": "eslint ./src ./test ./examples",
|
||||
"mocha": "mocha",
|
||||
"pretest": "npm run build",
|
||||
"test": "npm run eslint && istanbul cover ./node_modules/mocha/bin/_mocha"
|
||||
},
|
||||
"author": "Yago Pérez <yagoperezs@gmail.com>",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cypress/request": "^3.0.1",
|
||||
"@cypress/request-promise": "^5.0.0",
|
||||
"array.prototype.findindex": "^2.0.2",
|
||||
"bl": "^1.2.3",
|
||||
"debug": "^3.2.7",
|
||||
"eventemitter3": "^3.0.0",
|
||||
"file-type": "^3.9.0",
|
||||
"mime": "^1.6.0",
|
||||
"pump": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"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",
|
||||
"eslint": "^2.13.1",
|
||||
"eslint-config-airbnb": "^6.2.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": "^3.0.3",
|
||||
"mocha": "^3.5.3",
|
||||
"mocha-lcov-reporter": "^1.3.0",
|
||||
"node-static": "^0.7.10"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/yagop/node-telegram-bot-api.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/yagop/node-telegram-bot-api/issues"
|
||||
},
|
||||
"homepage": "https://github.com/yagop/node-telegram-bot-api"
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
exports.BaseError = class BaseError extends Error {
|
||||
/**
|
||||
* @class BaseError
|
||||
* @constructor
|
||||
* @private
|
||||
* @param {String} code Error code
|
||||
* @param {String} message Error message
|
||||
*/
|
||||
constructor(code, message) {
|
||||
super(`${code}: ${message}`);
|
||||
this.code = code;
|
||||
}
|
||||
toJSON() {
|
||||
return {
|
||||
code: this.code,
|
||||
message: this.message,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.FatalError = class FatalError extends exports.BaseError {
|
||||
/**
|
||||
* Fatal Error. Error code is `"EFATAL"`.
|
||||
* @class FatalError
|
||||
* @constructor
|
||||
* @param {String|Error} data Error object or message
|
||||
*/
|
||||
constructor(data) {
|
||||
const error = (typeof data === 'string') ? null : data;
|
||||
const message = error ? error.message : data;
|
||||
super('EFATAL', message);
|
||||
if (error) this.stack = error.stack;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.ParseError = class ParseError extends exports.BaseError {
|
||||
/**
|
||||
* Error during parsing. Error code is `"EPARSE"`.
|
||||
* @class ParseError
|
||||
* @constructor
|
||||
* @param {String} message Error message
|
||||
* @param {http.IncomingMessage} response Server response
|
||||
*/
|
||||
constructor(message, response) {
|
||||
super('EPARSE', message);
|
||||
this.response = response;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.TelegramError = class TelegramError extends exports.BaseError {
|
||||
/**
|
||||
* Error returned from Telegram. Error code is `"ETELEGRAM"`.
|
||||
* @class TelegramError
|
||||
* @constructor
|
||||
* @param {String} message Error message
|
||||
* @param {http.IncomingMessage} response Server response
|
||||
*/
|
||||
constructor(message, response) {
|
||||
super('ETELEGRAM', message);
|
||||
this.response = response;
|
||||
}
|
||||
};
|
||||
+3113
File diff suppressed because it is too large.
Load diff
+202
@@ -0,0 +1,202 @@
|
||||
const errors = require('./errors');
|
||||
const debug = require('debug')('node-telegram-bot-api');
|
||||
const deprecate = require('./utils').deprecate;
|
||||
const ANOTHER_WEB_HOOK_USED = 409;
|
||||
|
||||
|
||||
class TelegramBotPolling {
|
||||
/**
|
||||
* Handles polling against the Telegram servers.
|
||||
* @param {TelegramBot} bot
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
*/
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
this.options = (typeof bot.options.polling === 'boolean') ? {} : bot.options.polling;
|
||||
this.options.interval = (typeof this.options.interval === 'number') ? this.options.interval : 300;
|
||||
this.options.params = (typeof this.options.params === 'object') ? this.options.params : {};
|
||||
this.options.params.offset = (typeof this.options.params.offset === 'number') ? this.options.params.offset : 0;
|
||||
this.options.params.timeout = (typeof this.options.params.timeout === 'number') ? this.options.params.timeout : 10;
|
||||
if (typeof this.options.timeout === 'number') {
|
||||
deprecate('`options.polling.timeout` is deprecated. Use `options.polling.params` instead.');
|
||||
this.options.params.timeout = this.options.timeout;
|
||||
}
|
||||
this._lastUpdate = 0;
|
||||
this._lastRequest = null;
|
||||
this._abort = false;
|
||||
this._pollingTimeout = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start polling
|
||||
* @param {Object} [options]
|
||||
* @param {Object} [options.restart]
|
||||
* @return {Promise}
|
||||
*/
|
||||
start(options = {}) {
|
||||
if (this._lastRequest) {
|
||||
if (!options.restart) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this.stop({
|
||||
cancel: true,
|
||||
reason: 'Polling restart',
|
||||
}).then(() => {
|
||||
return this._polling();
|
||||
});
|
||||
}
|
||||
return this._polling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop polling
|
||||
* @param {Object} [options] Options
|
||||
* @param {Boolean} [options.cancel] Cancel current request
|
||||
* @param {String} [options.reason] Reason for stopping polling
|
||||
* @return {Promise}
|
||||
*/
|
||||
stop(options = {}) {
|
||||
if (!this._lastRequest) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const lastRequest = this._lastRequest;
|
||||
this._lastRequest = null;
|
||||
clearTimeout(this._pollingTimeout);
|
||||
if (options.cancel) {
|
||||
const reason = options.reason || 'Polling stop';
|
||||
lastRequest.cancel(reason);
|
||||
return Promise.resolve();
|
||||
}
|
||||
this._abort = true;
|
||||
return lastRequest.finally(() => {
|
||||
this._abort = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if is polling. Otherwise, `false`.
|
||||
*/
|
||||
isPolling() {
|
||||
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
|
||||
* @private
|
||||
*/
|
||||
_polling() {
|
||||
this._lastRequest = this
|
||||
._getUpdates()
|
||||
.then(updates => {
|
||||
this._lastUpdate = Date.now();
|
||||
debug('polling data %j', updates);
|
||||
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 (!err._processing) {
|
||||
return this._error(err);
|
||||
}
|
||||
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) {
|
||||
debug('Polling is aborted!');
|
||||
} else {
|
||||
debug('setTimeout for %s miliseconds', this.options.interval);
|
||||
this._pollingTimeout = setTimeout(() => this._polling(), this.options.interval);
|
||||
}
|
||||
});
|
||||
return this._lastRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset current webhook. Used when we detect that a webhook has been set
|
||||
* and we are trying to poll. Polling and WebHook are mutually exclusive.
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
* @private
|
||||
*/
|
||||
_unsetWebHook() {
|
||||
debug('unsetting webhook');
|
||||
return this.bot._request('setWebHook');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve updates
|
||||
*/
|
||||
_getUpdates() {
|
||||
debug('polling with options: %j', this.options.params);
|
||||
return this.bot.getUpdates(this.options.params)
|
||||
.catch(err => {
|
||||
if (err.response && err.response.statusCode === ANOTHER_WEB_HOOK_USED) {
|
||||
return this._unsetWebHook().then(() => {
|
||||
return this.bot.getUpdates(this.options.params);
|
||||
});
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TelegramBotPolling;
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
const errors = require('./errors');
|
||||
const debug = require('debug')('node-telegram-bot-api');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
const bl = require('bl');
|
||||
|
||||
class TelegramBotWebHook {
|
||||
/**
|
||||
* Sets up a webhook to receive updates
|
||||
* @param {TelegramBot} bot
|
||||
* @see https://core.telegram.org/bots/api#getting-updates
|
||||
*/
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
this.options = (typeof bot.options.webHook === 'boolean') ? {} : bot.options.webHook;
|
||||
this.options.host = this.options.host || '0.0.0.0';
|
||||
this.options.port = this.options.port || 8443;
|
||||
this.options.https = this.options.https || {};
|
||||
this.options.healthEndpoint = this.options.healthEndpoint || '/healthz';
|
||||
this._healthRegex = new RegExp(this.options.healthEndpoint);
|
||||
this._webServer = null;
|
||||
this._open = false;
|
||||
this._requestListener = this._requestListener.bind(this);
|
||||
this._parseBody = this._parseBody.bind(this);
|
||||
|
||||
if (this.options.key && this.options.cert) {
|
||||
debug('HTTPS WebHook enabled (by key/cert)');
|
||||
this.options.https.key = fs.readFileSync(this.options.key);
|
||||
this.options.https.cert = fs.readFileSync(this.options.cert);
|
||||
this._webServer = https.createServer(this.options.https, this._requestListener);
|
||||
} else if (this.options.pfx) {
|
||||
debug('HTTPS WebHook enabled (by pfx)');
|
||||
this.options.https.pfx = fs.readFileSync(this.options.pfx);
|
||||
this._webServer = https.createServer(this.options.https, this._requestListener);
|
||||
} else if (Object.keys(this.options.https).length) {
|
||||
debug('HTTPS WebHook enabled by (https)');
|
||||
this._webServer = https.createServer(this.options.https, this._requestListener);
|
||||
} else {
|
||||
debug('HTTP WebHook enabled');
|
||||
this._webServer = http.createServer(this._requestListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open WebHook by listening on the port
|
||||
* @return {Promise}
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._webServer.listen(this.options.port, this.options.host, () => {
|
||||
debug('WebHook listening on port %s', this.options.port);
|
||||
this._open = true;
|
||||
return resolve();
|
||||
});
|
||||
|
||||
this._webServer.once('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the webHook
|
||||
* @return {Promise}
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen()) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this._webServer.close(error => {
|
||||
if (error) return reject(error);
|
||||
this._open = false;
|
||||
return resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if server is listening. Otherwise, `false`.
|
||||
*/
|
||||
isOpen() {
|
||||
// NOTE: Since `http.Server.listening` was added in v5.7.0
|
||||
// and we still need to support Node v4,
|
||||
// we are going to fallback to 'this._open'.
|
||||
// The following LOC would suffice for newer versions of Node.js
|
||||
// return this._webServer.listening;
|
||||
return this._open;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle error thrown during processing of webhook request.
|
||||
* @private
|
||||
* @param {Error} error
|
||||
*/
|
||||
_error(error) {
|
||||
if (!this.bot.listeners('webhook_error').length) {
|
||||
return console.error('error: [webhook_error] %j', error); // eslint-disable-line no-console
|
||||
}
|
||||
return this.bot.emit('webhook_error', error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request body by passing it to 'callback'
|
||||
* @private
|
||||
*/
|
||||
_parseBody(error, body) {
|
||||
if (error) {
|
||||
return this._error(new errors.FatalError(error));
|
||||
}
|
||||
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(body.toString());
|
||||
} catch (parseError) {
|
||||
return this._error(new errors.ParseError(parseError.message));
|
||||
}
|
||||
|
||||
return this.bot.processUpdate(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for 'request' event on server
|
||||
* @private
|
||||
* @see https://nodejs.org/docs/latest/api/http.html#http_http_createserver_requestlistener
|
||||
* @see https://nodejs.org/docs/latest/api/https.html#https_https_createserver_options_requestlistener
|
||||
*/
|
||||
_requestListener(req, res) {
|
||||
debug('WebHook request URL: %s', req.url);
|
||||
debug('WebHook request headers: %j', req.headers);
|
||||
|
||||
if (req.url.indexOf(this.bot.token) !== -1) {
|
||||
if (req.method !== 'POST') {
|
||||
debug('WebHook request isn\'t a POST');
|
||||
res.statusCode = 418; // I'm a teabot!
|
||||
res.end();
|
||||
} else {
|
||||
req
|
||||
.pipe(bl(this._parseBody))
|
||||
.on('finish', () => res.end('OK'));
|
||||
}
|
||||
} else if (this._healthRegex.test(req.url)) {
|
||||
debug('WebHook health check passed');
|
||||
res.statusCode = 200;
|
||||
res.end('OK');
|
||||
} else {
|
||||
debug('WebHook request unauthorized');
|
||||
res.statusCode = 401;
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TelegramBotWebHook;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
const util = require('util');
|
||||
// Native deprecation warning
|
||||
exports.deprecate = (msg) => util.deprecate(() => { }, msg, 'node-telegram-bot-api')();
|
||||
Reference in new issue
Block a user