From 3f7a10f82567a0be04a424e0ddc360a73670c9d7 Mon Sep 17 00:00:00 2001 From: Oleg Morozenkov Date: Mon, 27 Jul 2015 20:59:09 +0300 Subject: Documentation --- include/tgbot/Api.h | 242 ++++++++++++++++++++++++++++++ include/tgbot/Bot.h | 81 ++++++++++ include/tgbot/EventBroadcaster.h | 117 +++++++++++++++ include/tgbot/EventHandler.h | 56 +++++++ include/tgbot/TgException.h | 43 ++++++ include/tgbot/TgTypeParser.h | 180 ++++++++++++++++++++++ include/tgbot/doxygenMain.h | 89 +++++++++++ include/tgbot/net/HttpClient.h | 61 ++++++++ include/tgbot/net/HttpParser.h | 68 +++++++++ include/tgbot/net/HttpReqArg.h | 69 +++++++++ include/tgbot/net/HttpServer.h | 103 +++++++++++++ include/tgbot/net/TgLongPoll.h | 55 +++++++ include/tgbot/net/TgWebhookLocalServer.h | 51 +++++++ include/tgbot/net/TgWebhookServer.h | 57 +++++++ include/tgbot/net/TgWebhookTcpServer.h | 50 ++++++ include/tgbot/net/Url.h | 67 +++++++++ include/tgbot/tools/StringTools.h | 91 +++++++++++ include/tgbot/types/Audio.h | 63 ++++++++ include/tgbot/types/Contact.h | 63 ++++++++ include/tgbot/types/Document.h | 70 +++++++++ include/tgbot/types/ForceReply.h | 58 +++++++ include/tgbot/types/GenericChat.h | 49 ++++++ include/tgbot/types/GenericReply.h | 44 ++++++ include/tgbot/types/GroupChat.h | 50 ++++++ include/tgbot/types/InputFile.h | 54 +++++++ include/tgbot/types/Location.h | 52 +++++++ include/tgbot/types/Message.h | 165 ++++++++++++++++++++ include/tgbot/types/PhotoSize.h | 63 ++++++++ include/tgbot/types/ReplyKeyboardHide.h | 55 +++++++ include/tgbot/types/ReplyKeyboardMarkup.h | 67 +++++++++ include/tgbot/types/Sticker.h | 70 +++++++++ include/tgbot/types/Update.h | 54 +++++++ include/tgbot/types/User.h | 60 ++++++++ include/tgbot/types/UserProfilePhotos.h | 55 +++++++ include/tgbot/types/Video.h | 80 ++++++++++ 35 files changed, 2652 insertions(+) create mode 100644 include/tgbot/Api.h create mode 100644 include/tgbot/Bot.h create mode 100644 include/tgbot/EventBroadcaster.h create mode 100644 include/tgbot/EventHandler.h create mode 100644 include/tgbot/TgException.h create mode 100644 include/tgbot/TgTypeParser.h create mode 100644 include/tgbot/doxygenMain.h create mode 100644 include/tgbot/net/HttpClient.h create mode 100644 include/tgbot/net/HttpParser.h create mode 100644 include/tgbot/net/HttpReqArg.h create mode 100644 include/tgbot/net/HttpServer.h create mode 100644 include/tgbot/net/TgLongPoll.h create mode 100644 include/tgbot/net/TgWebhookLocalServer.h create mode 100644 include/tgbot/net/TgWebhookServer.h create mode 100644 include/tgbot/net/TgWebhookTcpServer.h create mode 100644 include/tgbot/net/Url.h create mode 100644 include/tgbot/tools/StringTools.h create mode 100644 include/tgbot/types/Audio.h create mode 100644 include/tgbot/types/Contact.h create mode 100644 include/tgbot/types/Document.h create mode 100644 include/tgbot/types/ForceReply.h create mode 100644 include/tgbot/types/GenericChat.h create mode 100644 include/tgbot/types/GenericReply.h create mode 100644 include/tgbot/types/GroupChat.h create mode 100644 include/tgbot/types/InputFile.h create mode 100644 include/tgbot/types/Location.h create mode 100644 include/tgbot/types/Message.h create mode 100644 include/tgbot/types/PhotoSize.h create mode 100644 include/tgbot/types/ReplyKeyboardHide.h create mode 100644 include/tgbot/types/ReplyKeyboardMarkup.h create mode 100644 include/tgbot/types/Sticker.h create mode 100644 include/tgbot/types/Update.h create mode 100644 include/tgbot/types/User.h create mode 100644 include/tgbot/types/UserProfilePhotos.h create mode 100644 include/tgbot/types/Video.h (limited to 'include') diff --git a/include/tgbot/Api.h b/include/tgbot/Api.h new file mode 100644 index 0000000..1b4987a --- /dev/null +++ b/include/tgbot/Api.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_CPP_API_H +#define TGBOT_CPP_API_H + +#include +#include + +#include + +#include "tgbot/net/HttpReqArg.h" +#include "tgbot/types/User.h" +#include "tgbot/types/Message.h" +#include "tgbot/types/GenericReply.h" +#include "tgbot/types/InputFile.h" +#include "tgbot/types/UserProfilePhotos.h" +#include "tgbot/types/Update.h" + +namespace TgBot { + +class Bot; + +/** + * This class executes telegram api methods. Telegram docs: + * @ingroup general + */ +class Api { + +friend Bot; + +public: + Api(const std::string& token); + + /** + * A simple method for testing your bot's auth token. + * @return Basic information about the bot in form of a User object. + */ + User::Ptr getMe() const; + + /** + * Use this method to send text messages. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param text Text of the message to be sent. + * @param disableWebPagePreview Optional. Disables link previews for links in this message. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendMessage(int32_t chatId, const std::string& text, bool disableWebPagePreview = false, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to forward messages of any kind. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param fromChatId Unique identifier for the chat where the original message was sent — User or GroupChat id. + * @param messageId Unique message identifier. + * @return On success, the sent message is returned. + */ + Message::Ptr forwardMessage(int32_t chatId, int32_t fromChatId, int32_t messageId) const; + + /** + * Use this method to send photos. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param photo Photo to send. + * @param caption Optional. Photo caption. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendPhoto(int32_t chatId, const InputFile::Ptr& photo, const std::string& caption = "", int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send photos. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param photo Photo to send. Id of the photo that is already on the Telegram servers. + * @param caption Optional. Photo caption. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendPhoto(int32_t chatId, const std::string& photo, const std::string& caption = "", int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Document). + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param audio Audio to send. + * @param duration Duration of sent audio in seconds. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendAudio(int32_t chatId, const InputFile::Ptr& audio, int32_t duration = 0, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .ogg file encoded with OPUS (other formats may be sent as Document). + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param audio Id of the audio that is already on the Telegram servers. + * @param duration Duration of sent audio in seconds. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendAudio(int32_t chatId, const std::string& audio, int32_t duration = 0, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send general files. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param document Document to send. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendDocument(int32_t chatId, const InputFile::Ptr& document, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send general files. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param document Id of the document that is already on the Telegram servers. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendDocument(int32_t chatId, const std::string& document, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send .webp stickers. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param sticker Sticker to send. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendSticker(int32_t chatId, const InputFile::Ptr& sticker, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send .webp stickers. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param sticker Id of the sticker that is already on the Telegram servers. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. A object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendSticker(int32_t chatId, const std::string& sticker, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param video Video to send. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. An object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendVideo(int32_t chatId, const InputFile::Ptr& video, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param video Id of the video that is already on the Telegram servers. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. A object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendVideo(int32_t chatId, const std::string& video, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method to send point on the map. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param latitude Latitude of location. + * @param longitude Longitude of location. + * @param replyToMessageId Optional. If the message is a reply, ID of the original message. + * @param replyMarkup Optional. Additional interface options. A object for a custom reply keyboard, instructions to hide keyboard or to force a reply from the user. + * @return On success, the sent message is returned. + */ + Message::Ptr sendLocation(int32_t chatId, float latitude, float longitude, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + + /** + * Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). + * Example: The ImageBot needs some time to process a request and upload the image. Instead of sending a text message along the lines of “Retrieving image, please wait…”, the bot may use sendChatAction with action = upload_photo. The user will see a “sending photo” status for the bot. + * We only recommend using this method when a response from the bot will take a noticeable amount of time to arrive. + * @param chatId Unique identifier for the message recipient — User or GroupChat id. + * @param action Type of action to broadcast. Choose one, depending on what the user is about to receive: typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for location data. + */ + void sendChatAction(int32_t chatId, const std::string& action) const; + + /** + * Use this method to get a list of profile pictures for a user. + * @param userId Unique identifier of the target user. + * @param offset Optional. Sequential number of the first photo to be returned. By default, all photos are returned. + * @param limit Optional. Limits the number of photos to be retrieved. Values between 1—100 are accepted. Defaults to 100. + * @return A UserProfilePhotos object. + */ + UserProfilePhotos::Ptr getUserProfilePhotos(int32_t userId, int32_t offset = 0, int32_t limit = 100) const; + + /** + * Use this method to receive incoming updates using long polling. + * This method will not work if an outgoing webhook is set up. + * In order to avoid getting duplicate updates, recalculate offset after each server response. + * @param offset Optional. Identifier of the first update to be returned. Must be greater by one than the highest among the identifiers of previously received updates. By default, updates starting with the earliest unconfirmed update are returned. An update is considered confirmed as soon as getUpdates is called with an offset higher than its update_id. + * @param limit Optional. Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100. + * @param timeout Optional. Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. + * @return An Array of Update objects + */ + std::vector getUpdates(int32_t offset = 0, int32_t limit = 100, int32_t timeout = 0) const; + + /** + * Use this method to specify a url and receive incoming updates via an outgoing webhook. Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case of an unsuccessful request, we will give up after a reasonable amount of attempts. + * If you'd like to make sure that the Webhook request comes from Telegram, we recommend using a secret path in the URL, e.g. www.example.com/. Since nobody else knows your bot‘s token, you can be pretty sure it’s us. + * You will not be able to receive updates using getUpdates for as long as an outgoing webhook is set up. + * We currently do not support self-signed certificates. + * 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. + */ + void setWebhook(const std::string& url = "") const; + +private: + boost::property_tree::ptree sendRequest(const std::string& method, const std::vector& args = std::vector()) const; + + const std::string _token; +}; + +} + +#endif //TGBOT_CPP_API_H diff --git a/include/tgbot/Bot.h b/include/tgbot/Bot.h new file mode 100644 index 0000000..5e96642 --- /dev/null +++ b/include/tgbot/Bot.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_CPP_BOT_H +#define TGBOT_CPP_BOT_H + +#include + +#include "tgbot/Api.h" +#include "tgbot/EventBroadcaster.h" +#include "tgbot/EventHandler.h" + +namespace TgBot { + +/** + * This object holds other objects specific for this bot instance. + * @ingroup general + */ +class Bot { + +public: + explicit Bot(const std::string& token) : _token(token), _api(token), _eventHandler(&_eventBroadcaster) { + } + + /** + * @return Token for accessing api. + */ + inline const std::string& getToken() const { + return _token; + } + + /** + * @return Object which can execute Telegram Bot API methods. + */ + inline const Api& getApi() const { + return _api; + } + + /** + * @return Object which holds all event listeners. + */ + inline EventBroadcaster& getEvents() { + return _eventBroadcaster; + } + + /** + * @return Object which handles new update objects. Usually it's only needed for TgLongPoll, TgWebhookLocalServer and TgWebhookTcpServer objects. + */ + inline const EventHandler& getEventHandler() const { + return _eventHandler; + } + +private: + const std::string _token; + const Api _api; + EventBroadcaster _eventBroadcaster; + const EventHandler _eventHandler; +}; + +} + +#endif //TGBOT_CPP_BOT_H diff --git a/include/tgbot/EventBroadcaster.h b/include/tgbot/EventBroadcaster.h new file mode 100644 index 0000000..03d7df1 --- /dev/null +++ b/include/tgbot/EventBroadcaster.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_EVENTBROADCASTER_H +#define TGBOT_EVENTBROADCASTER_H + +#include +#include +#include +#include + +#include "tgbot/types/Message.h" + +namespace TgBot { + +class EventHandler; + +/** + * This class holds all event listeners. + * @ingroup general + */ +class EventBroadcaster { + +friend EventHandler; + +public: + typedef std::function MessageListener; + + /** + * Registers listener which receives all messages which the bot can ever receive. + * @param listener Listener. + */ + inline void onAnyMessage(const MessageListener& listener) { + _onAnyMessageListeners.push_back(listener); + } + + /** + * Registers listener which receives all messages with commands (messages with leading '/' char). + * @param commandName Command name which listener can handle. + * @param listener Listener. + */ + inline void onCommand(const std::string& commandName, const MessageListener& listener) { + _onCommandListeners[commandName] = listener; + } + + /** + * Registers listener which receives all messages with commands (messages with leading '/' char) which haven't been handled by other listeners. + * @param listener Listener. + */ + inline void onUnknownCommand(const MessageListener& listener) { + _onUnknownCommandListeners.push_back(listener); + } + + /** + * Registers listener which receives all messages without commands (messages with no leading '/' char) + * @param listener Listener. + */ + inline void onNonCommandMessage(const MessageListener& listener) { + _onNonCommandMessageListeners.push_back(listener); + } + +private: + inline void broadcastAnyMessage(const Message::Ptr& message) const { + for (const MessageListener& item : _onAnyMessageListeners) { + item(message); + } + } + + inline bool broadcastCommand(const std::string command, const Message::Ptr& message) const { + std::map::const_iterator iter = _onCommandListeners.find(command); + if (iter == _onCommandListeners.end()) { + return false; + } + iter->second(message); + return true; + } + + inline void broadcastUnknownCommand(const Message::Ptr& message) const { + for (const MessageListener& item : _onUnknownCommandListeners) { + item(message); + } + } + + inline void broadcastNonCommandMessage(const Message::Ptr& message) const { + for (const MessageListener& item : _onNonCommandMessageListeners) { + item(message); + } + } + + std::vector _onAnyMessageListeners; + std::map _onCommandListeners; + std::vector _onUnknownCommandListeners; + std::vector _onNonCommandMessageListeners; +}; + +} + +#endif //TGBOT_EVENTBROADCASTER_H diff --git a/include/tgbot/EventHandler.h b/include/tgbot/EventHandler.h new file mode 100644 index 0000000..abcf925 --- /dev/null +++ b/include/tgbot/EventHandler.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_EVENTHANDLER_H +#define TGBOT_EVENTHANDLER_H + +#include "tgbot/EventBroadcaster.h" +#include "tgbot/types/Update.h" +#include "tgbot/tools/StringTools.h" + +namespace TgBot { + +class EventHandler { + +public: + explicit EventHandler(const EventBroadcaster* broadcaster) : _broadcaster(broadcaster) { + } + + inline void handleUpdate(const Update::Ptr& update) const { + _broadcaster->broadcastAnyMessage(update->message); + if (StringTools::startsWith(update->message->text, "/")) { + std::string command = update->message->text.substr(1, update->message->text.find(' ') - 2); + if (!_broadcaster->broadcastCommand(command, update->message)) { + _broadcaster->broadcastUnknownCommand(update->message); + } + } else { + _broadcaster->broadcastNonCommandMessage(update->message); + } + } + +private: + const EventBroadcaster* _broadcaster; +}; + +} + +#endif //TGBOT_EVENTHANDLER_H diff --git a/include/tgbot/TgException.h b/include/tgbot/TgException.h new file mode 100644 index 0000000..6f01fd3 --- /dev/null +++ b/include/tgbot/TgException.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_TGEXCEPTION_H +#define TGBOT_TGEXCEPTION_H + +#include +#include + +namespace TgBot { + +/** + * Exception type which is only thrown when Telegram refuses API request. + * @ingroup general + */ +class TgException : public std::runtime_error { + +public: + explicit TgException(const std::string description); +}; + +} + +#endif //TGBOT_TGEXCEPTION_H diff --git a/include/tgbot/TgTypeParser.h b/include/tgbot/TgTypeParser.h new file mode 100644 index 0000000..0571c25 --- /dev/null +++ b/include/tgbot/TgTypeParser.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_CPP_TGTYPEPARSER_H +#define TGBOT_CPP_TGTYPEPARSER_H + +#include + +#include +#include + +#include "tgbot/types/User.h" +#include "tgbot/types/GroupChat.h" +#include "tgbot/types/Message.h" +#include "tgbot/types/PhotoSize.h" +#include "tgbot/types/Audio.h" +#include "tgbot/types/Document.h" +#include "tgbot/types/Sticker.h" +#include "tgbot/types/Video.h" +#include "tgbot/types/Contact.h" +#include "tgbot/types/Location.h" +#include "tgbot/types/Update.h" +#include "tgbot/types/UserProfilePhotos.h" +#include "tgbot/types/ReplyKeyboardMarkup.h" +#include "tgbot/types/ReplyKeyboardHide.h" +#include "tgbot/types/ForceReply.h" +#include "tgbot/types/GenericReply.h" + +namespace TgBot { + +class TgTypeParser { + +public: + static TgTypeParser& getInstance(); + + User::Ptr parseUser(const boost::property_tree::ptree& data) const; + std::string parseUser(const User::Ptr& object) const; + GroupChat::Ptr parseGroupChat(const boost::property_tree::ptree& data) const; + std::string parseGroupChat(const GroupChat::Ptr& object) const; + Message::Ptr parseMessage(const boost::property_tree::ptree& data) const; + std::string parseMessage(const Message::Ptr& object) const; + PhotoSize::Ptr parsePhotoSize(const boost::property_tree::ptree& data) const; + std::string parsePhotoSize(const PhotoSize::Ptr& object) const; + Audio::Ptr parseAudio(const boost::property_tree::ptree& data) const; + std::string parseAudio(const Audio::Ptr& object) const; + Document::Ptr parseDocument(const boost::property_tree::ptree& data) const; + std::string parseDocument(const Document::Ptr& object) const; + Sticker::Ptr parseSticker(const boost::property_tree::ptree& data) const; + std::string parseSticker(const Sticker::Ptr& object) const; + Video::Ptr parseVideo(const boost::property_tree::ptree& data) const; + std::string parseVideo(const Video::Ptr& object) const; + Contact::Ptr parseContact(const boost::property_tree::ptree& data) const; + std::string parseContact(const Contact::Ptr& object) const; + Location::Ptr parseLocation(const boost::property_tree::ptree& data) const; + std::string parseLocation(const Location::Ptr& object) const; + Update::Ptr parseUpdate(const boost::property_tree::ptree& data) const; + std::string parseUpdate(const Update::Ptr& object) const; + UserProfilePhotos::Ptr parseUserProfilePhotos(const boost::property_tree::ptree& data) const; + std::string parseUserProfilePhotos(const UserProfilePhotos::Ptr& object) const; + ReplyKeyboardMarkup::Ptr parseReplyKeyboardMarkup(const boost::property_tree::ptree& data) const; + std::string parseReplyKeyboardMarkup(const ReplyKeyboardMarkup::Ptr& object) const; + ReplyKeyboardHide::Ptr parseReplyKeyboardHide(const boost::property_tree::ptree& data) const; + std::string parseReplyKeyboardHide(const ReplyKeyboardHide::Ptr& object) const; + ForceReply::Ptr parseForceReply(const boost::property_tree::ptree& data) const; + std::string parseForceReply(const ForceReply::Ptr& object) const; + GenericChat::Ptr parseGenericChat(const boost::property_tree::ptree& data) const; + std::string parseGenericChat(const GenericChat::Ptr& object) const; + GenericReply::Ptr parseGenericReply(const boost::property_tree::ptree& data) const; + std::string parseGenericReply(const GenericReply::Ptr& object) const; + + inline boost::property_tree::ptree parseJson(const std::string& json) const { + boost::property_tree::ptree tree; + std::istringstream input(json); + boost::property_tree::read_json(input, tree); + return tree; + } + + template + std::shared_ptr tryParse(std::shared_ptr (TgTypeParser::*const parseFunc)(const boost::property_tree::ptree&) const, const boost::property_tree::ptree& data, const std::string& keyName) const { + auto treeItem = data.find(keyName); + if (treeItem == data.not_found()) { + return std::shared_ptr(); + } + return (this->*parseFunc)(treeItem->second); + } + + template + std::vector> parseArray(std::shared_ptr (TgTypeParser::*const parseFunc)(const boost::property_tree::ptree&) const, const boost::property_tree::ptree& data, const std::string& keyName) const { + std::vector> result; + auto treeItem = data.find(keyName); + if (treeItem == data.not_found()) { + return result; + } + for (const std::pair& innerTreeItem : treeItem->second) { + result.push_back((this->*parseFunc)(innerTreeItem.second)); + } + return result; + } + + template + std::vector>> parse2DArray(std::shared_ptr (TgTypeParser::*const parseFunc)(const boost::property_tree::ptree&) const, const boost::property_tree::ptree& data, const std::string& keyName) const { + std::vector>> result; + auto treeItem = data.find(keyName); + if (treeItem == data.not_found()) { + return result; + } + for (const std::pair& innerTreeItem : treeItem->second) { + std::vector> innerResult; + for (const std::pair& innerInnerTreeItem : innerTreeItem.second) { + innerResult.push_back((this->*parseFunc)(innerInnerTreeItem.second)); + } + result.push_back(innerResult); + } + return result; + } + + template + std::string parseArray(std::string (TgTypeParser::*const parseFunc)(const std::shared_ptr&) const, const std::vector>& objects) const { + std::string result; + result += '['; + for (const std::shared_ptr& item : objects) { + result += (this->*parseFunc)(item); + result += ','; + } + result.erase(result.length() - 1); + result += ']'; + return result; + } + + template + std::string parse2DArray(std::string (TgTypeParser::*const parseFunc)(const std::shared_ptr&) const, const std::vector>>& objects) const { + std::string result; + result += '['; + for (const std::vector>& item : objects) { + result += parseArray(parseFunc, item); + result += ','; + } + result.erase(result.length() - 1); + result += ']'; + return result; + } + +private: + template + void appendToJson(std::string& json, const std::string& varName, const T& value) const { + if (value == 0) { + return; + } + json += '"'; + json += varName; + json += "\":"; + json += value; + json += ','; + } + + void appendToJson(std::string& json, const std::string& varName, const std::string& value) const; +}; + +} + +#endif //TGBOT_CPP_TGTYPEPARSER_H diff --git a/include/tgbot/doxygenMain.h b/include/tgbot/doxygenMain.h new file mode 100644 index 0000000..9478b4f --- /dev/null +++ b/include/tgbot/doxygenMain.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_DOXYGENMAIN_H +#define TGBOT_DOXYGENMAIN_H + +/** + * @defgroup general + * @defgroup types + * @defgroup net + * @defgroup tools + * + * @mainpage + * + * @section Compilation + * + * Firstly you need to install some dependencies. You have to have boost library at the runtime and cmake at the compilation step to be able to use this library. + * On Debian-based distibutives you can do it with these commands: + * @code{.sh} +sudo apt-get install cmake libboost-dev + * @endcode + * + * To compile the library execute this commands: + * @code{.sh} +cd /path/where/you/have/cloned/the/library/repository +cmake . +make -j4 + * @endcode + * + * That's all. All you have to do now is just link compiled library to your project. + * + * @section Samples + * Simple echo bot which sends everything it recieves: + * @code{.cpp} +int main() { + TgBot::Bot bot("PLACE YOUR TOKEN HERE"); + bot.getEvents().onCommand("start", [&bot](Message::Ptr message) { + bot.getApi().sendMessage(message->chat->id, "Hi!"); + }); + bot.getEvents().onAnyMessage([&bot](Message::Ptr message) { + printf("User wrote %s\n", message->text.c_str()); + if (StringTools::startsWith(message->text, "/start")) { + return; + } + bot.getApi().sendMessage(message->chat->id, "Your message is: " + message->text); + }); + + try { + printf("Bot username: %s\n", bot.getApi().getMe()->username.c_str()); + + TgBot::TgLongPoll longPoll(bot); + while (true) { + printf("Long poll started\n"); + longPoll.start(); + } + } catch (TgBot::TgException& e) { + printf("error: %s\n", e.what()); + } + + return 0; +} + * @endcode + * + * All samples are located [here](https://github.com/reo7sp/tgbot-cpp/tree/master/samples) + * + * @section Feedback + * Feel free to [https://github.com/reo7sp/tgbot-cpp/issues](create new issues on GitHub) or [https://telegram.me/Reo_SP](contact me on Telegram) + */ + +#endif //TGBOT_DOXYGENMAIN_H diff --git a/include/tgbot/net/HttpClient.h b/include/tgbot/net/HttpClient.h new file mode 100644 index 0000000..d39e108 --- /dev/null +++ b/include/tgbot/net/HttpClient.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_HTTPCLIENT_H +#define TGBOT_HTTPCLIENT_H + +#include + +#include + +#include "tgbot/net/Url.h" +#include "tgbot/net/HttpReqArg.h" +#include "tgbot/net/HttpParser.h" + +namespace TgBot { + +/** + * This class makes http requests. + * @ingroup net + */ +class HttpClient { + +public: + /** + * Returns instance which lives during all application lifetime. + */ + static HttpClient& getInstance(); + + /** + * Sends a request to the url. + * If there's no args specified, a GET request will be sent, otherwise a POST request will be sent. + * If at least 1 arg is marked as file, the content type of a request will be multipart/form-data, otherwise it will be application/x-www-form-urlencoded. + */ + std::string makeRequest(const Url& url, const std::vector& args); + +private: + boost::asio::io_service _ioService; +}; + +} + +#endif //TGBOT_HTTPCLIENT_H diff --git a/include/tgbot/net/HttpParser.h b/include/tgbot/net/HttpParser.h new file mode 100644 index 0000000..dcb857b --- /dev/null +++ b/include/tgbot/net/HttpParser.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_HTTPPARSER_H +#define TGBOT_HTTPPARSER_H + +#include +#include + +#include "tgbot/net/Url.h" +#include "tgbot/net/HttpReqArg.h" + +namespace TgBot { + +class HttpParser { + +public: + static HttpParser& getInstance(); + + std::string generateRequest(const Url& url, const std::vector& args, bool isKeepAlive = false); + std::string generateMultipartFormData(const std::vector& args, const std::string& bondary); + std::string generateMultipartBoundary(const std::vector& args); + std::string generateWwwFormUrlencoded(const std::vector& args); + std::string generateResponse(const std::string& data, const std::string& mimeType = "text/plain", short unsigned statusCode = 200, const std::string& statusStr = "OK", bool isKeepAlive = false); + + inline std::string parseRequest(const std::string& data, std::map& headers) { + return parseHttp(true, data, headers); + } + + inline std::string parseRequest(const std::string& data) { + return parseHttp(true, data); + } + + inline std::string parseResponse(const std::string& data, std::map& headers) { + return parseHttp(false, data, headers); + } + + inline std::string parseResponse(const std::string& data) { + return parseHttp(false, data); + } + +private: + std::string parseHttp(bool isRequest, const std::string& data, std::map& headers); + std::string parseHttp(bool isRequest, const std::string& data); +}; + +} + +#endif //TGBOT_HTTPPARSER_H diff --git a/include/tgbot/net/HttpReqArg.h b/include/tgbot/net/HttpReqArg.h new file mode 100644 index 0000000..d70e8b5 --- /dev/null +++ b/include/tgbot/net/HttpReqArg.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_HTTPPARAMETER_H +#define TGBOT_HTTPPARAMETER_H + +#include + +#include + +namespace TgBot { + +/** + * This class represents argument in POST http requests. + * @ingroup net + */ +class HttpReqArg { + +public: + template + HttpReqArg(const std::string& name, const T& value, bool isFile = false, const std::string& mimeType = "text/plain") : + name(name), value(boost::lexical_cast(value)), isFile(isFile), mimeType(mimeType) + { + } + + /** + * Name of an argument. + */ + std::string name; + + /** + * Value of an argument. + */ + std::string value; + + /** + * Should be true if an argument value hold some file contents + */ + bool isFile = false; + + /** + * Mime type of an argument value. This field makes sense only if isFile is true. + */ + std::string mimeType = "text/plain"; +}; + +} + + +#endif //TGBOT_HTTPPARAMETER_H diff --git a/include/tgbot/net/HttpServer.h b/include/tgbot/net/HttpServer.h new file mode 100644 index 0000000..0a66900 --- /dev/null +++ b/include/tgbot/net/HttpServer.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_HTTPSERVER_H +#define TGBOT_HTTPSERVER_H + +#include + +#include + +#include "tgbot/net/HttpParser.h" + +namespace TgBot { + +/** + * This class handles HTTP requests from the Internet. + * @ingroup net + */ +template +class HttpServer { + +private: + class Connection; + +public: + typedef std::function)> ServerHandler; + + HttpServer(std::shared_ptr>& acceptor, const ServerHandler& handler) : _acceptor(acceptor), _handler(handler) { + } + + /** + * Starts receiving new connections. + */ + void start() { + std::shared_ptr> socket(new boost::asio::basic_stream_socket(acceptor->get_io_service())); + std::shared_ptr> connection(new Connection(socket, _handler)); + acceptor->async_accept(*connection->socket, [this, connection]() { + connection->start(); + start(); + }); + _ioService.run(); + } + + /** + * Stops receiving new connections. + */ + void stop() { + _ioService.stop(); + } + +private: + template + class Connection { + + public: + Connection(std::shared_ptr>& socket, const ServerHandler& handler) : socket(socket), _handler(handler) { + boost::asio::socket_base::keep_alive option(true); + socket.set_option(option); + } + + void start() { + data.reserve(10240); + socket->async_receive(data, [this]() { + std::map headers; + std::string body = HttpParser::parseResponse(data, headers); + socket->async_send(_handler(body, headers)); + }); + } + + std::shared_ptr> socket; + std::string data; + + private: + const ServerHandler _handler; + }; + + boost::asio::io_service _ioService; + std::shared_ptr> _acceptor; + const ServerHandler _handler; +}; + +} + +#endif //TGBOT_HTTPSERVER_H diff --git a/include/tgbot/net/TgLongPoll.h b/include/tgbot/net/TgLongPoll.h new file mode 100644 index 0000000..932fc6d --- /dev/null +++ b/include/tgbot/net/TgLongPoll.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_TGLONGPOLL_H +#define TGBOT_TGLONGPOLL_H + +#include "tgbot/Bot.h" +#include "tgbot/Api.h" +#include "tgbot/EventHandler.h" + +namespace TgBot { + +/** + * This class handles long polling and updates parsing. + * @ingroup net + */ +class TgLongPoll { + +public: + TgLongPoll(const Api* api, const EventHandler* eventHandler); + TgLongPoll(const Bot& bot); + + /** + * Starts long poll. After new update will come, this method will parse it and send to EventHandler which invokes your listeners. Designed to be executed in a loop. + */ + void start(); + +private: + int32_t _lastUpdateId = 0; + const Api* _api; + const EventHandler* _eventHandler; +}; + +} + +#endif //TGBOT_TGLONGPOLL_H diff --git a/include/tgbot/net/TgWebhookLocalServer.h b/include/tgbot/net/TgWebhookLocalServer.h new file mode 100644 index 0000000..7835f28 --- /dev/null +++ b/include/tgbot/net/TgWebhookLocalServer.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_TGWEBHOOKTCPSERVER_H +#define TGBOT_TGWEBHOOKTCPSERVER_H + +#include "tgbot/net/TgWebhookServer.h" + +namespace TgBot { + +/** + * This class setups HTTP server for receiving Telegram Update objects from unix socket. + * @ingroup net + */ +class TgWebhookLocalServer : public TgWebhookServer { + +public: + TgWebhookLocalServer(std::shared_ptr>& acceptor, const std::string& path, EventHandler* eventHandler) = delete; + + TgWebhookLocalServer(const std::string& path, const EventHandler* eventHandler) : + TgWebhookServer(std::shared_ptr>(new boost::asio::local::stream_protocol::acceptor(_ioService, boost::asio::local::stream_protocol::endpoint(path))), path, eventHandler) + { + } + + TgWebhookLocalServer(const std::string& path, const Bot& bot) : TgWebhookLocalServer(path, &bot.getEventHandler()) { + + } +}; + +} + +#endif //TGBOT_TGWEBHOOKTCPSERVER_H diff --git a/include/tgbot/net/TgWebhookServer.h b/include/tgbot/net/TgWebhookServer.h new file mode 100644 index 0000000..a8155ff --- /dev/null +++ b/include/tgbot/net/TgWebhookServer.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_TGHTTPSERVER_H +#define TGBOT_TGHTTPSERVER_H + +#include "tgbot/Bot.h" +#include "tgbot/EventHandler.h" +#include "tgbot/TgTypeParser.h" +#include "tgbot/net/HttpServer.h" + +namespace TgBot { + +template +class TgWebhookServer : public HttpServer { + +public: + TgWebhookServer(std::shared_ptr>& acceptor, const ServerHandler& handler) = delete; + + TgWebhookServer(std::shared_ptr>& acceptor, const std::string& path, const EventHandler* eventHandler) : + HttpServer(acceptor, [this, eventHandler, &path](const std::string& data, const std::map& headers) -> std::string { + if (headers["method"] == "POST" && headers["path"] == path) { + eventHandler->handleUpdate(TgTypeParser::getInstance().parseUpdate(TgTypeParser::getInstance().parseJson(data))); + } + return HttpParser::generateResponse(""); + }) + { + } + + TgWebhookServer(std::shared_ptr>& acceptor, const std::string& path, const Bot& bot) : + TgWebhookServer(acceptor, path, &bot.getEventHandler()) + { + } +}; + +} + +#endif //TGBOT_TGHTTPSERVER_H diff --git a/include/tgbot/net/TgWebhookTcpServer.h b/include/tgbot/net/TgWebhookTcpServer.h new file mode 100644 index 0000000..cac2638 --- /dev/null +++ b/include/tgbot/net/TgWebhookTcpServer.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_TGWEBHOOKTCPSERVER_H +#define TGBOT_TGWEBHOOKTCPSERVER_H + +#include "tgbot/net/TgWebhookServer.h" + +namespace TgBot { + +/** + * This class setups HTTP server for receiving Telegram Update objects from tcp connections. + * @ingroup net + */ +class TgWebhookTcpServer : public TgWebhookServer { + +public: + TgWebhookTcpServer(std::shared_ptr>& acceptor, const std::string& path, EventHandler* eventHandler) = delete; + + TgWebhookTcpServer(unsigned short port, const std::string& path, const EventHandler* eventHandler) : + TgWebhookServer(std::shared_ptr>(new boost::asio::ip::tcp::acceptor(_ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))), path, eventHandler) + { + } + + TgWebhookTcpServer(const std::string& path, const Bot& bot) : TgWebhookTcpServer(path, &bot.getEventHandler()) { + } +}; + +} + +#endif //TGBOT_TGWEBHOOKTCPSERVER_H diff --git a/include/tgbot/net/Url.h b/include/tgbot/net/Url.h new file mode 100644 index 0000000..818e934 --- /dev/null +++ b/include/tgbot/net/Url.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_CPP_URL_H +#define TGBOT_CPP_URL_H + +#include + +namespace TgBot { + +/** + * This class parses a string with the url + * @ingroup net + */ +class Url { + +public: + Url(const std::string& url); + + /** + * Protocol part of an url. Example: https:// + */ + std::string protocol; + + /** + * Host part of an url. Example: www.example.com + */ + std::string host; + + /** + * Path part of an url including preceding '/' char. Example: /index.html + */ + std::string path; + + /** + * Query part of an url without '?' char. Example: a=1&b=2&c=3 + */ + std::string query; + + /** + * Fragment part of an url without '#' char. Example: section1 + */ + std::string fragment; +}; + +} + +#endif //TGBOT_CPP_URL_H diff --git a/include/tgbot/tools/StringTools.h b/include/tgbot/tools/StringTools.h new file mode 100644 index 0000000..0a01b0d --- /dev/null +++ b/include/tgbot/tools/StringTools.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_CPP_STRINGTOOLS_H +#define TGBOT_CPP_STRINGTOOLS_H + +#include +#include +#include + +/** + * @ingroup tools + */ +namespace StringTools { + +/** + * Checks if first string is starting with second string and vice-versa + * @param str1 First string + * @param str2 Second string + */ +bool startsWith(const std::string& str1, const std::string& str2); + +/** + * Checks if first string is ending with second string and vice-versa + * @param str1 First string + * @param str2 Second string + */ +bool endsWith(const std::string& str1, const std::string& str2); + +/** + * Splits string to smaller substrings which have between them a delimiter. Resulting substrings won't have delimiter. + * @param str Source string + * @param delimiter Delimiter + * @param dest Array to which substrings will be saved. + */ +void split(const std::string& str, char delimiter, std::vector& dest); + +/** + * Generates pseudo random string. It's recommended to call srand before this method. + * @param length Length of resulting string. + */ +std::string generateRandomString(size_t length); + +/** + * Performs url encode. + * @param value Source url string + * @return Encoded url string + */ +std::string urlEncode(const std::string& value); + +/** + * Performs url decode. + * @param value Encoded url string + * @return Decoded url string + */ +std::string urlDecode(const std::string& value); + +/** + * Splits string to smaller substrings which have between them a delimiter. Resulting substrings won't have delimiter. + * @param str Source string + * @param delimiter Delimiter + * @return Array of substrings + */ +inline std::vector split(const std::string& str, char delimiter) { + std::vector result; + split(str, delimiter, result); + return result; +} + +} + +#endif //TGBOT_CPP_STRINGTOOLS_H diff --git a/include/tgbot/types/Audio.h b/include/tgbot/types/Audio.h new file mode 100644 index 0000000..8e255fe --- /dev/null +++ b/include/tgbot/types/Audio.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 Oleg Morozenkov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef TGBOT_CPP_AUDIO_H +#define TGBOT_CPP_AUDIO_H + +#include +#include + +namespace TgBot { + +/** + * This object represents an audio file (voice note). + * @ingroup types + */ +class Audio { + +public: + typedef std::shared_ptr