From c3ba72eb8ae63ef31688e3f4e4056b4f969abef4 Mon Sep 17 00:00:00 2001 From: llnulldisk <48621230+llnulldisk@users.noreply.github.com> Date: Mon, 2 Jan 2023 21:55:47 +0100 Subject: [PATCH] Update to Bot API 6.4 --- README.md | 2 +- include/tgbot/Api.h | 89 ++++++++++++-- include/tgbot/TgTypeParser.h | 16 +++ include/tgbot/types/Chat.h | 15 +++ include/tgbot/types/ForumTopicEdited.h | 30 +++++ include/tgbot/types/GeneralForumTopicHidden.h | 21 ++++ .../tgbot/types/GeneralForumTopicUnhidden.h | 21 ++++ include/tgbot/types/InputMedia.h | 6 +- include/tgbot/types/InputMediaAnimation.h | 8 +- include/tgbot/types/InputMediaPhoto.h | 6 +- include/tgbot/types/InputMediaVideo.h | 12 +- include/tgbot/types/Message.h | 29 +++++ include/tgbot/types/ReplyKeyboardMarkup.h | 24 ++-- include/tgbot/types/WriteAccessAllowed.h | 21 ++++ src/Api.cpp | 113 ++++++++++++++---- src/TgTypeParser.cpp | 90 ++++++++++++++ 16 files changed, 455 insertions(+), 48 deletions(-) create mode 100644 include/tgbot/types/ForumTopicEdited.h create mode 100644 include/tgbot/types/GeneralForumTopicHidden.h create mode 100644 include/tgbot/types/GeneralForumTopicUnhidden.h create mode 100644 include/tgbot/types/WriteAccessAllowed.h diff --git a/README.md b/README.md index a65ac0091..202533b82 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Documentation is located [here](http://reo7sp.github.io/tgbot-cpp). ## State -- [x] Bot API 3.0 ~ 6.3 +- [x] Bot API 3.0 ~ 6.4 ## Sample diff --git a/include/tgbot/Api.h b/include/tgbot/Api.h index ae910320d..c3ae9220f 100644 --- a/include/tgbot/Api.h +++ b/include/tgbot/Api.h @@ -258,6 +258,7 @@ friend class Bot; * @param allowSendingWithoutReply Optional. Pass True if the message should be sent even if the specified replied-to message is not found * @param protectContent Optional. Protects the contents of the sent message from forwarding and saving * @param messageThreadId Optional. Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param hasSpoiler Optional. Pass True if the photo needs to be covered with a spoiler animation * * @return On success, the sent Message is returned. */ @@ -271,7 +272,8 @@ friend class Bot; const std::vector& captionEntities = std::vector(), bool allowSendingWithoutReply = false, bool protectContent = false, - std::int32_t messageThreadId = 0) const; + std::int32_t messageThreadId = 0, + bool hasSpoiler = false) const; /** * @brief Use this method to send audio files, if you want Telegram clients to display them in the music player. @@ -371,6 +373,7 @@ friend class Bot; * @param allowSendingWithoutReply Optional. Pass True if the message should be sent even if the specified replied-to message is not found * @param protectContent Optional. Protects the contents of the sent message from forwarding and saving * @param messageThreadId Optional. Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param hasSpoiler Optional. Pass True if the video needs to be covered with a spoiler animation * * @return On success, the sent Message is returned. */ @@ -389,7 +392,8 @@ friend class Bot; const std::vector& captionEntities = std::vector(), bool allowSendingWithoutReply = false, bool protectContent = false, - std::int32_t messageThreadId = 0) const; + std::int32_t messageThreadId = 0, + bool hasSpoiler = false) const; /** * @brief Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). @@ -411,6 +415,7 @@ friend class Bot; * @param allowSendingWithoutReply Optional. Pass True if the message should be sent even if the specified replied-to message is not found * @param protectContent Optional. Protects the contents of the sent message from forwarding and saving * @param messageThreadId Optional. Unique identifier for the target message thread (topic) of the forum; for forum supergroups only + * @param hasSpoiler Optional. Pass True if the animation needs to be covered with a spoiler animation * * @return On success, the sent Message is returned. */ @@ -428,7 +433,8 @@ friend class Bot; const std::vector& captionEntities = std::vector(), bool allowSendingWithoutReply = false, bool protectContent = false, - std::int32_t messageThreadId = 0) const; + std::int32_t messageThreadId = 0, + bool hasSpoiler = false) const; /** * @brief Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. @@ -732,18 +738,20 @@ friend class Bot; * The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). * * Example: The ImageBot needs some time to process a request and upload the image. - * Instead of sending a text message along the lines of “Retrieving image, please wait…”, the bot may use sendChatAction with action = upload_photo. + * Instead of sending a text message along the lines of “Retrieving image, please wait…”, the bot may use Api::sendChatAction with action = upload_photo. * The user will see a “sending photo” status for the bot. * * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive. * * @param chatId Unique identifier for the target chat or username of the target channel (in the format @channelusername) * @param action Type of action to broadcast. Choose one, depending on what the user is about to receive: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_voice or upload_voice for voice notes, upload_document for general files, choose_sticker for stickers, find_location for location data, record_video_note or upload_video_note for video notes. + * @param messageThreadId Optional. Unique identifier for the target message thread; supergroups only * - * @return True on success. + * @return Returns True on success. */ bool sendChatAction(std::int64_t chatId, - const std::string& action) const; + const std::string& action, + std::int32_t messageThreadId = 0) const; /** * @brief Use this method to get a list of profile pictures for a user. @@ -1149,6 +1157,8 @@ friend class Bot; /** * @brief Use this method to get information about a member of a chat. * + * The method is guaranteed to work for other users, only if the bot is an administrator in the chat. + * * @param chatId Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) * @param userId Unique identifier of the target user * @@ -1214,15 +1224,15 @@ friend class Bot; * * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) * @param messageThreadId Unique identifier for the target message thread of the forum topic - * @param name New topic name, 1-128 characters - * @param iconCustomEmojiId New unique identifier of the custom emoji shown as the topic icon. Use Api::getForumTopicIconStickers to get all allowed custom emoji identifiers + * @param name Optional. New topic name, 0-128 characters. If not specified or empty, the current name of the topic will be kept + * @param iconCustomEmojiId Optional. New unique identifier of the custom emoji shown as the topic icon. Use Api::getForumTopicIconStickers to get all allowed custom emoji identifiers. Pass an empty string to remove the icon. If not specified, the current icon will be kept * * @return Returns True on success. */ bool editForumTopic(boost::variant chatId, std::int32_t messageThreadId, - const std::string& name, - const std::string& iconCustomEmojiId) const; + const std::string& name = "", + boost::variant iconCustomEmojiId = 0) const; /** * @brief Use this method to close an open topic in a forum supergroup chat. @@ -1276,6 +1286,65 @@ friend class Bot; bool unpinAllForumTopicMessages(boost::variant chatId, std::int32_t messageThreadId) const; + /** + * @brief Use this method to edit the name of the 'General' topic in a forum supergroup chat. + * + * The bot must be an administrator in the chat for this to work and must have canManageTopics administrator rights. + * + * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) + * @param name New topic name, 1-128 characters + * + * @return Returns True on success. + */ + bool editGeneralForumTopic(boost::variant chatId, + std::string name) const; + + /** + * @brief Use this method to close an open 'General' topic in a forum supergroup chat. + * + * The bot must be an administrator in the chat for this to work and must have the canManageTopics administrator rights. + * + * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) + * + * @return Returns True on success. + */ + bool closeGeneralForumTopic(boost::variant chatId) const; + + /** + * @brief Use this method to reopen a closed 'General' topic in a forum supergroup chat. + * + * The bot must be an administrator in the chat for this to work and must have the canManageTopics administrator rights. + * The topic will be automatically unhidden if it was hidden. + * + * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) + * + * @return Returns True on success. + */ + bool reopenGeneralForumTopic(boost::variant chatId) const; + + /** + * @brief Use this method to hide the 'General' topic in a forum supergroup chat. + * + * The bot must be an administrator in the chat for this to work and must have the canManageTopics administrator rights. + * The topic will be automatically closed if it was open. + * + * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) + * + * @return Returns True on success. + */ + bool hideGeneralForumTopic(boost::variant chatId) const; + + /** + * @brief Use this method to unhide the 'General' topic in a forum supergroup chat. + * + * The bot must be an administrator in the chat for this to work and must have the canManageTopics administrator rights. + * + * @param chatId Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername) + * + * @return Returns True on success. + */ + bool unhideGeneralForumTopic(boost::variant chatId) const; + /** * @brief Use this method to send answers to callback queries sent from inline keyboards. * diff --git a/include/tgbot/TgTypeParser.h b/include/tgbot/TgTypeParser.h index b303c4768..66c1f8ffa 100644 --- a/include/tgbot/TgTypeParser.h +++ b/include/tgbot/TgTypeParser.h @@ -28,7 +28,11 @@ #include "tgbot/types/MessageAutoDeleteTimerChanged.h" #include "tgbot/types/ForumTopicCreated.h" #include "tgbot/types/ForumTopicClosed.h" +#include "tgbot/types/ForumTopicEdited.h" #include "tgbot/types/ForumTopicReopened.h" +#include "tgbot/types/GeneralForumTopicHidden.h" +#include "tgbot/types/GeneralForumTopicUnhidden.h" +#include "tgbot/types/WriteAccessAllowed.h" #include "tgbot/types/VideoChatScheduled.h" #include "tgbot/types/VideoChatStarted.h" #include "tgbot/types/VideoChatEnded.h" @@ -236,9 +240,21 @@ class TGBOT_API TgTypeParser { ForumTopicClosed::Ptr parseJsonAndGetForumTopicClosed(const boost::property_tree::ptree& data) const; std::string parseForumTopicClosed(const ForumTopicClosed::Ptr& object) const; + ForumTopicEdited::Ptr parseJsonAndGetForumTopicEdited(const boost::property_tree::ptree& data) const; + std::string parseForumTopicEdited(const ForumTopicEdited::Ptr& object) const; + ForumTopicReopened::Ptr parseJsonAndGetForumTopicReopened(const boost::property_tree::ptree& data) const; std::string parseForumTopicReopened(const ForumTopicReopened::Ptr& object) const; + GeneralForumTopicHidden::Ptr parseJsonAndGetGeneralForumTopicHidden(const boost::property_tree::ptree& data) const; + std::string parseGeneralForumTopicHidden(const GeneralForumTopicHidden::Ptr& object) const; + + GeneralForumTopicUnhidden::Ptr parseJsonAndGetGeneralForumTopicUnhidden(const boost::property_tree::ptree& data) const; + std::string parseGeneralForumTopicUnhidden(const GeneralForumTopicUnhidden::Ptr& object) const; + + WriteAccessAllowed::Ptr parseJsonAndGetWriteAccessAllowed(const boost::property_tree::ptree& data) const; + std::string parseWriteAccessAllowed(const WriteAccessAllowed::Ptr& object) const; + VideoChatScheduled::Ptr parseJsonAndGetVideoChatScheduled(const boost::property_tree::ptree& data) const; std::string parseVideoChatScheduled(const VideoChatScheduled::Ptr& object) const; diff --git a/include/tgbot/types/Chat.h b/include/tgbot/types/Chat.h index 2d31289c1..24013004c 100644 --- a/include/tgbot/types/Chat.h +++ b/include/tgbot/types/Chat.h @@ -167,6 +167,21 @@ class Chat { */ std::int32_t messageAutoDeleteTime; + /** + * @brief Optional. True, if aggressive anti-spam checks are enabled in the supergroup. + * + * The field is only available to chat administrators. + * Returned only in Api::getChat. + */ + bool hasAggressiveAntiSpamEnabled; + + /** + * @brief Optional. True, if non-administrators can only get the list of bots and administrators in the chat. + * + * Returned only in Api::getChat. + */ + bool hasHiddenMembers; + /** * @brief Optional. True, if messages from the chat can't be forwarded to other chats. * diff --git a/include/tgbot/types/ForumTopicEdited.h b/include/tgbot/types/ForumTopicEdited.h new file mode 100644 index 000000000..18b75bca9 --- /dev/null +++ b/include/tgbot/types/ForumTopicEdited.h @@ -0,0 +1,30 @@ +#ifndef TGBOT_FORUMTOPICEDITED_H +#define TGBOT_FORUMTOPICEDITED_H + +#include +#include + +namespace TgBot { + +/** + * @brief This object represents a service message about an edited forum topic. + * + * @ingroup types + */ +class ForumTopicEdited { +public: + typedef std::shared_ptr Ptr; + + /** + * @brief Optional. New name of the topic, if it was edited + */ + std::string name; + + /** + * @brief Optional. New identifier of the custom emoji shown as the topic icon, if it was edited; an empty string if the icon was removed + */ + std::string iconCustomEmojiId; +}; +} + +#endif //TGBOT_FORUMTOPICEDITED_H diff --git a/include/tgbot/types/GeneralForumTopicHidden.h b/include/tgbot/types/GeneralForumTopicHidden.h new file mode 100644 index 000000000..1a32a773c --- /dev/null +++ b/include/tgbot/types/GeneralForumTopicHidden.h @@ -0,0 +1,21 @@ +#ifndef TGBOT_GENERALFORUMTOPICHIDDEN_H +#define TGBOT_GENERALFORUMTOPICHIDDEN_H + +#include + +namespace TgBot { + +/** + * @brief This object represents a service message about General forum topic hidden in the chat. + * + * Currently holds no information. + * + * @ingroup types + */ +class GeneralForumTopicHidden { +public: + typedef std::shared_ptr Ptr; +}; +} + +#endif //TGBOT_GENERALFORUMTOPICHIDDEN_H diff --git a/include/tgbot/types/GeneralForumTopicUnhidden.h b/include/tgbot/types/GeneralForumTopicUnhidden.h new file mode 100644 index 000000000..e2b33a32c --- /dev/null +++ b/include/tgbot/types/GeneralForumTopicUnhidden.h @@ -0,0 +1,21 @@ +#ifndef TGBOT_GENERALFORUMTOPICUNHIDDEN_H +#define TGBOT_GENERALFORUMTOPICUNHIDDEN_H + +#include + +namespace TgBot { + +/** + * @brief This object represents a service message about General forum topic unhidden in the chat. + * + * Currently holds no information. + * + * @ingroup types + */ +class GeneralForumTopicUnhidden { +public: + typedef std::shared_ptr Ptr; +}; +} + +#endif //TGBOT_GENERALFORUMTOPICUNHIDDEN_H diff --git a/include/tgbot/types/InputMedia.h b/include/tgbot/types/InputMedia.h index c7ff6c048..9ce50c30f 100644 --- a/include/tgbot/types/InputMedia.h +++ b/include/tgbot/types/InputMedia.h @@ -31,24 +31,26 @@ class InputMedia { /** * @brief File to send. + * * Pass a fileId to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://” to upload a new one using multipart/form-data under name. * https://core.telegram.org/bots/api#sending-files */ std::string media; /** - * @brief Optional. Caption of the media to to be sent, 0-1024 characters after entities parsing + * @brief Optional. Caption of the media to be sent, 0-1024 characters after entities parsing */ std::string caption; /** * @brief Optional. Mode for parsing entities in the media caption. + * * See https://core.telegram.org/bots/api#formatting-options for more details. */ std::string parseMode; /** - * @brief Optional. List of special entities that appear in the caption, which can be specified instead of InputMedia::parseMode + * @brief Optional. List of special entities that appear in the caption, which can be specified instead of parseMode */ std::vector captionEntities; }; diff --git a/include/tgbot/types/InputMediaAnimation.h b/include/tgbot/types/InputMediaAnimation.h index b6109a0c0..1cc262178 100644 --- a/include/tgbot/types/InputMediaAnimation.h +++ b/include/tgbot/types/InputMediaAnimation.h @@ -26,6 +26,7 @@ class InputMediaAnimation : public InputMedia { /** * @brief Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. + * * The thumbnail should be in JPEG format and less than 200 kB in size. * A thumbnail's width and height should not exceed 320. * Ignored if the file is not uploaded using multipart/form-data. @@ -45,9 +46,14 @@ class InputMediaAnimation : public InputMedia { std::int32_t height; /** - * @brief Optional. Animation duration + * @brief Optional. Animation duration in seconds */ std::int32_t duration; + + /** + * @brief Optional. Pass True if the animation needs to be covered with a spoiler animation + */ + bool hasSpoiler; }; } diff --git a/include/tgbot/types/InputMediaPhoto.h b/include/tgbot/types/InputMediaPhoto.h index 998981d4c..5897beb81 100644 --- a/include/tgbot/types/InputMediaPhoto.h +++ b/include/tgbot/types/InputMediaPhoto.h @@ -4,7 +4,6 @@ #include "tgbot/types/InputMedia.h" #include -#include namespace TgBot { @@ -22,6 +21,11 @@ class InputMediaPhoto : public InputMedia { InputMediaPhoto() { this->type = TYPE; } + + /** + * @brief Optional. Pass True if the photo needs to be covered with a spoiler animation + */ + bool hasSpoiler; }; } diff --git a/include/tgbot/types/InputMediaVideo.h b/include/tgbot/types/InputMediaVideo.h index 348d97315..2645c9114 100644 --- a/include/tgbot/types/InputMediaVideo.h +++ b/include/tgbot/types/InputMediaVideo.h @@ -26,8 +26,9 @@ class InputMediaVideo : public InputMedia { /** * @brief Optional. Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported server-side. + * * The thumbnail should be in JPEG format and less than 200 kB in size. - * A thumbnail's width and height should not exceed 320. + * A thumbnail's width and height should not exceed 320. * Ignored if the file is not uploaded using multipart/form-data. * Thumbnails can't be reused and can be only uploaded as a new file, so you can pass “attach://” if the thumbnail was uploaded using multipart/form-data under . * https://core.telegram.org/bots/api#sending-files @@ -45,14 +46,19 @@ class InputMediaVideo : public InputMedia { std::int32_t height; /** - * @brief Optional. Video duration + * @brief Optional. Video duration in seconds */ std::int32_t duration; /** - * @brief Optional. Pass True, if the uploaded video is suitable for streaming + * @brief Optional. Pass True if the uploaded video is suitable for streaming */ bool supportsStreaming; + + /** + * @brief Optional. Pass True if the video needs to be covered with a spoiler animation + */ + bool hasSpoiler; }; } diff --git a/include/tgbot/types/Message.h b/include/tgbot/types/Message.h index 4d1ea7b4b..11ba95454 100644 --- a/include/tgbot/types/Message.h +++ b/include/tgbot/types/Message.h @@ -22,11 +22,15 @@ #include "tgbot/types/MessageAutoDeleteTimerChanged.h" #include "tgbot/types/Invoice.h" #include "tgbot/types/SuccessfulPayment.h" +#include "tgbot/types/WriteAccessAllowed.h" #include "tgbot/types/PassportData.h" #include "tgbot/types/ProximityAlertTriggered.h" #include "tgbot/types/ForumTopicCreated.h" +#include "tgbot/types/ForumTopicEdited.h" #include "tgbot/types/ForumTopicClosed.h" #include "tgbot/types/ForumTopicReopened.h" +#include "tgbot/types/GeneralForumTopicHidden.h" +#include "tgbot/types/GeneralForumTopicUnhidden.h" #include "tgbot/types/VideoChatScheduled.h" #include "tgbot/types/VideoChatStarted.h" #include "tgbot/types/VideoChatEnded.h" @@ -219,6 +223,11 @@ class Message { */ std::vector captionEntities; + /** + * @brief Optional. True, if the message media is covered by a spoiler animation + */ + bool hasMediaSpoiler; + /** * @brief Optional. Message is a shared contact, information about the contact */ @@ -346,6 +355,11 @@ class Message { */ std::string connectedWebsite; + /** + * @brief Optional. Service message: the user allowed the bot added to the attachment menu to write messages + */ + WriteAccessAllowed::Ptr writeAccessAllowed; + /** * @brief Optional. Telegram Passport data */ @@ -363,6 +377,11 @@ class Message { */ ForumTopicCreated::Ptr forumTopicCreated; + /** + * @brief Optional. Service message: forum topic edited + */ + ForumTopicEdited::Ptr forumTopicEdited; + /** * @brief Optional. Service message: forum topic closed */ @@ -373,6 +392,16 @@ class Message { */ ForumTopicReopened::Ptr forumTopicReopened; + /** + * @brief Optional. Service message: the 'General' forum topic hidden + */ + GeneralForumTopicHidden::Ptr generalForumTopicHidden; + + /** + * @brief Optional. Service message: the 'General' forum topic unhidden + */ + GeneralForumTopicUnhidden::Ptr generalForumTopicUnhidden; + /** * @brief Optional. Service message: video chat scheduled */ diff --git a/include/tgbot/types/ReplyKeyboardMarkup.h b/include/tgbot/types/ReplyKeyboardMarkup.h index f122934eb..d40d76786 100644 --- a/include/tgbot/types/ReplyKeyboardMarkup.h +++ b/include/tgbot/types/ReplyKeyboardMarkup.h @@ -1,17 +1,17 @@ -#ifndef TGBOT_CPP_REPLYKEYBOARDMARKUP_H -#define TGBOT_CPP_REPLYKEYBOARDMARKUP_H +#ifndef TGBOT_REPLYKEYBOARDMARKUP_H +#define TGBOT_REPLYKEYBOARDMARKUP_H #include "tgbot/types/GenericReply.h" #include "tgbot/types/KeyboardButton.h" -#include #include +#include #include namespace TgBot { /** - * @brief This object represents a custom keyboard with reply options (see https://core.telegram.org/bots#keyboards for details and examples). + * @brief This object represents a custom keyboard with reply options (see https://core.telegram.org/bots/features#keyboards for details and examples). * * @ingroup types */ @@ -25,16 +25,25 @@ class ReplyKeyboardMarkup : public GenericReply { */ std::vector> keyboard; + /** + * @brief Optional. Requests clients to always show the keyboard when the regular keyboard is hidden. + * + * Defaults to false, in which case the custom keyboard can be hidden and opened with a keyboard icon. + */ + bool isPersistent; + /** * @brief Optional. Requests clients to resize the keyboard vertically for optimal fit (e.g., make the keyboard smaller if there are just two rows of buttons). + * * Defaults to false, in which case the custom keyboard is always of the same height as the app's standard keyboard. */ bool resizeKeyboard; /** * @brief Optional. Requests clients to hide the keyboard as soon as it's been used. - * The keyboard will still be available, but clients will automatically display the usual letter-keyboard in the chat – the user can press a special button in the input field to see the custom keyboard again. - * Defaults to false + * + * The keyboard will still be available, but clients will automatically display the usual letter-keyboard in the chat - the user can press a special button in the input field to see the custom keyboard again. + * Defaults to false. */ bool oneTimeKeyboard; @@ -45,6 +54,7 @@ class ReplyKeyboardMarkup : public GenericReply { /** * @brief Optional. Use this parameter if you want to show the keyboard to specific users only. + * * Targets: 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply (has replyToMessageId), sender of the original message. * * Example: A user requests to change the bot's language, bot replies to the request with a keyboard to select the new language. @@ -54,4 +64,4 @@ class ReplyKeyboardMarkup : public GenericReply { }; } -#endif //TGBOT_CPP_REPLYKEYBOARDMARKUP_H +#endif //TGBOT_REPLYKEYBOARDMARKUP_H diff --git a/include/tgbot/types/WriteAccessAllowed.h b/include/tgbot/types/WriteAccessAllowed.h new file mode 100644 index 000000000..d01aa3134 --- /dev/null +++ b/include/tgbot/types/WriteAccessAllowed.h @@ -0,0 +1,21 @@ +#ifndef TGBOT_WRITEACCESSALLOWED_H +#define TGBOT_WRITEACCESSALLOWED_H + +#include + +namespace TgBot { + +/** + * @brief This object represents a service message about a user allowing a bot added to the attachment menu to write messages. + * + * Currently holds no information. + * + * @ingroup types + */ +class WriteAccessAllowed { +public: + typedef std::shared_ptr Ptr; +}; +} + +#endif //TGBOT_WRITEACCESSALLOWED_H diff --git a/src/Api.cpp b/src/Api.cpp index dc4076fac..54854f8ae 100644 --- a/src/Api.cpp +++ b/src/Api.cpp @@ -238,9 +238,10 @@ Message::Ptr Api::sendPhoto(boost::variant chatId, const std::vector& captionEntities, bool allowSendingWithoutReply, bool protectContent, - std::int32_t messageThreadId) const { + std::int32_t messageThreadId, + bool hasSpoiler) const { std::vector args; - args.reserve(11); + args.reserve(12); args.emplace_back("chat_id", chatId); if (messageThreadId != 0) { @@ -261,19 +262,22 @@ Message::Ptr Api::sendPhoto(boost::variant chatId, if (!captionEntities.empty()) { args.emplace_back("caption_entities", _tgTypeParser.parseArray(&TgTypeParser::parseMessageEntity, captionEntities)); } + if (hasSpoiler) { + args.emplace_back("has_spoiler", hasSpoiler); + } if (disableNotification) { args.emplace_back("disable_notification", disableNotification); } if (protectContent) { args.emplace_back("protect_content", protectContent); } - if (replyToMessageId) { + if (replyToMessageId != 0) { args.emplace_back("reply_to_message_id", replyToMessageId); } if (allowSendingWithoutReply) { args.emplace_back("allow_sending_without_reply", allowSendingWithoutReply); } - if (replyMarkup) { + if (replyMarkup != nullptr) { args.emplace_back("reply_markup", _tgTypeParser.parseGenericReply(replyMarkup)); } @@ -435,9 +439,10 @@ Message::Ptr Api::sendVideo(boost::variant chatId, const std::vector& captionEntities, bool allowSendingWithoutReply, bool protectContent, - std::int32_t messageThreadId) const { + std::int32_t messageThreadId, + bool hasSpoiler) const { std::vector args; - args.reserve(16); + args.reserve(17); args.emplace_back("chat_id", chatId); if (messageThreadId != 0) { @@ -449,13 +454,13 @@ Message::Ptr Api::sendVideo(boost::variant chatId, } else { // std::string args.emplace_back("video", boost::get(video)); } - if (duration) { + if (duration != 0) { args.emplace_back("duration", duration); } - if (width) { + if (width != 0) { args.emplace_back("width", width); } - if (height) { + if (height != 0) { args.emplace_back("height", height); } if (thumb.which() == 0) { // InputFile::Ptr @@ -476,6 +481,9 @@ Message::Ptr Api::sendVideo(boost::variant chatId, if (!captionEntities.empty()) { args.emplace_back("caption_entities", _tgTypeParser.parseArray(&TgTypeParser::parseMessageEntity, captionEntities)); } + if (hasSpoiler) { + args.emplace_back("has_spoiler", hasSpoiler); + } if (supportsStreaming) { args.emplace_back("supports_streaming", supportsStreaming); } @@ -485,13 +493,13 @@ Message::Ptr Api::sendVideo(boost::variant chatId, if (protectContent) { args.emplace_back("protect_content", protectContent); } - if (replyToMessageId) { + if (replyToMessageId != 0) { args.emplace_back("reply_to_message_id", replyToMessageId); } if (allowSendingWithoutReply) { args.emplace_back("allow_sending_without_reply", allowSendingWithoutReply); } - if (replyMarkup) { + if (replyMarkup != nullptr) { args.emplace_back("reply_markup", _tgTypeParser.parseGenericReply(replyMarkup)); } @@ -512,9 +520,10 @@ Message::Ptr Api::sendAnimation(boost::variant chatId const std::vector& captionEntities, bool allowSendingWithoutReply, bool protectContent, - std::int32_t messageThreadId) const { + std::int32_t messageThreadId, + bool hasSpoiler ) const { std::vector args; - args.reserve(15); + args.reserve(16); args.emplace_back("chat_id", chatId); if (messageThreadId != 0) { @@ -526,13 +535,13 @@ Message::Ptr Api::sendAnimation(boost::variant chatId } else { // std::string args.emplace_back("animation", boost::get(animation)); } - if (duration) { + if (duration != 0) { args.emplace_back("duration", duration); } - if (width) { + if (width != 0) { args.emplace_back("width", width); } - if (height) { + if (height != 0) { args.emplace_back("height", height); } if (thumb.which() == 0) { // InputFile::Ptr @@ -553,19 +562,22 @@ Message::Ptr Api::sendAnimation(boost::variant chatId if (!captionEntities.empty()) { args.emplace_back("caption_entities", _tgTypeParser.parseArray(&TgTypeParser::parseMessageEntity, captionEntities)); } + if (hasSpoiler) { + args.emplace_back("has_spoiler", hasSpoiler); + } if (disableNotification) { args.emplace_back("disable_notification", disableNotification); } if (protectContent) { args.emplace_back("protect_content", protectContent); } - if (replyToMessageId) { + if (replyToMessageId != 0) { args.emplace_back("reply_to_message_id", replyToMessageId); } if (allowSendingWithoutReply) { args.emplace_back("allow_sending_without_reply", allowSendingWithoutReply); } - if (replyMarkup) { + if (replyMarkup != nullptr) { args.emplace_back("reply_markup", _tgTypeParser.parseGenericReply(replyMarkup)); } @@ -1052,12 +1064,16 @@ Message::Ptr Api::sendDice(boost::variant chatId, } bool Api::sendChatAction(std::int64_t chatId, - const std::string& action) const { + const std::string& action, + std::int32_t messageThreadId) const { std::vector args; - args.reserve(2); + args.reserve(3); args.emplace_back("chat_id", chatId); args.emplace_back("action", action); + if (messageThreadId != 0) { + args.emplace_back("message_thread_id", messageThreadId); + } return sendRequest("sendChatAction", args).get("", false); } @@ -1512,14 +1528,18 @@ ForumTopic::Ptr Api::createForumTopic(boost::variant bool Api::editForumTopic(boost::variant chatId, std::int32_t messageThreadId, const std::string& name, - const std::string& iconCustomEmojiId) const { + boost::variant iconCustomEmojiId) const { std::vector args; args.reserve(4); args.emplace_back("chat_id", chatId); args.emplace_back("message_thread_id", messageThreadId); - args.emplace_back("name", name); - args.emplace_back("icon_custom_emoji_id", iconCustomEmojiId); + if (!name.empty()) { + args.emplace_back("name", name); + } + if (iconCustomEmojiId.which() == 1) { // std::string + args.emplace_back("icon_custom_emoji_id", boost::get(iconCustomEmojiId)); + } return sendRequest("editForumTopic", args).get("", false); } @@ -1568,6 +1588,53 @@ bool Api::unpinAllForumTopicMessages(boost::variant c return sendRequest("unpinAllForumTopicMessages", args).get("", false); } +bool Api::editGeneralForumTopic(boost::variant chatId, + std::string name) const { + std::vector args; + args.reserve(2); + + args.emplace_back("chat_id", chatId); + args.emplace_back("name", name); + + return sendRequest("editGeneralForumTopic", args).get("", false); +} + +bool Api::closeGeneralForumTopic(boost::variant chatId) const { + std::vector args; + args.reserve(1); + + args.emplace_back("chat_id", chatId); + + return sendRequest("closeGeneralForumTopic", args).get("", false); +} + +bool Api::reopenGeneralForumTopic(boost::variant chatId) const { + std::vector args; + args.reserve(1); + + args.emplace_back("chat_id", chatId); + + return sendRequest("reopenGeneralForumTopic", args).get("", false); +} + +bool Api::hideGeneralForumTopic(boost::variant chatId) const { + std::vector args; + args.reserve(1); + + args.emplace_back("chat_id", chatId); + + return sendRequest("hideGeneralForumTopic", args).get("", false); +} + +bool Api::unhideGeneralForumTopic(boost::variant chatId) const { + std::vector args; + args.reserve(1); + + args.emplace_back("chat_id", chatId); + + return sendRequest("unhideGeneralForumTopic", args).get("", false); +} + bool Api::answerCallbackQuery(const std::string& callbackQueryId, const std::string& text, bool showAlert, diff --git a/src/TgTypeParser.cpp b/src/TgTypeParser.cpp index a31172f00..24173c41b 100644 --- a/src/TgTypeParser.cpp +++ b/src/TgTypeParser.cpp @@ -164,6 +164,8 @@ Chat::Ptr TgTypeParser::parseJsonAndGetChat(const boost::property_tree::ptree& d result->slowModeDelay = data.get("slow_mode_delay", 0); result->messageAutoDeleteTime = data.get("message_auto_delete_time", 0); result->hasProtectedContent = data.get("has_protected_content", false); + result->hasAggressiveAntiSpamEnabled = data.get("has_aggressive_anti_spam_enabled", false); + result->hasHiddenMembers = data.get("has_hidden_members", false); result->stickerSetName = data.get("sticker_set_name", ""); result->canSetStickerSet = data.get("can_set_sticker_set", false); result->linkedChatId = data.get("linked_chat_id", 0); @@ -209,6 +211,8 @@ std::string TgTypeParser::parseChat(const Chat::Ptr& object) const { appendToJson(result, "permissions", parseChatPermissions(object->permissions)); appendToJson(result, "slow_mode_delay", object->slowModeDelay); appendToJson(result, "message_auto_delete_time", object->messageAutoDeleteTime); + appendToJson(result, "has_aggressive_anti_spam_enabled", object->hasAggressiveAntiSpamEnabled); + appendToJson(result, "has_hidden_members", object->hasHiddenMembers); appendToJson(result, "has_protected_content", object->hasProtectedContent); appendToJson(result, "sticker_set_name", object->stickerSetName); appendToJson(result, "can_set_sticker_set", object->canSetStickerSet); @@ -253,6 +257,7 @@ Message::Ptr TgTypeParser::parseJsonAndGetMessage(const boost::property_tree::pt result->voice = tryParseJson(&TgTypeParser::parseJsonAndGetVoice, data, "voice"); result->caption = data.get("caption", ""); result->captionEntities = parseJsonAndGetArray(&TgTypeParser::parseJsonAndGetMessageEntity, data, "caption_entities"); + result->hasMediaSpoiler = data.get("has_media_spoiler", false); result->contact = tryParseJson(&TgTypeParser::parseJsonAndGetContact, data, "contact"); result->dice = tryParseJson(&TgTypeParser::parseJsonAndGetDice, data, "dice"); result->game = tryParseJson(&TgTypeParser::parseJsonAndGetGame, data, "game"); @@ -274,11 +279,15 @@ Message::Ptr TgTypeParser::parseJsonAndGetMessage(const boost::property_tree::pt result->invoice = tryParseJson(&TgTypeParser::parseJsonAndGetInvoice, data, "invoice"); result->successfulPayment = tryParseJson(&TgTypeParser::parseJsonAndGetSuccessfulPayment, data, "successful_payment"); result->connectedWebsite = data.get("connected_website", ""); + result->writeAccessAllowed = tryParseJson(&TgTypeParser::parseJsonAndGetWriteAccessAllowed, data, "write_access_allowed"); result->passportData = tryParseJson(&TgTypeParser::parseJsonAndGetPassportData, data, "passport_data"); result->proximityAlertTriggered = tryParseJson(&TgTypeParser::parseJsonAndGetProximityAlertTriggered, data, "proximity_alert_triggered"); result->forumTopicCreated = tryParseJson(&TgTypeParser::parseJsonAndGetForumTopicCreated, data, "forum_topic_created"); + result->forumTopicEdited = tryParseJson(&TgTypeParser::parseJsonAndGetForumTopicEdited, data, "forum_topic_edited"); result->forumTopicClosed = tryParseJson(&TgTypeParser::parseJsonAndGetForumTopicClosed, data, "forum_topic_closed"); result->forumTopicReopened = tryParseJson(&TgTypeParser::parseJsonAndGetForumTopicReopened, data, "forum_topic_reopened"); + result->generalForumTopicHidden = tryParseJson(&TgTypeParser::parseJsonAndGetGeneralForumTopicHidden, data, "general_forum_topic_hidden"); + result->generalForumTopicUnhidden = tryParseJson(&TgTypeParser::parseJsonAndGetGeneralForumTopicUnhidden, data, "general_forum_topic_unhidden"); result->videoChatScheduled = tryParseJson(&TgTypeParser::parseJsonAndGetVideoChatScheduled, data, "video_chat_scheduled"); result->videoChatStarted = tryParseJson(&TgTypeParser::parseJsonAndGetVideoChatStarted, data, "video_chat_started"); result->videoChatEnded = tryParseJson(&TgTypeParser::parseJsonAndGetVideoChatEnded, data, "video_chat_ended"); @@ -326,6 +335,7 @@ std::string TgTypeParser::parseMessage(const Message::Ptr& object) const { appendToJson(result, "voice", parseVoice(object->voice)); appendToJson(result, "caption", object->caption); appendToJson(result, "caption_entities", parseArray(&TgTypeParser::parseMessageEntity, object->captionEntities)); + appendToJson(result, "has_media_spoiler", object->hasMediaSpoiler); appendToJson(result, "contact", parseContact(object->contact)); appendToJson(result, "dice", parseDice(object->dice)); appendToJson(result, "game", parseGame(object->game)); @@ -347,11 +357,15 @@ std::string TgTypeParser::parseMessage(const Message::Ptr& object) const { appendToJson(result, "invoice", parseInvoice(object->invoice)); appendToJson(result, "successful_payment", parseSuccessfulPayment(object->successfulPayment)); appendToJson(result, "connected_website", object->connectedWebsite); + appendToJson(result, "write_access_allowed", parseWriteAccessAllowed(object->writeAccessAllowed)); appendToJson(result, "passport_data", parsePassportData(object->passportData)); appendToJson(result, "proximity_alert_triggered", parseProximityAlertTriggered(object->proximityAlertTriggered)); appendToJson(result, "forum_topic_created", parseForumTopicCreated(object->forumTopicCreated)); + appendToJson(result, "forum_topic_edited", parseForumTopicEdited(object->forumTopicEdited)); appendToJson(result, "forum_topic_closed", parseForumTopicClosed(object->forumTopicClosed)); appendToJson(result, "forum_topic_reopened", parseForumTopicReopened(object->forumTopicReopened)); + appendToJson(result, "general_forum_topic_hidden", parseGeneralForumTopicHidden(object->generalForumTopicHidden)); + appendToJson(result, "general_forum_topic_unhidden", parseGeneralForumTopicUnhidden(object->generalForumTopicUnhidden)); appendToJson(result, "video_chat_scheduled", parseVideoChatScheduled(object->videoChatScheduled)); appendToJson(result, "video_chat_started", parseVideoChatStarted(object->videoChatStarted)); appendToJson(result, "video_chat_ended", parseVideoChatEnded(object->videoChatEnded)); @@ -981,6 +995,26 @@ std::string TgTypeParser::parseForumTopicClosed(const ForumTopicClosed::Ptr& obj return result; } +ForumTopicEdited::Ptr TgTypeParser::parseJsonAndGetForumTopicEdited(const boost::property_tree::ptree& data) const { + auto result(std::make_shared()); + result->name = data.get("name", ""); + result->iconCustomEmojiId = data.get("icon_custom_emoji_id", ""); + return result; +} + +std::string TgTypeParser::parseForumTopicEdited(const ForumTopicEdited::Ptr& object) const { + if (!object) { + return ""; + } + std::string result; + result += '{'; + appendToJson(result, "name", object->name); + appendToJson(result, "icon_custom_emoji_id", object->iconCustomEmojiId); + removeLastComma(result); + result += '}'; + return result; +} + ForumTopicReopened::Ptr TgTypeParser::parseJsonAndGetForumTopicReopened(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); return result; @@ -997,6 +1031,54 @@ std::string TgTypeParser::parseForumTopicReopened(const ForumTopicReopened::Ptr& return result; } +GeneralForumTopicHidden::Ptr TgTypeParser::parseJsonAndGetGeneralForumTopicHidden(const boost::property_tree::ptree& data) const { + auto result(std::make_shared()); + return result; +} + +std::string TgTypeParser::parseGeneralForumTopicHidden(const GeneralForumTopicHidden::Ptr& object) const { + if (!object) { + return ""; + } + std::string result; + result += '{'; + //removeLastComma(result); + result += '}'; + return result; +} + +GeneralForumTopicUnhidden::Ptr TgTypeParser::parseJsonAndGetGeneralForumTopicUnhidden(const boost::property_tree::ptree& data) const { + auto result(std::make_shared()); + return result; +} + +std::string TgTypeParser::parseGeneralForumTopicUnhidden(const GeneralForumTopicUnhidden::Ptr& object) const { + if (!object) { + return ""; + } + std::string result; + result += '{'; + //removeLastComma(result); + result += '}'; + return result; +} + +WriteAccessAllowed::Ptr TgTypeParser::parseJsonAndGetWriteAccessAllowed(const boost::property_tree::ptree& data) const { + auto result(std::make_shared()); + return result; +} + +std::string TgTypeParser::parseWriteAccessAllowed(const WriteAccessAllowed::Ptr& object) const { + if (!object) { + return ""; + } + std::string result; + result += '{'; + //removeLastComma(result); + result += '}'; + return result; +} + VideoChatScheduled::Ptr TgTypeParser::parseJsonAndGetVideoChatScheduled(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); result->startDate = data.get("start_date", 0); @@ -1133,6 +1215,7 @@ ReplyKeyboardMarkup::Ptr TgTypeParser::parseJsonAndGetReplyKeyboardMarkup(const for (const auto& item : data.find("keyboard")->second) { result->keyboard.push_back(parseJsonAndGetArray(&TgTypeParser::parseJsonAndGetKeyboardButton, item.second)); } + result->isPersistent = data.get("is_persistent", false); result->resizeKeyboard = data.get("resize_keyboard", false); result->oneTimeKeyboard = data.get("one_time_keyboard", false); result->inputFieldPlaceholder = data.get("input_field_placeholder", ""); @@ -1159,6 +1242,7 @@ std::string TgTypeParser::parseReplyKeyboardMarkup(const ReplyKeyboardMarkup::Pt if (!object->keyboard.empty()) removeLastComma(result); result += "],"; + appendToJson(result, "is_persistent", object->isPersistent); appendToJson(result, "resize_keyboard", object->resizeKeyboard); appendToJson(result, "one_time_keyboard", object->oneTimeKeyboard); appendToJson(result, "input_field_placeholder", object->inputFieldPlaceholder); @@ -2186,6 +2270,7 @@ std::string TgTypeParser::parseInputMedia(const InputMedia::Ptr& object) const { InputMediaPhoto::Ptr TgTypeParser::parseJsonAndGetInputMediaPhoto(const boost::property_tree::ptree& data) const { // NOTE: This function will be called by parseJsonAndGetInputMedia(). auto result(std::make_shared()); + result->hasSpoiler = data.get("has_spoiler", false); return result; } @@ -2196,6 +2281,7 @@ std::string TgTypeParser::parseInputMediaPhoto(const InputMediaPhoto::Ptr& objec // This function will be called by parseInputMedia(), so I don't add // curly brackets to the result std::string. std::string result; + appendToJson(result, "has_spoiler", object->hasSpoiler); // The last comma will be erased by parseInputMedia(). return result; } @@ -2208,6 +2294,7 @@ InputMediaVideo::Ptr TgTypeParser::parseJsonAndGetInputMediaVideo(const boost::p result->height = data.get("height", 0); result->duration = data.get("duration", 0); result->supportsStreaming = data.get("supports_streaming", false); + result->hasSpoiler = data.get("has_spoiler", false); return result; } @@ -2223,6 +2310,7 @@ std::string TgTypeParser::parseInputMediaVideo(const InputMediaVideo::Ptr& objec appendToJson(result, "height", object->height); appendToJson(result, "duration", object->duration); appendToJson(result, "supports_streaming", object->supportsStreaming); + appendToJson(result, "has_spoiler", object->hasSpoiler); // The last comma will be erased by parseInputMedia(). return result; } @@ -2234,6 +2322,7 @@ InputMediaAnimation::Ptr TgTypeParser::parseJsonAndGetInputMediaAnimation(const result->width = data.get("width", 0); result->height = data.get("height", 0); result->duration = data.get("duration", 0); + result->hasSpoiler = data.get("has_spoiler", false); return result; } @@ -2248,6 +2337,7 @@ std::string TgTypeParser::parseInputMediaAnimation(const InputMediaAnimation::Pt appendToJson(result, "width", object->width); appendToJson(result, "height", object->height); appendToJson(result, "duration", object->duration); + appendToJson(result, "has_spoiler", object->hasSpoiler); // The last comma will be erased by parseInputMedia(). return result; }