diff --git a/CHANGELOG.md b/CHANGELOG.md
index f659140..61f564b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,21 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [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:
diff --git a/README.md b/README.md
index 36ac782..7e720ff 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Node.js module to interact with the official [Telegram Bot API](https://core.telegram.org/bots/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)
diff --git a/doc/api.md b/doc/api.md
index fb78579..1da6c16 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -54,6 +54,8 @@ TelegramBot
* [.createChatInviteLink(chatId, [options])](#TelegramBot+createChatInviteLink) ⇒ Object
* [.editChatInviteLink(chatId, inviteLink, [options])](#TelegramBot+editChatInviteLink) ⇒ Object
* [.revokeChatInviteLink(chatId, [options])](#TelegramBot+revokeChatInviteLink) ⇒ Object
+ * [.approveChatJoinRequest(chatId, userId, [options])](#TelegramBot+approveChatJoinRequest) ⇒ Boolean
+ * [.declineChatJoinRequest(chatId, userId, [options])](#TelegramBot+declineChatJoinRequest) ⇒ Boolean
* [.setChatPhoto(chatId, photo, [options], [fileOptions])](#TelegramBot+setChatPhoto) ⇒ Promise
* [.deleteChatPhoto(chatId, [options])](#TelegramBot+deleteChatPhoto) ⇒ Promise
* [.setChatTitle(chatId, title, [options])](#TelegramBot+setChatTitle) ⇒ Promise
@@ -584,7 +586,8 @@ Send chat action.
`typing` for text messages,
`upload_photo` for photos, `record_video` or `upload_video` for videos,
`record_voice` or `upload_voice` for audio files, `upload_document` for general files,
-`find_location` for location data.
+`choose_sticker` for stickers, `find_location` for location data,
+`record_video_note` or `upload_video_note` for video notes.
**Kind**: instance method of [TelegramBot
](#TelegramBot)
**See**: https://core.telegram.org/bots/api#sendchataction
@@ -782,6 +785,40 @@ Returns the revoked invite link as ChatInviteLink object.
| chatId | Number
\| String
| Unique identifier for the target chat or username of the target supergroup |
| [options] | Object
| Additional Telegram query options |
+
+
+### telegramBot.approveChatJoinRequest(chatId, userId, [options]) ⇒ Boolean
+Use this method to approve a chat join request.
+The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right.
+Returns True on success.
+
+**Kind**: instance method of [TelegramBot
](#TelegramBot)
+**Returns**: Boolean
- True on success
+**See**: https://core.telegram.org/bots/api#approvechatjoinrequest
+
+| Param | Type | Description |
+| --- | --- | --- |
+| chatId | Number
\| String
| Unique identifier for the target chat or username of the target supergroup |
+| userId | Number
| Unique identifier of the target user |
+| [options] | Object
| Additional Telegram query options |
+
+
+
+### telegramBot.declineChatJoinRequest(chatId, userId, [options]) ⇒ Boolean
+Use this method to decline a chat join request.
+The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right.
+Returns True on success.
+
+**Kind**: instance method of [TelegramBot
](#TelegramBot)
+**Returns**: Boolean
- True on success
+**See**: https://core.telegram.org/bots/api#declinechatjoinrequest
+
+| Param | Type | Description |
+| --- | --- | --- |
+| chatId | Number
\| String
| Unique identifier for the target chat or username of the target supergroup |
+| userId | Number
| Unique identifier of the target user |
+| [options] | Object
| Additional Telegram query options |
+
### telegramBot.setChatPhoto(chatId, photo, [options], [fileOptions]) ⇒ Promise
diff --git a/package.json b/package.json
index 03cdc3c..5bf2bce 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "node-telegram-bot-api",
- "version": "0.54.0",
+ "version": "0.55.0",
"description": "Telegram Bot API",
"main": "./index.js",
"directories": {
diff --git a/src/telegram.js b/src/telegram.js
index 15eb07b..7c84f20 100644
--- a/src/telegram.js
+++ b/src/telegram.js
@@ -624,6 +624,7 @@ class TelegramBot extends EventEmitter {
const pollAnswer = update.poll_answer;
const chatMember = update.chat_member;
const myChatMember = update.my_chat_member;
+ const chatJoinRequest = update.chat_join_request;
if (message) {
debug('Process Update message %j', message);
@@ -713,6 +714,9 @@ class TelegramBot extends EventEmitter {
} else if (myChatMember) {
debug('Process Update my_chat_member %j', myChatMember);
this.emit('my_chat_member', myChatMember);
+ } else if (chatJoinRequest) {
+ debug('Process Update my_chat_member %j', chatJoinRequest);
+ this.emit('chat_join_request', chatJoinRequest);
}
}
@@ -1017,7 +1021,8 @@ class TelegramBot extends EventEmitter {
* `typing` for text messages,
* `upload_photo` for photos, `record_video` or `upload_video` for videos,
* `record_voice` or `upload_voice` for audio files, `upload_document` for general files,
- * `find_location` for location data.
+ * `choose_sticker` for stickers, `find_location` for location data,
+ * `record_video_note` or `upload_video_note` for video notes.
*
* @param {Number|String} chatId Unique identifier for the message recipient
* @param {String} action Type of action to broadcast.
@@ -1225,6 +1230,40 @@ class TelegramBot extends EventEmitter {
return this._request('revokeChatInviteLink', { form });
}
+ /**
+ * Use this method to approve a chat join request.
+ * The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right.
+ * Returns True on success.
+ *
+ * @param {Number|String} chatId Unique identifier for the target chat or username of the target supergroup
+ * @param {Number} userId Unique identifier of the target user
+ * @param {Object} [options] Additional Telegram query options
+ * @return {Boolean} True on success
+ * @see https://core.telegram.org/bots/api#approvechatjoinrequest
+ */
+ approveChatJoinRequest(chatId, userId, form = {}) {
+ form.chat_id = chatId;
+ form.user_id = userId;
+ return this._request('approveChatJoinRequest', { form });
+ }
+
+ /**
+ * Use this method to decline a chat join request.
+ * The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right.
+ * Returns True on success.
+ *
+ * @param {Number|String} chatId Unique identifier for the target chat or username of the target supergroup
+ * @param {Number} userId Unique identifier of the target user
+ * @param {Object} [options] Additional Telegram query options
+ * @return {Boolean} True on success
+ * @see https://core.telegram.org/bots/api#declinechatjoinrequest
+ */
+ declineChatJoinRequest(chatId, userId, form = {}) {
+ form.chat_id = chatId;
+ form.user_id = userId;
+ return this._request('declineChatJoinRequest', { form });
+ }
+
/**
* Use this method to set a new profile photo for the chat. Photos can't be changed for private chats.
@@ -1477,7 +1516,43 @@ class TelegramBot extends EventEmitter {
* @see https://core.telegram.org/bots/api#editmessagemedia
*/
editMessageMedia(media, form = {}) {
+ const regexAttach = /attach:\/\/.+/;
+
+ if (typeof media.media === 'string' && regexAttach.test(media.media)) {
+ const opts = {
+ qs: form,
+ };
+
+ opts.formData = {};
+
+ const payload = Object.assign({}, media);
+ delete payload.media;
+
+ try {
+ const attachName = String(0);
+ const [formData] = this._formatSendData(
+ attachName,
+ media.media.replace('attach://', ''),
+ media.fileOptions,
+ );
+
+ if (formData) {
+ opts.formData[attachName] = formData[attachName];
+ payload.media = `attach://${attachName}`;
+ } else {
+ throw new errors.FatalError(`Failed to process the replacement action for your ${media.type}`);
+ }
+ } catch (ex) {
+ return Promise.reject(ex);
+ }
+
+ opts.qs.media = JSON.stringify(payload);
+
+ return this._request('editMessageMedia', opts);
+ }
+
form.media = stringify(media);
+
return this._request('editMessageMedia', { form });
}