From 299dced3dcf7d02c60f104dcfe4e99d412201dbe Mon Sep 17 00:00:00 2001 From: Kirill Kirilenko Date: Thu, 16 Feb 2017 02:10:41 +0300 Subject: [PATCH] InlineKeyboardMarkup test support. --- include/telebotxx/RequestOptions.hpp | 73 +++++++++++++ include/telebotxx/SendMessageRequest.hpp | 2 + src/RequestOptions.cpp | 126 +++++++++++++++++++++++ src/SendMessageRequest.cpp | 80 +++++++++++++- tests/TestApi.cpp | 16 +++ 5 files changed, 296 insertions(+), 1 deletion(-) diff --git a/include/telebotxx/RequestOptions.hpp b/include/telebotxx/RequestOptions.hpp index 33bd2b7..fd2e3d4 100644 --- a/include/telebotxx/RequestOptions.hpp +++ b/include/telebotxx/RequestOptions.hpp @@ -109,6 +109,79 @@ private: boost::variant value_; }; +TELEBOTXX_DECLARE_STRING_PARAM_CLASS(CallbackData) + +TELEBOTXX_DECLARE_STRING_PARAM_CLASS(SwitchInlineQuery) + +TELEBOTXX_DECLARE_STRING_PARAM_CLASS(SwitchInlineQueryCurrentChat) + +class InlineKeyboardButton +{ +public: + explicit InlineKeyboardButton(const std::string& text, const Url& url); + explicit InlineKeyboardButton(const std::string& text, const CallbackData&); + explicit InlineKeyboardButton(const std::string& text, const SwitchInlineQuery&); + explicit InlineKeyboardButton(const std::string& text, const SwitchInlineQueryCurrentChat&); + InlineKeyboardButton(const InlineKeyboardButton&); + InlineKeyboardButton(InlineKeyboardButton&&); + ~InlineKeyboardButton(); + + enum class ActionType { Url, CallbackData, SwitchInlineQuery, SwitchInlineQueryCurrentChat }; + ActionType getActionType() const; + + const std::string& getText() const; + const Url& getUrl() const; + const CallbackData& getCallbackData() const; + const SwitchInlineQuery& getSwitchInlineQuery() const; + const SwitchInlineQueryCurrentChat& getSwitchInlineQueryCurrentChat() const; + +private: + ActionType actionType_; + std::string text_; + boost::variant value_; + // \todo CallbackGame +}; + +using InlineKeyboardButtonRow = std::vector; + +class InlineKeyboardMarkup +{ +public: + void addRow(const InlineKeyboardButtonRow& row); + + const std::vector& getRows() const; + +private: + std::vector rows_; +}; + +class ReplyKeyboardMarkup +{ + +}; + +class ReplyMarkup +{ +public: + explicit ReplyMarkup(const InlineKeyboardMarkup&); + explicit ReplyMarkup(const ReplyKeyboardMarkup&); + ReplyMarkup(const ReplyMarkup&); + ReplyMarkup(ReplyMarkup&&); + ~ReplyMarkup(); + + enum class Type { InlineKeyboardMarkup, ReplyKeyboardMarkup, ReplyKeyboardRemove, ForceReply }; + Type getType() const; + + const InlineKeyboardMarkup& getInlineKeyboardMarkup() const; + + void swap(ReplyMarkup&); + const ReplyMarkup& operator=(ReplyMarkup); + +private: + Type type_; + boost::variant value_; +}; + } #endif // TELEBOTXX_REQUEST_OPTIONS_HPP diff --git a/include/telebotxx/SendMessageRequest.hpp b/include/telebotxx/SendMessageRequest.hpp index d9334e0..bd51626 100644 --- a/include/telebotxx/SendMessageRequest.hpp +++ b/include/telebotxx/SendMessageRequest.hpp @@ -19,11 +19,13 @@ public: void setDisableWebPagePreview(const DisableWebPagePreview& disableWebPagePreview); void setDisableNotification(const DisableNotification& disableNotification); void setReplyToMessageId(const ReplyTo& replyToMessageId); + void setReplyMarkup(const ReplyMarkup& replyMarkup); void setOption(ParseMode mode); void setOption(const DisableWebPagePreview& disableWebPagePreview); void setOption(const DisableNotification& disableNotification); void setOption(const ReplyTo& replyToMessageId); + void setOption(const ReplyMarkup& replyMarkup); Message execute(); diff --git a/src/RequestOptions.cpp b/src/RequestOptions.cpp index 54f80ae..adc78f2 100644 --- a/src/RequestOptions.cpp +++ b/src/RequestOptions.cpp @@ -21,7 +21,9 @@ ChatId::ChatId(const std::string& str) } ChatId::ChatId(const ChatId& other) = default; + ChatId::ChatId(ChatId&& other) = default; + ChatId::~ChatId() = default; ChatId::Type ChatId::getType() const @@ -125,7 +127,9 @@ Photo::Photo(const Url& url) } Photo::Photo(const Photo& other) = default; + Photo::Photo(Photo&& other) = default; + Photo::~Photo() = default; Photo::Type Photo::getType() const @@ -153,4 +157,126 @@ const Url& Photo::getUrl() const return boost::get(value_); } +//////////////////////////////////////////////////////////////// + +TELEBOTXX_DEFINE_STRING_PARAM_CLASS(CallbackData) + +//////////////////////////////////////////////////////////////// + +TELEBOTXX_DEFINE_STRING_PARAM_CLASS(SwitchInlineQuery) + +//////////////////////////////////////////////////////////////// + +TELEBOTXX_DEFINE_STRING_PARAM_CLASS(SwitchInlineQueryCurrentChat) + +//////////////////////////////////////////////////////////////// + +InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const Url& url) + : actionType_(ActionType::Url), text_(text), value_(url) +{ +} + +InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const CallbackData& callbackData) + : actionType_(ActionType::CallbackData), text_(text), value_(callbackData) +{ +} + +InlineKeyboardButton::InlineKeyboardButton(const std::string& text, const SwitchInlineQuery& switchInlineQuery) + : actionType_(ActionType::SwitchInlineQuery), text_(text), value_(switchInlineQuery) +{ +} + +InlineKeyboardButton::InlineKeyboardButton(const std::string& text, + const SwitchInlineQueryCurrentChat& switchInlineQueryCurrentChat) + : actionType_(ActionType::SwitchInlineQueryCurrentChat), text_(text), value_(switchInlineQueryCurrentChat) +{ +} + +InlineKeyboardButton::InlineKeyboardButton(const InlineKeyboardButton& other) = default; + +InlineKeyboardButton::InlineKeyboardButton(InlineKeyboardButton&& other) = default; + +InlineKeyboardButton::~InlineKeyboardButton() = default; + +InlineKeyboardButton::ActionType InlineKeyboardButton::getActionType() const +{ + return actionType_; +} + +const std::string& InlineKeyboardButton::getText() const +{ + return text_; +} + +const Url& InlineKeyboardButton::getUrl() const +{ + return boost::get(value_);; +} + +const CallbackData& InlineKeyboardButton::getCallbackData() const +{ + return boost::get(value_); +} + +const SwitchInlineQuery& InlineKeyboardButton::getSwitchInlineQuery() const +{ + return boost::get(value_); +} + +const SwitchInlineQueryCurrentChat& InlineKeyboardButton::getSwitchInlineQueryCurrentChat() const +{ + return boost::get(value_); +} + +//////////////////////////////////////////////////////////////// + +void InlineKeyboardMarkup::addRow(const InlineKeyboardButtonRow& row) +{ + rows_.push_back(row); +} + +const std::vector& InlineKeyboardMarkup::getRows() const +{ + return rows_; +} + +//////////////////////////////////////////////////////////////// + +ReplyMarkup::ReplyMarkup(const InlineKeyboardMarkup& keyboard) + : type_(Type::InlineKeyboardMarkup), value_(keyboard) +{ +} + +ReplyMarkup::ReplyMarkup(const ReplyKeyboardMarkup& keyboard) + : type_(Type::ReplyKeyboardMarkup), value_(keyboard) +{ +} + +ReplyMarkup::ReplyMarkup(const ReplyMarkup&) = default; +ReplyMarkup::ReplyMarkup(ReplyMarkup&&) = default; +ReplyMarkup::~ReplyMarkup() = default; + +ReplyMarkup::Type ReplyMarkup::getType() const +{ + return type_; +} + +const InlineKeyboardMarkup& ReplyMarkup::getInlineKeyboardMarkup() const +{ + return boost::get(value_); +} + +void ReplyMarkup::swap(ReplyMarkup& other) +{ + using std::swap; + swap(type_, other.type_); + swap(value_, other.value_); +} + +const ReplyMarkup& ReplyMarkup::operator=(ReplyMarkup other) +{ + swap(other); + return *this; +} + } diff --git a/src/SendMessageRequest.cpp b/src/SendMessageRequest.cpp index 7ec45e8..4880ce1 100644 --- a/src/SendMessageRequest.cpp +++ b/src/SendMessageRequest.cpp @@ -11,6 +11,44 @@ namespace telebotxx { +void writeInlineKeyboardButton(rapidjson::Writer& writer, const InlineKeyboardButton& button) +{ + writer.StartObject(); + + writer.String("text"); + writer.String(button.getText().c_str()); + + switch (button.getActionType()) + { + case InlineKeyboardButton::ActionType::Url: + { + writer.String("url"); + writer.String(button.getUrl().getValue().c_str()); + break; + } + case InlineKeyboardButton::ActionType::CallbackData: + { + writer.String("callback_data"); + writer.String(button.getCallbackData().getValue().c_str()); + break; + } + case InlineKeyboardButton::ActionType::SwitchInlineQuery: + { + writer.String("switch_inline_query"); + writer.String(button.getSwitchInlineQuery().getValue().c_str()); + break; + } + case InlineKeyboardButton::ActionType::SwitchInlineQueryCurrentChat: + { + writer.String("switch_inline_query_current_chat"); + writer.String(button.getSwitchInlineQueryCurrentChat().getValue().c_str()); + break; + } + } + + writer.EndObject(); +} + class SendMessageRequest::Impl { public: @@ -39,6 +77,11 @@ public: replyToMessageId_ = replyToMessageId; } + void setReplyMarkup(const ReplyMarkup& replyMarkup) + { + replyMarkup_ = replyMarkup; + } + Message execute() { // Construct JSON body @@ -87,7 +130,31 @@ public: writer.Int(replyToMessageId_->value()); } - /// \todo: Add reply_markup + // Add reply_markup + if (replyMarkup_) + { + writer.String("reply_markup"); + writer.StartObject(); + writer.String("inline_keyboard"); + if (replyMarkup_->getType() == ReplyMarkup::Type::InlineKeyboardMarkup) + { + writer.StartArray(); + auto rows = replyMarkup_->getInlineKeyboardMarkup().getRows(); + for (auto& row : rows) + { + writer.StartArray(); + for (auto& button : row) + { + writeInlineKeyboardButton(writer, button); + } + writer.EndArray(); + } + writer.EndArray(); + } + else + writer.String(chatId_.getUsername().c_str()); + writer.EndObject(); + } writer.EndObject(); @@ -120,6 +187,7 @@ private: boost::optional disableWebPagePreview_; boost::optional disableNotification_; boost::optional replyToMessageId_; + boost::optional replyMarkup_; }; SendMessageRequest::SendMessageRequest(const std::string& telegramMainUrl, const ChatId& chat, const Text& text) @@ -151,6 +219,11 @@ void SendMessageRequest::setReplyToMessageId(const ReplyTo& replyToMessageId) impl_->setReplyToMessageId(replyToMessageId); } +void SendMessageRequest::setReplyMarkup(const ReplyMarkup& replyMarkup) +{ + impl_->setReplyMarkup(replyMarkup); +} + void SendMessageRequest::setOption(ParseMode mode) { setParseMode(mode); @@ -171,6 +244,11 @@ void SendMessageRequest::setOption(const ReplyTo& replyToMessageId) setReplyToMessageId(replyToMessageId); } +void SendMessageRequest::setOption(const ReplyMarkup& replyMarkup) +{ + setReplyMarkup(replyMarkup); +} + Message SendMessageRequest::execute() { return impl_->execute(); diff --git a/tests/TestApi.cpp b/tests/TestApi.cpp index a64a964..25f3318 100644 --- a/tests/TestApi.cpp +++ b/tests/TestApi.cpp @@ -143,6 +143,22 @@ BOOST_AUTO_TEST_SUITE(TestBotApi) )); } + BOOST_AUTO_TEST_CASE(SendMessageWithInlineKeyboard) + { + PRINT_TESTNAME; + BOOST_REQUIRE(bot); + InlineKeyboardMarkup markup; + markup.addRow(InlineKeyboardButtonRow{ + InlineKeyboardButton("Google", Url{"http://google.com/"}), + InlineKeyboardButton("Google", Url{"http://google.com/"}) + }); + markup.addRow(InlineKeyboardButtonRow{InlineKeyboardButton("Google", CallbackData{"HELLO"})}); + BOOST_REQUIRE_NO_THROW(bot->sendMessage(ChatId{chat}, + Text{"Message with inline keyboard"}, + ReplyMarkup{markup} + )); + } + BOOST_AUTO_TEST_CASE(SendPhotoFile) { PRINT_TESTNAME;