diff options
author | Oleg Morozenkov <omorozenkov@gmail.com> | 2016-04-03 00:09:06 +0400 |
---|---|---|
committer | Oleg Morozenkov <omorozenkov@gmail.com> | 2016-04-03 00:09:06 +0400 |
commit | b6fd8d8ff899240580c5973bd75d74c5167b8d3d (patch) | |
tree | b24d43cd2a13ba923de495961bf9a5e613ae683a | |
parent | 2195ce0768fa8903633164c0c45060c412cd5670 (diff) | |
parent | b937e88dd43a7708f40af6a3c333046e3121a77a (diff) |
Merge pull request #19 from aadeg/master
Implementing inline mode BIS
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | include/tgbot/Api.h | 14 | ||||
-rw-r--r-- | include/tgbot/EventBroadcaster.h | 44 | ||||
-rw-r--r-- | include/tgbot/EventHandler.h | 42 | ||||
-rw-r--r-- | include/tgbot/TgTypeParser.h | 24 | ||||
-rw-r--r-- | include/tgbot/net/HttpReqArg.h | 2 | ||||
-rw-r--r-- | include/tgbot/tgbot.h | 8 | ||||
-rw-r--r-- | include/tgbot/types/ChosenInlineResult.h | 40 | ||||
-rw-r--r-- | include/tgbot/types/InlineQuery.h | 46 | ||||
-rw-r--r-- | include/tgbot/types/InlineQueryResult.h | 66 | ||||
-rw-r--r-- | include/tgbot/types/InlineQueryResultArticle.h | 59 | ||||
-rw-r--r-- | include/tgbot/types/InlineQueryResultGif.h | 54 | ||||
-rw-r--r-- | include/tgbot/types/InlineQueryResultMpeg4Gif.h | 50 | ||||
-rw-r--r-- | include/tgbot/types/InlineQueryResultPhoto.h | 58 | ||||
-rw-r--r-- | include/tgbot/types/InlineQueryResultVideo.h | 60 | ||||
-rw-r--r-- | include/tgbot/types/Message.h | 23 | ||||
-rw-r--r-- | include/tgbot/types/Update.h | 12 | ||||
-rw-r--r-- | src/Api.cpp | 12 | ||||
-rw-r--r-- | src/TgTypeParser.cpp | 254 | ||||
-rw-r--r-- | src/types/InlineQueryResult.cpp | 16 |
20 files changed, 859 insertions, 27 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a31acc0..c13a633 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ set(SRC_LIST src/net/HttpParser.cpp src/net/TgLongPoll.cpp src/tools/StringTools.cpp -) + src/types/InlineQueryResult.cpp) ### libs # threads diff --git a/include/tgbot/Api.h b/include/tgbot/Api.h index b33cd03..66f41b5 100644 --- a/include/tgbot/Api.h +++ b/include/tgbot/Api.h @@ -35,6 +35,7 @@ #include "tgbot/types/InputFile.h" #include "tgbot/types/UserProfilePhotos.h" #include "tgbot/types/Update.h" +#include "tgbot/types/InlineQueryResult.h" namespace TgBot { @@ -229,8 +230,21 @@ public: * Ports currently supported for Webhooks: 443, 80, 88, 8443. * @param url Optional. HTTPS url to send updates to. Use an empty string to remove webhook integration. */ + // TODO Add support to self-signed certificate void setWebhook(const std::string& url = "") const; + /** + * Use this method to send answers to an inline query. + * No mode that 50 results per query are allowed. + * @param inlineQueryId Unique identifier for the answered query. + * @param results Array of results for the inline query. + * @param cacheTime The maximum amount of time in seconds that the result of the inline query may be cached on the server. Defaults to 300. + * @param isPersonal Pass True, if results may be cached on the server side only for the user that sent the query. By default, results may be returned to any user who sends the same query. + * @param nextOffset Pass the offset that a client should send in the next query with the same text to receive more results. Pass an empty string if there are no more results or if you don‘t support pagination. Offset length can’t exceed 64 bytes. + */ + void answerInlineQuery(const std::string& inlineQueryId, const std::vector<InlineQueryResult::Ptr>& results, + int32_t cacheTime=300, bool isPersonal=false, const std::string& nextOffset="") const; + private: boost::property_tree::ptree sendRequest(const std::string& method, const std::vector<HttpReqArg>& args = std::vector<HttpReqArg>()) const; diff --git a/include/tgbot/EventBroadcaster.h b/include/tgbot/EventBroadcaster.h index 3ec8865..d97dbbb 100644 --- a/include/tgbot/EventBroadcaster.h +++ b/include/tgbot/EventBroadcaster.h @@ -29,6 +29,8 @@ #include <map> #include "tgbot/types/Message.h" +#include "tgbot/types/InlineQuery.h" +#include "tgbot/types/ChosenInlineResult.h" namespace TgBot { @@ -44,6 +46,8 @@ friend EventHandler; public: typedef std::function<void (const Message::Ptr&)> MessageListener; + typedef std::function<void (const InlineQuery::Ptr&)> InlineQueryListener; + typedef std::function<void (const ChosenInlineResult::Ptr&)> ChosenInlineResultListener; /** * Registers listener which receives all messages which the bot can ever receive. @@ -78,13 +82,29 @@ public: _onNonCommandMessageListeners.push_back(listener); } + inline void onInlineQuery(const InlineQueryListener& listener) { + _onInlineQueryListeners.push_back(listener); + } + + inline void onChosenInlineResult(const ChosenInlineResultListener& listener){ + _onChosenInlineResultListeners.push_back(listener); + } + private: - inline void broadcastAnyMessage(const Message::Ptr& message) const { - for (const MessageListener& item : _onAnyMessageListeners) { - item(message); + template<typename ListenerType, typename ObjectType> + inline void broadcast(const std::vector<ListenerType>& listeners, const ObjectType& object) const { + if (!object) + return; + + for (const ListenerType& item : listeners) { + item(object); } } + inline void broadcastAnyMessage(const Message::Ptr& message) const { + broadcast<MessageListener, Message::Ptr>(_onAnyMessageListeners, message); + } + inline bool broadcastCommand(const std::string command, const Message::Ptr& message) const { std::map<std::string, MessageListener>::const_iterator iter = _onCommandListeners.find(command); if (iter == _onCommandListeners.end()) { @@ -95,21 +115,27 @@ private: } inline void broadcastUnknownCommand(const Message::Ptr& message) const { - for (const MessageListener& item : _onUnknownCommandListeners) { - item(message); - } + broadcast<MessageListener, Message::Ptr>(_onUnknownCommandListeners, message); } inline void broadcastNonCommandMessage(const Message::Ptr& message) const { - for (const MessageListener& item : _onNonCommandMessageListeners) { - item(message); - } + broadcast<MessageListener, Message::Ptr>(_onNonCommandMessageListeners, message); + } + + inline void broadcastInlineQuery(const InlineQuery::Ptr& query) const { + broadcast<InlineQueryListener, InlineQuery::Ptr>(_onInlineQueryListeners, query); + } + + inline void broadcastChosenInlineResult(const ChosenInlineResult::Ptr& result) const { + broadcast<ChosenInlineResultListener, ChosenInlineResult::Ptr>(_onChosenInlineResultListeners, result); } std::vector<MessageListener> _onAnyMessageListeners; std::map<std::string, MessageListener> _onCommandListeners; std::vector<MessageListener> _onUnknownCommandListeners; std::vector<MessageListener> _onNonCommandMessageListeners; + std::vector<InlineQueryListener> _onInlineQueryListeners; + std::vector<ChosenInlineResultListener> _onChosenInlineResultListeners; }; } diff --git a/include/tgbot/EventHandler.h b/include/tgbot/EventHandler.h index bb277a8..64f74cd 100644 --- a/include/tgbot/EventHandler.h +++ b/include/tgbot/EventHandler.h @@ -31,34 +31,44 @@ namespace TgBot { class EventHandler { -public: - explicit EventHandler(const EventBroadcaster* broadcaster) : _broadcaster(broadcaster) { - } + void handleMessage(const Message::Ptr& message) const { + _broadcaster->broadcastAnyMessage(message); - inline void handleUpdate(const Update::Ptr& update) const { - _broadcaster->broadcastAnyMessage(update->message); - if (StringTools::startsWith(update->message->text, "/")) { + if (StringTools::startsWith(message->text, "/")) { unsigned long splitPosition; - unsigned long spacePosition = update->message->text.find(' '); - unsigned long atSymbolPosition = update->message->text.find('@'); - if (spacePosition == update->message->text.npos) { - if (atSymbolPosition == update->message->text.npos) { - splitPosition = update->message->text.size(); + unsigned long spacePosition = message->text.find(' '); + unsigned long atSymbolPosition = message->text.find('@'); + if (spacePosition == message->text.npos) { + if (atSymbolPosition == message->text.npos) { + splitPosition = message->text.size(); } else { splitPosition = atSymbolPosition; } - } else if (atSymbolPosition == update->message->text.npos) { + } else if (atSymbolPosition == message->text.npos) { splitPosition = spacePosition; } else { splitPosition = std::min(spacePosition, atSymbolPosition); } - std::string command = update->message->text.substr(1, splitPosition - 1); - if (!_broadcaster->broadcastCommand(command, update->message)) { - _broadcaster->broadcastUnknownCommand(update->message); + std::string command = message->text.substr(1, splitPosition - 1); + if (!_broadcaster->broadcastCommand(command, message)) { + _broadcaster->broadcastUnknownCommand(message); } } else { - _broadcaster->broadcastNonCommandMessage(update->message); + _broadcaster->broadcastNonCommandMessage(message); } + }; + +public: + explicit EventHandler(const EventBroadcaster* broadcaster) : _broadcaster(broadcaster) { + } + + inline void handleUpdate(const Update::Ptr& update) const { + if (update->inlineQuery != NULL) + _broadcaster->broadcastInlineQuery(update->inlineQuery); + if (update->chosenInlineResult != NULL) + _broadcaster->broadcastChosenInlineResult(update->chosenInlineResult); + if (update->message != NULL) + handleMessage(update->message); } private: diff --git a/include/tgbot/TgTypeParser.h b/include/tgbot/TgTypeParser.h index 670e35e..f52d106 100644 --- a/include/tgbot/TgTypeParser.h +++ b/include/tgbot/TgTypeParser.h @@ -44,6 +44,14 @@ #include "tgbot/types/ReplyKeyboardHide.h" #include "tgbot/types/ForceReply.h" #include "tgbot/types/GenericReply.h" +#include "tgbot/types/InlineQuery.h" +#include "tgbot/types/InlineQueryResult.h" +#include "tgbot/types/InlineQueryResultArticle.h" +#include "tgbot/types/InlineQueryResultPhoto.h" +#include "tgbot/types/InlineQueryResultGif.h" +#include "tgbot/types/InlineQueryResultMpeg4Gif.h" +#include "tgbot/types/InlineQueryResultVideo.h" +#include "tgbot/types/ChosenInlineResult.h" namespace TgBot { @@ -90,6 +98,22 @@ public: std::string parseForceReply(const ForceReply::Ptr& object) const; GenericReply::Ptr parseJsonAndGetGenericReply(const boost::property_tree::ptree& data) const; std::string parseGenericReply(const GenericReply::Ptr& object) const; + InlineQuery::Ptr parseJsonAndGetInlineQuery(const boost::property_tree::ptree& data) const; + std::string parseInlineQuery(const InlineQuery::Ptr& object) const; + InlineQueryResult::Ptr parseJsonAndGetInlineQueryResult(const boost::property_tree::ptree& data) const; + std::string parseInlineQueryResult(const InlineQueryResult::Ptr& object) const; + InlineQueryResultArticle::Ptr parseJsonAndGetInlineQueryResultArticle(const boost::property_tree::ptree& data) const; + std::string parseInlineQueryResultArticle(const InlineQueryResultArticle::Ptr& object) const; + InlineQueryResultPhoto::Ptr parseJsonAndGetInlineQueryResultPhoto(const boost::property_tree::ptree& data) const; + std::string parseInlineQueryResultPhoto(const InlineQueryResultPhoto::Ptr& object) const; + InlineQueryResultGif::Ptr parseJsonAndGetInlineQueryResultGif(const boost::property_tree::ptree& data) const; + std::string parseInlineQueryResultGif(const InlineQueryResultGif::Ptr& object) const; + InlineQueryResultMpeg4Gif::Ptr parseJsonAndGetInlineQueryResultMpeg4Gif(const boost::property_tree::ptree& data) const; + std::string parseInlineQueryResultMpeg4Gif(const InlineQueryResultMpeg4Gif::Ptr& object) const; + InlineQueryResultVideo::Ptr parseJsonAndGetInlineQueryResultVideo(const boost::property_tree::ptree& data) const; + std::string parseInlineQueryResultVideo(const InlineQueryResultVideo::Ptr& object) const; + ChosenInlineResult::Ptr parseJsonAndGetChosenInlineResult(const boost::property_tree::ptree& data) const; + std::string parseChosenInlineResult(const ChosenInlineResult::Ptr& object) const; inline boost::property_tree::ptree parseJson(const std::string& json) const { boost::property_tree::ptree tree; diff --git a/include/tgbot/net/HttpReqArg.h b/include/tgbot/net/HttpReqArg.h index f0e4492..5aa60fd 100644 --- a/include/tgbot/net/HttpReqArg.h +++ b/include/tgbot/net/HttpReqArg.h @@ -24,6 +24,8 @@ #define TGBOT_HTTPPARAMETER_H #include <string> +#include <vector> +#include <functional> #include <boost/lexical_cast.hpp> diff --git a/include/tgbot/tgbot.h b/include/tgbot/tgbot.h index f377d1e..34dc0a9 100644 --- a/include/tgbot/tgbot.h +++ b/include/tgbot/tgbot.h @@ -45,6 +45,14 @@ #include "tgbot/types/User.h" #include "tgbot/types/UserProfilePhotos.h" #include "tgbot/types/Video.h" +#include "tgbot/types/InlineQuery.h" +#include "tgbot/types/InlineQueryResult.h" +#include "tgbot/types/InlineQueryResultArticle.h" +#include "tgbot/types/InlineQueryResultGif.h" +#include "tgbot/types/InlineQueryResultMpeg4Gif.h" +#include "tgbot/types/InlineQueryResultPhoto.h" +#include "tgbot/types/InlineQueryResultVideo.h" +#include "tgbot/types/ChosenInlineResult.h" #include "tgbot/tools/StringTools.h" #include "tgbot/net/HttpClient.h" #include "tgbot/net/HttpParser.h" diff --git a/include/tgbot/types/ChosenInlineResult.h b/include/tgbot/types/ChosenInlineResult.h new file mode 100644 index 0000000..c6d730e --- /dev/null +++ b/include/tgbot/types/ChosenInlineResult.h @@ -0,0 +1,40 @@ +// +// Created by Andrea Giove on 27/03/16. +// + +#ifndef TGBOT_CHOSENINLINERESULT_H +#define TGBOT_CHOSENINLINERESULT_H + +#include <string> +#include <memory> + +#include "tgbot/types/User.h" + +namespace TgBot { + +/** + * This object represents a result of an inline query that was chosen by the user and sent to their chat partner. + * @ingroup types + */ +class ChosenInlineResult { +public: + typedef std::shared_ptr<ChosenInlineResult> Ptr; + + /** + * The unique identifier for the result that was chosen. + */ + std::string resultId; + + /** + * The user that chose the result. + */ + User::Ptr from; + + /** + * The query that was used to obtain the result. + */ + std::string query; +}; +} + +#endif //TGBOT_CHOSENINLINERESULT_H diff --git a/include/tgbot/types/InlineQuery.h b/include/tgbot/types/InlineQuery.h new file mode 100644 index 0000000..a469ea7 --- /dev/null +++ b/include/tgbot/types/InlineQuery.h @@ -0,0 +1,46 @@ +// +// Created by Andrea Giove on 26/03/16. +// + +#ifndef TGBOT_INLINEQUERY_H +#define TGBOT_INLINEQUERY_H + +#include <memory> +#include <string> + +#include "tgbot/types/User.h" + +namespace TgBot { + +/** + * This object represents an incoming inline query. + * @ingroup types + */ +class InlineQuery { +public: + typedef std::shared_ptr<InlineQuery> Ptr; + + /** + * Unique query identifier. + */ + std::string id; + + /** + * Sender. + */ + User::Ptr from; + + /** + * Text of the query. + */ + std::string query; + + /** + * Offset of the results to be returned. + */ + std::string offset; +}; + +} + +#endif //TGBOT_INLINEQUERY_H diff --git a/include/tgbot/types/InlineQueryResult.h b/include/tgbot/types/InlineQueryResult.h new file mode 100644 index 0000000..d3eb968 --- /dev/null +++ b/include/tgbot/types/InlineQueryResult.h @@ -0,0 +1,66 @@ +// +// Created by Andrea Giove on 26/03/16. +// + +#ifndef TGBOT_INLINEQUERYRESULT_H +#define TGBOT_INLINEQUERYRESULT_H + +#include <memory> +#include <string> + +namespace TgBot { + +/** + * This abstract class is base of all inline query results. + * @ingroup types + */ +class InlineQueryResult { +public: + typedef std::shared_ptr<InlineQueryResult> Ptr; + + InlineQueryResult() { + this->disableWebPagePreview = false; + } + + virtual ~InlineQueryResult() { } + + /** + * Type of the result. + */ + std::string type; + + /** + * Unique identifier for this result. (1-64 bytes) + */ + std::string id; + + /** + * Optional. Title of the result. + */ + std::string title; + + /** + * Text of the message t be sent. (1-4096 characters) + */ + std::string messageText; + + /** + * Optional. Send Markdown or HTML, if you want Telegram apps to + * show bold, italic, fixed-width text or inline URLs in your bot's message. + */ + std::string parseMode; + + /** + * Optional. Disables link previews for links in the send message. + */ + bool disableWebPagePreview; + + /** + * Optional. Url of the thumbnail for the result. + */ + std::string thumbUrl; + +}; +} + +#endif //TGBOT_INLINEQUERYRESULT_H diff --git a/include/tgbot/types/InlineQueryResultArticle.h b/include/tgbot/types/InlineQueryResultArticle.h new file mode 100644 index 0000000..c903255 --- /dev/null +++ b/include/tgbot/types/InlineQueryResultArticle.h @@ -0,0 +1,59 @@ +// +// Created by Andrea Giove on 26/03/16. +// + +#ifndef TGBOT_INLINEQUERYRESULTARTICLE_H +#define TGBOT_INLINEQUERYRESULTARTICLE_H + +#include <string> +#include <memory> + +#include "tgbot/types/InlineQueryResult.h" + +namespace TgBot { + +/** + * Represents a link to an article of web page. + * @ingroup types + */ +class InlineQueryResultArticle : public InlineQueryResult { +public: + static const std::string TYPE; + + typedef std::shared_ptr<InlineQueryResultArticle> Ptr; + + InlineQueryResultArticle() { + this->type = TYPE; + this->hideUrl = false; + this->thumbHeight = 0; + this->thumbWidth = 0; + } + + /** + * Optional. URL of the result. + */ + std::string url; + + /** + * Optional. Pass True if you don't want the URL to be shown in the message. + */ + bool hideUrl; + + /** + * Optional. Short description of the result. + */ + std::string description; + + /** + * Optional. Thumbnail width. + */ + int32_t thumbWidth; + + /** + * Optinal. Thumbnail height + */ + int32_t thumbHeight; +}; +} + +#endif //TGBOT_INLINEQUERYRESULTARTICLE_H diff --git a/include/tgbot/types/InlineQueryResultGif.h b/include/tgbot/types/InlineQueryResultGif.h new file mode 100644 index 0000000..8892f56 --- /dev/null +++ b/include/tgbot/types/InlineQueryResultGif.h @@ -0,0 +1,54 @@ +// +// Created by Andrea Giove on 27/03/16. +// + +#ifndef TGBOT_INLINEQUERYRESULTGIF_H +#define TGBOT_INLINEQUERYRESULTGIF_H + +#include <string> +#include <memory> + +#include "tgbot/types/InlineQueryResult.h" + +namespace TgBot { + +/** + * Represents a link to an animated GIF file. + * @ingroup types + */ +class InlineQueryResultGif : public InlineQueryResult { +public: + static const std::string TYPE; + + typedef std::shared_ptr<InlineQueryResultGif> Ptr; + + InlineQueryResultGif() { + this->type = TYPE; + this->gifWidth = 0; + this->gifHeight = 0; + } + + /** + * A valid URL for the GIF file. + */ + std::string gifUrl; + + /** + * Optional. Width of the GIF. + */ + int32_t gifWidth; + + /** + * Optional. Height of the GIF. + */ + int32_t gifHeight; + + /** + * Optional. Caption for the GIF file to be sent. + */ + std::string caption; + +}; +} + +#endif //TGBOT_INLINEQUERYRESULTGIF_H diff --git a/include/tgbot/types/InlineQueryResultMpeg4Gif.h b/include/tgbot/types/InlineQueryResultMpeg4Gif.h new file mode 100644 index 0000000..0ba80aa --- /dev/null +++ b/include/tgbot/types/InlineQueryResultMpeg4Gif.h @@ -0,0 +1,50 @@ +// +// Created by Andrea Giove on 27/03/16. +// + +#ifndef TGBOT_INLINEQUERYRESULTMPEG4GIF_H +#define TGBOT_INLINEQUERYRESULTMPEG4GIF_H + +namespace TgBot { + +/** + * Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). + * @ingroup types + */ +class InlineQueryResultMpeg4Gif : public InlineQueryResult { +public: + static const std::string TYPE; + + typedef std::shared_ptr<InlineQueryResultMpeg4Gif> Ptr; + + InlineQueryResultMpeg4Gif() { + this->type = TYPE; + this->mpeg4Width = 0; + this->mpeg4Height = 0; + } + + /** + * A valid URL for the MP4 file. + */ + std::string mpeg4Url; + + /** + * Optional. Video width. + */ + int32_t mpeg4Width; + + /** + * Optional. Video height. + */ + int32_t mpeg4Height; + + /** + * Optional. Caption of the MPEG-4 file to be sent. + */ + std::string caption; + + +}; +} + +#endif //TGBOT_INLINEQUERYRESULTMPEG4GIF_H diff --git a/include/tgbot/types/InlineQueryResultPhoto.h b/include/tgbot/types/InlineQueryResultPhoto.h new file mode 100644 index 0000000..1c333f6 --- /dev/null +++ b/include/tgbot/types/InlineQueryResultPhoto.h @@ -0,0 +1,58 @@ +// +// Created by Andrea Giove on 26/03/16. +// + +#ifndef TGBOT_INLINEQUERYRESULTPHOTO_H +#define TGBOT_INLINEQUERYRESULTPHOTO_H + +#include <string> +#include <memory> + +#include "tgbot/types/InlineQueryResult.h" + +namespace TgBot { + +/** + * Represents a link to a photo. + * @ingroup types + */ +class InlineQueryResultPhoto : public InlineQueryResult { +public: + static const std::string TYPE; + + typedef std::shared_ptr<InlineQueryResultPhoto> Ptr; + + InlineQueryResultPhoto() { + this->type = TYPE; + this->photoWidth = 0; + this->photoHeight = 0; + } + + /** + * A valid URL of the photo. + */ + std::string photoUrl; + + /** + * Optional. Width of the photo. + */ + int32_t photoWidth; + + /** + * Optional. Height of the photo. + */ + int32_t photoHeight; + + /** + * Optional. Short description of the result. + */ + std::string description; + + /** + * Optional. Caption of the photo to be sent. + */ + std::string caption; +}; +} + +#endif //TGBOT_INLINEQUERYRESULTPHOTO_H diff --git a/include/tgbot/types/InlineQueryResultVideo.h b/include/tgbot/types/InlineQueryResultVideo.h new file mode 100644 index 0000000..6449c6d --- /dev/null +++ b/include/tgbot/types/InlineQueryResultVideo.h @@ -0,0 +1,60 @@ +// +// Created by Andrea Giove on 27/03/16. +// + +#ifndef TGBOT_INLINEQUERYRESULTVIDEO_H +#define TGBOT_INLINEQUERYRESULTVIDEO_H + +namespace TgBot { + +/** + * Represents link to a page containing an embedded video player or a video file. + * @ingroup types + */ +class InlineQueryResultVideo : public InlineQueryResult { +public: + static const std::string TYPE; + + typedef std::shared_ptr<InlineQueryResultVideo> Ptr; + + InlineQueryResultVideo() { + this->type = TYPE; + this->videoWidth = 0; + this->videoHeight = 0; + this->videoDuration = 0; + }; + + /** + * A valid URL for the embedded video player or video file. + */ + std::string videoUrl; + + /** + * Mime type of the content of video url, "text/html" or "video/mp4". + */ + std::string mimeType; + + /** + * Optional. Video width. + */ + int32_t videoWidth; + + /** + * Optional. Video height. + */ + int32_t videoHeight; + + /** + * Optional. Video duration. + */ + int32_t videoDuration; + + /** + * Optional. Short description of the result. + */ + std::string description; + +}; +} + +#endif //TGBOT_INLINEQUERYRESULTVIDEO_H diff --git a/include/tgbot/types/Message.h b/include/tgbot/types/Message.h index daedf03..ea53cf3 100644 --- a/include/tgbot/types/Message.h +++ b/include/tgbot/types/Message.h @@ -114,6 +114,8 @@ public: */ Video::Ptr video; + // TODO voice + /** * Optional. Message is a shared contact, information about the contact. */ @@ -158,6 +160,27 @@ public: * Optional. Text description of the photo or the video. */ std::string caption; + + /** + * Optional. Service message: the supergroup has been created. + */ + bool supergroupChatCreated; + + /** + * Optional. Service message: the channel has been created. + */ + bool channelChatCreated; + + /** + * Optional. The group has been migrated to a supergroup with the specified identifier, not exceeding 1e13 by absolute value. + */ + int64_t migrateToChatId; + + /** + * Optional. The supergroup has been migrated from a group with the specified identifier, not exceeding 1e13 by absolute value + */ + int64_t migrateFromChatId; + }; } diff --git a/include/tgbot/types/Update.h b/include/tgbot/types/Update.h index 9bf3a19..9ae8d73 100644 --- a/include/tgbot/types/Update.h +++ b/include/tgbot/types/Update.h @@ -26,6 +26,8 @@ #include <memory> #include "tgbot/types/Message.h" +#include "tgbot/types/InlineQuery.h" +#include "tgbot/types/ChosenInlineResult.h" namespace TgBot { @@ -47,6 +49,16 @@ public: * Optional. New incoming message of any kind — text, photo, sticker, etc. */ Message::Ptr message; + + /** + * Optional. New incoming inline query + */ + InlineQuery::Ptr inlineQuery; + + /** + * Optional. The result of an inline query that was chosen by a user and sent to their chat partner. + */ + ChosenInlineResult::Ptr chosenInlineResult; }; } diff --git a/src/Api.cpp b/src/Api.cpp index 2e27e1d..ed06d27 100644 --- a/src/Api.cpp +++ b/src/Api.cpp @@ -255,6 +255,18 @@ void Api::setWebhook(const string& url) const { sendRequest("setWebhook", args); } +void Api::answerInlineQuery(const std::string& inlineQueryId, const std::vector<InlineQueryResult::Ptr>& results, + int32_t cacheTime, bool isPersonal, const std::string& nextOffset) const { + vector<HttpReqArg> args; + args.push_back(HttpReqArg("inline_query_id", inlineQueryId)); + string resultsJson = TgTypeParser::getInstance().parseArray<InlineQueryResult>(&TgTypeParser::parseInlineQueryResult, results); + args.push_back(HttpReqArg("results", resultsJson)); + args.push_back(HttpReqArg("cache_time", cacheTime)); + args.push_back(HttpReqArg("is_personal", isPersonal)); + args.push_back(HttpReqArg("next_offset", nextOffset)); + sendRequest("answerInlineQuery", args); +} + ptree Api::sendRequest(const string& method, const vector<HttpReqArg>& args) const { string url = "https://api.telegram.org/bot"; diff --git a/src/TgTypeParser.cpp b/src/TgTypeParser.cpp index db44eff..6672c04 100644 --- a/src/TgTypeParser.cpp +++ b/src/TgTypeParser.cpp @@ -126,6 +126,10 @@ Message::Ptr TgTypeParser::parseJsonAndGetMessage(const ptree& data) const { result->deleteChatPhoto = data.get("delete_chat_photo", false); result->groupChatCreated = data.get("group_chat_created", false); result->caption = data.get("caption", false); + result->supergroupChatCreated = data.get("supergroup_chat_created", false); + result->channelChatCreated = data.get("channel_chat_created", false); + result->migrateToChatId = data.get<int64_t>("migrate_to_chat_id", 0); + result->migrateFromChatId = data.get<int64_t>("migrate_from_chat_id", 0); return result; } @@ -157,6 +161,10 @@ string TgTypeParser::parseMessage(const Message::Ptr& object) const { appendToJson(result, "delete_chat_photo", object->deleteChatPhoto); appendToJson(result, "group_chat_created", object->groupChatCreated); appendToJson(result, "caption", object->caption); + appendToJson(result, "supergroup_chat_created", object->supergroupChatCreated); + appendToJson(result, "channel_chat_created", object->channelChatCreated); + appendToJson(result, "migrate_to_chat_id", object->migrateToChatId); + appendToJson(result, "migrate_from_chat_id", object->migrateFromChatId); result.erase(result.length() - 1); result += '}'; return result; @@ -339,7 +347,9 @@ string TgTypeParser::parseLocation(const Location::Ptr& object) const { Update::Ptr TgTypeParser::parseJsonAndGetUpdate(const ptree& data) const { Update::Ptr result(new Update); result->updateId = data.get<int32_t>("update_id"); - result->message = parseJsonAndGetMessage(data.find("message")->second); + result->message = tryParseJson<Message>(&TgTypeParser::parseJsonAndGetMessage, data, "message"); + result->inlineQuery = tryParseJson<InlineQuery>(&TgTypeParser::parseJsonAndGetInlineQuery, data, "inline_query"); + result->chosenInlineResult = tryParseJson<ChosenInlineResult>(&TgTypeParser::parseJsonAndGetChosenInlineResult, data, "chosen_inline_result"); return result; } @@ -351,6 +361,8 @@ string TgTypeParser::parseUpdate(const Update::Ptr& object) const { result += '{'; appendToJson(result, "update_id", object->updateId); appendToJson(result, "message", parseMessage(object->message)); + appendToJson(result, "inline_query", parseInlineQuery(object->inlineQuery)); + appendToJson(result, "chosen_inline_result", parseChosenInlineResult(object->chosenInlineResult)); result.erase(result.length() - 1); result += '}'; return result; @@ -479,6 +491,246 @@ std::string TgTypeParser::parseGenericReply(const GenericReply::Ptr& object) con } } +InlineQuery::Ptr TgTypeParser::parseJsonAndGetInlineQuery(const boost::property_tree::ptree& data) const { + InlineQuery::Ptr result(new InlineQuery); + result->id = data.get<string>("id"); + result->from = tryParseJson<User>(&TgTypeParser::parseJsonAndGetUser, data, "from"); + result->query = data.get<string>("query"); + result->offset = data.get<string>("offset"); + + return result; +} + +std::string TgTypeParser::parseInlineQuery(const InlineQuery::Ptr& object) const{ + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "id", object->id); + appendToJson(result, "from", parseUser(object->from)); + appendToJson(result, "query", object->query); + appendToJson(result, "offset", object->offset); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +InlineQueryResult::Ptr TgTypeParser::parseJsonAndGetInlineQueryResult(const boost::property_tree::ptree& data) const { + string type = data.get<string>("type"); + InlineQueryResult::Ptr result; + + if (type == InlineQueryResultArticle::TYPE) { + result = static_pointer_cast<InlineQueryResult>(parseJsonAndGetInlineQueryResultArticle(data)); + } else if (type == InlineQueryResultPhoto::TYPE) { + result = static_pointer_cast<InlineQueryResult>(parseJsonAndGetInlineQueryResultPhoto(data)); + } else if (type == InlineQueryResultGif::TYPE) { + result = static_pointer_cast<InlineQueryResult>(parseJsonAndGetInlineQueryResultGif(data)); + } else if (type == InlineQueryResultMpeg4Gif::TYPE) { + result = static_pointer_cast<InlineQueryResult>(parseJsonAndGetInlineQueryResultMpeg4Gif(data)); + } else if (type == InlineQueryResultVideo::TYPE) { + result = static_pointer_cast<InlineQueryResult>(parseJsonAndGetInlineQueryResultVideo(data)); + } else { + result = make_shared<InlineQueryResult>(); + } + + result->id = data.get<string>("id"); + result->title = data.get<string>("title", ""); + result->messageText = data.get<string>("message_text", ""); + result->parseMode = data.get<string>("parse_mode", ""); + result->disableWebPagePreview = data.get("disable_web_page_preview", false); + result->thumbUrl = data.get<string>("thumb_url", ""); + + return result; +} + +std::string TgTypeParser::parseInlineQueryResult(const InlineQueryResult::Ptr& object) const { + if (!object){ + return ""; + } + + string result; + result += '{'; + appendToJson(result, "id", object->id); + appendToJson(result, "type", object->type); + appendToJson(result, "title", object->title); + appendToJson(result, "message_text", object->messageText); + appendToJson(result, "parse_mode", object->parseMode); + appendToJson(result, "disable_web_page_preview", object->disableWebPagePreview); + appendToJson(result, "thumb_url", object->thumbUrl); + + if (object->type == InlineQueryResultArticle::TYPE){ + result += parseInlineQueryResultArticle(static_pointer_cast<InlineQueryResultArticle>(object)); + } else if (object->type == InlineQueryResultPhoto::TYPE){ + result += parseInlineQueryResultPhoto(static_pointer_cast<InlineQueryResultPhoto>(object)); + } else if (object->type == InlineQueryResultGif::TYPE){ + result += parseInlineQueryResultGif(static_pointer_cast<InlineQueryResultGif>(object)); + } else if (object->type == InlineQueryResultMpeg4Gif::TYPE){ + result += parseInlineQueryResultMpeg4Gif(static_pointer_cast<InlineQueryResultMpeg4Gif>(object)); + } else if (object->type == InlineQueryResultVideo::TYPE){ + result += parseInlineQueryResultVideo(static_pointer_cast<InlineQueryResultVideo>(object)); + } + + result.erase(result.length() - 1); + result += '}'; + return result; +} + +InlineQueryResultArticle::Ptr TgTypeParser::parseJsonAndGetInlineQueryResultArticle(const boost::property_tree::ptree& data) const { + // NOTE: This function will be called by parseJsonAndGgetInlineQueryResult(). + InlineQueryResultArticle::Ptr result(new InlineQueryResultArticle); + result->url = data.get<string>("url", ""); + result->hideUrl = data.get("hide_url", false); + result->description = data.get<string>("description", ""); + result->thumbWidth = data.get("thumb_width", 0); + result->thumbHeight = data.get("thumb_height", 0); + return result; +} + +std::string TgTypeParser::parseInlineQueryResultArticle(const InlineQueryResultArticle::Ptr& object) const { + if (!object){ + return " "; + } + // This function will be called by parseInlineQueryResult(), so I don't add + // curly brackets to the result string. + string result; + appendToJson(result, "url", object->url); + appendToJson(result, "hide_url", object->hideUrl); + appendToJson(result, "description", object->description); + appendToJson(result, "thumb_width", object->thumbWidth); + appendToJson(result, "thumb_height", object->thumbHeight); + // The last comma will be erased by parseInlineQueryResult(). + return result; +} + +InlineQueryResultPhoto::Ptr TgTypeParser::parseJsonAndGetInlineQueryResultPhoto(const boost::property_tree::ptree& data) const { + // NOTE: This function will be called by parseJsonAndGgetInlineQueryResult(). + InlineQueryResultPhoto::Ptr result(new InlineQueryResultPhoto); + result->photoUrl = data.get<string>("photo_url", ""); + result->photoWidth = data.get("photo_width", 0); + result->photoHeight = data.get("photo_height", 0); + result->description = data.get<string>("description", ""); + result->caption = data.get<string>("caption", ""); + return result; +} + +std::string TgTypeParser::parseInlineQueryResultPhoto(const InlineQueryResultPhoto::Ptr& object) const{ + if (!object){ + return " "; + } + // This function will be called by parseInlineQueryResult(), so I don't add + // curly brackets to the result string. + string result; + appendToJson(result, "photo_url", object->photoUrl); + appendToJson(result, "photo_width", object->photoWidth); + appendToJson(result, "photo_height", object->photoHeight); + appendToJson(result, "description", object->description); + appendToJson(result, "caption", object->caption); + // The last comma will be erased by parseInlineQueryResult(). + return result; +} + +InlineQueryResultGif::Ptr TgTypeParser::parseJsonAndGetInlineQueryResultGif(const boost::property_tree::ptree& data) const { + // NOTE: This function will be called by parseJsonAndGgetInlineQueryResult(). + InlineQueryResultGif::Ptr result(new InlineQueryResultGif); + result->gifUrl = data.get<string>("gif_url", ""); + result->gifWidth = data.get("gif_width", 0); + result->gifHeight = data.get("gif_height", 0); + result->caption = data.get<string>("caption", ""); + return result; +} +std::string TgTypeParser::parseInlineQueryResultGif(const InlineQueryResultGif::Ptr& object) const { + if (!object){ + return " "; + } + // This function will be called by parseInlineQueryResult(), so I don't add + // curly brackets to the result string. + string result; + appendToJson(result, "gif_url", object->gifUrl); + appendToJson(result, "gif_width", object->gifWidth); + appendToJson(result, "gif_height", object->gifHeight); + appendToJson(result, "caption", object->caption); + // The last comma will be erased by parseInlineQueryResult(). + return result; +} + +InlineQueryResultMpeg4Gif::Ptr TgTypeParser::parseJsonAndGetInlineQueryResultMpeg4Gif(const boost::property_tree::ptree& data) const { + // NOTE: This function will be called by parseJsonAndGgetInlineQueryResult(). + InlineQueryResultMpeg4Gif::Ptr result(new InlineQueryResultMpeg4Gif); + result->mpeg4Url = data.get<string>("mpeg4_url"); + result->mpeg4Width = data.get("mpeg4_width", 0); + result->mpeg4Height = data.get("mpeg4_height", 0); + result->caption = data.get("caption", ""); + return result; +} + +std::string TgTypeParser::parseInlineQueryResultMpeg4Gif(const InlineQueryResultMpeg4Gif::Ptr& object) const { + if (!object){ + return " "; + } + // This function will be called by parseInlineQueryResult(), so I don't add + // curly brackets to the result string. + string result; + appendToJson(result, "mpeg4_url", object->mpeg4Url); + appendToJson(result, "mpeg4_width", object->mpeg4Width); + appendToJson(result, "mpeg4_height", object->mpeg4Height); + appendToJson(result, "caption", object->caption); + // The last comma will be erased by parseInlineQueryResult(). + return result; +} + +InlineQueryResultVideo::Ptr TgTypeParser::parseJsonAndGetInlineQueryResultVideo(const boost::property_tree::ptree& data) const { + // NOTE: This function will be called by parseJsonAndGgetInlineQueryResult(). + InlineQueryResultVideo::Ptr result(new InlineQueryResultVideo); + result->videoUrl = data.get<string>("video_url"); + result->mimeType = data.get<string>("mime_type"); + result->videoWidth = data.get("video_height", 0); + result->videoHeight = data.get("video_height", 0); + result->videoDuration = data.get("video_duration", 0); + result->description = data.get<string>("description", ""); + return result; +} + +std::string TgTypeParser::parseInlineQueryResultVideo(const InlineQueryResultVideo::Ptr& object) const { + if (!object){ + return " "; + } + // This function will be called by parseInlineQueryResult(), so I don't add + // curly brackets to the result string. + string result; + appendToJson(result, "video_url", object->videoUrl); + appendToJson(result, "mime_type", object->mimeType); + appendToJson(result, "video_width", object->videoWidth); + appendToJson(result, "video_height", object->videoHeight); + appendToJson(result, "video_duration", object->videoDuration); + appendToJson(result, "description", object->description); + // The last comma will be erased by parseInlineQueryResult(). + return result; +} + +ChosenInlineResult::Ptr TgTypeParser::parseJsonAndGetChosenInlineResult(const boost::property_tree::ptree& data) const { + ChosenInlineResult::Ptr result(new ChosenInlineResult); + result->resultId = data.get<string>("result_id"); + result->from = tryParseJson<User>(&TgTypeParser::parseJsonAndGetUser, data, "from"); + result->query = data.get<string>("query"); + return result; +} + +std::string TgTypeParser::parseChosenInlineResult(const ChosenInlineResult::Ptr& object) const { + if (!object){ + return ""; + } + + string result; + result += '{'; + appendToJson(result, "result_id", object->resultId); + appendToJson(result, "from", parseUser(object->from)); + appendToJson(result, "query", object->query); + result.erase(result.length() - 1); + result += '}'; + return result; +} + void TgTypeParser::appendToJson(string& json, const string& varName, const string& value) const { if (value.empty()) { return; diff --git a/src/types/InlineQueryResult.cpp b/src/types/InlineQueryResult.cpp new file mode 100644 index 0000000..be1f14a --- /dev/null +++ b/src/types/InlineQueryResult.cpp @@ -0,0 +1,16 @@ +// +// Created by Andrea Giove on 27/03/16. +// +#include "tgbot/types/InlineQueryResultArticle.h" +#include "tgbot/types/InlineQueryResultGif.h" +#include "tgbot/types/InlineQueryResultMpeg4Gif.h" +#include "tgbot/types/InlineQueryResultPhoto.h" +#include "tgbot/types/InlineQueryResultVideo.h" + +using namespace TgBot; + +const std::string InlineQueryResultArticle::TYPE = "article"; +const std::string InlineQueryResultGif::TYPE = "gif"; +const std::string InlineQueryResultMpeg4Gif::TYPE = "mpeg4_gif"; +const std::string InlineQueryResultPhoto::TYPE = "photo"; +const std::string InlineQueryResultVideo::TYPE = "video"; |