summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOleg Morozenkov <omorozenkov@gmail.com>2015-08-11 22:13:23 +0300
committerOleg Morozenkov <omorozenkov@gmail.com>2015-08-11 22:13:23 +0300
commit376b88ec09ef8cf71dd823467406c58204485fcc (patch)
tree9ca599b854d18006c65b26003ce7dbdd416fdf18 /src
parentd7fbf7149d0e0c1c30972dab68d510ef6ac377dd (diff)
Fixed compiler's errors in TgTypeParser + fixed indentation + some other fixes
Diffstat (limited to 'src')
-rw-r--r--src/Api.cpp346
-rw-r--r--src/TgTypeParser.cpp792
-rw-r--r--src/net/HttpClient.cpp42
-rw-r--r--src/net/HttpParser.cpp292
-rw-r--r--src/net/TgLongPoll.cpp14
-rw-r--r--src/net/Url.cpp88
-rw-r--r--src/tools/Api.cpp279
-rw-r--r--src/tools/StringTools.cpp118
-rw-r--r--src/tools/TgException.cpp30
-rw-r--r--src/tools/TgTypeParser.cpp490
-rw-r--r--src/tools/net/HttpClient.cpp67
-rw-r--r--src/tools/net/HttpParser.cpp204
-rw-r--r--src/tools/net/TgLongPoll.cpp43
-rw-r--r--src/tools/net/Url.cpp85
-rw-r--r--src/tools/tools/StringTools.cpp119
15 files changed, 2163 insertions, 846 deletions
diff --git a/src/Api.cpp b/src/Api.cpp
index 0c04081..da0aa7b 100644
--- a/src/Api.cpp
+++ b/src/Api.cpp
@@ -31,234 +31,234 @@ using namespace boost::property_tree;
namespace TgBot {
-Api::Api(const std::string& token) : _token(token) {
+Api::Api(const string& token) : _token(token) {
}
User::Ptr Api::getMe() const {
- return TgTypeParser::getInstance().parseUser(sendRequest("getMe").find("result")->second);
+ return TgTypeParser::getInstance().parseJsonAndGetUser(sendRequest("getMe"));
}
Message::Ptr Api::sendMessage(int32_t chatId, const string& text, bool disableWebPagePreview, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("text", text));
- if (disableWebPagePreview) {
- args.push_back(HttpReqArg("disable_web_page_preview", disableWebPagePreview));
- }
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendMessage", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("text", text));
+ if (disableWebPagePreview) {
+ args.push_back(HttpReqArg("disable_web_page_preview", disableWebPagePreview));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendMessage", args));
}
Message::Ptr Api::forwardMessage(int32_t chatId, int32_t fromChatId, int32_t messageId) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("from_chat_id", fromChatId));
- args.push_back(HttpReqArg("message_id", messageId));
- return TgTypeParser::getInstance().parseMessage(sendRequest("forwardMessage", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("from_chat_id", fromChatId));
+ args.push_back(HttpReqArg("message_id", messageId));
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("forwardMessage", args));
}
Message::Ptr Api::sendPhoto(int32_t chatId, const InputFile::Ptr& photo, const string& caption, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("photo", photo->data, true, photo->mimeType));
- if (!caption.empty()) {
- args.push_back(HttpReqArg("caption", caption));
- }
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendPhoto", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("photo", photo->data, true, photo->mimeType));
+ if (!caption.empty()) {
+ args.push_back(HttpReqArg("caption", caption));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendPhoto", args));
}
Message::Ptr Api::sendPhoto(int32_t chatId, const string& photo, const string& caption, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("photo", photo));
- if (!caption.empty()) {
- args.push_back(HttpReqArg("caption", caption));
- }
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendPhoto", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("photo", photo));
+ if (!caption.empty()) {
+ args.push_back(HttpReqArg("caption", caption));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendPhoto", args));
}
Message::Ptr Api::sendAudio(int32_t chatId, const InputFile::Ptr& audio, int32_t duration, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("audio", audio->data, true, audio->mimeType));
- if (duration) {
- args.push_back(HttpReqArg("duration", duration));
- }
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendAudio", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("audio", audio->data, true, audio->mimeType));
+ if (duration) {
+ args.push_back(HttpReqArg("duration", duration));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendAudio", args));
}
Message::Ptr Api::sendAudio(int32_t chatId, const string& audio, int32_t duration, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("audio", audio));
- if (duration) {
- args.push_back(HttpReqArg("duration", duration));
- }
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendAudio", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("audio", audio));
+ if (duration) {
+ args.push_back(HttpReqArg("duration", duration));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendAudio", args));
}
Message::Ptr Api::sendDocument(int32_t chatId, const InputFile::Ptr& document, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("document", document->data, true, document->mimeType));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendDocument", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("document", document->data, true, document->mimeType));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendDocument", args));
}
Message::Ptr Api::sendDocument(int32_t chatId, const string& document, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("document", document));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendDocument", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("document", document));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendDocument", args));
}
Message::Ptr Api::sendSticker(int32_t chatId, const InputFile::Ptr& sticker, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("sticker", sticker->data, true, sticker->mimeType));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendSticker", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("sticker", sticker->data, true, sticker->mimeType));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendSticker", args));
}
Message::Ptr Api::sendSticker(int32_t chatId, const string& sticker, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("sticker", sticker));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendSticker", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("sticker", sticker));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendSticker", args));
}
Message::Ptr Api::sendVideo(int32_t chatId, const InputFile::Ptr& video, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("video", video->data, true, video->mimeType));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendVideo", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("video", video->data, true, video->mimeType));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendVideo", args));
}
Message::Ptr Api::sendVideo(int32_t chatId, const string& video, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("video", video));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendVideo", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("video", video));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendVideo", args));
}
Message::Ptr Api::sendLocation(int32_t chatId, float latitude, float longitude, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("latitude", latitude));
- args.push_back(HttpReqArg("longitude", longitude));
- if (replyToMessageId) {
- args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
- }
- if (replyMarkup) {
- args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
- }
- return TgTypeParser::getInstance().parseMessage(sendRequest("sendLocation", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("latitude", latitude));
+ args.push_back(HttpReqArg("longitude", longitude));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetMessage(sendRequest("sendLocation", args));
}
void Api::sendChatAction(int32_t chatId, const string& action) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("chat_id", chatId));
- args.push_back(HttpReqArg("action", action));
- sendRequest("sendChatAction", args);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("action", action));
+ sendRequest("sendChatAction", args);
}
UserProfilePhotos::Ptr Api::getUserProfilePhotos(int32_t userId, int32_t offset, int32_t limit) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("user_id", userId));
- if (offset) {
- args.push_back(HttpReqArg("offset", offset));
- }
- limit = max(1, min(100, limit));
- args.push_back(HttpReqArg("limit", limit));
- return TgTypeParser::getInstance().parseUserProfilePhotos(sendRequest("getUserProfilePhotos", args).find("result")->second);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("user_id", userId));
+ if (offset) {
+ args.push_back(HttpReqArg("offset", offset));
+ }
+ limit = max(1, min(100, limit));
+ args.push_back(HttpReqArg("limit", limit));
+ return TgTypeParser::getInstance().parseJsonAndGetUserProfilePhotos(sendRequest("getUserProfilePhotos", args));
}
vector<Update::Ptr> Api::getUpdates(int32_t offset, int32_t limit, int32_t timeout) const {
- vector<HttpReqArg> args;
- if (offset) {
- args.push_back(HttpReqArg("offset", offset));
- }
- limit = max(1, min(100, limit));
- args.push_back(HttpReqArg("limit", limit));
- if (timeout) {
- args.push_back(HttpReqArg("timeout", timeout));
- }
- return TgTypeParser::getInstance().parseArray<Update>(TgTypeParser::getInstance().parseUpdate, sendRequest("getUpdates", args), "result");
+ vector<HttpReqArg> args;
+ if (offset) {
+ args.push_back(HttpReqArg("offset", offset));
+ }
+ limit = max(1, min(100, limit));
+ args.push_back(HttpReqArg("limit", limit));
+ if (timeout) {
+ args.push_back(HttpReqArg("timeout", timeout));
+ }
+ return TgTypeParser::getInstance().parseJsonAndGetArray<Update>(&TgTypeParser::parseJsonAndGetUpdate, sendRequest("getUpdates", args), "result");
}
void Api::setWebhook(const string& url) const {
- vector<HttpReqArg> args;
- args.push_back(HttpReqArg("url", url));
- sendRequest("setWebhook", args);
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("url", url));
+ sendRequest("setWebhook", args);
}
-boost::property_tree::ptree Api::sendRequest(const std::string& method, const std::vector<HttpReqArg>& args) const {
- std::string url = "https://api.telegram.org/bot";
- url += _token;
- url += "/";
+ptree Api::sendRequest(const string& method, const vector<HttpReqArg>& args) const {
+ string url = "https://api.telegram.org/bot";
+ url += _token;
+ url += "/";
url += method;
string serverResponse = HttpClient::getInstance().makeRequest(url, args);
if (serverResponse.find("<html>") != serverResponse.npos) {
@@ -267,7 +267,7 @@ boost::property_tree::ptree Api::sendRequest(const std::string& method, const st
ptree result = TgTypeParser::getInstance().parseJson(serverResponse);
try {
if (result.get<bool>("ok")) {
- return result;
+ return result.find("result")->second;
} else {
throw TgException(result.get("description", ""));
}
diff --git a/src/TgTypeParser.cpp b/src/TgTypeParser.cpp
index 9a1f93a..81d2119 100644
--- a/src/TgTypeParser.cpp
+++ b/src/TgTypeParser.cpp
@@ -28,463 +28,463 @@ using namespace boost::property_tree;
namespace TgBot {
TgTypeParser& TgTypeParser::getInstance() {
- static TgTypeParser result;
- return result;
+ static TgTypeParser result;
+ return result;
}
-User::Ptr TgTypeParser::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;
+User::Ptr TgTypeParser::parseJsonAndGetUser(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 TgTypeParser::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 TgTypeParser::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;
+ 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 TgTypeParser::parseJsonAndGetGroupChat(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 TgTypeParser::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 TgTypeParser::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);
- result->caption = data.get("caption", false);
- return result;
+ 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 TgTypeParser::parseJsonAndGetMessage(const ptree& data) const {
+ Message::Ptr result(new Message);
+ result->messageId = data.get<int32_t>("message_id");
+ result->from = parseJsonAndGetUser(data.find("from")->second);
+ result->date = data.get<int32_t>("date");
+ result->chat = parseJsonAndGetGenericChat(data.find("chat")->second);
+ result->forwardFrom = tryParseJson<User>(&TgTypeParser::parseJsonAndGetUser, data, "forward_from");
+ result->forwardDate = data.get("forward_date", 0);
+ result->replyToMessage = tryParseJson<Message>(&TgTypeParser::parseJsonAndGetMessage, data, "reply_to_message");
+ result->text = data.get("text", "");
+ result->audio = tryParseJson<Audio>(&TgTypeParser::parseJsonAndGetAudio, data, "audio");
+ result->document = tryParseJson<Document>(&TgTypeParser::parseJsonAndGetDocument, data, "document");
+ result->photo = parseJsonAndGetArray<PhotoSize>(&TgTypeParser::parseJsonAndGetPhotoSize, data, "photo");
+ result->sticker = tryParseJson<Sticker>(&TgTypeParser::parseJsonAndGetSticker, data, "sticker");
+ result->video = tryParseJson<Video>(&TgTypeParser::parseJsonAndGetVideo, data, "video");
+ result->contact = tryParseJson<Contact>(&TgTypeParser::parseJsonAndGetContact, data, "contact");
+ result->location = tryParseJson<Location>(&TgTypeParser::parseJsonAndGetLocation, data, "location");
+ result->newChatParticipant = tryParseJson<User>(&TgTypeParser::parseJsonAndGetUser, data, "new_chat_participant");
+ result->leftChatParticipant = tryParseJson<User>(&TgTypeParser::parseJsonAndGetUser, data, "left_chat_participant");
+ result->newChatTitle = data.get("new_chat_title", "");
+ result->newChatPhoto = parseJsonAndGetArray<PhotoSize>(&TgTypeParser::parseJsonAndGetPhotoSize, data, "new_chat_photo");
+ result->deleteChatPhoto = data.get("delete_chat_photo", false);
+ result->groupChatCreated = data.get("group_chat_created", false);
+ result->caption = data.get("caption", false);
+ return result;
}
string TgTypeParser::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);
- appendToJson(result, "caption", object->caption);
- result.erase(result.length() - 1);
- result += '}';
- return result;
-}
-
-PhotoSize::Ptr TgTypeParser::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;
+ 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(&TgTypeParser::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(&TgTypeParser::parsePhotoSize, object->newChatPhoto));
+ appendToJson(result, "delete_chat_photo", object->deleteChatPhoto);
+ appendToJson(result, "group_chat_created", object->groupChatCreated);
+ appendToJson(result, "caption", object->caption);
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
+}
+
+PhotoSize::Ptr TgTypeParser::parseJsonAndGetPhotoSize(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 TgTypeParser::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 TgTypeParser::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;
+ 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 TgTypeParser::parseJsonAndGetAudio(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 TgTypeParser::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 TgTypeParser::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;
+ 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 TgTypeParser::parseJsonAndGetDocument(const ptree& data) const {
+ Document::Ptr result(new Document);
+ result->fileId = data.get<string>("file_id");
+ result->thumb = parseJsonAndGetPhotoSize(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 TgTypeParser::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 TgTypeParser::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;
+ 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 TgTypeParser::parseJsonAndGetSticker(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 = parseJsonAndGetPhotoSize(data.find("thumb")->second);
+ result->fileSize = data.get("file_size", 0);
+ return result;
}
string TgTypeParser::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 TgTypeParser::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);
- return result;
+ 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 TgTypeParser::parseJsonAndGetVideo(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 = parseJsonAndGetPhotoSize(data.find("thumb")->second);
+ result->mimeType = data.get("mime_type", "");
+ result->fileSize = data.get("file_size", 0);
+ return result;
}
string TgTypeParser::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);
- result.erase(result.length() - 1);
- result += '}';
- return result;
-}
-
-Contact::Ptr TgTypeParser::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;
+ 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);
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
+}
+
+Contact::Ptr TgTypeParser::parseJsonAndGetContact(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 TgTypeParser::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 TgTypeParser::parseLocation(const ptree& data) const {
- Location::Ptr result(new Location);
- result->longitude = data.get<float>("longitude");
- result->latitude = data.get<float>("latitude");
- return result;
+ 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 TgTypeParser::parseJsonAndGetLocation(const ptree& data) const {
+ Location::Ptr result(new Location);
+ result->longitude = data.get<float>("longitude");
+ result->latitude = data.get<float>("latitude");
+ return result;
}
string TgTypeParser::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;
+ 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 TgTypeParser::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;
+Update::Ptr TgTypeParser::parseJsonAndGetUpdate(const ptree& data) const {
+ Update::Ptr result(new Update);
+ result->updateId = data.get<int32_t>("update_id");
+ result->message = parseJsonAndGetMessage(data.find("message")->second);
+ return result;
}
string TgTypeParser::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;
+ 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 TgTypeParser::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;
+UserProfilePhotos::Ptr TgTypeParser::parseJsonAndGetUserProfilePhotos(const ptree& data) const {
+ UserProfilePhotos::Ptr result(new UserProfilePhotos);
+ result->totalCount = data.get<int32_t>("total_count");
+ result->photos = parseJsonAndGet2DArray<PhotoSize>(&TgTypeParser::parseJsonAndGetPhotoSize, data, "photos");
+ return result;
}
string TgTypeParser::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 TgTypeParser::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;
+ if (!object) {
+ return "";
+ }
+ string result;
+ result += '{';
+ appendToJson(result, "total_count", object->totalCount);
+ appendToJson(result, "photos", parse2DArray(&TgTypeParser::parsePhotoSize, object->photos));
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
+}
+
+ReplyKeyboardMarkup::Ptr TgTypeParser::parseJsonAndGetReplyKeyboardMarkup(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 TgTypeParser::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 TgTypeParser::parseReplyKeyboardHide(const boost::property_tree::ptree& data) const {
- ReplyKeyboardHide::Ptr result(new ReplyKeyboardHide);
- result->selective = data.get<bool>("selective");
- return result;
+ 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 TgTypeParser::parseJsonAndGetReplyKeyboardHide(const boost::property_tree::ptree& data) const {
+ ReplyKeyboardHide::Ptr result(new ReplyKeyboardHide);
+ result->selective = data.get<bool>("selective");
+ return result;
}
std::string TgTypeParser::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;
+ if (!object) {
+ return "";
+ }
+ string result;
+ result += '{';
+ appendToJson(result, "selective", object->selective);
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
}
-ForceReply::Ptr TgTypeParser::parseForceReply(const boost::property_tree::ptree& data) const {
- ForceReply::Ptr result(new ForceReply);
- result->selective = data.get<bool>("selective");
- return result;
+ForceReply::Ptr TgTypeParser::parseJsonAndGetForceReply(const boost::property_tree::ptree& data) const {
+ ForceReply::Ptr result(new ForceReply);
+ result->selective = data.get<bool>("selective");
+ return result;
}
std::string TgTypeParser::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;
+ if (!object) {
+ return "";
+ }
+ string result;
+ result += '{';
+ appendToJson(result, "selective", object->selective);
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
}
-GenericChat::Ptr TgTypeParser::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));
- }
+GenericChat::Ptr TgTypeParser::parseJsonAndGetGenericChat(const ptree& data) const {
+ if (data.find("first_name") == data.not_found()) {
+ return static_pointer_cast<GenericChat>(parseJsonAndGetGroupChat(data));
+ } else {
+ return static_pointer_cast<GenericChat>(parseJsonAndGetUser(data));
+ }
}
string TgTypeParser::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 TgTypeParser::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));
- }
+ 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 TgTypeParser::parseJsonAndGetGenericReply(const boost::property_tree::ptree& data) const {
+ if (data.find("force_reply") != data.not_found()) {
+ return static_pointer_cast<GenericReply>(parseJsonAndGetForceReply(data));
+ } else if (data.find("hide_keyboard") != data.not_found()) {
+ return static_pointer_cast<GenericReply>(parseJsonAndGetReplyKeyboardHide(data));
+ } else {
+ return static_pointer_cast<GenericReply>(parseJsonAndGetReplyKeyboardMarkup(data));
+ }
}
std::string TgTypeParser::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));
- }
+ 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 TgTypeParser::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
+ if (value.empty()) {
+ return;
+ }
+ json += '"';
+ json += varName;
+ json += "\":";
+ if (value.front() != '{') {
+ json += '"';
+ }
+ json += value;
+ if (value.back() != '}') {
+ json += '"';
+ }
+ json += ',';
+}
+
+}
diff --git a/src/net/HttpClient.cpp b/src/net/HttpClient.cpp
index 5027b09..b9813ad 100644
--- a/src/net/HttpClient.cpp
+++ b/src/net/HttpClient.cpp
@@ -32,36 +32,36 @@ using namespace boost::asio::local;
namespace TgBot {
HttpClient& HttpClient::getInstance() {
- static HttpClient result;
- return result;
+ static HttpClient result;
+ return result;
}
string HttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) {
- ssl::context context(ssl::context::sslv23);
- context.set_default_verify_paths();
+ 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);
+ 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));
+ 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);
+ 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 = HttpParser::getInstance().generateRequest(url, args, false);
- write(socket, buffer(requestText.c_str(), requestText.length()));
+ string requestText = HttpParser::getInstance().generateRequest(url, args, false);
+ write(socket, buffer(requestText.c_str(), requestText.length()));
- string response;
- char buff[1024];
- boost::system::error_code error;
- while (!error) {
- size_t bytes = read(socket, buffer(buff), error);
- response += string(buff, bytes);
- }
+ string response;
+ char buff[1024];
+ boost::system::error_code error;
+ while (!error) {
+ size_t bytes = read(socket, buffer(buff), error);
+ response += string(buff, bytes);
+ }
- return HttpParser::getInstance().parseResponse(response);
+ return HttpParser::getInstance().parseResponse(response);
}
}
diff --git a/src/net/HttpParser.cpp b/src/net/HttpParser.cpp
index ae9de62..a2d9108 100644
--- a/src/net/HttpParser.cpp
+++ b/src/net/HttpParser.cpp
@@ -32,173 +32,173 @@ using namespace boost;
namespace TgBot {
HttpParser& HttpParser::getInstance() {
- static HttpParser result;
- return result;
+ static HttpParser result;
+ return result;
}
string HttpParser::generateRequest(const Url& url, const vector<HttpReqArg>& args, bool isKeepAlive) {
- string result;
- if (args.empty()) {
- result += "GET ";
- } else {
- result += "POST ";
- }
- result += url.path;
- result += url.query.empty() ? "" : "?" + url.query;
- result += " HTTP/1.1\r\n";
- result += "Host: ";
- result += url.host;
- result += "\r\nConnection: ";
- if (isKeepAlive) {
- result += "keep-alive";
- } else {
- result += "close";
- }
- result += "\r\n";
- if (args.empty()) {
- result += "\r\n";
- } else {
- string requestData;
-
- string bondary = generateMultipartBoundary(args);
- if (bondary.empty()) {
- result += "Content-Type: application/x-www-form-urlencoded\r\n";
- requestData = generateWwwFormUrlencoded(args);
- } else {
- result += "Content-Type: multipart/form-data; boundary=";
- result += bondary;
- result += "\r\n";
- requestData = generateMultipartFormData(args, bondary);
- }
-
- result += "Content-Length: ";
- result += lexical_cast<string>(requestData.length());
- result += "\r\n\r\n";
- result += requestData;
- }
- return result;
+ string result;
+ if (args.empty()) {
+ result += "GET ";
+ } else {
+ result += "POST ";
+ }
+ result += url.path;
+ result += url.query.empty() ? "" : "?" + url.query;
+ result += " HTTP/1.1\r\n";
+ result += "Host: ";
+ result += url.host;
+ result += "\r\nConnection: ";
+ if (isKeepAlive) {
+ result += "keep-alive";
+ } else {
+ result += "close";
+ }
+ result += "\r\n";
+ if (args.empty()) {
+ result += "\r\n";
+ } else {
+ string requestData;
+
+ string bondary = generateMultipartBoundary(args);
+ if (bondary.empty()) {
+ result += "Content-Type: application/x-www-form-urlencoded\r\n";
+ requestData = generateWwwFormUrlencoded(args);
+ } else {
+ result += "Content-Type: multipart/form-data; boundary=";
+ result += bondary;
+ result += "\r\n";
+ requestData = generateMultipartFormData(args, bondary);
+ }
+
+ result += "Content-Length: ";
+ result += lexical_cast<string>(requestData.length());
+ result += "\r\n\r\n";
+ result += requestData;
+ }
+ return result;
}
string HttpParser::generateMultipartFormData(const vector<HttpReqArg>& args, const string& bondary) {
- string result;
- for (const HttpReqArg& item : args) {
- result += "--";
- result += bondary;
- result += "\r\nContent-Disposition: form-data; name=\"";
- result += item.name;
- result += "\"\r\n";
- if (item.isFile) {
- result += "Content-Type: ";
- result += item.mimeType;
- result += "\r\n";
- }
- result += "\r\n";
- result += item.value;
- result += "\r\n";
- }
- return result;
+ string result;
+ for (const HttpReqArg& item : args) {
+ result += "--";
+ result += bondary;
+ result += "\r\nContent-Disposition: form-data; name=\"";
+ result += item.name;
+ result += "\"\r\n";
+ if (item.isFile) {
+ result += "Content-Type: ";
+ result += item.mimeType;
+ result += "\r\n";
+ }
+ result += "\r\n";
+ result += item.value;
+ result += "\r\n";
+ }
+ return result;
}
string HttpParser::generateMultipartBoundary(const vector<HttpReqArg>& args) {
- string result;
- srand((unsigned int) time(nullptr));
- for (const HttpReqArg& item : args) {
- if (item.isFile) {
- while (result.empty() || item.value.find(result) != item.value.npos) {
- result += StringTools::generateRandomString(4);
- }
- }
- }
- return result;
+ string result;
+ srand((unsigned int) time(nullptr));
+ for (const HttpReqArg& item : args) {
+ if (item.isFile) {
+ while (result.empty() || item.value.find(result) != item.value.npos) {
+ result += StringTools::generateRandomString(4);
+ }
+ }
+ }
+ return result;
}
string HttpParser::generateWwwFormUrlencoded(const vector<HttpReqArg>& args) {
- string result;
-
- bool firstRun = true;
- for (const HttpReqArg& item : args) {
- if (firstRun) {
- firstRun = false;
- } else {
- result += '&';
- }
- result += StringTools::urlEncode(item.name);
- result += '=';
- result += StringTools::urlEncode(item.value);
- }
-
- return result;
+ string result;
+
+ bool firstRun = true;
+ for (const HttpReqArg& item : args) {
+ if (firstRun) {
+ firstRun = false;
+ } else {
+ result += '&';
+ }
+ result += StringTools::urlEncode(item.name);
+ result += '=';
+ result += StringTools::urlEncode(item.value);
+ }
+
+ return result;
}
string HttpParser::generateResponse(const string& data, const string& mimeType, unsigned short statusCode, const string& statusStr, bool isKeepAlive) {
- string result;
- result += "HTTP/1.1 ";
- result += lexical_cast<string>(statusCode);
- result += ' ';
- result += statusStr;
- result += "\r\nContent-Type: ";
- result += mimeType;
- result += "\r\nContent-Length: ";
- result += lexical_cast<string>(data.length());
- result += "\r\n\r\n";
- result += data;
- return result;
+ string result;
+ result += "HTTP/1.1 ";
+ result += lexical_cast<string>(statusCode);
+ result += ' ';
+ result += statusStr;
+ result += "\r\nContent-Type: ";
+ result += mimeType;
+ result += "\r\nContent-Length: ";
+ result += lexical_cast<string>(data.length());
+ result += "\r\n\r\n";
+ result += data;
+ return result;
}
string HttpParser::parseHttp(bool isRequest, const string& data, map<string, string>& headers) {
- bool onlyNewLineChar = false;
- size_t headerEnd = data.find("\r\n\r\n");
- if (headerEnd == data.npos) {
- headerEnd = data.find("\n\n");
- if (headerEnd != data.npos) {
- onlyNewLineChar = true;
- headerEnd += 2;
- }
- } else {
- headerEnd += 4;
- }
-
- size_t lineStart = 0;
- size_t lineEnd = 0;
- size_t lineSepPos = 0;
- size_t lastLineEnd = data.npos;
- while (lastLineEnd != lineEnd) {
- lastLineEnd = lineEnd;
- if (lineEnd == 0) {
- if (isRequest) {
- lineSepPos = data.find(' ');
- lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
- headers["method"] = data.substr(0, lineSepPos);
- headers["path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
- } else {
- lineSepPos = data.find(' ');
- lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
- headers["status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
- }
- } else {
- lineStart = lineEnd;
- lineStart += onlyNewLineChar ? 1 : 2;
- lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n", lineStart);
- lineSepPos = data.find(':', lineStart);
- if (lineEnd >= headerEnd || lastLineEnd == lineEnd || lineSepPos >= headerEnd) {
- break;
- }
- headers[to_lower_copy(data.substr(lineStart, lineSepPos - lineStart))] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
- }
- }
-
- return headerEnd == data.npos ? "" : data.substr(headerEnd);
+ bool onlyNewLineChar = false;
+ size_t headerEnd = data.find("\r\n\r\n");
+ if (headerEnd == data.npos) {
+ headerEnd = data.find("\n\n");
+ if (headerEnd != data.npos) {
+ onlyNewLineChar = true;
+ headerEnd += 2;
+ }
+ } else {
+ headerEnd += 4;
+ }
+
+ size_t lineStart = 0;
+ size_t lineEnd = 0;
+ size_t lineSepPos = 0;
+ size_t lastLineEnd = data.npos;
+ while (lastLineEnd != lineEnd) {
+ lastLineEnd = lineEnd;
+ if (lineEnd == 0) {
+ if (isRequest) {
+ lineSepPos = data.find(' ');
+ lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
+ headers["method"] = data.substr(0, lineSepPos);
+ headers["path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
+ } else {
+ lineSepPos = data.find(' ');
+ lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
+ headers["status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
+ }
+ } else {
+ lineStart = lineEnd;
+ lineStart += onlyNewLineChar ? 1 : 2;
+ lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n", lineStart);
+ lineSepPos = data.find(':', lineStart);
+ if (lineEnd >= headerEnd || lastLineEnd == lineEnd || lineSepPos >= headerEnd) {
+ break;
+ }
+ headers[to_lower_copy(data.substr(lineStart, lineSepPos - lineStart))] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
+ }
+ }
+
+ return headerEnd == data.npos ? "" : data.substr(headerEnd);
}
string HttpParser::parseHttp(bool isRequest, const string& data) {
- size_t headerEnd = data.find("\r\n\r\n");
- if (headerEnd == data.npos) {
- headerEnd = data.find("\n\n");
- }
- if (headerEnd == data.npos) {
- headerEnd = 0;
- }
- return data.substr(headerEnd);
+ size_t headerEnd = data.find("\r\n\r\n");
+ if (headerEnd == data.npos) {
+ headerEnd = data.find("\n\n");
+ }
+ if (headerEnd == data.npos) {
+ headerEnd = 0;
+ }
+ return data.substr(headerEnd);
}
}
diff --git a/src/net/TgLongPoll.cpp b/src/net/TgLongPoll.cpp
index f420e92..91bf058 100644
--- a/src/net/TgLongPoll.cpp
+++ b/src/net/TgLongPoll.cpp
@@ -31,13 +31,13 @@ TgLongPoll::TgLongPoll(const Bot& bot) : TgLongPoll(&bot.getApi(), &bot.getEvent
}
void TgLongPoll::start() {
- std::vector<Update::Ptr> updates = _api->getUpdates(_lastUpdateId, 100, 60);
- for (Update::Ptr& item : updates) {
- if (item->updateId >= _lastUpdateId) {
- _lastUpdateId = item->updateId + 1;
- }
- _eventHandler->handleUpdate(item);
- }
+ std::vector<Update::Ptr> updates = _api->getUpdates(_lastUpdateId, 100, 60);
+ for (Update::Ptr& item : updates) {
+ if (item->updateId >= _lastUpdateId) {
+ _lastUpdateId = item->updateId + 1;
+ }
+ _eventHandler->handleUpdate(item);
+ }
}
}
diff --git a/src/net/Url.cpp b/src/net/Url.cpp
index c773f3b..44d9089 100644
--- a/src/net/Url.cpp
+++ b/src/net/Url.cpp
@@ -29,52 +29,52 @@ using namespace std;
namespace TgBot {
Url::Url(const string& url) {
- bool isProtocolParsed = false;
- bool isHostParsed = false;
- bool isPathParsed = false;
- bool isQueryParsed = false;
+ bool isProtocolParsed = false;
+ bool isHostParsed = false;
+ bool isPathParsed = false;
+ bool isQueryParsed = false;
- for (size_t i = 0, count = url.length(); i < count; ++i) {
- char c = url[i];
+ 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 += '/';
- } else if (c == '?') {
- isHostParsed = isPathParsed = true;
- path += '/';
- } else if (c == '#') {
- isHostParsed = isPathParsed = isQueryParsed = true;
- path += '/';
- } else {
- host += c;
- }
- } else if (!isPathParsed) {
- if (c == '?') {
- isPathParsed = true;
- } else if (c == '#') {
- isPathParsed = isQueryParsed = true;
- } else {
- path += c;
- }
- } else if (!isQueryParsed) {
- if (c == '#') {
- isQueryParsed = true;
- } else {
- query += c;
- }
- } else {
- fragment += c;
- }
- }
+ if (!isProtocolParsed) {
+ if (c == ':') {
+ isProtocolParsed = true;
+ i += 2;
+ } else {
+ protocol += c;
+ }
+ } else if (!isHostParsed) {
+ if (c == '/') {
+ isHostParsed = true;
+ path += '/';
+ } else if (c == '?') {
+ isHostParsed = isPathParsed = true;
+ path += '/';
+ } else if (c == '#') {
+ isHostParsed = isPathParsed = isQueryParsed = true;
+ path += '/';
+ } else {
+ host += c;
+ }
+ } else if (!isPathParsed) {
+ if (c == '?') {
+ isPathParsed = true;
+ } else if (c == '#') {
+ isPathParsed = isQueryParsed = true;
+ } else {
+ path += c;
+ }
+ } else if (!isQueryParsed) {
+ if (c == '#') {
+ isQueryParsed = true;
+ } else {
+ query += c;
+ }
+ } else {
+ fragment += c;
+ }
+ }
host = StringTools::urlEncode(host, ".");
path = StringTools::urlEncode(path, "/");
diff --git a/src/tools/Api.cpp b/src/tools/Api.cpp
new file mode 100644
index 0000000..0bd970c
--- /dev/null
+++ b/src/tools/Api.cpp
@@ -0,0 +1,279 @@
+/*
+ * 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 "tgbot/Api.h"
+
+#include "tgbot/TgTypeParser.h"
+#include "tgbot/TgException.h"
+#include "tgbot/net/HttpClient.h"
+
+using namespace std;
+using namespace boost::property_tree;
+
+namespace TgBot {
+
+Api::Api(const std::string& token) : _token(token) {
+}
+
+User::Ptr Api::getMe() const {
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("text", text));
+ if (disableWebPagePreview) {
+ args.push_back(HttpReqArg("disable_web_page_preview", disableWebPagePreview));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseMessage(sendRequest("sendMessage", args).find("result")->second);
+}
+
+Message::Ptr Api::forwardMessage(int32_t chatId, int32_t fromChatId, int32_t messageId) const {
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("from_chat_id", fromChatId));
+ args.push_back(HttpReqArg("message_id", messageId));
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("photo", photo->data, true, photo->mimeType));
+ if (!caption.empty()) {
+ args.push_back(HttpReqArg("caption", caption));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("photo", photo));
+ if (!caption.empty()) {
+ args.push_back(HttpReqArg("caption", caption));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseMessage(sendRequest("sendPhoto", args).find("result")->second);
+}
+
+Message::Ptr Api::sendAudio(int32_t chatId, const InputFile::Ptr& audio, int32_t duration, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("audio", audio->data, true, audio->mimeType));
+ if (duration) {
+ args.push_back(HttpReqArg("duration", duration));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseMessage(sendRequest("sendAudio", args).find("result")->second);
+}
+
+Message::Ptr Api::sendAudio(int32_t chatId, const string& audio, int32_t duration, int32_t replyToMessageId, const GenericReply::Ptr& replyMarkup) const {
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("audio", audio));
+ if (duration) {
+ args.push_back(HttpReqArg("duration", duration));
+ }
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("document", document->data, true, document->mimeType));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("document", document));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("sticker", sticker->data, true, sticker->mimeType));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("sticker", sticker));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("video", video->data, true, video->mimeType));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("video", video));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().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<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("latitude", latitude));
+ args.push_back(HttpReqArg("longitude", longitude));
+ if (replyToMessageId) {
+ args.push_back(HttpReqArg("reply_to_message_id", replyToMessageId));
+ }
+ if (replyMarkup) {
+ args.push_back(HttpReqArg("reply_markup", TgTypeParser::getInstance().parseGenericReply(replyMarkup)));
+ }
+ return TgTypeParser::getInstance().parseMessage(sendRequest("sendLocation", args).find("result")->second);
+}
+
+void Api::sendChatAction(int32_t chatId, const string& action) const {
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("chat_id", chatId));
+ args.push_back(HttpReqArg("action", action));
+ sendRequest("sendChatAction", args);
+}
+
+UserProfilePhotos::Ptr Api::getUserProfilePhotos(int32_t userId, int32_t offset, int32_t limit) const {
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("user_id", userId));
+ if (offset) {
+ args.push_back(HttpReqArg("offset", offset));
+ }
+ limit = max(1, min(100, limit));
+ args.push_back(HttpReqArg("limit", limit));
+ return TgTypeParser::getInstance().parseUserProfilePhotos(sendRequest("getUserProfilePhotos", args).find("result")->second);
+}
+
+vector<Update::Ptr> Api::getUpdates(int32_t offset, int32_t limit, int32_t timeout) const {
+ vector<HttpReqArg> args;
+ if (offset) {
+ args.push_back(HttpReqArg("offset", offset));
+ }
+ limit = max(1, min(100, limit));
+ args.push_back(HttpReqArg("limit", limit));
+ if (timeout) {
+ args.push_back(HttpReqArg("timeout", timeout));
+ }
+ return TgTypeParser::getInstance().parseArray<Update>(TgTypeParser::getInstance().parseUpdate, sendRequest("getUpdates", args), "result");
+}
+
+void Api::setWebhook(const string& url) const {
+ vector<HttpReqArg> args;
+ args.push_back(HttpReqArg("url", url));
+ sendRequest("setWebhook", args);
+}
+
+boost::property_tree::ptree Api::sendRequest(const std::string& method, const std::vector<HttpReqArg>& args) const {
+ std::string url = "https://api.telegram.org/bot";
+ url += _token;
+ url += "/";
+ url += method;
+ string serverResponse = HttpClient::getInstance().makeRequest(url, args);
+ if (serverResponse.find("<html>") != serverResponse.npos) {
+ throw TgException("Bad request");
+ }
+ ptree result = TgTypeParser::getInstance().parseJson(serverResponse);
+ try {
+ if (result.get<bool>("ok")) {
+ return result;
+ } else {
+ throw TgException(result.get("description", ""));
+ }
+ } catch (boost::property_tree::ptree_error& e) {
+ throw TgException("");
+ }
+}
+
+}
diff --git a/src/tools/StringTools.cpp b/src/tools/StringTools.cpp
index deb8fa1..0a6dbc3 100644
--- a/src/tools/StringTools.cpp
+++ b/src/tools/StringTools.cpp
@@ -35,17 +35,17 @@ bool startsWith(const string& str1, const string& str2) {
return false;
}
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;
+ 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) {
@@ -53,67 +53,67 @@ bool endsWith(const string& str1, const string& str2) {
return false;
}
string::const_iterator it1(str1.end());
- string::const_iterator begin1(str1.begin());
- string::const_iterator it2(str2.end());
- string::const_iterator begin2(str2.begin());
- while (it1 != begin1 && it2 != begin2) {
- if (*it1 != *it2) {
- return false;
- }
- --it1;
- --it2;
- }
- return true;
+ string::const_iterator begin1(str1.begin());
+ string::const_iterator it2(str2.end());
+ string::const_iterator begin2(str2.begin());
+ while (it1 != begin1 && it2 != begin2) {
+ 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);
- }
+ 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;
+ 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, const std::string additionalLegitChars) {
- static const string legitPunctuation = "-_.~";
- ostringstream result;
- result.fill('0');
- result << hex;
- for (const char& c : value) {
- if (isalnum(c) || legitPunctuation.find(c) != legitPunctuation.npos || additionalLegitChars.find(c) != additionalLegitChars.npos) {
- result << c;
- } else {
- result << '%' << setw(2) << int((unsigned char) c);
- }
- }
+ static const string legitPunctuation = "-_.~";
+ ostringstream result;
+ result.fill('0');
+ result << hex;
+ for (const char& c : value) {
+ if (isalnum(c) || legitPunctuation.find(c) != legitPunctuation.npos || additionalLegitChars.find(c) != additionalLegitChars.npos) {
+ result << c;
+ } else {
+ result << '%' << setw(2) << int((unsigned char) c);
+ }
+ }
- return result.str();
+ return result.str();
}
string urlDecode(const string& value) {
- string result;
- for (size_t i = 0, count = value.length(); i < count; ++i) {
- const char c = value[i];
- if (c == '%') {
- int t = 0;
- sscanf(value.substr(i + 1, 2).c_str(), "%x", &t);
- result += (char) t;
- i += 2;
- } else {
- result += c;
- }
- }
- return result;
+ string result;
+ for (size_t i = 0, count = value.length(); i < count; ++i) {
+ const char c = value[i];
+ if (c == '%') {
+ int t = 0;
+ sscanf(value.substr(i + 1, 2).c_str(), "%x", &t);
+ result += (char) t;
+ i += 2;
+ } else {
+ result += c;
+ }
+ }
+ return result;
}
}
diff --git a/src/tools/TgException.cpp b/src/tools/TgException.cpp
new file mode 100644
index 0000000..0c118ec
--- /dev/null
+++ b/src/tools/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 "tgbot/TgException.h"
+
+namespace TgBot {
+
+TgBot::TgException::TgException(const std::string description) : runtime_error(description) {
+}
+
+}
diff --git a/src/tools/TgTypeParser.cpp b/src/tools/TgTypeParser.cpp
new file mode 100644
index 0000000..a9c6812
--- /dev/null
+++ b/src/tools/TgTypeParser.cpp
@@ -0,0 +1,490 @@
+/*
+ * 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 "tgbot/TgTypeParser.h"
+
+using namespace std;
+using namespace boost::property_tree;
+
+namespace TgBot {
+
+TgTypeParser& TgTypeParser::getInstance() {
+ static TgTypeParser result;
+ return result;
+}
+
+User::Ptr TgTypeParser::parseJsonAndGetUser(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetGroupChat(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetMessage(const ptree& data) const {
+ Message::Ptr result(new Message);
+ result->messageId = data.get<int32_t>("message_id");
+ result->from = parseJsonAndGetUser(data.find("from")->second);
+ result->date = data.get<int32_t>("date");
+ result->chat = parseJsonAndGetGenericChat(data.find("chat")->second);
+ result->forwardFrom = tryParseJson<User>(&TgTypeParser::parseJsonAndGetUser, data, "forward_from");
+ result->forwardDate = data.get("forward_date", 0);
+ result->replyToMessage = tryParseJson<Message>(parseJsonAndGetMessage, data, "reply_to_message");
+ result->text = data.get("text", "");
+ result->audio = tryParseJson<Audio>(parseJsonAndGetAudio, data, "audio");
+ result->document = tryParseJson<Document>(parseJsonAndGetDocument, data, "document");
+ result->photo = parseArray<PhotoSize>(parseJsonAndGetPhotoSize, data, "photo");
+ result->sticker = tryParseJson<Sticker>(parseJsonAndGetSticker, data, "sticker");
+ result->video = tryParseJson<Video>(parseJsonAndGetVideo, data, "video");
+ result->contact = tryParseJson<Contact>(parseJsonAndGetContact, data, "contact");
+ result->location = tryParseJson<Location>(parseJsonAndGetLocation, data, "location");
+ result->newChatParticipant = tryParseJson<User>(parseJsonAndGetUser, data, "new_chat_participant");
+ result->leftChatParticipant = tryParseJson<User>(parseJsonAndGetUser, data, "left_chat_participant");
+ result->newChatTitle = data.get("new_chat_title", "");
+ result->newChatPhoto = parseJsonAndGetArray<PhotoSize>(parseJsonAndGetPhotoSize, data, "new_chat_photo");
+ result->deleteChatPhoto = data.get("delete_chat_photo", false);
+ result->groupChatCreated = data.get("group_chat_created", false);
+ result->caption = data.get("caption", false);
+ return result;
+}
+
+string TgTypeParser::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);
+ appendToJson(result, "caption", object->caption);
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
+}
+
+PhotoSize::Ptr TgTypeParser::parseJsonAndGetPhotoSize(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetAudio(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetDocument(const ptree& data) const {
+ Document::Ptr result(new Document);
+ result->fileId = data.get<string>("file_id");
+ result->thumb = parseJsonAndGetPhotoSize(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetSticker(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 = parseJsonAndGetPhotoSize(data.find("thumb")->second);
+ result->fileSize = data.get("file_size", 0);
+ return result;
+}
+
+string TgTypeParser::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 TgTypeParser::parseJsonAndGetVideo(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 = parseJsonAndGetPhotoSize(data.find("thumb")->second);
+ result->mimeType = data.get("mime_type", "");
+ result->fileSize = data.get("file_size", 0);
+ return result;
+}
+
+string TgTypeParser::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);
+ result.erase(result.length() - 1);
+ result += '}';
+ return result;
+}
+
+Contact::Ptr TgTypeParser::parseJsonAndGetContact(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetLocation(const ptree& data) const {
+ Location::Ptr result(new Location);
+ result->longitude = data.get<float>("longitude");
+ result->latitude = data.get<float>("latitude");
+ return result;
+}
+
+string TgTypeParser::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 TgTypeParser::parseJsonAndGetUpdate(const ptree& data) const {
+ Update::Ptr result(new Update);
+ result->updateId = data.get<int32_t>("update_id");
+ result->message = parseJsonAndGetMessage(data.find("message")->second);
+ return result;
+}
+
+string TgTypeParser::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 TgTypeParser::parseJsonAndGetUserProfilePhotos(const ptree& data) const {
+ UserProfilePhotos::Ptr result(new UserProfilePhotos);
+ result->totalCount = data.get<int32_t>("total_count");
+ result->photos = parseJsonAndGet2DArray<PhotoSize>(parseJsonAndGetPhotoSize, data, "photos");
+ return result;
+}
+
+string TgTypeParser::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 TgTypeParser::parseJsonAndGetReplyKeyboardMarkup(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 TgTypeParser::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 TgTypeParser::parseJsonAndGetReplyKeyboardHide(const boost::property_tree::ptree& data) const {
+ ReplyKeyboardHide::Ptr result(new ReplyKeyboardHide);
+ result->selective = data.get<bool>("selective");
+ return result;
+}
+
+std::string TgTypeParser::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 TgTypeParser::parseJsonAndGetForceReply(const boost::property_tree::ptree& data) const {
+ ForceReply::Ptr result(new ForceReply);
+ result->selective = data.get<bool>("selective");
+ return result;
+}
+
+std::string TgTypeParser::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 TgTypeParser::parseJsonAndGetGenericChat(const ptree& data) const {
+ if (data.find("first_name") == data.not_found()) {
+ return static_pointer_cast<GenericChat>(parseJsonAndGetGroupChat(data));
+ } else {
+ return static_pointer_cast<GenericChat>(parseJsonAndGetUser(data));
+ }
+}
+
+string TgTypeParser::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 TgTypeParser::parseJsonAndGetGenericReply(const boost::property_tree::ptree& data) const {
+ if (data.find("force_reply") != data.not_found()) {
+ return static_pointer_cast<GenericReply>(parseJsonAndGetForceReply(data));
+ } else if (data.find("hide_keyboard") != data.not_found()) {
+ return static_pointer_cast<GenericReply>(parseJsonAndGetReplyKeyboardHide(data));
+ } else {
+ return static_pointer_cast<GenericReply>(parseJsonAndGetReplyKeyboardMarkup(data));
+ }
+}
+
+std::string TgTypeParser::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 TgTypeParser::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 += ',';
+}
+
+}
diff --git a/src/tools/net/HttpClient.cpp b/src/tools/net/HttpClient.cpp
new file mode 100644
index 0000000..b9813ad
--- /dev/null
+++ b/src/tools/net/HttpClient.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 Oleg Morozenkov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "tgbot/net/HttpClient.h"
+
+#include <boost/asio/ssl.hpp>
+
+using namespace std;
+using namespace boost::asio;
+using namespace boost::asio::ip;
+using namespace boost::asio::local;
+
+namespace TgBot {
+
+HttpClient& HttpClient::getInstance() {
+ static HttpClient result;
+ return result;
+}
+
+string HttpClient::makeRequest(const Url& url, const vector<HttpReqArg>& args) {
+ 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 = HttpParser::getInstance().generateRequest(url, args, false);
+ write(socket, buffer(requestText.c_str(), requestText.length()));
+
+ string response;
+ char buff[1024];
+ boost::system::error_code error;
+ while (!error) {
+ size_t bytes = read(socket, buffer(buff), error);
+ response += string(buff, bytes);
+ }
+
+ return HttpParser::getInstance().parseResponse(response);
+}
+
+}
diff --git a/src/tools/net/HttpParser.cpp b/src/tools/net/HttpParser.cpp
new file mode 100644
index 0000000..a2d9108
--- /dev/null
+++ b/src/tools/net/HttpParser.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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 "tgbot/net/HttpParser.h"
+
+#include <boost/algorithm/string.hpp>
+
+#include "tgbot/tools/StringTools.h"
+
+using namespace std;
+using namespace boost;
+
+namespace TgBot {
+
+HttpParser& HttpParser::getInstance() {
+ static HttpParser result;
+ return result;
+}
+
+string HttpParser::generateRequest(const Url& url, const vector<HttpReqArg>& args, bool isKeepAlive) {
+ string result;
+ if (args.empty()) {
+ result += "GET ";
+ } else {
+ result += "POST ";
+ }
+ result += url.path;
+ result += url.query.empty() ? "" : "?" + url.query;
+ result += " HTTP/1.1\r\n";
+ result += "Host: ";
+ result += url.host;
+ result += "\r\nConnection: ";
+ if (isKeepAlive) {
+ result += "keep-alive";
+ } else {
+ result += "close";
+ }
+ result += "\r\n";
+ if (args.empty()) {
+ result += "\r\n";
+ } else {
+ string requestData;
+
+ string bondary = generateMultipartBoundary(args);
+ if (bondary.empty()) {
+ result += "Content-Type: application/x-www-form-urlencoded\r\n";
+ requestData = generateWwwFormUrlencoded(args);
+ } else {
+ result += "Content-Type: multipart/form-data; boundary=";
+ result += bondary;
+ result += "\r\n";
+ requestData = generateMultipartFormData(args, bondary);
+ }
+
+ result += "Content-Length: ";
+ result += lexical_cast<string>(requestData.length());
+ result += "\r\n\r\n";
+ result += requestData;
+ }
+ return result;
+}
+
+string HttpParser::generateMultipartFormData(const vector<HttpReqArg>& args, const string& bondary) {
+ string result;
+ for (const HttpReqArg& item : args) {
+ result += "--";
+ result += bondary;
+ result += "\r\nContent-Disposition: form-data; name=\"";
+ result += item.name;
+ result += "\"\r\n";
+ if (item.isFile) {
+ result += "Content-Type: ";
+ result += item.mimeType;
+ result += "\r\n";
+ }
+ result += "\r\n";
+ result += item.value;
+ result += "\r\n";
+ }
+ return result;
+}
+
+string HttpParser::generateMultipartBoundary(const vector<HttpReqArg>& args) {
+ string result;
+ srand((unsigned int) time(nullptr));
+ for (const HttpReqArg& item : args) {
+ if (item.isFile) {
+ while (result.empty() || item.value.find(result) != item.value.npos) {
+ result += StringTools::generateRandomString(4);
+ }
+ }
+ }
+ return result;
+}
+
+string HttpParser::generateWwwFormUrlencoded(const vector<HttpReqArg>& args) {
+ string result;
+
+ bool firstRun = true;
+ for (const HttpReqArg& item : args) {
+ if (firstRun) {
+ firstRun = false;
+ } else {
+ result += '&';
+ }
+ result += StringTools::urlEncode(item.name);
+ result += '=';
+ result += StringTools::urlEncode(item.value);
+ }
+
+ return result;
+}
+
+string HttpParser::generateResponse(const string& data, const string& mimeType, unsigned short statusCode, const string& statusStr, bool isKeepAlive) {
+ string result;
+ result += "HTTP/1.1 ";
+ result += lexical_cast<string>(statusCode);
+ result += ' ';
+ result += statusStr;
+ result += "\r\nContent-Type: ";
+ result += mimeType;
+ result += "\r\nContent-Length: ";
+ result += lexical_cast<string>(data.length());
+ result += "\r\n\r\n";
+ result += data;
+ return result;
+}
+
+string HttpParser::parseHttp(bool isRequest, const string& data, map<string, string>& headers) {
+ bool onlyNewLineChar = false;
+ size_t headerEnd = data.find("\r\n\r\n");
+ if (headerEnd == data.npos) {
+ headerEnd = data.find("\n\n");
+ if (headerEnd != data.npos) {
+ onlyNewLineChar = true;
+ headerEnd += 2;
+ }
+ } else {
+ headerEnd += 4;
+ }
+
+ size_t lineStart = 0;
+ size_t lineEnd = 0;
+ size_t lineSepPos = 0;
+ size_t lastLineEnd = data.npos;
+ while (lastLineEnd != lineEnd) {
+ lastLineEnd = lineEnd;
+ if (lineEnd == 0) {
+ if (isRequest) {
+ lineSepPos = data.find(' ');
+ lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
+ headers["method"] = data.substr(0, lineSepPos);
+ headers["path"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
+ } else {
+ lineSepPos = data.find(' ');
+ lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n");
+ headers["status"] = data.substr(lineSepPos + 1, data.find(' ', lineSepPos + 1) - lineSepPos - 1);
+ }
+ } else {
+ lineStart = lineEnd;
+ lineStart += onlyNewLineChar ? 1 : 2;
+ lineEnd = data.find(onlyNewLineChar ? "\n" : "\r\n", lineStart);
+ lineSepPos = data.find(':', lineStart);
+ if (lineEnd >= headerEnd || lastLineEnd == lineEnd || lineSepPos >= headerEnd) {
+ break;
+ }
+ headers[to_lower_copy(data.substr(lineStart, lineSepPos - lineStart))] = trim_copy(data.substr(lineSepPos + 1, lineEnd - lineSepPos - 1));
+ }
+ }
+
+ return headerEnd == data.npos ? "" : data.substr(headerEnd);
+}
+
+string HttpParser::parseHttp(bool isRequest, const string& data) {
+ size_t headerEnd = data.find("\r\n\r\n");
+ if (headerEnd == data.npos) {
+ headerEnd = data.find("\n\n");
+ }
+ if (headerEnd == data.npos) {
+ headerEnd = 0;
+ }
+ return data.substr(headerEnd);
+}
+
+}
diff --git a/src/tools/net/TgLongPoll.cpp b/src/tools/net/TgLongPoll.cpp
new file mode 100644
index 0000000..91bf058
--- /dev/null
+++ b/src/tools/net/TgLongPoll.cpp
@@ -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.
+ */
+
+#include "tgbot/net/TgLongPoll.h"
+
+namespace TgBot {
+
+TgLongPoll::TgLongPoll(const Api* api, const EventHandler* eventHandler) : _api(api), _eventHandler(eventHandler) {
+}
+
+TgLongPoll::TgLongPoll(const Bot& bot) : TgLongPoll(&bot.getApi(), &bot.getEventHandler()) {
+}
+
+void TgLongPoll::start() {
+ std::vector<Update::Ptr> updates = _api->getUpdates(_lastUpdateId, 100, 60);
+ for (Update::Ptr& item : updates) {
+ if (item->updateId >= _lastUpdateId) {
+ _lastUpdateId = item->updateId + 1;
+ }
+ _eventHandler->handleUpdate(item);
+ }
+}
+
+}
diff --git a/src/tools/net/Url.cpp b/src/tools/net/Url.cpp
new file mode 100644
index 0000000..44d9089
--- /dev/null
+++ b/src/tools/net/Url.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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 "tgbot/net/Url.h"
+
+#include "tgbot/tools/StringTools.h"
+
+using namespace std;
+
+namespace TgBot {
+
+Url::Url(const string& url) {
+ bool isProtocolParsed = false;
+ bool isHostParsed = false;
+ bool isPathParsed = false;
+ bool isQueryParsed = 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 += '/';
+ } else if (c == '?') {
+ isHostParsed = isPathParsed = true;
+ path += '/';
+ } else if (c == '#') {
+ isHostParsed = isPathParsed = isQueryParsed = true;
+ path += '/';
+ } else {
+ host += c;
+ }
+ } else if (!isPathParsed) {
+ if (c == '?') {
+ isPathParsed = true;
+ } else if (c == '#') {
+ isPathParsed = isQueryParsed = true;
+ } else {
+ path += c;
+ }
+ } else if (!isQueryParsed) {
+ if (c == '#') {
+ isQueryParsed = true;
+ } else {
+ query += c;
+ }
+ } else {
+ fragment += c;
+ }
+ }
+
+ host = StringTools::urlEncode(host, ".");
+ path = StringTools::urlEncode(path, "/");
+ query = StringTools::urlEncode(query, "&");
+ fragment = StringTools::urlEncode(fragment);
+}
+
+}
diff --git a/src/tools/tools/StringTools.cpp b/src/tools/tools/StringTools.cpp
new file mode 100644
index 0000000..0a6dbc3
--- /dev/null
+++ b/src/tools/tools/StringTools.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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 "tgbot/tools/StringTools.h"
+
+#include <stdlib.h>
+#include <iomanip>
+#include <stdio.h>
+
+using namespace std;
+
+namespace StringTools {
+
+bool startsWith(const string& str1, const string& str2) {
+ if (str1.length() < str2.length()) {
+ return false;
+ }
+ 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) {
+ if (str1.length() < str2.length()) {
+ return false;
+ }
+ string::const_iterator it1(str1.end());
+ string::const_iterator begin1(str1.begin());
+ string::const_iterator it2(str2.end());
+ string::const_iterator begin2(str2.begin());
+ while (it1 != begin1 && it2 != begin2) {
+ 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, const std::string additionalLegitChars) {
+ static const string legitPunctuation = "-_.~";
+ ostringstream result;
+ result.fill('0');
+ result << hex;
+ for (const char& c : value) {
+ if (isalnum(c) || legitPunctuation.find(c) != legitPunctuation.npos || additionalLegitChars.find(c) != additionalLegitChars.npos) {
+ result << c;
+ } else {
+ result << '%' << setw(2) << int((unsigned char) c);
+ }
+ }
+
+ return result.str();
+}
+
+string urlDecode(const string& value) {
+ string result;
+ for (size_t i = 0, count = value.length(); i < count; ++i) {
+ const char c = value[i];
+ if (c == '%') {
+ int t = 0;
+ sscanf(value.substr(i + 1, 2).c_str(), "%x", &t);
+ result += (char) t;
+ i += 2;
+ } else {
+ result += c;
+ }
+ }
+ return result;
+}
+
+}