summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Morozenkov <omorozenkov@gmail.com>2015-07-05 01:17:15 +0300
committerOleg Morozenkov <omorozenkov@gmail.com>2015-07-05 01:17:15 +0300
commit6717e588e71d0586613053521b2dc591405410ba (patch)
tree4d3a77ed16db9c107e8da179b6cea59bc8c67452
parentab2be5c0e4003450be7a914573ef9edbee3626a4 (diff)
First version
-rw-r--r--.gitignore3
-rw-r--r--CMakeLists.txt44
-rw-r--r--samples/CMakeLists.txt1
-rw-r--r--samples/echobot/CMakeLists.txt4
-rw-r--r--samples/echobot/src/main.cpp66
-rw-r--r--src/tgbot/Api.cpp270
-rw-r--r--src/tgbot/Api.h77
-rw-r--r--src/tgbot/Bot.cpp52
-rw-r--r--src/tgbot/Bot.h90
-rw-r--r--src/tgbot/EventManager.cpp56
-rw-r--r--src/tgbot/EventManager.h75
-rw-r--r--src/tgbot/Http.cpp172
-rw-r--r--src/tgbot/Http.h125
-rw-r--r--src/tgbot/Parser.cpp485
-rw-r--r--src/tgbot/Parser.h178
-rw-r--r--src/tgbot/TgException.cpp30
-rw-r--r--src/tgbot/TgException.h39
-rw-r--r--src/tgbot/Url.cpp65
-rw-r--r--src/tgbot/Url.h43
-rw-r--r--src/tgbot/tools/StringTools.cpp98
-rw-r--r--src/tgbot/tools/StringTools.h46
-rw-r--r--src/tgbot/types/Audio.h44
-rw-r--r--src/tgbot/types/Contact.h44
-rw-r--r--src/tgbot/types/Document.h47
-rw-r--r--src/tgbot/types/ForceReply.h43
-rw-r--r--src/tgbot/types/GenericChat.h42
-rw-r--r--src/tgbot/types/GenericReply.h40
-rw-r--r--src/tgbot/types/GroupChat.h43
-rw-r--r--src/tgbot/types/InputFile.h43
-rw-r--r--src/tgbot/types/Location.h41
-rw-r--r--src/tgbot/types/Message.h73
-rw-r--r--src/tgbot/types/PhotoSize.h44
-rw-r--r--src/tgbot/types/ReplyKeyboardHide.h43
-rw-r--r--src/tgbot/types/ReplyKeyboardMarkup.h47
-rw-r--r--src/tgbot/types/Sticker.h47
-rw-r--r--src/tgbot/types/Update.h43
-rw-r--r--src/tgbot/types/User.h45
-rw-r--r--src/tgbot/types/UserProfilePhotos.h44
-rw-r--r--src/tgbot/types/Video.h50
39 files changed, 2841 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 52540e7..8813d62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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