diff options
39 files changed, 2841 insertions, 1 deletions
@@ -1,5 +1,6 @@ CMakeCache.txt -CMakeFiles +CMakeFiles/ Makefile cmake_install.cmake install_manifest.txt +.idea/
\ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..a625dd8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.0) +project(TgBot) + +### options +option(ENABLE_TESTS "Set to ON to enable building of tests and samples" ON) + +### sources +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +include_directories("${PROJECT_SOURCE_DIR}/src") +set(SRC_LIST + src/tgbot/Bot.cpp + src/tgbot/Api.cpp + src/tgbot/EventManager.cpp + src/tgbot/Http.cpp + src/tgbot/Url.cpp + src/tgbot/Parser.cpp + src/tgbot/TgException.cpp + src/tgbot/tools/StringTools.cpp +) + +### libs +# openssl +find_package(OpenSSL REQUIRED) +include_directories(${OPENSSL_INCLUDE_DIR}) + +# boost +set(Boost_USE_MULTITHREADED ON) +find_package(Boost COMPONENTS system container iostreams REQUIRED) +include_directories(${Boost_INCLUDE_DIR}) + +set(LIB_LIST + ${Boost_LIBRARIES} + ${OPENSSL_LIBRARIES} +) + +### building project +add_library(${PROJECT_NAME} ${SRC_LIST}) +target_link_libraries(${PROJECT_NAME} ${LIB_LIST}) + +### tests +if (ENABLE_TESTS) + message(STATUS "Building of tests and sambles is enabled") + add_subdirectory(samples) +endif() diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt new file mode 100644 index 0000000..35c00f2 --- /dev/null +++ b/samples/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(echobot) diff --git a/samples/echobot/CMakeLists.txt b/samples/echobot/CMakeLists.txt new file mode 100644 index 0000000..c8c02ea --- /dev/null +++ b/samples/echobot/CMakeLists.txt @@ -0,0 +1,4 @@ +set(SAMPLE_NAME echobot) + +add_executable(${SAMPLE_NAME} src/main.cpp) +target_link_libraries(${SAMPLE_NAME} TgBot)
\ No newline at end of file diff --git a/samples/echobot/src/main.cpp b/samples/echobot/src/main.cpp new file mode 100644 index 0000000..4874aab --- /dev/null +++ b/samples/echobot/src/main.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include <signal.h> +#include <stdio.h> +#include <exception> + +#include <tgbot/Bot.h> +#include <tgbot/tools/StringTools.h> +#include <tgbot/TgException.h> + +using namespace std; +using namespace TgBot; + +bool sigintGot = false; + +int main() { + signal(SIGINT, [](int s) { + printf("SIGINT got"); + sigintGot = true; + }); + + Bot bot("PLACE_YOUR_TOKEN_HERE"); + bot.getEvents().onCommand("start", [](Message::Ptr message, Bot* const bot) { + bot->getApi().sendMessage(message->chat->id, "Hi!"); + }); + bot.getEvents().onAnyMessage([](Message::Ptr message, Bot* const bot) { + 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()); + + while (!sigintGot) { + printf("Long poll started\n"); + bot.startLongPoll(); + } + } catch (TgException& e) { + printf("error: %s\n", e.what()); + } + + return 0; +} diff --git a/src/tgbot/Api.cpp b/src/tgbot/Api.cpp new file mode 100644 index 0000000..9dd7314 --- /dev/null +++ b/src/tgbot/Api.cpp @@ -0,0 +1,270 @@ +/* + * 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. + */ + +#include "Api.h" + +#include <boost/property_tree/json_parser.hpp> + +#include "tgbot/Bot.h" +#include "tgbot/TgException.h" + +using namespace std; +using namespace boost::property_tree; + +namespace TgBot { + +Api::Api(Bot* const bot) : _bot(bot) { +} + +User::Ptr Api::getMe() const { + return _bot->getParser().parseUser(sendRequest("getMe").find("result")->second); +} + +Message::Ptr Api::sendMessage(int32_t chatId, const string& text, bool disableWebPagePreview, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("text", text)); + if (disableWebPagePreview) { + args.push_back(Http::Argument("disable_web_page_preview", disableWebPagePreview)); + } + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendMessage", args).find("result")->second); +} + +Message::Ptr Api::forwardMessage(int32_t chatId, int32_t fromChatId, int32_t messageId) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("from_chat_id", fromChatId)); + args.push_back(Http::Argument("message_id", messageId)); + return _bot->getParser().parseMessage(sendRequest("forwardMessage", args).find("result")->second); +} + +Message::Ptr Api::sendPhoto(int32_t chatId, const InputFile::Ptr& photo, const string& caption, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("photo", photo->data, true, photo->mimeType)); + if (!caption.empty()) { + args.push_back(Http::Argument("caption", caption)); + } + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendPhoto", args).find("result")->second); +} + +Message::Ptr Api::sendPhoto(int32_t chatId, const string& photo, const string& caption, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("photo", photo)); + if (!caption.empty()) { + args.push_back(Http::Argument("caption", caption)); + } + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendPhoto", args).find("result")->second); +} + +Message::Ptr Api::sendAudio(int32_t chatId, const InputFile::Ptr& audio, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("audio", audio->data, true, audio->mimeType)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendAudio", args).find("result")->second); +} + +Message::Ptr Api::sendAudio(int32_t chatId, const string& audio, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("audio", audio)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendAudio", args).find("result")->second); +} + +Message::Ptr Api::sendDocument(int32_t chatId, const InputFile::Ptr& document, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("document", document->data, true, document->mimeType)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendDocument", args).find("result")->second); +} + +Message::Ptr Api::sendDocument(int32_t chatId, const string& document, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("document", document)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendDocument", args).find("result")->second); +} + +Message::Ptr Api::sendSticker(int32_t chatId, const InputFile::Ptr& sticker, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("sticker", sticker->data, true, sticker->mimeType)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendSticker", args).find("result")->second); +} + +Message::Ptr Api::sendSticker(int32_t chatId, const string& sticker, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("sticker", sticker)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendSticker", args).find("result")->second); +} + +Message::Ptr Api::sendVideo(int32_t chatId, const InputFile::Ptr& video, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("video", video->data, true, video->mimeType)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendVideo", args).find("result")->second); +} + +Message::Ptr Api::sendVideo(int32_t chatId, const string& video, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("video", video)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendVideo", args).find("result")->second); +} + +Message::Ptr Api::sendLocation(int32_t chatId, float latitude, float longitude, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("latitude", latitude)); + args.push_back(Http::Argument("longitude", longitude)); + if (replyToMessageId) { + args.push_back(Http::Argument("reply_to_message_id", replyToMessageId)); + } + if (replyMarkup) { + args.push_back(Http::Argument("reply_markup", _bot->getParser().parseGenericReply(replyMarkup))); + } + return _bot->getParser().parseMessage(sendRequest("sendLocation", args).find("result")->second); +} + +void Api::sendChatAction(int32_t chatId, const string& action) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("chat_id", chatId)); + args.push_back(Http::Argument("action", action)); + sendRequest("sendChatAction", args); +} + +UserProfilePhotos::Ptr Api::getUserProfilePhotos(int32_t userId, int32_t offset, int32_t limit) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("user_id", userId)); + if (offset) { + args.push_back(Http::Argument("offset", offset)); + } + limit = max(1, min(100, limit)); + args.push_back(Http::Argument("limit", limit)); + return _bot->getParser().parseUserProfilePhotos(sendRequest("getUserProfilePhotos", args).find("result")->second); +} + +vector<Update::Ptr> Api::getUpdates(int32_t offset, int32_t limit, int32_t timeout) const { + vector<Http::Argument> args; + if (offset) { + args.push_back(Http::Argument("offset", offset)); + } + limit = max(1, min(100, limit)); + args.push_back(Http::Argument("limit", limit)); + if (timeout) { + args.push_back(Http::Argument("timeout", timeout)); + } + return _bot->getParser().parseArray<Update>(_bot->getParser().parseUpdate, sendRequest("getUpdates", args), "result"); +} + +void Api::setWebhook(const string& url) const { + vector<Http::Argument> args; + args.push_back(Http::Argument("url", url)); + sendRequest("setWebhook", args); +} + +boost::property_tree::ptree Api::sendRequest(const std::string& method, const std::vector<Http::Argument>& args) const { + std::string url = "https://api.telegram.org/bot"; + url += _bot->getToken(); + url += "/"; + url += method; + try { + ptree result = _bot->getParser().parseJson(_bot->getHttp().makeRequest(url, args)); + if (result.get<bool>("ok")) { + return result; + } else { + throw TgException(result.get("description", "")); + } + } catch (boost::property_tree::ptree_error& e) { + return ptree(); + } +} + +} diff --git a/src/tgbot/Api.h b/src/tgbot/Api.h new file mode 100644 index 0000000..c10fe56 --- /dev/null +++ b/src/tgbot/Api.h @@ -0,0 +1,77 @@ +/* + * 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 <string> +#include <vector> + +#include <boost/property_tree/ptree.hpp> + +#include "tgbot/Http.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; + +class Api { + +friend Bot; + +public: + User::Ptr getMe() const; + Message::Ptr sendMessage(int32_t chatId, const std::string& text, bool disableWebPagePreview = false, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr forwardMessage(int32_t chatId, int32_t fromChatId, int32_t messageId) const; + 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; + 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; + Message::Ptr sendAudio(int32_t chatId, const InputFile::Ptr& audio, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendAudio(int32_t chatId, const std::string& audio, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendDocument(int32_t chatId, const InputFile::Ptr& document, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendDocument(int32_t chatId, const std::string& document, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendSticker(int32_t chatId, const InputFile::Ptr& sticker, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendSticker(int32_t chatId, const std::string& sticker, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendVideo(int32_t chatId, const InputFile::Ptr& video, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendVideo(int32_t chatId, const std::string& video, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + Message::Ptr sendLocation(int32_t chatId, float latitude, float longitude, int32_t replyToMessageId = 0, const GenericReply::Ptr& replyMarkup = GenericReply::Ptr()) const; + void sendChatAction(int32_t chatId, const std::string& action) const; + UserProfilePhotos::Ptr getUserProfilePhotos(int32_t userId, int32_t offset = 0, int32_t limit = 100) const; + std::vector<Update::Ptr> getUpdates(int32_t offset = 0, int32_t limit = 100, int32_t timeout = 0) const; + void setWebhook(const std::string& url = "") const; + +private: + explicit Api(Bot* const bot); + + boost::property_tree::ptree sendRequest(const std::string& method, const std::vector<Http::Argument>& args = std::vector<Http::Argument>()) const; + + Bot* const _bot; +}; + +} + +#endif //TGBOT_CPP_API_H diff --git a/src/tgbot/Bot.cpp b/src/tgbot/Bot.cpp new file mode 100644 index 0000000..091b548 --- /dev/null +++ b/src/tgbot/Bot.cpp @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#include "Bot.h" + +using namespace std; +using namespace boost::property_tree; + +namespace TgBot { + +Bot::Bot(const string& token) : + _token(token), + _api(this), + _events(this), + _http(), + _parser(), + _webhooksServerHandler([this](const string& data) { + _events.handleUpdate(_parser.parseUpdate(_parser.parseJson(data))); + }) +{ +} + +void Bot::startLongPoll() { + std::vector<Update::Ptr> updates = _api.getUpdates(_lastUpdateId, 100, 60); + for (Update::Ptr& item : updates) { + if (item->updateId >= _lastUpdateId) { + _lastUpdateId = item->updateId + 1; + } + _events.handleUpdate(item); + } +} + +} diff --git a/src/tgbot/Bot.h b/src/tgbot/Bot.h new file mode 100644 index 0000000..488ceb1 --- /dev/null +++ b/src/tgbot/Bot.h @@ -0,0 +1,90 @@ +/* + * 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 <string> + +#include "tgbot/Api.h" +#include "tgbot/EventManager.h" +#include "tgbot/Http.h" +#include "tgbot/Parser.h" + +namespace TgBot { + +class Bot { + +public: + explicit Bot(const std::string& token); + + void startLongPoll(); + + inline void startServer(unsigned short port) { + _http.startServer(port, _webhooksServerHandler); + } + + inline void startServer(const std::string& unixSocketPath) { + _http.startServer(unixSocketPath, _webhooksServerHandler); + } + + inline const std::string& getToken() const { + return _token; + } + + inline const Api& getApi() const { + return _api; + } + + inline const EventManager& getEvents() const { + return _events; + } + + inline EventManager& getEvents() { + return _events; + } + + inline const Http& getHttp() const { + return _http; + } + + inline Http& getHttp() { + return _http; + } + + inline const Parser& getParser() const { + return _parser; + } + +private: + const std::string _token; + const Api _api; + EventManager _events; + Http _http; + const Parser _parser; + const Http::ServerHandler _webhooksServerHandler; + int32_t _lastUpdateId = 0; +}; + +} + +#endif //TGBOT_CPP_BOT_H diff --git a/src/tgbot/EventManager.cpp b/src/tgbot/EventManager.cpp new file mode 100644 index 0000000..fdd4859 --- /dev/null +++ b/src/tgbot/EventManager.cpp @@ -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. + */ + +#include "EventManager.h" + +#include "tgbot/tools/StringTools.h" + +using namespace std; + +namespace TgBot { + +EventManager::EventManager(Bot* const bot) : _bot(bot) { +} + +void EventManager::handleUpdate(const Update::Ptr& update) { + for (EventManager::Listener& item : _onAnyMessageListeners) { + item(update->message, _bot); + } + if (StringTools::startsWith(update->message->text, "/")) { + string command = update->message->text.substr(1, update->message->text.find(' ') - 2); + for (pair<const string, Listener>& item : _onCommandListeners) { + if (item.first == command) { + item.second(update->message, _bot); + return; + } + } + for (EventManager::Listener& item : _onUnknownCommandListeners) { + item(update->message, _bot); + } + } else { + for (EventManager::Listener& item : _onNonCommandMessageListeners) { + item(update->message, _bot); + } + } +} + +} diff --git a/src/tgbot/EventManager.h b/src/tgbot/EventManager.h new file mode 100644 index 0000000..cfe0b04 --- /dev/null +++ b/src/tgbot/EventManager.h @@ -0,0 +1,75 @@ +/* + * 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_EVENTMANAGER_H +#define TGBOT_CPP_EVENTMANAGER_H + +#include <string> +#include <functional> +#include <vector> +#include <map> + +#include "tgbot/types/Update.h" +#include "tgbot/types/Message.h" + +namespace TgBot { + +class Bot; + +class EventManager { + +friend Bot; + +public: + typedef std::function<void (const Message::Ptr&, Bot* const)> Listener; + + inline void onAnyMessage(const Listener& listener) { + _onAnyMessageListeners.push_back(listener); + } + + inline void onCommand(const std::string& commandName, const Listener& listener) { + _onCommandListeners[commandName] = listener; + } + + inline void onUnknownCommand(const Listener& listener) { + _onUnknownCommandListeners.push_back(listener); + } + + inline void onNonCommandMessage(const Listener& listener) { + _onNonCommandMessageListeners.push_back(listener); + } + +private: + explicit EventManager(Bot* const bot); + + void handleUpdate(const Update::Ptr& update); + + Bot* const _bot; + std::vector<Listener> _onAnyMessageListeners; + std::map<std::string, Listener> _onCommandListeners; + std::vector<Listener> _onUnknownCommandListeners; + std::vector<Listener> _onNonCommandMessageListeners; +}; + +} + +#endif //TGBOT_CPP_EVENTMANAGER_H diff --git a/src/tgbot/Http.cpp b/src/tgbot/Http.cpp new file mode 100644 index 0000000..d512e88 --- /dev/null +++ b/src/tgbot/Http.cpp @@ -0,0 +1,172 @@ +/* + * 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. + */ + +#include "Http.h" + +#include <iostream> + +#include <boost/asio/ssl.hpp> + +#include "tgbot/tools/StringTools.h" + +using namespace std; +using namespace boost::asio; +using namespace boost::asio::ip; +using namespace boost::asio::local; +using boost::lexical_cast; + +namespace TgBot { + +string Http::makeRequest(const Url& url, const vector<Argument>& args) { + string result; + + ssl::context context(ssl::context::sslv23); + context.set_default_verify_paths(); + + ssl::stream<tcp::socket> socket(_ioService, context); + tcp::resolver resolver(_ioService); + tcp::resolver::query query(url.host, url.protocol); + connect(socket.lowest_layer(), resolver.resolve(query)); + + socket.set_verify_mode(ssl::verify_none); + socket.set_verify_callback(ssl::rfc2818_verification(url.host)); + socket.handshake(ssl::stream<tcp::socket>::client); + + string requestText; + if (args.empty()) { + requestText += "GET "; + } else { + requestText += "POST "; + } + requestText += url.path; + requestText += url.query.empty() ? "" : "?" + url.query; + requestText += " HTTP/1.1\r\n"; + requestText += "Host: "; + requestText += url.host; + requestText += "\r\nConnection: close\r\n"; + if (args.empty()) { + requestText += "\r\n"; + } else { + string requestData; + + bool isMultipart = false; + string bondary; + srand((unsigned int) time(nullptr)); + for (const Argument& item : args) { + if (item.isFile) { + isMultipart = true; + while (bondary.empty() || item.value.find(bondary) != item.value.npos) { + bondary += StringTools::generateRandomString(4); + } + } + } + if (isMultipart) { + requestText += "Content-Type: multipart/form-data; boundary="; + requestText += bondary; + requestText += "\r\n"; + for (const Argument& item : args) { + requestData += "--"; + requestData += bondary; + requestData += "\r\nContent-Disposition: form-data; name=\""; + requestData += item.name; + requestData += "\"\r\n"; + if (item.isFile) { + requestData += "Content-Type: "; + requestData += item.mimeType; + requestData += "\r\n"; + } + requestData += "\r\n"; + requestData += item.value; + requestData += "\r\n\r\n"; + } + } else { + requestText += "Content-Type: application/x-www-form-urlencoded\r\n"; + bool firstRun = true; + for (const Argument& item : args) { + if (firstRun) { + firstRun = false; + } else { + requestData += '&'; + } + requestData += StringTools::urlEncode(item.name); + requestData += '='; + requestData += StringTools::urlEncode(item.value); + } + } + + requestText += "Content-Length: "; + requestText += lexical_cast<string>(requestData.length()); + requestText += "\r\n\r\n"; + requestText += requestData; + } + write(socket, buffer(requestText.c_str(), requestText.length())); + + char buff[1024]; + boost::system::error_code error; + while (!error) { + size_t bytes = read(socket, buffer(buff), error); + result += string(buff, bytes); + } + + cout << "REQUEST" << endl << requestText << endl << "RESPONSE" << endl << result << endl; + + size_t headerEnd = result.find("\r\n\r\n"); + if (headerEnd == result.npos) { + headerEnd = result.find("\n\n"); + } + if (headerEnd == result.npos) { + headerEnd = 0; + } + result.erase(0, headerEnd); + + return result; +} + +void Http::startServer(unsigned short port, const Http::ServerHandler& handler) { + stopServer(); + _serverHandler = handler; + tcp::acceptor* acceptor = new tcp::acceptor(_ioService, tcp::endpoint(tcp::v4(), port)); + _tcpServer = new Server<tcp>(this, acceptor); + _ioService.run(); +} + +void Http::startServer(const std::string& unixSocketPath, const Http::ServerHandler& handler) { + stopServer(); + _serverHandler = handler; + stream_protocol::acceptor* acceptor = new stream_protocol::acceptor(_ioService, stream_protocol::endpoint(unixSocketPath)); + _unixSocketServer = new Server<stream_protocol>(this, acceptor); + _ioService.run(); +} + +void Http::stopServer() { + _ioService.stop(); + if (_tcpServer != nullptr) { + delete _tcpServer; + _tcpServer = nullptr; + } + if (_unixSocketServer != nullptr) { + delete _unixSocketServer; + _unixSocketServer = nullptr; + } +} + +}
\ No newline at end of file diff --git a/src/tgbot/Http.h b/src/tgbot/Http.h new file mode 100644 index 0000000..aedcd93 --- /dev/null +++ b/src/tgbot/Http.h @@ -0,0 +1,125 @@ +/* + * 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_HTTP_H +#define TGBOT_CPP_HTTP_H + +#include <string> + +#include <boost/asio.hpp> +#include <boost/lexical_cast.hpp> + +#include "tgbot/Url.h" + +namespace TgBot { + +class Http { + +public: + typedef std::function<void (const std::string&)> ServerHandler; + + class Argument { + + public: + template<typename T> + Argument(const std::string& name, const T& value, bool isFile = false, const std::string& mimeType = "") : + name(name), value(boost::lexical_cast<std::string>(value)), isFile(isFile), mimeType(mimeType) + { + } + + std::string name; + std::string value; + bool isFile = false; + std::string mimeType; + }; + + std::string makeRequest(const Url& url, const std::vector<Argument>& args); + void startServer(unsigned short port, const ServerHandler& handler); + void startServer(const std::string& unixSocketPath, const ServerHandler& handler); + void stopServer(); + +private: + template<typename Protocol> + class Connection { + + public: + Connection(Http* http, boost::asio::basic_stream_socket<Protocol>* socket) : http(http), socket(socket) { + } + + ~Connection() { + delete socket; + } + + void start() { + data.reserve(10240); + socket->async_receive(data, [this]() { + size_t headerEnd = data.find("\r\n\r\n"); + if (headerEnd == data.npos) { + headerEnd = data.find("\n\n"); + } + if (headerEnd == data.npos) { + headerEnd = 0; + } + data.erase(0, headerEnd); + http->_serverHandler(data); + }); + } + + Http* http; + boost::asio::basic_stream_socket<Protocol>* socket; + std::string data; + }; + + template<typename Protocol> + class Server { + + public: + Server(Http* http, boost::asio::basic_socket_acceptor<Protocol>* acceptor) : http(http), acceptor(acceptor) { + } + + ~Server() { + delete acceptor; + } + + void start() { + boost::asio::basic_stream_socket<Protocol>* socket = new boost::asio::basic_stream_socket<Protocol>(acceptor->get_io_service()); + std::shared_ptr<Http::Connection<Protocol>> connection(new Connection<Protocol>(http, socket)); + acceptor->async_accept(*connection->socket, [this, connection]() { + connection->start(); + start(); + }); + } + + Http* http; + boost::asio::basic_socket_acceptor<Protocol>* acceptor; + }; + + + boost::asio::io_service _ioService; + Server<boost::asio::ip::tcp>* _tcpServer = nullptr; + Server<boost::asio::local::stream_protocol>* _unixSocketServer = nullptr; + ServerHandler _serverHandler; +}; + +} + +#endif //TGBOT_CPP_HTTP_H diff --git a/src/tgbot/Parser.cpp b/src/tgbot/Parser.cpp new file mode 100644 index 0000000..3730607 --- /dev/null +++ b/src/tgbot/Parser.cpp @@ -0,0 +1,485 @@ +/* + * 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. + */ + +#include "Parser.h" + +using namespace std; +using namespace boost::property_tree; + +namespace TgBot { + +User::Ptr Parser::parseUser(const ptree& data) const { + User::Ptr result(new User); + result->id = data.get<int32_t>("id"); + result->firstName = data.get<string>("first_name"); + result->lastName = data.get("last_name", ""); + result->username = data.get("username", ""); + return result; +} + +string Parser::parseUser(const User::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "id", object->id); + appendToJson(result, "first_name", object->firstName); + appendToJson(result, "last_name", object->lastName); + appendToJson(result, "username", object->username); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +GroupChat::Ptr Parser::parseGroupChat(const ptree& data) const { + GroupChat::Ptr result(new GroupChat); + result->id = data.get<int32_t>("id"); + result->title = data.get<string>("title"); + return result; +} + +string Parser::parseGroupChat(const GroupChat::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "id", object->id); + appendToJson(result, "title", object->title); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Message::Ptr Parser::parseMessage(const ptree& data) const { + Message::Ptr result(new Message); + result->messageId = data.get<int32_t>("message_id"); + result->from = parseUser(data.find("from")->second); + result->date = data.get<int32_t>("date"); + result->chat = parseGenericChat(data.find("chat")->second); + result->forwardFrom = tryParse<User>(parseUser, data, "forward_from"); + result->forwardDate = data.get("forward_date", 0); + result->replyToMessage = tryParse<Message>(parseMessage, data, "reply_to_message"); + result->text = data.get("text", ""); + result->audio = tryParse<Audio>(parseAudio, data, "audio"); + result->document = tryParse<Document>(parseDocument, data, "document"); + result->photo = parseArray<PhotoSize>(parsePhotoSize, data, "photo"); + result->sticker = tryParse<Sticker>(parseSticker, data, "sticker"); + result->video = tryParse<Video>(parseVideo, data, "video"); + result->contact = tryParse<Contact>(parseContact, data, "contact"); + result->location = tryParse<Location>(parseLocation, data, "location"); + result->newChatParticipant = tryParse<User>(parseUser, data, "new_chat_participant"); + result->leftChatParticipant = tryParse<User>(parseUser, data, "left_chat_participant"); + result->newChatTitle = data.get("new_chat_title", ""); + result->newChatPhoto = parseArray<PhotoSize>(parsePhotoSize, data, "new_chat_photo"); + result->deleteChatPhoto = data.get("delete_chat_photo", false); + result->groupChatCreated = data.get("group_chat_created", false); + return result; +} + +string Parser::parseMessage(const Message::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "message_id", object->messageId); + appendToJson(result, "from", parseUser(object->from)); + appendToJson(result, "date", object->date); + appendToJson(result, "chat", parseGenericChat(object->chat)); + appendToJson(result, "forward_from", parseUser(object->forwardFrom)); + appendToJson(result, "forward_date", object->forwardDate); + appendToJson(result, "reply_to_message", parseMessage(object->replyToMessage)); + appendToJson(result, "text", object->text); + appendToJson(result, "audio", parseAudio(object->audio)); + appendToJson(result, "document", parseDocument(object->document)); + appendToJson(result, "photo", parseArray(parsePhotoSize, object->photo)); + appendToJson(result, "sticker", parseSticker(object->sticker)); + appendToJson(result, "video", parseVideo(object->video)); + appendToJson(result, "contact", parseContact(object->contact)); + appendToJson(result, "location", parseLocation(object->location)); + appendToJson(result, "new_chat_participant", parseUser(object->newChatParticipant)); + appendToJson(result, "left_chat_participant", parseUser(object->leftChatParticipant)); + appendToJson(result, "new_chat_title", object->newChatTitle); + appendToJson(result, "new_chat_photo", parseArray(parsePhotoSize, object->newChatPhoto)); + appendToJson(result, "delete_chat_photo", object->deleteChatPhoto); + appendToJson(result, "group_chat_created", object->groupChatCreated); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +PhotoSize::Ptr Parser::parsePhotoSize(const ptree& data) const { + PhotoSize::Ptr result(new PhotoSize); + result->fileId = data.get<string>("file_id"); + result->width = data.get<int32_t>("width"); + result->height = data.get<int32_t>("height"); + result->fileSize = data.get("file_size", 0); + return result; +} + +string Parser::parsePhotoSize(const PhotoSize::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "file_id", object->fileId); + appendToJson(result, "width", object->width); + appendToJson(result, "height", object->height); + appendToJson(result, "file_size", object->fileSize); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Audio::Ptr Parser::parseAudio(const ptree& data) const { + Audio::Ptr result(new Audio); + result->fileId = data.get<string>("file_id"); + result->duration = data.get<int32_t>("duration"); + result->mimeType = data.get("mime_type", ""); + result->fileSize = data.get("file_size", 0); + return result; +} + +string Parser::parseAudio(const Audio::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "file_id", object->fileId); + appendToJson(result, "duration", object->duration); + appendToJson(result, "mime_type", object->mimeType); + appendToJson(result, "file_size", object->fileSize); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Document::Ptr Parser::parseDocument(const ptree& data) const { + Document::Ptr result(new Document); + result->fileId = data.get<string>("file_id"); + result->thumb = parsePhotoSize(data.find("thumb")->second); + result->fileName = data.get("file_name", ""); + result->mimeType = data.get("mime_type", ""); + result->fileSize = data.get("file_size", 0); + return result; +} + +string Parser::parseDocument(const Document::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "file_id", object->fileId); + appendToJson(result, "thumb", parsePhotoSize(object->thumb)); + appendToJson(result, "file_name", object->fileName); + appendToJson(result, "mime_type", object->mimeType); + appendToJson(result, "file_size", object->fileSize); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Sticker::Ptr Parser::parseSticker(const ptree& data) const { + Sticker::Ptr result(new Sticker); + result->fileId = data.get<string>("file_id"); + result->width = data.get<int32_t>("width"); + result->height = data.get<int32_t>("height"); + result->thumb = parsePhotoSize(data.find("thumb")->second); + result->fileSize = data.get("file_size", 0); + return result; +} + +string Parser::parseSticker(const Sticker::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "file_id", object->fileId); + appendToJson(result, "width", object->width); + appendToJson(result, "height", object->height); + appendToJson(result, "thumb", parsePhotoSize(object->thumb)); + appendToJson(result, "file_size", object->fileSize); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Video::Ptr Parser::parseVideo(const ptree& data) const { + Video::Ptr result(new Video); + result->fileId = data.get<string>("file_id"); + result->width = data.get<int32_t>("width"); + result->height = data.get<int32_t>("height"); + result->duration = data.get<int32_t>("duration"); + result->thumb = parsePhotoSize(data.find("thumb")->second); + result->mimeType = data.get("mime_type", ""); + result->fileSize = data.get("file_size", 0); + result->caption = data.get("caption", ""); + return result; +} + +string Parser::parseVideo(const Video::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "file_id", object->fileId); + appendToJson(result, "width", object->width); + appendToJson(result, "height", object->height); + appendToJson(result, "duration", object->duration); + appendToJson(result, "thumb", parsePhotoSize(object->thumb)); + appendToJson(result, "mime_type", object->mimeType); + appendToJson(result, "file_size", object->fileSize); + appendToJson(result, "caption", object->caption); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Contact::Ptr Parser::parseContact(const ptree& data) const { + Contact::Ptr result(new Contact); + result->phoneNumber = data.get<string>("phone_number"); + result->firstName = data.get<string>("first_name"); + result->lastName = data.get("last_name", ""); + result->userId = data.get("user_id", ""); + return result; +} + +string Parser::parseContact(const Contact::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "phone_number", object->phoneNumber); + appendToJson(result, "first_name", object->firstName); + appendToJson(result, "last_name", object->lastName); + appendToJson(result, "user_id", object->userId); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Location::Ptr Parser::parseLocation(const ptree& data) const { + Location::Ptr result(new Location); + result->longitude = data.get<float>("longitude"); + result->latitude = data.get<float>("latitude"); + return result; +} + +string Parser::parseLocation(const Location::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "longitude", object->longitude); + appendToJson(result, "latitude", object->latitude); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +Update::Ptr Parser::parseUpdate(const ptree& data) const { + Update::Ptr result(new Update); + result->updateId = data.get<int32_t>("update_id"); + result->message = parseMessage(data.find("message")->second); + return result; +} + +string Parser::parseUpdate(const Update::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "update_id", object->updateId); + appendToJson(result, "message", parseMessage(object->message)); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +UserProfilePhotos::Ptr Parser::parseUserProfilePhotos(const ptree& data) const { + UserProfilePhotos::Ptr result(new UserProfilePhotos); + result->totalCount = data.get<int32_t>("total_count"); + result->photos = parse2DArray<PhotoSize>(parsePhotoSize, data, "photos"); + return result; +} + +string Parser::parseUserProfilePhotos(const UserProfilePhotos::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "total_count", object->totalCount); + appendToJson(result, "photos", parse2DArray(parsePhotoSize, object->photos)); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +ReplyKeyboardMarkup::Ptr Parser::parseReplyKeyboardMarkup(const boost::property_tree::ptree& data) const { + ReplyKeyboardMarkup::Ptr result(new ReplyKeyboardMarkup); + for (const pair<const string, ptree>& item : data.find("keyboard")->second) { + vector<string> array; + for (const pair<const string, ptree>& innerItem : item.second) { + array.push_back(innerItem.second.data()); + } + result->keyboard.push_back(array); + } + result->resizeKeyboard = data.get<bool>("resize_keyboard"); + result->oneTimeKeyboard = data.get<bool>("one_time_keyboard"); + result->selective = data.get<bool>("selective"); + return result; +} + +std::string Parser::parseReplyKeyboardMarkup(const ReplyKeyboardMarkup::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + result += "\"keyboard\":["; + for (vector<string>& item : object->keyboard) { + result += '['; + for (string& innerItem : item) { + result += '"'; + result += innerItem; + result += "\","; + } + result.erase(result.length() - 1); + result += "],"; + } + result.erase(result.length() - 1); + result += "],"; + appendToJson(result, "resize_keyboard", object->resizeKeyboard); + appendToJson(result, "one_time_keyboard", object->oneTimeKeyboard); + appendToJson(result, "selective", object->selective); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +ReplyKeyboardHide::Ptr Parser::parseReplyKeyboardHide(const boost::property_tree::ptree& data) const { + ReplyKeyboardHide::Ptr result(new ReplyKeyboardHide); + result->selective = data.get<bool>("selective"); + return result; +} + +std::string Parser::parseReplyKeyboardHide(const ReplyKeyboardHide::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "selective", object->selective); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +ForceReply::Ptr Parser::parseForceReply(const boost::property_tree::ptree& data) const { + ForceReply::Ptr result(new ForceReply); + result->selective = data.get<bool>("selective"); + return result; +} + +std::string Parser::parseForceReply(const ForceReply::Ptr& object) const { + if (!object) { + return ""; + } + string result; + result += '{'; + appendToJson(result, "selective", object->selective); + result.erase(result.length() - 1); + result += '}'; + return result; +} + +GenericChat::Ptr Parser::parseGenericChat(const ptree& data) const { + if (data.find("first_name") == data.not_found()) { + return static_pointer_cast<GenericChat>(parseGroupChat(data)); + } else { + return static_pointer_cast<GenericChat>(parseUser(data)); + } +} + +string Parser::parseGenericChat(const GenericChat::Ptr& object) const { + if (!object) { + return ""; + } + if (dynamic_pointer_cast<User>(object) == nullptr) { + return parseGroupChat(static_pointer_cast<GroupChat>(object)); + } else { + return parseUser(static_pointer_cast<User>(object)); + } +} + +GenericReply::Ptr Parser::parseGenericReply(const boost::property_tree::ptree& data) const { + if (data.find("force_reply") != data.not_found()) { + return static_pointer_cast<GenericReply>(parseForceReply(data)); + } else if (data.find("hide_keyboard") != data.not_found()) { + return static_pointer_cast<GenericReply>(parseReplyKeyboardHide(data)); + } else { + return static_pointer_cast<GenericReply>(parseReplyKeyboardMarkup(data)); + } +} + +std::string Parser::parseGenericReply(const GenericReply::Ptr& object) const { + if (!object) { + return ""; + } + if (dynamic_pointer_cast<ForceReply>(object) != nullptr) { + return parseForceReply(static_pointer_cast<ForceReply>(object)); + } else if (dynamic_pointer_cast<ReplyKeyboardHide>(object) != nullptr) { + return parseReplyKeyboardHide(static_pointer_cast<ReplyKeyboardHide>(object)); + } else { + return parseReplyKeyboardMarkup(static_pointer_cast<ReplyKeyboardMarkup>(object)); + } +} + +void Parser::appendToJson(string& json, const string& varName, const string& value) const { + if (value.empty()) { + return; + } + json += '"'; + json += varName; + json += "\":"; + if (value.front() != '{') { + json += '"'; + } + json += value; + if (value.back() != '}') { + json += '"'; + } + json += ','; +} + +}
\ No newline at end of file diff --git a/src/tgbot/Parser.h b/src/tgbot/Parser.h new file mode 100644 index 0000000..48a7cea --- /dev/null +++ b/src/tgbot/Parser.h @@ -0,0 +1,178 @@ +/* + * 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_PARSER_H +#define TGBOT_CPP_PARSER_H + +#include <string> + +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/json_parser.hpp> + +#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 Parser { + +public: + 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<typename T> + std::shared_ptr<T> tryParse(std::shared_ptr<T> (Parser::*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<T>(); + } + return (this->*parseFunc)(treeItem->second); + } + + template<typename T> + std::vector<std::shared_ptr<T>> parseArray(std::shared_ptr<T> (Parser::*const parseFunc)(const boost::property_tree::ptree&) const, const boost::property_tree::ptree& data, const std::string& keyName) const { + std::vector<std::shared_ptr<T>> result; + auto treeItem = data.find(keyName); + if (treeItem == data.not_found()) { + return result; + } + for (const std::pair<const std::string, boost::property_tree::ptree>& innerTreeItem : treeItem->second) { + result.push_back((this->*parseFunc)(innerTreeItem.second)); + } + return result; + } + + template<typename T> + std::vector<std::vector<std::shared_ptr<T>>> parse2DArray(std::shared_ptr<T> (Parser::*const parseFunc)(const boost::property_tree::ptree&) const, const boost::property_tree::ptree& data, const std::string& keyName) const { + std::vector<std::vector<std::shared_ptr<T>>> result; + auto treeItem = data.find(keyName); + if (treeItem == data.not_found()) { + return result; + } + for (const std::pair<const std::string, boost::property_tree::ptree>& innerTreeItem : treeItem->second) { + std::vector<std::shared_ptr<T>> innerResult; + for (const std::pair<const std::string, boost::property_tree::ptree>& innerInnerTreeItem : innerTreeItem.second) { + innerResult.push_back((this->*parseFunc)(innerInnerTreeItem.second)); + } + result.push_back(innerResult); + } + return result; + } + + template<typename T> + std::string parseArray(std::string (Parser::*const parseFunc)(const std::shared_ptr<T>&) const, const std::vector<std::shared_ptr<T>>& objects) const { + std::string result; + result += '['; + for (const std::shared_ptr<T>& item : objects) { + result += (this->*parseFunc)(item); + result += ','; + } + result.erase(result.length() - 1); + result += ']'; + return result; + } + + template<typename T> + std::string parse2DArray(std::string (Parser::*const parseFunc)(const std::shared_ptr<T>&) const, const std::vector<std::vector<std::shared_ptr<T>>>& objects) const { + std::string result; + result += '['; + for (const std::vector<std::shared_ptr<T>>& item : objects) { + result += parseArray(parseFunc, item); + result += ','; + } + result.erase(result.length() - 1); + result += ']'; + return result; + } + +private: + template<typename T> + 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_PARSER_H diff --git a/src/tgbot/TgException.cpp b/src/tgbot/TgException.cpp new file mode 100644 index 0000000..2c8263e --- /dev/null +++ b/src/tgbot/TgException.cpp @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "TgException.h" + +namespace TgBot { + +TgBot::TgException::TgException(const std::string description) : runtime_error(description) { +} + +} diff --git a/src/tgbot/TgException.h b/src/tgbot/TgException.h new file mode 100644 index 0000000..c283a06 --- /dev/null +++ b/src/tgbot/TgException.h @@ -0,0 +1,39 @@ +/* + * 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 <string> +#include <stdexcept> + +namespace TgBot { + +class TgException : public std::runtime_error { + +public: + explicit TgException(const std::string description); +}; + +} + +#endif //TGBOT_TGEXCEPTION_H diff --git a/src/tgbot/Url.cpp b/src/tgbot/Url.cpp new file mode 100644 index 0000000..94b9004 --- /dev/null +++ b/src/tgbot/Url.cpp @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#include "Url.h" + +using namespace std; + +namespace TgBot { + +Url::Url(const string& url) { + bool isProtocolParsed = false; + bool isHostParsed = false; + bool isPathParsed = false; + + for (size_t i = 0, count = url.length(); i < count; ++i) { + char c = url[i]; + + if (!isProtocolParsed) { + if (c == ':') { + isProtocolParsed = true; + i += 2; + } else { + protocol += c; + } + } else if (!isHostParsed) { + if (c == '/') { + isHostParsed = true; + path += c; + } else if (c == '?') { + isHostParsed = isPathParsed = true; + } else { + host += c; + } + } else if (!isPathParsed) { + if (c == '?') { + isPathParsed = true; + } else { + path += c; + } + } else { + query += c; + } + } +} + +} diff --git a/src/tgbot/Url.h b/src/tgbot/Url.h new file mode 100644 index 0000000..de5a7d2 --- /dev/null +++ b/src/tgbot/Url.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_CPP_URL_H +#define TGBOT_CPP_URL_H + +#include <string> + +namespace TgBot { + +class Url { + +public: + Url(const std::string& url); + + std::string protocol; + std::string host; + std::string path; + std::string query; +}; + +} + +#endif //TGBOT_CPP_URL_H diff --git a/src/tgbot/tools/StringTools.cpp b/src/tgbot/tools/StringTools.cpp new file mode 100644 index 0000000..7a8b740 --- /dev/null +++ b/src/tgbot/tools/StringTools.cpp @@ -0,0 +1,98 @@ +/* + * 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. + */ + +#include "StringTools.h" + +#include <stdlib.h> +#include <iomanip> + +using namespace std; + +namespace StringTools { + +bool startsWith(const string& str1, const string& str2) { + string::const_iterator it1(str1.begin()); + string::const_iterator end1(str1.end()); + string::const_iterator it2(str2.begin()); + string::const_iterator end2(str2.end()); + while (it1 != end1 && it2 != end2) { + if (*it1 != *it2) { + return false; + } + ++it1; + ++it2; + } + return true; +} + +bool endsWith(const string& str1, const string& str2) { + string::const_iterator it1(str1.end()); + string::const_iterator start1(str1.begin()); + string::const_iterator it2(str2.begin()); + string::const_iterator end2(str2.end()); + while (it1 != start1 && it2 != end2) { + if (*it1 != *it2) { + return false; + } + --it1; + ++it2; + } + return true; +} + +void split(const string& str, char delimiter, vector<string>& dest) { + istringstream stream(str); + string s; + while (getline(stream, s, delimiter)) { + dest.push_back(s); + } +} + +string generateRandomString(size_t length) { + static const string chars("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890-=[]\\;',./!@#$%^&*()_+{}|:\"<>?`~"); + static const size_t charsLen = chars.length(); + string result; + for (int i = 0; i < length; ++i) { + result += chars[rand() % charsLen]; + } + return result; +} + +string urlEncode(const string& value) { + static const string legitPunctuation = "-_.~!*()'"; + ostringstream result; + result.fill('0'); + result << hex; + for (const char& c : value) { + if (isalnum(c) || legitPunctuation.find(c) != legitPunctuation.npos) { + result << c; + } else if (c == ' ') { + result << '+'; + } else { + result << '%' << setw(2) << int((unsigned char) c); + } + } + + return result.str(); +} + +} diff --git a/src/tgbot/tools/StringTools.h b/src/tgbot/tools/StringTools.h new file mode 100644 index 0000000..0c94338 --- /dev/null +++ b/src/tgbot/tools/StringTools.h @@ -0,0 +1,46 @@ +/* + * 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 <vector> +#include <string> +#include <sstream> + +namespace StringTools { + +bool startsWith(const std::string& str1, const std::string& str2); +bool endsWith(const std::string& str1, const std::string& str2); +void split(const std::string& str, char delimiter, std::vector<std::string>& dest); +std::string generateRandomString(size_t length); +std::string urlEncode(const std::string& value); + +inline std::vector<std::string> split(const std::string& str, char delimiter) { + std::vector<std::string> result; + split(str, delimiter, result); + return result; +} + +} + +#endif //TGBOT_CPP_STRINGTOOLS_H diff --git a/src/tgbot/types/Audio.h b/src/tgbot/types/Audio.h new file mode 100644 index 0000000..56374e4 --- /dev/null +++ b/src/tgbot/types/Audio.h @@ -0,0 +1,44 @@ +/* + * 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 <string> +#include <memory> + +namespace TgBot { + +class Audio { + +public: + typedef std::shared_ptr<Audio> Ptr; + + std::string fileId; + int32_t duration; + std::string mimeType; + int32_t fileSize; +}; + +} + +#endif //TGBOT_CPP_AUDIO_H diff --git a/src/tgbot/types/Contact.h b/src/tgbot/types/Contact.h new file mode 100644 index 0000000..1e79e53 --- /dev/null +++ b/src/tgbot/types/Contact.h @@ -0,0 +1,44 @@ +/* + * 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_CONTACT_H +#define TGBOT_CPP_CONTACT_H + +#include <string> +#include <memory> + +namespace TgBot { + +class Contact { + +public: + typedef std::shared_ptr<Contact> Ptr; + + std::string phoneNumber; + std::string firstName; + std::string lastName; + std::string userId; +}; + +} + +#endif //TGBOT_CPP_CONTACT_H diff --git a/src/tgbot/types/Document.h b/src/tgbot/types/Document.h new file mode 100644 index 0000000..6dd32c7 --- /dev/null +++ b/src/tgbot/types/Document.h @@ -0,0 +1,47 @@ +/* + * 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_DOCUMENT_H +#define TGBOT_CPP_DOCUMENT_H + +#include <string> +#include <memory> + +#include "tgbot/types/PhotoSize.h" + +namespace TgBot { + +class Document { + +public: + typedef std::shared_ptr<Document> Ptr; + + std::string fileId; + PhotoSize::Ptr thumb; + std::string fileName; + std::string mimeType; + int32_t fileSize; +}; + +} + +#endif //TGBOT_CPP_DOCUMENT_H diff --git a/src/tgbot/types/ForceReply.h b/src/tgbot/types/ForceReply.h new file mode 100644 index 0000000..d0ee706 --- /dev/null +++ b/src/tgbot/types/ForceReply.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_CPP_FORCEREPLY_H +#define TGBOT_CPP_FORCEREPLY_H + +#include <memory> + +#include "tgbot/types/GenericReply.h" + +namespace TgBot { + +class ForceReply : public GenericReply { + +public: + typedef std::shared_ptr<ForceReply> Ptr; + + const bool forceReply = true; + bool selective; +}; + +} + +#endif //TGBOT_CPP_FORCEREPLY_H diff --git a/src/tgbot/types/GenericChat.h b/src/tgbot/types/GenericChat.h new file mode 100644 index 0000000..f641620 --- /dev/null +++ b/src/tgbot/types/GenericChat.h @@ -0,0 +1,42 @@ +/* + * 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_GENERICCHAT_H +#define TGBOT_CPP_GENERICCHAT_H + +#include <memory> + +namespace TgBot { + +class GenericChat { + +public: + typedef std::shared_ptr<GenericChat> Ptr; + + virtual ~GenericChat() { } + + int32_t id; +}; + +} + +#endif //TGBOT_CPP_GENERICCHAT_H diff --git a/src/tgbot/types/GenericReply.h b/src/tgbot/types/GenericReply.h new file mode 100644 index 0000000..5b03ea5 --- /dev/null +++ b/src/tgbot/types/GenericReply.h @@ -0,0 +1,40 @@ +/* + * 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_GENERICREPLY_H +#define TGBOT_CPP_GENERICREPLY_H + +#include <memory> + +namespace TgBot { + +class GenericReply { + +public: + typedef std::shared_ptr<GenericReply> Ptr; + + virtual ~GenericReply() { } +}; + +} + +#endif //TGBOT_CPP_GENERICREPLY_H diff --git a/src/tgbot/types/GroupChat.h b/src/tgbot/types/GroupChat.h new file mode 100644 index 0000000..e9f1989 --- /dev/null +++ b/src/tgbot/types/GroupChat.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_CPP_GROUPCHAT_H +#define TGBOT_CPP_GROUPCHAT_H + +#include <string> +#include <memory> + +#include "tgbot/types/GenericChat.h" + +namespace TgBot { + +class GroupChat : public GenericChat { + +public: + typedef std::shared_ptr<GroupChat> Ptr; + + std::string title; +}; + +} + +#endif //TGBOT_CPP_GROUPCHAT_H diff --git a/src/tgbot/types/InputFile.h b/src/tgbot/types/InputFile.h new file mode 100644 index 0000000..0c92d80 --- /dev/null +++ b/src/tgbot/types/InputFile.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_CPP_INPUTFILE_H +#define TGBOT_CPP_INPUTFILE_H + +#include <string> +#include <memory> +#include <utility> + +namespace TgBot { + +class InputFile { + +public: + typedef std::shared_ptr<InputFile> Ptr; + + std::string data; + std::string mimeType; +}; + +} + +#endif //TGBOT_CPP_INPUTFILE_H diff --git a/src/tgbot/types/Location.h b/src/tgbot/types/Location.h new file mode 100644 index 0000000..e689d71 --- /dev/null +++ b/src/tgbot/types/Location.h @@ -0,0 +1,41 @@ +/* + * 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_LOCATION_H +#define TGBOT_CPP_LOCATION_H + +#include <memory> + +namespace TgBot { + +class Location { + +public: + typedef std::shared_ptr<Location> Ptr; + + float longitude; + float latitude; +}; + +} + +#endif //TGBOT_CPP_LOCATION_H diff --git a/src/tgbot/types/Message.h b/src/tgbot/types/Message.h new file mode 100644 index 0000000..155a66c --- /dev/null +++ b/src/tgbot/types/Message.h @@ -0,0 +1,73 @@ +/* + * 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_MESSAGE_H +#define TGBOT_CPP_MESSAGE_H + +#include <string> +#include <vector> +#include <memory> + +#include "tgbot/types/User.h" +#include "tgbot/types/GenericChat.h" +#include "tgbot/types/Message.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/PhotoSize.h" + +namespace TgBot { + +class Message { + +public: + typedef std::shared_ptr<Message> Ptr; + + int32_t messageId; + User::Ptr from; + int32_t date; + GenericChat::Ptr chat; + User::Ptr forwardFrom; + int32_t forwardDate; + Message::Ptr replyToMessage; + std::string text; + Audio::Ptr audio; + Document::Ptr document; + std::vector<PhotoSize::Ptr> photo; + Sticker::Ptr sticker; + Video::Ptr video; + Contact::Ptr contact; + Location::Ptr location; + User::Ptr newChatParticipant; + User::Ptr leftChatParticipant; + std::string newChatTitle; + std::vector<PhotoSize::Ptr> newChatPhoto; + bool deleteChatPhoto; + bool groupChatCreated; +}; + +} + +#endif //TGBOT_CPP_MESSAGE_H diff --git a/src/tgbot/types/PhotoSize.h b/src/tgbot/types/PhotoSize.h new file mode 100644 index 0000000..b048c15 --- /dev/null +++ b/src/tgbot/types/PhotoSize.h @@ -0,0 +1,44 @@ +/* + * 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_PHOTOSIZE_H +#define TGBOT_CPP_PHOTOSIZE_H + +#include <string> +#include <memory> + +namespace TgBot { + +class PhotoSize { + +public: + typedef std::shared_ptr<PhotoSize> Ptr; + + std::string fileId; + int32_t width; + int32_t height; + int32_t fileSize; +}; + +} + +#endif //TGBOT_CPP_PHOTOSIZE_H diff --git a/src/tgbot/types/ReplyKeyboardHide.h b/src/tgbot/types/ReplyKeyboardHide.h new file mode 100644 index 0000000..f1dc867 --- /dev/null +++ b/src/tgbot/types/ReplyKeyboardHide.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_CPP_REPLYKEYBOARDHIDE_H +#define TGBOT_CPP_REPLYKEYBOARDHIDE_H + +#include <memory> + +#include "tgbot/types/GenericReply.h" + +namespace TgBot { + +class ReplyKeyboardHide : public GenericReply { + +public: + typedef std::shared_ptr<ReplyKeyboardHide> Ptr; + + const bool hideKeyboard = true; + bool selective; +}; + +} + +#endif //TGBOT_CPP_REPLYKEYBOARDHIDE_H diff --git a/src/tgbot/types/ReplyKeyboardMarkup.h b/src/tgbot/types/ReplyKeyboardMarkup.h new file mode 100644 index 0000000..84b7799 --- /dev/null +++ b/src/tgbot/types/ReplyKeyboardMarkup.h @@ -0,0 +1,47 @@ +/* + * 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_REPLYKEYBOARDMARKUP_H +#define TGBOT_CPP_REPLYKEYBOARDMARKUP_H + +#include <string> +#include <vector> +#include <memory> + +#include "tgbot/types/GenericReply.h" + +namespace TgBot { + +class ReplyKeyboardMarkup : public GenericReply { + +public: + typedef std::shared_ptr<ReplyKeyboardMarkup> Ptr; + + std::vector<std::vector<std::string>> keyboard; + bool resizeKeyboard; + bool oneTimeKeyboard; + bool selective; +}; + +} + +#endif //TGBOT_CPP_REPLYKEYBOARDMARKUP_H diff --git a/src/tgbot/types/Sticker.h b/src/tgbot/types/Sticker.h new file mode 100644 index 0000000..7110ef9 --- /dev/null +++ b/src/tgbot/types/Sticker.h @@ -0,0 +1,47 @@ +/* + * 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_STICKER_H +#define TGBOT_CPP_STICKER_H + +#include <string> +#include <memory> + +#include "tgbot/types/PhotoSize.h" + +namespace TgBot { + +class Sticker { + +public: + typedef std::shared_ptr<Sticker> Ptr; + + std::string fileId; + int32_t width; + int32_t height; + PhotoSize::Ptr thumb; + int32_t fileSize; +}; + +} + +#endif //TGBOT_CPP_STICKER_H diff --git a/src/tgbot/types/Update.h b/src/tgbot/types/Update.h new file mode 100644 index 0000000..a0b7d50 --- /dev/null +++ b/src/tgbot/types/Update.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_CPP_UPDATE_H +#define TGBOT_CPP_UPDATE_H + +#include <memory> + +#include "tgbot/types/Message.h" + +namespace TgBot { + +class Update { + +public: + typedef std::shared_ptr<Update> Ptr; + + int32_t updateId; + Message::Ptr message; +}; + +} + +#endif //TGBOT_CPP_UPDATE_H diff --git a/src/tgbot/types/User.h b/src/tgbot/types/User.h new file mode 100644 index 0000000..7f0710d --- /dev/null +++ b/src/tgbot/types/User.h @@ -0,0 +1,45 @@ +/* + * 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_USER_H +#define TGBOT_CPP_USER_H + +#include <string> +#include <memory> + +#include "tgbot/types/GenericChat.h" + +namespace TgBot { + +class User : public GenericChat { + +public: + typedef std::shared_ptr<User> Ptr; + + std::string firstName; + std::string lastName; + std::string username; +}; + +} + +#endif //TGBOT_CPP_USER_H diff --git a/src/tgbot/types/UserProfilePhotos.h b/src/tgbot/types/UserProfilePhotos.h new file mode 100644 index 0000000..cef4921 --- /dev/null +++ b/src/tgbot/types/UserProfilePhotos.h @@ -0,0 +1,44 @@ +/* + * 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_USERPROFILEPHOTOS_H +#define TGBOT_CPP_USERPROFILEPHOTOS_H + +#include <vector> +#include <memory> + +#include "tgbot/types/PhotoSize.h" + +namespace TgBot { + +class UserProfilePhotos { + +public: + typedef std::shared_ptr<UserProfilePhotos> Ptr; + + int32_t totalCount; + std::vector<std::vector<PhotoSize::Ptr>> photos; +}; + +} + +#endif //TGBOT_CPP_USERPROFILEPHOTOS_H diff --git a/src/tgbot/types/Video.h b/src/tgbot/types/Video.h new file mode 100644 index 0000000..6c2c441 --- /dev/null +++ b/src/tgbot/types/Video.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_CPP_VIDEO_H +#define TGBOT_CPP_VIDEO_H + +#include <string> +#include <memory> + +#include "tgbot/types/PhotoSize.h" + +namespace TgBot { + +class Video { + +public: + typedef std::shared_ptr<Video> Ptr; + + std::string fileId; + int32_t width; + int32_t height; + int32_t duration; + PhotoSize::Ptr thumb; + std::string mimeType; + int32_t fileSize; + std::string caption; +}; + +} + +#endif //TGBOT_CPP_VIDEO_H |