From d5a26908981a45e3ec895ca513713bf8f4bcad16 Mon Sep 17 00:00:00 2001 From: uralm1 Date: Sun, 17 Nov 2024 20:49:03 +0500 Subject: [PATCH] Add type templates Optional and Required, simplify parsers --- include/tgbot/Optional.h | 21 +++++ include/tgbot/TgTypeParser.h | 15 +++- include/tgbot/types/ForceReply.h | 5 +- include/tgbot/types/InlineKeyboardButton.h | 21 ++--- include/tgbot/types/LinkPreviewOptions.h | 13 +-- include/tgbot/types/LoginUrl.h | 10 ++- include/tgbot/types/MessageEntity.h | 15 ++-- include/tgbot/types/ReplyKeyboardMarkup.h | 13 +-- include/tgbot/types/ReplyKeyboardRemove.h | 5 +- include/tgbot/types/ReplyParameters.h | 16 ++-- .../tgbot/types/SwitchInlineQueryChosenChat.h | 12 +-- include/tgbot/types/User.h | 26 +++--- src/TgTypeParser.cpp | 88 +++++++++---------- 13 files changed, 153 insertions(+), 107 deletions(-) create mode 100644 include/tgbot/Optional.h diff --git a/include/tgbot/Optional.h b/include/tgbot/Optional.h new file mode 100644 index 000000000..b3563d486 --- /dev/null +++ b/include/tgbot/Optional.h @@ -0,0 +1,21 @@ +#ifndef TGBOT_OPTIONAL_H +#define TGBOT_OPTIONAL_H + +#include + +namespace TgBot { + +template + using Optional = boost::optional; + +// use for: OptionalPtr> +// for pointers, we assume optional value == nullptr (or not owned, etc) +template + using OptionalPtr = T; + +template + using Required = T; + +} + +#endif //TGBOT_OPTIONAL_H diff --git a/include/tgbot/TgTypeParser.h b/include/tgbot/TgTypeParser.h index 661930e01..b29efcb6a 100644 --- a/include/tgbot/TgTypeParser.h +++ b/include/tgbot/TgTypeParser.h @@ -2,6 +2,7 @@ #define TGBOT_TGTYPEPARSER_H #include "tgbot/export.h" +#include "tgbot/Optional.h" #include "tgbot/types/Update.h" #include "tgbot/types/WebhookInfo.h" #include "tgbot/types/User.h" @@ -898,7 +899,19 @@ class TGBOT_API TgTypeParser { private: inline void removeLastComma(std::string& input) const { - input.erase(input.length() - 1); + if (!input.empty() && input.back() == ',') input.erase(input.length() - 1); + } + + template + inline void appendToJson(std::string& json, const std::string& varName, const Optional& value) const { + if (!value) { + return; + } + json += '"'; + json += varName; + json += R"(":)"; + json += *(value); + json += ','; } template diff --git a/include/tgbot/types/ForceReply.h b/include/tgbot/types/ForceReply.h index 131e1cb86..35f42d601 100644 --- a/include/tgbot/types/ForceReply.h +++ b/include/tgbot/types/ForceReply.h @@ -2,6 +2,7 @@ #define TGBOT_FORCEREPLY_H #include "tgbot/types/GenericReply.h" +#include "tgbot/Optional.h" #include #include @@ -35,14 +36,14 @@ class ForceReply : public GenericReply { /** * @brief Optional. The placeholder to be shown in the input field when the reply is active; 1-64 characters */ - std::string inputFieldPlaceholder; + Optional inputFieldPlaceholder; /** * @brief Optional. Use this parameter if you want to force reply from 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 to a message in the same chat and forum topic, sender of the original message. */ - bool selective; + Optional selective; }; } diff --git a/include/tgbot/types/InlineKeyboardButton.h b/include/tgbot/types/InlineKeyboardButton.h index c71b5db57..35bad3f12 100644 --- a/include/tgbot/types/InlineKeyboardButton.h +++ b/include/tgbot/types/InlineKeyboardButton.h @@ -5,6 +5,7 @@ #include "tgbot/types/LoginUrl.h" #include "tgbot/types/SwitchInlineQueryChosenChat.h" #include "tgbot/types/CallbackGame.h" +#include "tgbot/Optional.h" #include #include @@ -26,19 +27,19 @@ class InlineKeyboardButton { /** * @brief Label text on the button */ - std::string text; + Required text; /** * @brief Optional. HTTP or tg:// URL to be opened when the button is pressed. * * Links tg://user?id= can be used to mention a user by their identifier without using a username, if this is allowed by their privacy settings. */ - std::string url; + Optional url; /** * @brief Optional. Data to be sent in a [callback query](https://core.telegram.org/bots/api#callbackquery) to the bot when button is pressed, 1-64 bytes */ - std::string callbackData; + Optional callbackData; /** * @brief Optional. Description of the [Web App](https://core.telegram.org/bots/webapps) that will be launched when the user presses the button. @@ -46,21 +47,21 @@ class InlineKeyboardButton { * The Web App will be able to send an arbitrary message on behalf of the user using the method Api::answerWebAppQuery. * Available only in private chats between a user and the bot. */ - WebAppInfo::Ptr webApp; + OptionalPtr webApp; /** * @brief Optional. An HTTPS URL used to automatically authorize the user. * * Can be used as a replacement for the [Telegram Login Widget](https://core.telegram.org/widgets/login). */ - LoginUrl::Ptr loginUrl; + OptionalPtr loginUrl; /** * @brief Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. * * May be empty, in which case just the bot's username will be inserted. */ - std::string switchInlineQuery; + Optional switchInlineQuery; /** * @brief Optional. If set, pressing the button will insert the bot's username and the specified inline query in the current chat's input field. @@ -68,26 +69,26 @@ class InlineKeyboardButton { * May be empty, in which case only the bot's username will be inserted. * This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. */ - std::string switchInlineQueryCurrentChat; + Optional switchInlineQueryCurrentChat; /** * @brief Optional. If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field */ - SwitchInlineQueryChosenChat::Ptr switchInlineQueryChosenChat; + OptionalPtr switchInlineQueryChosenChat; /** * @brief Optional. Description of the game that will be launched when the user presses the button. * * NOTE: This type of button must always be the first button in the first row. */ - CallbackGame::Ptr callbackGame; + OptionalPtr callbackGame; /** * @brief Optional. Specify True, to send a [Pay button](https://core.telegram.org/bots/api#payments). * * NOTE: This type of button must always be the first button in the first row and can only be used in invoice messages. */ - bool pay; + Optional pay; }; } diff --git a/include/tgbot/types/LinkPreviewOptions.h b/include/tgbot/types/LinkPreviewOptions.h index b3f91efac..c2a3df845 100644 --- a/include/tgbot/types/LinkPreviewOptions.h +++ b/include/tgbot/types/LinkPreviewOptions.h @@ -1,9 +1,10 @@ #ifndef TGBOT_LINKPREVIEWOPTIONS_H #define TGBOT_LINKPREVIEWOPTIONS_H +#include "tgbot/Optional.h" + #include #include -#include namespace TgBot { @@ -20,29 +21,29 @@ class LinkPreviewOptions { /** * @brief Optional. True, if the link preview is disabled */ - boost::optional isDisabled; + Optional isDisabled; /** * @brief Optional. URL to use for the link preview. * * If empty, then the first URL found in the message text will be used */ - boost::optional url; + Optional url; /** * @brief Optional. True, if the media in the link preview is supposed to be shrunk; ignored if the URL isn't explicitly specified or media size change isn't supported for the preview */ - boost::optional preferSmallMedia; + Optional preferSmallMedia; /** * @brief Optional. True, if the media in the link preview is supposed to be enlarged; ignored if the URL isn't explicitly specified or media size change isn't supported for the preview */ - boost::optional preferLargeMedia; + Optional preferLargeMedia; /** * @brief Optional. True, if the link preview must be shown above the message text; otherwise, the link preview will be shown below the message text */ - boost::optional showAboveText; + Optional showAboveText; }; } diff --git a/include/tgbot/types/LoginUrl.h b/include/tgbot/types/LoginUrl.h index 575a3a0b8..fce83e53d 100644 --- a/include/tgbot/types/LoginUrl.h +++ b/include/tgbot/types/LoginUrl.h @@ -1,6 +1,8 @@ #ifndef TGBOT_LOGINURL_H #define TGBOT_LOGINURL_H +#include "tgbot/Optional.h" + #include #include @@ -27,12 +29,12 @@ class LoginUrl { * * NOTE: You must always check the hash of the received data to verify the authentication and the integrity of the data as described in https://core.telegram.org/widgets/login#checking-authorization */ - std::string url; + Required url; /** * @brief Optional. New text of the button in forwarded messages. */ - std::string forwardText; + Optional forwardText; /** * @brief Optional. Username of a bot, which will be used for user authorization. @@ -41,12 +43,12 @@ class LoginUrl { * The url's domain must be the same as the domain linked with the bot. * See https://core.telegram.org/widgets/login#linking-your-domain-to-the-bot for more details. */ - std::string botUsername; + Optional botUsername; /** * @brief Optional. Pass True to request the permission for your bot to send messages to the user. */ - bool requestWriteAccess; + Optional requestWriteAccess; }; } diff --git a/include/tgbot/types/MessageEntity.h b/include/tgbot/types/MessageEntity.h index 7ebe49e41..12da9d400 100644 --- a/include/tgbot/types/MessageEntity.h +++ b/include/tgbot/types/MessageEntity.h @@ -1,6 +1,7 @@ #ifndef TGBOT_MESSAGEENTITY_H #define TGBOT_MESSAGEENTITY_H +#include "tgbot/Optional.h" #include "tgbot/types/User.h" #include @@ -33,40 +34,40 @@ class MessageEntity { * * Currently, can be Type::Mention (@username), Type::Hashtag (#hashtag), Type::Cashtag ($USD), Type::BotCommand (/start@jobs_bot), Type::Url (https://telegram.org), Type::Email (do-not-reply@telegram.org), Type::PhoneNumber (+1-212-555-0123), Type::Bold (bold text), Type::Italic (italic text), Type::Underline (underlined text), Type::Strikethrough (strikethrough text), Type::Spoiler (spoiler message), Type::Blockquote (block quotation), Type::Code (monowidth string), Type::Pre (monowidth block), Type::TextLink (for clickable text URLs), Type::TextMention (for users [without usernames](https://telegram.org/blog/edit#new-mentions)), Type::CustomEmoji (for inline custom emoji stickers) */ - Type type; + Required type; /** * @brief Offset in [UTF-16 code units](https://core.telegram.org/api/entities#entity-length) to the start of the entity * */ - std::int32_t offset; + Required offset; /** * @brief Length of the entity in [UTF-16 code units](https://core.telegram.org/api/entities#entity-length) */ - std::int32_t length; + Required length; /** * @brief Optional. For Type::TextLink only, URL that will be opened after user taps on the text */ - std::string url; + Optional url; /** * @brief Optional. For Type::TextMention only, the mentioned user */ - User::Ptr user; + OptionalPtr user; /** * @brief Optional. For Type::Pre only, the programming language of the entity text */ - std::string language; + Optional language; /** * @brief Optional. For Type::CustomEmoji only, unique identifier of the custom emoji. * * Use Api::getCustomEmojiStickers to get full information about the sticker */ - std::string customEmojiId; + Optional customEmojiId; }; } diff --git a/include/tgbot/types/ReplyKeyboardMarkup.h b/include/tgbot/types/ReplyKeyboardMarkup.h index f70b2fca2..e7b62f30c 100644 --- a/include/tgbot/types/ReplyKeyboardMarkup.h +++ b/include/tgbot/types/ReplyKeyboardMarkup.h @@ -1,6 +1,7 @@ #ifndef TGBOT_REPLYKEYBOARDMARKUP_H #define TGBOT_REPLYKEYBOARDMARKUP_H +#include "tgbot/Optional.h" #include "tgbot/types/GenericReply.h" #include "tgbot/types/KeyboardButton.h" @@ -23,21 +24,21 @@ class ReplyKeyboardMarkup : public GenericReply { /** * @brief Array of button rows, each represented by an Array of KeyboardButton objects */ - std::vector> keyboard; + Required>> 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; + Optional 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; + Optional resizeKeyboard; /** * @brief Optional. Requests clients to hide the keyboard as soon as it's been used. @@ -45,12 +46,12 @@ class ReplyKeyboardMarkup : public GenericReply { * 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; + Optional oneTimeKeyboard; /** * @brief Optional. The placeholder to be shown in the input field when the keyboard is active; 1-64 characters */ - std::string inputFieldPlaceholder; + Optional inputFieldPlaceholder; /** * @brief Optional. Use this parameter if you want to show the keyboard to specific users only. @@ -59,7 +60,7 @@ class ReplyKeyboardMarkup : public GenericReply { * Example: A user requests to change the bot's language, bot replies to the request with a keyboard to select the new language. * Other users in the group don't see the keyboard. */ - bool selective; + Optional selective; }; } diff --git a/include/tgbot/types/ReplyKeyboardRemove.h b/include/tgbot/types/ReplyKeyboardRemove.h index 3a2bb94b1..aba9ca758 100644 --- a/include/tgbot/types/ReplyKeyboardRemove.h +++ b/include/tgbot/types/ReplyKeyboardRemove.h @@ -1,6 +1,7 @@ #ifndef TGBOT_REPLYKEYBOARDREMOVE_H #define TGBOT_REPLYKEYBOARDREMOVE_H +#include "tgbot/Optional.h" #include "tgbot/types/GenericReply.h" #include @@ -23,7 +24,7 @@ class ReplyKeyboardRemove : public GenericReply { /** * @brief Requests clients to remove the custom keyboard (user will not be able to summon this keyboard; if you want to hide the keyboard from sight but keep it accessible, use oneTimeKeyboard in ReplyKeyboardMarkup) */ - bool removeKeyboard; + Required removeKeyboard; /** * @brief Optional. Use this parameter if you want to remove the keyboard for specific users only. @@ -31,7 +32,7 @@ class ReplyKeyboardRemove : public GenericReply { * Targets: 1) users that are @mentioned in the text of the Message object; 2) if the bot's message is a reply to a message in the same chat and forum topic, sender of the original message. * Example: A user votes in a poll, bot returns confirmation message in reply to the vote and removes the keyboard for that user, while still showing the keyboard with poll options to users who haven't voted yet. */ - bool selective; + Optional selective; }; } diff --git a/include/tgbot/types/ReplyParameters.h b/include/tgbot/types/ReplyParameters.h index ee2ad7be2..ca646e7e0 100644 --- a/include/tgbot/types/ReplyParameters.h +++ b/include/tgbot/types/ReplyParameters.h @@ -2,12 +2,12 @@ #define TGBOT_REPLYPARAMETERS_H #include "tgbot/types/MessageEntity.h" +#include "tgbot/Optional.h" #include #include #include #include -#include namespace TgBot { @@ -24,14 +24,14 @@ class ReplyParameters { /** * @brief Identifier of the message that will be replied to in the current chat, or in the chat chatId if it is specified */ - std::int32_t messageId; + Required messageId; /** * @brief Optional. If the message to be replied to is from a different chat, unique identifier for the chat or username of the channel (in the format @channelusername). * * Not supported for messages sent on behalf of a business account. */ - boost::optional chatId; + Optional chatId; /** * @brief Optional. Pass True if the message should be sent even if the specified message to be replied to is not found. @@ -39,7 +39,7 @@ class ReplyParameters { * Always False for replies in another chat or forum topic. * Always True for messages sent on behalf of a business account. */ - boost::optional allowSendingWithoutReply; + Optional allowSendingWithoutReply; /** * @brief Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing. @@ -47,26 +47,26 @@ class ReplyParameters { * The quote must be an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and customEmoji entities. * The message will fail to send if the quote isn't found in the original message. */ - boost::optional quote; + Optional quote; /** * @brief Optional. Mode for parsing entities in the quote. * * See [formatting options](https://core.telegram.org/bots/api#formatting-options) for more details. */ - boost::optional quoteParseMode; + Optional quoteParseMode; /** * @brief Optional. A JSON-serialized list of special entities that appear in the quote. * * It can be specified instead of quoteParseMode. */ - boost::optional> quoteEntities; + Optional> quoteEntities; /** * @brief Optional. Position of the quote in the original message in UTF-16 code units */ - boost::optional quotePosition; + Optional quotePosition; }; } diff --git a/include/tgbot/types/SwitchInlineQueryChosenChat.h b/include/tgbot/types/SwitchInlineQueryChosenChat.h index b0ecf2cba..53591570b 100644 --- a/include/tgbot/types/SwitchInlineQueryChosenChat.h +++ b/include/tgbot/types/SwitchInlineQueryChosenChat.h @@ -1,6 +1,8 @@ #ifndef TGBOT_SWITCHINLINEQUERYCHOSENCHAT_H #define TGBOT_SWITCHINLINEQUERYCHOSENCHAT_H +#include "tgbot/Optional.h" + #include #include @@ -19,27 +21,27 @@ class SwitchInlineQueryChosenChat { /** * @brief Optional. The default inline query to be inserted in the input field. If left empty, only the bot's username will be inserted */ - std::string query; + Optional query; /** * @brief Optional. True, if private chats with users can be chosen */ - bool allowUserChats; + Optional allowUserChats; /** * @brief Optional. True, if private chats with bots can be chosen */ - bool allowBotChats; + Optional allowBotChats; /** * @brief Optional. True, if group and supergroup chats can be chosen */ - bool allowGroupChats; + Optional allowGroupChats; /** * @brief Optional. True, if channel chats can be chosen */ - bool allowChannelChats; + Optional allowChannelChats; }; } diff --git a/include/tgbot/types/User.h b/include/tgbot/types/User.h index 6b28e1dfc..e00f640b0 100644 --- a/include/tgbot/types/User.h +++ b/include/tgbot/types/User.h @@ -1,6 +1,8 @@ #ifndef TGBOT_USER_H #define TGBOT_USER_H +#include "tgbot/Optional.h" + #include #include #include @@ -23,70 +25,70 @@ class User { * This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. * But it has at most 52 significant bits, so a 64-bit integer or double-precision float type are safe for storing this identifier. */ - std::int64_t id; + Required id; /** * @brief True, if this user is a bot */ - bool isBot; + Required isBot; /** * @brief User's or bot's first name */ - std::string firstName; + Required firstName; /** * @brief Optional. User's or bot's last name */ - std::string lastName; + Optional lastName; /** * @brief Optional. User's or bot's username */ - std::string username; + Optional username; /** * @brief Optional. [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) of the user's language */ - std::string languageCode; + Optional languageCode; /** * @brief Optional. True, if this user is a Telegram Premium user */ - bool isPremium; + Optional isPremium; /** * @brief Optional. True, if this user added the bot to the attachment menu */ - bool addedToAttachmentMenu; + Optional addedToAttachmentMenu; /** * @brief Optional. True, if the bot can be invited to groups. * * Returned only in Api::getMe. */ - bool canJoinGroups; + Optional canJoinGroups; /** * @brief Optional. True, if [privacy mode](https://core.telegram.org/bots/features#privacy-mode) is disabled for the bot. * * Returned only in Api::getMe. */ - bool canReadAllGroupMessages; + Optional canReadAllGroupMessages; /** * @brief Optional. True, if the bot supports inline queries. * * Returned only in Api::getMe. */ - bool supportsInlineQueries; + Optional supportsInlineQueries; /** * @brief Optional. True, if the bot can be connected to a Telegram Business account to receive its messages. * * Returned only in Api::getMe. */ - bool canConnectToBusiness; + Optional canConnectToBusiness; }; } diff --git a/src/TgTypeParser.cpp b/src/TgTypeParser.cpp index 5f75730d2..b2a8b5b0a 100644 --- a/src/TgTypeParser.cpp +++ b/src/TgTypeParser.cpp @@ -109,15 +109,15 @@ User::Ptr TgTypeParser::parseJsonAndGetUser(const boost::property_tree::ptree& d result->id = data.get("id", 0); result->isBot = data.get("is_bot", false); result->firstName = data.get("first_name", ""); - result->lastName = data.get("last_name", ""); - result->username = data.get("username", ""); - result->languageCode = data.get("language_code", ""); - result->isPremium = data.get("is_premium", false); - result->addedToAttachmentMenu = data.get("added_to_attachment_menu", false); - result->canJoinGroups = data.get("can_join_groups", false); - result->canReadAllGroupMessages = data.get("can_read_all_group_messages", false); - result->supportsInlineQueries = data.get("supports_inline_queries", false); - result->canConnectToBusiness = data.get("can_connect_to_business", false); + result->lastName = data.get_optional("last_name"); + result->username = data.get_optional("username"); + result->languageCode = data.get_optional("language_code"); + result->isPremium = data.get_optional("is_premium"); + result->addedToAttachmentMenu = data.get_optional("added_to_attachment_menu"); + result->canJoinGroups = data.get_optional("can_join_groups"); + result->canReadAllGroupMessages = data.get_optional("can_read_all_group_messages"); + result->supportsInlineQueries = data.get_optional("supports_inline_queries"); + result->canConnectToBusiness = data.get_optional("can_connect_to_business"); return result; } @@ -525,10 +525,10 @@ MessageEntity::Ptr TgTypeParser::parseJsonAndGetMessageEntity(const boost::prope } result->offset = data.get("offset", 0); result->length = data.get("length", 0); - result->url = data.get("url", ""); + result->url = data.get_optional("url"); result->user = tryParseJson(&TgTypeParser::parseJsonAndGetUser, data, "user"); - result->language = data.get("language", ""); - result->customEmojiId = data.get("custom_emoji_id", ""); + result->language = data.get_optional("language"); + result->customEmojiId = data.get_optional("custom_emoji_id"); return result; } @@ -693,12 +693,12 @@ std::string TgTypeParser::parseReplyParameters(const ReplyParameters::Ptr& objec std::string result; result += '{'; appendToJson(result, "message_id", object->messageId); - if (object->chatId) appendToJson(result, "chat_id", *(object->chatId)); - if (object->allowSendingWithoutReply) appendToJson(result, "allow_sending_without_reply", *(object->allowSendingWithoutReply)); - if (object->quote) appendToJson(result, "quote", *(object->quote)); - if (object->quoteParseMode) appendToJson(result, "quote_parse_mode", *(object->quoteParseMode)); + appendToJson(result, "chat_id", object->chatId); + appendToJson(result, "allow_sending_without_reply", object->allowSendingWithoutReply); + appendToJson(result, "quote", object->quote); + appendToJson(result, "quote_parse_mode", object->quoteParseMode); if (object->quoteEntities) appendToJson(result, "quote_entities", parseArray(&TgTypeParser::parseMessageEntity, *(object->quoteEntities))); - if (object->quotePosition) appendToJson(result, "quote_position", *(object->quotePosition)); + appendToJson(result, "quote_position", object->quotePosition); removeLastComma(result); result += '}'; return result; @@ -1736,11 +1736,11 @@ std::string TgTypeParser::parseLinkPreviewOptions(const LinkPreviewOptions::Ptr& } std::string result; result += '{'; - if (object->isDisabled) appendToJson(result, "is_disabled", *(object->isDisabled)); - if (object->url) appendToJson(result, "url", *(object->url)); - if (object->preferSmallMedia) appendToJson(result, "prefer_small_media", *(object->preferSmallMedia)); - if (object->preferLargeMedia) appendToJson(result, "prefer_large_media", *(object->preferLargeMedia)); - if (object->showAboveText) appendToJson(result, "show_above_text", *(object->showAboveText)); + appendToJson(result, "is_disabled", object->isDisabled); + appendToJson(result, "url", object->url); + appendToJson(result, "prefer_small_media", object->preferSmallMedia); + appendToJson(result, "prefer_large_media", object->preferLargeMedia); + appendToJson(result, "show_above_text", object->showAboveText); removeLastComma(result); result += '}'; return result; @@ -1813,11 +1813,11 @@ 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", ""); - result->selective = data.get("selective", false); + result->isPersistent = data.get_optional("is_persistent"); + result->resizeKeyboard = data.get_optional("resize_keyboard"); + result->oneTimeKeyboard = data.get_optional("one_time_keyboard"); + result->inputFieldPlaceholder = data.get_optional("input_field_placeholder"); + result->selective = data.get_optional("selective"); return result; } @@ -1969,7 +1969,7 @@ std::string TgTypeParser::parseKeyboardButtonPollType(const KeyboardButtonPollTy ReplyKeyboardRemove::Ptr TgTypeParser::parseJsonAndGetReplyKeyboardRemove(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); result->removeKeyboard = data.get("remove_keyboard", false); - result->selective = data.get("selective", false); + result->selective = data.get_optional("selective"); return result; } @@ -2019,15 +2019,15 @@ std::string TgTypeParser::parseInlineKeyboardMarkup(const InlineKeyboardMarkup:: InlineKeyboardButton::Ptr TgTypeParser::parseJsonAndGetInlineKeyboardButton(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); result->text = data.get("text", ""); - result->url = data.get("url", ""); - result->callbackData = data.get("callback_data", ""); + result->url = data.get_optional("url"); + result->callbackData = data.get_optional("callback_data"); result->webApp = tryParseJson(&TgTypeParser::parseJsonAndGetWebAppInfo, data, "web_app"); result->loginUrl = tryParseJson(&TgTypeParser::parseJsonAndGetLoginUrl, data, "login_url"); - result->switchInlineQuery = data.get("switch_inline_query", ""); - result->switchInlineQueryCurrentChat = data.get("switch_inline_query_current_chat", ""); + result->switchInlineQuery = data.get_optional("switch_inline_query"); + result->switchInlineQueryCurrentChat = data.get_optional("switch_inline_query_current_chat"); result->switchInlineQueryChosenChat = tryParseJson(&TgTypeParser::parseJsonAndGetSwitchInlineQueryChosenChat, data, "switch_inline_query_chosen_chat"); result->callbackGame = tryParseJson(&TgTypeParser::parseJsonAndGetCallbackGame, data, "callback_game"); - result->pay = data.get("pay", false); + result->pay = data.get_optional("pay"); return result; } @@ -2055,9 +2055,9 @@ std::string TgTypeParser::parseInlineKeyboardButton(const InlineKeyboardButton:: LoginUrl::Ptr TgTypeParser::parseJsonAndGetLoginUrl(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); result->url = data.get("url", ""); - result->forwardText = data.get("forward_text", ""); - result->botUsername = data.get("bot_username", ""); - result->requestWriteAccess = data.get("request_write_access", false); + result->forwardText = data.get_optional("forward_text"); + result->botUsername = data.get_optional("bot_username"); + result->requestWriteAccess = data.get_optional("request_write_access"); return result; } @@ -2078,11 +2078,11 @@ std::string TgTypeParser::parseLoginUrl(const LoginUrl::Ptr& object) const { SwitchInlineQueryChosenChat::Ptr TgTypeParser::parseJsonAndGetSwitchInlineQueryChosenChat(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); - result->query = data.get("query", ""); - result->allowUserChats = data.get("allow_user_chats", false); - result->allowBotChats = data.get("allow_bot_chats", false); - result->allowGroupChats = data.get("allow_group_chats", false); - result->allowChannelChats = data.get("allow_channel_chats", false); + result->query = data.get_optional("query"); + result->allowUserChats = data.get_optional("allow_user_chats"); + result->allowBotChats = data.get_optional("allow_bot_chats"); + result->allowGroupChats = data.get_optional("allow_group_chats"); + result->allowChannelChats = data.get_optional("allow_channel_chats"); return result; } @@ -2135,8 +2135,8 @@ std::string TgTypeParser::parseCallbackQuery(const CallbackQuery::Ptr& object) c ForceReply::Ptr TgTypeParser::parseJsonAndGetForceReply(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); result->forceReply = data.get("force_reply", false); - result->inputFieldPlaceholder = data.get("input_field_placeholder", ""); - result->selective = data.get("selective", false); + result->inputFieldPlaceholder = data.get_optional("input_field_placeholder"); + result->selective = data.get_optional("selective"); return result; } @@ -5564,7 +5564,7 @@ std::string TgTypeParser::parseGenericReply(const GenericReply::Ptr& object) con } void TgTypeParser::appendToJson(std::string& json, const std::string& varName, const std::string& value) const { - if (value.empty()) { + if (value.empty()) { //FIXME return; } json += '"';