From 66b89bf4c6f285362480c15d4136e5f8d3b728a5 Mon Sep 17 00:00:00 2001 From: uralm1 Date: Fri, 8 Nov 2024 16:03:45 +0500 Subject: [PATCH 1/3] Wrap optional fields with boost::optional (LinkPreviewOptions, ReplyParameters only) --- include/tgbot/types/LinkPreviewOptions.h | 11 +++--- include/tgbot/types/ReplyParameters.h | 13 +++---- src/TgTypeParser.cpp | 46 ++++++++++++------------ 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/include/tgbot/types/LinkPreviewOptions.h b/include/tgbot/types/LinkPreviewOptions.h index b4c5325e..b3f91efa 100644 --- a/include/tgbot/types/LinkPreviewOptions.h +++ b/include/tgbot/types/LinkPreviewOptions.h @@ -3,6 +3,7 @@ #include #include +#include namespace TgBot { @@ -19,29 +20,29 @@ class LinkPreviewOptions { /** * @brief Optional. True, if the link preview is disabled */ - bool isDisabled; + boost::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 */ - std::string url; + boost::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 */ - bool preferSmallMedia; + boost::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 */ - bool preferLargeMedia; + boost::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 */ - bool showAboveText; + boost::optional showAboveText; }; } diff --git a/include/tgbot/types/ReplyParameters.h b/include/tgbot/types/ReplyParameters.h index 537de072..ee2ad7be 100644 --- a/include/tgbot/types/ReplyParameters.h +++ b/include/tgbot/types/ReplyParameters.h @@ -7,6 +7,7 @@ #include #include #include +#include namespace TgBot { @@ -30,7 +31,7 @@ class ReplyParameters { * * Not supported for messages sent on behalf of a business account. */ - std::int64_t chatId; + boost::optional chatId; /** * @brief Optional. Pass True if the message should be sent even if the specified message to be replied to is not found. @@ -38,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. */ - bool allowSendingWithoutReply; + boost::optional allowSendingWithoutReply; /** * @brief Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing. @@ -46,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. */ - std::string quote; + boost::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. */ - std::string quoteParseMode; + boost::optional quoteParseMode; /** * @brief Optional. A JSON-serialized list of special entities that appear in the quote. * * It can be specified instead of quoteParseMode. */ - std::vector quoteEntities; + boost::optional> quoteEntities; /** * @brief Optional. Position of the quote in the original message in UTF-16 code units */ - std::int32_t quotePosition; + boost::optional quotePosition; }; } diff --git a/src/TgTypeParser.cpp b/src/TgTypeParser.cpp index d3e9bd92..5f75730d 100644 --- a/src/TgTypeParser.cpp +++ b/src/TgTypeParser.cpp @@ -675,12 +675,14 @@ std::string TgTypeParser::parseExternalReplyInfo(const ExternalReplyInfo::Ptr& o ReplyParameters::Ptr TgTypeParser::parseJsonAndGetReplyParameters(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); result->messageId = data.get("message_id", 0); - result->chatId = data.get("chat_id", 0); - result->allowSendingWithoutReply = data.get("allow_sending_without_reply", false); - result->quote = data.get("quote", ""); - result->quoteParseMode = data.get("quote_parse_mode", ""); - result->quoteEntities = parseJsonAndGetArray(&TgTypeParser::parseJsonAndGetMessageEntity, data, "quote_entities"); - result->quotePosition = data.get("quote_position", 0); + result->chatId = data.get_optional("chat_id"); + result->allowSendingWithoutReply = data.get_optional("allow_sending_without_reply"); + result->quote = data.get_optional("quote"); + result->quoteParseMode = data.get_optional("quote_parse_mode"); + if (data.find("quote_entities") != data.not_found()) { + result->quoteEntities = parseJsonAndGetArray(&TgTypeParser::parseJsonAndGetMessageEntity, data, "quote_entities"); + } + result->quotePosition = data.get_optional("quote_position"); return result; } @@ -691,12 +693,12 @@ std::string TgTypeParser::parseReplyParameters(const ReplyParameters::Ptr& objec std::string result; result += '{'; appendToJson(result, "message_id", object->messageId); - 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); - appendToJson(result, "quote_entities", parseArray(&TgTypeParser::parseMessageEntity, object->quoteEntities)); - appendToJson(result, "quote_position", object->quotePosition); + 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)); + if (object->quoteEntities) appendToJson(result, "quote_entities", parseArray(&TgTypeParser::parseMessageEntity, *(object->quoteEntities))); + if (object->quotePosition) appendToJson(result, "quote_position", *(object->quotePosition)); removeLastComma(result); result += '}'; return result; @@ -1720,11 +1722,11 @@ std::string TgTypeParser::parseGiveawayCompleted(const GiveawayCompleted::Ptr& o LinkPreviewOptions::Ptr TgTypeParser::parseJsonAndGetLinkPreviewOptions(const boost::property_tree::ptree& data) const { auto result(std::make_shared()); - result->isDisabled = data.get("is_disabled", false); - result->url = data.get("url", ""); - result->preferSmallMedia = data.get("prefer_small_media", false); - result->preferLargeMedia = data.get("prefer_large_media", false); - result->showAboveText = data.get("show_above_text", false); + result->isDisabled = data.get_optional("is_disabled"); + result->url = data.get_optional("url"); + result->preferSmallMedia = data.get_optional("prefer_small_media"); + result->preferLargeMedia = data.get_optional("prefer_large_media"); + result->showAboveText = data.get_optional("show_above_text"); return result; } @@ -1734,11 +1736,11 @@ std::string TgTypeParser::parseLinkPreviewOptions(const LinkPreviewOptions::Ptr& } std::string result; result += '{'; - 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); + 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)); removeLastComma(result); result += '}'; return result; From 42567f5f5b79fe6595a529ce6450bcbf975fcbff Mon Sep 17 00:00:00 2001 From: uralm1 Date: Sun, 17 Nov 2024 20:49:03 +0500 Subject: [PATCH 2/3] 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 +++--- samples/echobot-curl-client/src/main.cpp | 2 +- samples/echobot-setmycommands/src/main.cpp | 2 +- samples/echobot-submodule/src/main.cpp | 2 +- samples/echobot-webhook-server/src/main.cpp | 2 +- samples/echobot/src/main.cpp | 2 +- samples/inline-keyboard/src/main.cpp | 2 +- samples/photo/src/main.cpp | 2 +- samples/receive-file/src/main.cpp | 2 +- samples/received-text-processing/src/main.cpp | 2 +- samples/reply-keyboard/src/main.cpp | 2 +- src/TgTypeParser.cpp | 88 +++++++++---------- 23 files changed, 163 insertions(+), 117 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 00000000..b3563d48 --- /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 661930e0..850c41f6 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 131e1cb8..35f42d60 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 c71b5db5..35bad3f1 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 b3f91efa..c2a3df84 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 575a3a0b..fce83e53 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 7ebe49e4..12da9d40 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 f70b2fca..e7b62f30 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 3a2bb94b..aba9ca75 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 ee2ad7be..ca646e7e 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 b0ecf2cb..53591570 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 6b28e1df..e00f640b 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/samples/echobot-curl-client/src/main.cpp b/samples/echobot-curl-client/src/main.cpp index a957011b..d845bbd7 100644 --- a/samples/echobot-curl-client/src/main.cpp +++ b/samples/echobot-curl-client/src/main.cpp @@ -33,7 +33,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/echobot-setmycommands/src/main.cpp b/samples/echobot-setmycommands/src/main.cpp index afb9e353..7b0ef606 100644 --- a/samples/echobot-setmycommands/src/main.cpp +++ b/samples/echobot-setmycommands/src/main.cpp @@ -59,7 +59,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/echobot-submodule/src/main.cpp b/samples/echobot-submodule/src/main.cpp index c26cbdf2..b12631a0 100644 --- a/samples/echobot-submodule/src/main.cpp +++ b/samples/echobot-submodule/src/main.cpp @@ -31,7 +31,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/echobot-webhook-server/src/main.cpp b/samples/echobot-webhook-server/src/main.cpp index 2919c2e3..0e48ddc0 100644 --- a/samples/echobot-webhook-server/src/main.cpp +++ b/samples/echobot-webhook-server/src/main.cpp @@ -33,7 +33,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); TgWebhookTcpServer webhookServer(8080, bot); diff --git a/samples/echobot/src/main.cpp b/samples/echobot/src/main.cpp index c26cbdf2..7ea3abba 100644 --- a/samples/echobot/src/main.cpp +++ b/samples/echobot/src/main.cpp @@ -31,7 +31,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username.value_or(string{"unknown"}).c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/inline-keyboard/src/main.cpp b/samples/inline-keyboard/src/main.cpp index b84d363d..6dd4a3f3 100644 --- a/samples/inline-keyboard/src/main.cpp +++ b/samples/inline-keyboard/src/main.cpp @@ -44,7 +44,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/photo/src/main.cpp b/samples/photo/src/main.cpp index d6bfe83b..08322756 100644 --- a/samples/photo/src/main.cpp +++ b/samples/photo/src/main.cpp @@ -30,7 +30,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/receive-file/src/main.cpp b/samples/receive-file/src/main.cpp index 59725348..a17da66d 100644 --- a/samples/receive-file/src/main.cpp +++ b/samples/receive-file/src/main.cpp @@ -36,7 +36,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/received-text-processing/src/main.cpp b/samples/received-text-processing/src/main.cpp index b6069e94..9cf4887a 100644 --- a/samples/received-text-processing/src/main.cpp +++ b/samples/received-text-processing/src/main.cpp @@ -46,7 +46,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); while (true) { diff --git a/samples/reply-keyboard/src/main.cpp b/samples/reply-keyboard/src/main.cpp index 877302bd..cf716900 100644 --- a/samples/reply-keyboard/src/main.cpp +++ b/samples/reply-keyboard/src/main.cpp @@ -73,7 +73,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/src/TgTypeParser.cpp b/src/TgTypeParser.cpp index 5f75730d..b2a8b5b0 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 += '"'; From d336b7a96ec8166835cc74303eaded3ee8815233 Mon Sep 17 00:00:00 2001 From: uralm1 Date: Mon, 18 Nov 2024 13:44:48 +0500 Subject: [PATCH 3/3] README.md, OptionalNullPtr<>, potential ub in samples --- README.md | 2 +- include/tgbot/Optional.h | 10 +++++----- include/tgbot/TgTypeParser.h | 8 ++------ include/tgbot/types/InlineKeyboardButton.h | 8 ++++---- include/tgbot/types/MessageEntity.h | 2 +- samples/echobot-curl-client/src/main.cpp | 2 +- samples/echobot-setmycommands/src/main.cpp | 2 +- samples/echobot-submodule/src/main.cpp | 2 +- samples/echobot-webhook-server/src/main.cpp | 2 +- samples/echobot/src/main.cpp | 5 ++++- samples/inline-keyboard/src/main.cpp | 2 +- samples/photo/src/main.cpp | 2 +- samples/receive-file/src/main.cpp | 2 +- samples/received-text-processing/src/main.cpp | 2 +- samples/reply-keyboard/src/main.cpp | 2 +- 15 files changed, 26 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index d20f8fc0..1739eca0 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ int main() { bot.getApi().sendMessage(message->chat->id, "Your message is: " + message->text); }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); TgBot::TgLongPoll longPoll(bot); while (true) { printf("Long poll started\n"); diff --git a/include/tgbot/Optional.h b/include/tgbot/Optional.h index b3563d48..a1b5abdd 100644 --- a/include/tgbot/Optional.h +++ b/include/tgbot/Optional.h @@ -5,16 +5,16 @@ namespace TgBot { +// Optional via boost::optional template - using Optional = boost::optional; + using Optional = boost::optional; -// use for: OptionalPtr> -// for pointers, we assume optional value == nullptr (or not owned, etc) +// Optional is nullptr (for std::shared/unique_ptr<> etc) template - using OptionalPtr = T; + using OptionalNullPtr = T; template - using Required = T; + using Required = T; } diff --git a/include/tgbot/TgTypeParser.h b/include/tgbot/TgTypeParser.h index 850c41f6..eba210c9 100644 --- a/include/tgbot/TgTypeParser.h +++ b/include/tgbot/TgTypeParser.h @@ -899,7 +899,7 @@ class TGBOT_API TgTypeParser { private: inline void removeLastComma(std::string& input) const { - if (!input.empty() && input.back() == ',') input.erase(input.length() - 1); + if (!input.empty() && input.back() == ',') input.pop_back(); } template @@ -907,11 +907,7 @@ class TGBOT_API TgTypeParser { if (!value) { return; } - json += '"'; - json += varName; - json += R"(":)"; - json += *value; - json += ','; + appendToJson(json, varName, *value); } template diff --git a/include/tgbot/types/InlineKeyboardButton.h b/include/tgbot/types/InlineKeyboardButton.h index 35bad3f1..925493d6 100644 --- a/include/tgbot/types/InlineKeyboardButton.h +++ b/include/tgbot/types/InlineKeyboardButton.h @@ -47,14 +47,14 @@ 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. */ - OptionalPtr webApp; + OptionalNullPtr 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). */ - OptionalPtr loginUrl; + OptionalNullPtr 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. @@ -74,14 +74,14 @@ class InlineKeyboardButton { /** * @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 */ - OptionalPtr switchInlineQueryChosenChat; + OptionalNullPtr 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. */ - OptionalPtr callbackGame; + OptionalNullPtr callbackGame; /** * @brief Optional. Specify True, to send a [Pay button](https://core.telegram.org/bots/api#payments). diff --git a/include/tgbot/types/MessageEntity.h b/include/tgbot/types/MessageEntity.h index 12da9d40..de07ee80 100644 --- a/include/tgbot/types/MessageEntity.h +++ b/include/tgbot/types/MessageEntity.h @@ -55,7 +55,7 @@ class MessageEntity { /** * @brief Optional. For Type::TextMention only, the mentioned user */ - OptionalPtr user; + OptionalNullPtr user; /** * @brief Optional. For Type::Pre only, the programming language of the entity text diff --git a/samples/echobot-curl-client/src/main.cpp b/samples/echobot-curl-client/src/main.cpp index d845bbd7..0aee5e2f 100644 --- a/samples/echobot-curl-client/src/main.cpp +++ b/samples/echobot-curl-client/src/main.cpp @@ -33,7 +33,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/echobot-setmycommands/src/main.cpp b/samples/echobot-setmycommands/src/main.cpp index 7b0ef606..16d6d5f9 100644 --- a/samples/echobot-setmycommands/src/main.cpp +++ b/samples/echobot-setmycommands/src/main.cpp @@ -59,7 +59,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/echobot-submodule/src/main.cpp b/samples/echobot-submodule/src/main.cpp index b12631a0..aa15aee8 100644 --- a/samples/echobot-submodule/src/main.cpp +++ b/samples/echobot-submodule/src/main.cpp @@ -31,7 +31,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/echobot-webhook-server/src/main.cpp b/samples/echobot-webhook-server/src/main.cpp index 0e48ddc0..afc4e077 100644 --- a/samples/echobot-webhook-server/src/main.cpp +++ b/samples/echobot-webhook-server/src/main.cpp @@ -33,7 +33,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); TgWebhookTcpServer webhookServer(8080, bot); diff --git a/samples/echobot/src/main.cpp b/samples/echobot/src/main.cpp index 7ea3abba..9aa6a8ee 100644 --- a/samples/echobot/src/main.cpp +++ b/samples/echobot/src/main.cpp @@ -31,7 +31,10 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username.value_or(string{"unknown"}).c_str()); + auto user = bot.getApi().getMe(); + printf("Bot name: %s, username: %s\n", + user->firstName.c_str(), + user->username.value_or(string{"unknown"}).c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/inline-keyboard/src/main.cpp b/samples/inline-keyboard/src/main.cpp index 6dd4a3f3..94359d4c 100644 --- a/samples/inline-keyboard/src/main.cpp +++ b/samples/inline-keyboard/src/main.cpp @@ -44,7 +44,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/photo/src/main.cpp b/samples/photo/src/main.cpp index 08322756..6ba74ea4 100644 --- a/samples/photo/src/main.cpp +++ b/samples/photo/src/main.cpp @@ -30,7 +30,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/receive-file/src/main.cpp b/samples/receive-file/src/main.cpp index a17da66d..5d29c616 100644 --- a/samples/receive-file/src/main.cpp +++ b/samples/receive-file/src/main.cpp @@ -36,7 +36,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot); diff --git a/samples/received-text-processing/src/main.cpp b/samples/received-text-processing/src/main.cpp index 9cf4887a..97a203e4 100644 --- a/samples/received-text-processing/src/main.cpp +++ b/samples/received-text-processing/src/main.cpp @@ -46,7 +46,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); while (true) { diff --git a/samples/reply-keyboard/src/main.cpp b/samples/reply-keyboard/src/main.cpp index cf716900..fb4d122a 100644 --- a/samples/reply-keyboard/src/main.cpp +++ b/samples/reply-keyboard/src/main.cpp @@ -73,7 +73,7 @@ int main() { }); try { - printf("Bot username: %s\n", bot.getApi().getMe()->username->c_str()); + printf("Bot name: %s\n", bot.getApi().getMe()->firstName.c_str()); bot.getApi().deleteWebhook(); TgLongPoll longPoll(bot);