From d487bce0e46cc7163b2ecacdd884107147646ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hauke=20Z=C3=BChl?= Date: Fri, 29 Apr 2016 19:38:14 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + CMakeLists.txt | 33 +++++++ README.md | 2 +- include/Audio.h | 23 +++++ include/Chat.h | 26 ++++++ include/Contact.h | 21 +++++ include/Document.h | 24 +++++ include/Location.h | 18 ++++ include/Message.h | 78 ++++++++++++++++ include/MessageEntity.h | 27 ++++++ include/PhotoSize.h | 21 +++++ include/Sticker.h | 24 +++++ include/TelegramBot.h | 63 +++++++++++++ include/User.h | 21 +++++ include/Venue.h | 22 +++++ include/Video.h | 26 ++++++ include/Voice.h | 21 +++++ include/exec.h | 8 ++ include/explode.h | 9 ++ include/http_build_query.h | 9 ++ include/json_encode.h | 10 +++ include/std.h | 23 +++++ src/Audio.cc | 11 +++ src/Chat.cc | 21 +++++ src/Contact.cc | 9 ++ src/Document.cc | 10 +++ src/Location.cc | 7 ++ src/Message.cc | 134 +++++++++++++++++++++++++++ src/MessageEntity.cc | 14 +++ src/PhotoSize.cc | 9 ++ src/Sticker.cc | 10 +++ src/TelegramBot.cc | 179 +++++++++++++++++++++++++++++++++++++ src/User.cc | 9 ++ src/Venue.cc | 9 ++ src/Video.cc | 12 +++ src/Voice.cc | 9 ++ src/exec.cc | 21 +++++ src/explode.cc | 28 ++++++ src/http_build_query.cc | 14 +++ src/json_encode.cc | 13 +++ src/std.cc | 97 ++++++++++++++++++++ 41 files changed, 1125 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 include/Audio.h create mode 100644 include/Chat.h create mode 100644 include/Contact.h create mode 100644 include/Document.h create mode 100644 include/Location.h create mode 100644 include/Message.h create mode 100644 include/MessageEntity.h create mode 100644 include/PhotoSize.h create mode 100644 include/Sticker.h create mode 100644 include/TelegramBot.h create mode 100644 include/User.h create mode 100644 include/Venue.h create mode 100644 include/Video.h create mode 100644 include/Voice.h create mode 100644 include/exec.h create mode 100644 include/explode.h create mode 100644 include/http_build_query.h create mode 100644 include/json_encode.h create mode 100644 include/std.h create mode 100644 src/Audio.cc create mode 100644 src/Chat.cc create mode 100644 src/Contact.cc create mode 100644 src/Document.cc create mode 100644 src/Location.cc create mode 100644 src/Message.cc create mode 100644 src/MessageEntity.cc create mode 100644 src/PhotoSize.cc create mode 100644 src/Sticker.cc create mode 100644 src/TelegramBot.cc create mode 100644 src/User.cc create mode 100644 src/Venue.cc create mode 100644 src/Video.cc create mode 100644 src/Voice.cc create mode 100644 src/exec.cc create mode 100644 src/explode.cc create mode 100644 src/http_build_query.cc create mode 100644 src/json_encode.cc create mode 100644 src/std.cc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..232c66a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +set (HEADERS + Audio.h + Document.h + json_encode.h + PhotoSize.h + User.h + Chat.h + exec.h + Location.h + std.h + Venue.h + Contact.h + explode.h + MessageEntity.h + Sticker.h + Video.h + defines.h + http_build_query.h + Message.h + TelegramBot.h + Voice.h +) + +cmake_minimum_required(VERSION 2.8) + +project(libtg) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR/include) +add_library(tg SHARED main.cc) + +install(TARGETS tg DESTINATION lib) +install(FILES ${HEADERS} DESTINATION include) + diff --git a/README.md b/README.md index a8ec413..9332261 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # LibTgBotPP -A simple Telegram Bot C++ library +A simple Telegram Bot C++ library diff --git a/include/Audio.h b/include/Audio.h new file mode 100644 index 0000000..79b4d5c --- /dev/null +++ b/include/Audio.h @@ -0,0 +1,23 @@ +#ifndef _TG_AUDIO_H_ +#define _TG_AUDIO_H_ + +#include +#include + +namespace Telegram { + + class Audio { + public: + Audio(Json::Value); + + private: + std::string file_id; + Json::Int64 duration; + std::string performer; + std::string title; + std::string mime_type; + Json::Int64 file_size; + }; +} + +#endif diff --git a/include/Chat.h b/include/Chat.h new file mode 100644 index 0000000..576b92c --- /dev/null +++ b/include/Chat.h @@ -0,0 +1,26 @@ +#ifndef _TG_CHAT_H_ +#define _TG_CHAT_H_ + +#include +#include + +namespace Telegram { + + class Chat { + public: + Chat(Json::Value); + + Json::Int64 getId(); + std::string getUsername(); + + private: + Json::Int64 id; + std::string type; + std::string title; + std::string username; + std::string first_name; + std::string last_name; + }; +} + +#endif diff --git a/include/Contact.h b/include/Contact.h new file mode 100644 index 0000000..765f2e5 --- /dev/null +++ b/include/Contact.h @@ -0,0 +1,21 @@ +#ifndef _TG_CONTACT_H_ +#define _TG_CONTACT_H_ + +#include +#include + +namespace Telegram { + + class Contact { + public: + Contact(Json::Value); + + private: + std::string phone_number; + std::string first_name; + std::string last_name; + Json::Int64 user_id; + }; +} + +#endif diff --git a/include/Document.h b/include/Document.h new file mode 100644 index 0000000..d5a1271 --- /dev/null +++ b/include/Document.h @@ -0,0 +1,24 @@ +#ifndef _TG_DOCUMENT_H_ +#define _TG_DOCUMENT_H_ + +#include +#include + +#include "PhotoSize.h" + +namespace Telegram { + + class Document { + public: + Document(Json::Value); + + private: + std::string file_id; + PhotoSize *thumb; + std::string file_name; + std::string mime_type; + Json::Int64 file_size; + }; +} + +#endif diff --git a/include/Location.h b/include/Location.h new file mode 100644 index 0000000..a7959f3 --- /dev/null +++ b/include/Location.h @@ -0,0 +1,18 @@ +#ifndef __TG_LOCATION_H_ +#define __TG_LOCATION_H_ + +#include + +namespace Telegram { + + class Location { + public: + Location(Json::Value); + + private: + float longitude; + float latitude; + }; +} + +#endif diff --git a/include/Message.h b/include/Message.h new file mode 100644 index 0000000..6d31ef2 --- /dev/null +++ b/include/Message.h @@ -0,0 +1,78 @@ +#ifndef _TG_MESSAGE_H_ +#define _TG_MESSAGE_H_ + +#include + +#include +#include + +#include "Audio.h" +#include "Chat.h" +#include "Contact.h" +#include "Document.h" +#include "Location.h" +#include "MessageEntity.h" +#include "PhotoSize.h" +#include "Sticker.h" +#include "User.h" +#include "Venue.h" +#include "Video.h" +#include "Voice.h" + +namespace Telegram { + + /** + * See https://core.telegram.org/bots/api#message + */ + class Message { + public: + // Constructors + Message(void); + Message(Json::Value); + Message(std::string); + + void setEntities(Json::Value); + std::vector setPhotos(Json::Value); + + Telegram::Chat *getChat(); + std::string getText(); + Telegram::TMessageEntities getEntities(); + + private: + Json::UInt64 message_id; + User *from; + Json::Int64 date; + Chat *chat; + User *forward_from; + Json::Int64 forward_date; + Message *reply_to_message; + std::string text; + Telegram::TMessageEntities entities; + Audio *audio; + Document *document; + std::vector photo; + Sticker *sticker; + Video *video; + Voice *voice; + std::string caption; + Contact *contact; + Location *location; + Venue *venue; + User *new_chat_member; + User *left_chat_member; + std::string new_chat_title; + std::vector new_chat_photo; + int delete_chat_photo; + int group_chat_created; + int supergroup_chat_created; + Json::Int64 migrate_to_chat_id; + Json::Int64 migrate_from_chat_id; + Message *pinned_message; + + // Methods + void init(void); + void init(Json::Value); + }; +} + +#endif diff --git a/include/MessageEntity.h b/include/MessageEntity.h new file mode 100644 index 0000000..6b3c320 --- /dev/null +++ b/include/MessageEntity.h @@ -0,0 +1,27 @@ +#ifndef _TG_MESSAGEENTITY_H_ +#define _TG_MESSAGEENTITY_H_ + +#include +#include +#include + +namespace Telegram { + + class MessageEntity { + public: + MessageEntity(Json::Value); + + std::string getType(); + + private: + std::string type; + Json::Int64 offset; + Json::Int64 length; + std::string url; + }; + + typedef std::vector TMessageEntities; + +} + +#endif diff --git a/include/PhotoSize.h b/include/PhotoSize.h new file mode 100644 index 0000000..45e8929 --- /dev/null +++ b/include/PhotoSize.h @@ -0,0 +1,21 @@ +#ifndef _TG_PHOTOSIZE_H_ +#define _TG_PHOTOSIZE_H_ + +#include +#include + +namespace Telegram { + + class PhotoSize { + public: + PhotoSize(Json::Value); + + private: + std::string file_id; + Json::Int64 width; + Json::Int64 height; + Json::Int64 file_size; + }; +} + +#endif diff --git a/include/Sticker.h b/include/Sticker.h new file mode 100644 index 0000000..da6d17c --- /dev/null +++ b/include/Sticker.h @@ -0,0 +1,24 @@ +#ifndef _TG_STICKER_H_ +#define _TG_STICKER_H_ + +#include +#include + +#include "PhotoSize.h" + +namespace Telegram { + + class Sticker { + public: + Sticker(Json::Value); + + private: + std::string file_id; + Json::Int64 width; + Json::Int64 height; + PhotoSize *thumb; + Json::Int64 file_size; + }; +} + +#endif diff --git a/include/TelegramBot.h b/include/TelegramBot.h new file mode 100644 index 0000000..e285943 --- /dev/null +++ b/include/TelegramBot.h @@ -0,0 +1,63 @@ +#ifndef _TELEGRAM_BOT_H_ +#define _TELEGRAM_BOT_H_ + +#include +#include + +#include +#include + +#include "Message.h" + +namespace Telegram { + + class TelegramBot; + + // Typedef for callbacks + typedef std::vector TCommandLine; + typedef std::string(*CommandCallback)(TelegramBot*, TCommandLine); + typedef struct { + std::string command; + CommandCallback callback; + std::string help_text; + } TCommand; + typedef std::map TCommandMap; + + class TelegramBot { + + public: + TelegramBot(); + TelegramBot(std::string); + + void addCommand(TCommand); + void setWebhook(std::string); + void processMessage(std::string); + void sendMessage(std::string, Json::Int64); + void sendMessage(std::string, std::string); + + Telegram::Message *getMessage(); + std::map getCommandMap(); + + // Callback methods + /* + std::string start(Telegram::TelegramBot, tvCommandLine); + std::string help(tvCommandLine); + std::string whoami(tvCommandLine); + std::string loadavg(tvCommandLine); + std::string proc(tvCommandLine); + */ + + private: + std::string api_url; + Telegram::Message *msg; + TCommandMap command_map; + Json::Int64 chat_id; + + void init(); + void apiRequest(std::string, std::map); + void apiRequestJson(std::string, std::map); + std::string processCommand(std::string); + }; +} + +#endif diff --git a/include/User.h b/include/User.h new file mode 100644 index 0000000..943e1b7 --- /dev/null +++ b/include/User.h @@ -0,0 +1,21 @@ +#ifndef _TG_USER_H_ +#define _TG_USER_H_ + +#include +#include + +namespace Telegram { + + class User { + public: + User(Json::Value); + + private: + Json::Int64 id; + std::string first_name; + std::string last_name; + std::string username; + }; +} + +#endif diff --git a/include/Venue.h b/include/Venue.h new file mode 100644 index 0000000..c2ef36f --- /dev/null +++ b/include/Venue.h @@ -0,0 +1,22 @@ +#ifndef _TG_VENUE_H_ +#define _TG_VENUE_H_ + +#include + +#include "Location.h" + +namespace Telegram { + + class Venue { + public: + Venue(Json::Value); + + private: + Location *location; + std::string title; + std::string address; + std::string foursquare_id; + }; +} + +#endif diff --git a/include/Video.h b/include/Video.h new file mode 100644 index 0000000..95401a4 --- /dev/null +++ b/include/Video.h @@ -0,0 +1,26 @@ +#ifndef _TG_VIDEO_H_ +#define _TG_VIDEO_H_ + +#include +#include + +#include "PhotoSize.h" + +namespace Telegram { + + class Video { + public: + Video(Json::Value); + + private: + std::string file_id; + Json::Int64 width; + Json::Int64 height; + Json::Int64 duration; + PhotoSize *thumb; + std::string mime_type; + Json::Int64 file_size; + }; +} + +#endif diff --git a/include/Voice.h b/include/Voice.h new file mode 100644 index 0000000..7d2b196 --- /dev/null +++ b/include/Voice.h @@ -0,0 +1,21 @@ +#ifndef _TG_VOICE_H_ +#define _TG_VOICE_H_ + +#include +#include + +namespace Telegram { + + class Voice { + public: + Voice(Json::Value); + + private: + std::string file_id; + Json::Int64 duration; + std::string mime_type; + Json::Int64 file_size; + }; +} + +#endif diff --git a/include/exec.h b/include/exec.h new file mode 100644 index 0000000..509a5a1 --- /dev/null +++ b/include/exec.h @@ -0,0 +1,8 @@ +#ifndef __EXEC_H__ +#define __EXEC_H__ + +#include + +std::string exec(const char*); + +#endif diff --git a/include/explode.h b/include/explode.h new file mode 100644 index 0000000..2be65b3 --- /dev/null +++ b/include/explode.h @@ -0,0 +1,9 @@ +#ifndef __explode_h__ +#define __explode_h__ + +#include +#include + +std::vector explode( const std::string&, const std::string &); + +#endif diff --git a/include/http_build_query.h b/include/http_build_query.h new file mode 100644 index 0000000..318c4af --- /dev/null +++ b/include/http_build_query.h @@ -0,0 +1,9 @@ +#ifndef __HTTP_BUILD_QUERY_H__ +#define __HTTP_BUILD_QUERY_H__ + +#include +#include + +std::string http_build_query(std::map); + +#endif diff --git a/include/json_encode.h b/include/json_encode.h new file mode 100644 index 0000000..e9c1068 --- /dev/null +++ b/include/json_encode.h @@ -0,0 +1,10 @@ +#ifndef __JSON_ENCODE_H__ +#define __JSON_ENCODE_H__ + +#include +#include +#include + +std::string json_encode(std::map); + +#endif diff --git a/include/std.h b/include/std.h new file mode 100644 index 0000000..30872b3 --- /dev/null +++ b/include/std.h @@ -0,0 +1,23 @@ +#ifndef __STD_H__ +#define __STD_H__ + +#include +#include +#include +#include + +// Makro(s) +#define SSTR( x ) static_cast< std::ostringstream & >(( std::ostringstream() << std::dec << x ) ).str() + +typedef unsigned long long int uint64; + +uint64 stoi(std::string); +std::string itos(uint64); +std::string currentDate(); +std::vector split(const std::string &text, char sep = ' '); +float stof(std::string); +std::string trim(const std::string&); +std::string gethome(); +void Log(std::string); + +#endif diff --git a/src/Audio.cc b/src/Audio.cc new file mode 100644 index 0000000..7cf1013 --- /dev/null +++ b/src/Audio.cc @@ -0,0 +1,11 @@ +#include "Audio.h" + +Telegram::Audio::Audio(Json::Value json) { + + this->file_id = json["file_id"].asString(); + this->duration = json["duration"].asUInt64(); + this->performer = json["performer"].asString(); + this->title = json["title"].asString(); + this->mime_type = json["mime_type"].asString(); + this->file_size = json["file_size"].asUInt64(); +} diff --git a/src/Chat.cc b/src/Chat.cc new file mode 100644 index 0000000..8541d1e --- /dev/null +++ b/src/Chat.cc @@ -0,0 +1,21 @@ +#include "Chat.h" + +Telegram::Chat::Chat(Json::Value json) { + + this->id = json["id"].asUInt64(); + this->type = json["type"].asString(); + this->title = json["title"].asString(); + this->username = json["username"].asString(); + this->first_name = json["first_name"].asString(); + this->last_name = json["last_name"].asString(); +} + +Json::Int64 Telegram::Chat::getId() { + + return(this->id); +} + +std::string Telegram::Chat::getUsername() { + + return(this->username); +} diff --git a/src/Contact.cc b/src/Contact.cc new file mode 100644 index 0000000..86cd5dd --- /dev/null +++ b/src/Contact.cc @@ -0,0 +1,9 @@ +#include "Contact.h" + +Telegram::Contact::Contact(Json::Value json) { + + this->phone_number = json["phone_number"].asString(); + this->first_name = json["first_name"].asString(); + this->last_name = json["last_name"].asString(); + this->user_id = json["user_id"].asInt64(); +} diff --git a/src/Document.cc b/src/Document.cc new file mode 100644 index 0000000..f55823b --- /dev/null +++ b/src/Document.cc @@ -0,0 +1,10 @@ +#include "Document.h" + +Telegram::Document::Document(Json::Value json) { + + this->file_id = json["file_id"].asString(); + this->thumb = new PhotoSize(json["thumb"]); + this->file_name = json["file_name"].asString(); + this->mime_type = json["mime_type"].asString(); + this->file_size = json["file_size"].asInt64(); +} diff --git a/src/Location.cc b/src/Location.cc new file mode 100644 index 0000000..5db5f5e --- /dev/null +++ b/src/Location.cc @@ -0,0 +1,7 @@ +#include "Location.h" + +Telegram::Location::Location(Json::Value json) { + + this->longitude = json["longitude"].asFloat(); + this->latitude = json["latitude"].asFloat(); +} diff --git a/src/Message.cc b/src/Message.cc new file mode 100644 index 0000000..e565a00 --- /dev/null +++ b/src/Message.cc @@ -0,0 +1,134 @@ +#include "Message.h" + +// Generic constructor +// @TODO: Make this an "init"-Method and call it from the constructor +Telegram::Message::Message(void) { + + this->init(); +} + +Telegram::Message::Message(Json::Value json) { + + if (json["message"].isNull()) { + this->init(); + return; + } + + this->init(json); +} + +Telegram::Message::Message(std::string message) { + + Json::Value json; + Json::Reader reader; + + reader.parse(message, json); + + this->init(json); +} + +void Telegram::Message::init(void) { + + this->message_id = 0; + this->from = NULL; + this->date = 0; + this->chat = NULL; + this->forward_from = NULL; + this->forward_date = 0; + this->reply_to_message = NULL; + this->text = ""; + this->entities.clear(); + this->audio = NULL; + this->document = NULL; + this->photo.clear(); + this->sticker = NULL; + this->video = NULL; + this->voice = NULL; + this->caption = ""; + this->contact = NULL; + this->location = NULL; + this->venue = NULL; + this->new_chat_member = NULL; + this->left_chat_member = NULL; + this->new_chat_title = ""; + this->new_chat_photo.clear(); + this->delete_chat_photo = 0; + this->group_chat_created = 0; + this->supergroup_chat_created = 0; + this->migrate_to_chat_id = 0; + this->pinned_message = NULL; +} + +void Telegram::Message::init(Json::Value json) { + + Json::Value msg = json["message"]; + + this->message_id = msg["message_id"].asUInt64(); + this->from = new Telegram::User(msg["from"]); + this->date = msg["date"].asUInt64(); + this->chat = new Telegram::Chat(msg["chat"]); + this->forward_from = new Telegram::User(msg["forward_from"]); + this->forward_date = msg["forward_date"].asUInt64(); + this->reply_to_message = new Telegram::Message(msg["reply_to_message"]); + this->text = msg["text"].asString(); + this->setEntities(msg["entities"]); + this->audio = new Audio(msg["audio"]); + this->document = new Document(msg["document"]); + this->photo = this->setPhotos(msg["photo"]); + this->sticker = new Sticker(msg["sticker"]); + this->video = new Video(msg["video"]); + this->voice = new Voice(msg["voice"]); + this->caption = msg["caption"].asString(); + this->contact = new Contact(msg["contact"]); + this->location = new Location(msg["location"]); + this->venue = new Venue(msg["venue"]); + this->new_chat_member = new User(msg["new_chat_member"]); + this->left_chat_member = new User(msg["left_chat_member"]); + this->new_chat_title = msg["new_chat_title"].asString(); + this->new_chat_photo = this->setPhotos(msg["new_chat_photo"]); + this->delete_chat_photo = msg["delete_chat_photo"].asInt64(); + this->group_chat_created = msg["group_chat_created"].asInt64(); + this->supergroup_chat_created = msg["supergroup_chat_created"].asInt64(); + this->migrate_to_chat_id = msg["migrate_to_chat_id"].asUInt64(); + this->migrate_from_chat_id = msg["migrate_from_chat_id"].asUInt64(); + this->pinned_message = new Message(msg["pinned_message"]); +} + +// Setter +void Telegram::Message::setEntities(Json::Value entities) { + + Json::ArrayIndex size = entities.size(); + for(Json::ArrayIndex i = 0; i < size; i++) { + Telegram::MessageEntity *entity = new Telegram::MessageEntity(entities[i]); + this->entities.push_back(entity); + } +} + +std::vector Telegram::Message::setPhotos(Json::Value photos) { + + Json::ArrayIndex size = photos.size(); + std::vector vPhotos; + + for(Json::ArrayIndex i = 0; i < size; i++) { + Telegram::PhotoSize *photo_size = new Telegram::PhotoSize(photos[i]); + vPhotos.push_back(photo_size); + } + + return(vPhotos); +} + +// Getter +Telegram::Chat *Telegram::Message::getChat() { + + return(this->chat); +} + +std::string Telegram::Message::getText() { + + return(this->text); +} + +Telegram::TMessageEntities Telegram::Message::getEntities() { + + return(this->entities); +} diff --git a/src/MessageEntity.cc b/src/MessageEntity.cc new file mode 100644 index 0000000..d903a5b --- /dev/null +++ b/src/MessageEntity.cc @@ -0,0 +1,14 @@ +#include "MessageEntity.h" + +Telegram::MessageEntity::MessageEntity(Json::Value json) { + + this->type = json["type"].asString(); + this->offset = json["offset"].asUInt64(); + this->length = json["length"].asUInt64(); + this->url = json["url"].asString(); +} + +std::string Telegram::MessageEntity::getType() { + + return(this->type); +} diff --git a/src/PhotoSize.cc b/src/PhotoSize.cc new file mode 100644 index 0000000..a110d1a --- /dev/null +++ b/src/PhotoSize.cc @@ -0,0 +1,9 @@ +#include "PhotoSize.h" + +Telegram::PhotoSize::PhotoSize(Json::Value json) { + + this->file_id = json["file_id"].asString(); + this->width = json["width"].asInt64(); + this->height = json["height"].asInt64(); + this->file_size = json["file_size"].asInt64(); +} diff --git a/src/Sticker.cc b/src/Sticker.cc new file mode 100644 index 0000000..b78aab2 --- /dev/null +++ b/src/Sticker.cc @@ -0,0 +1,10 @@ +#include "Sticker.h" + +Telegram::Sticker::Sticker(Json::Value json) { + + this->file_id = json["file_id"].asString(); + this->width = json["width"].asInt64(); + this->height = json["height"].asInt64(); + this->thumb = new PhotoSize(json["thumb"]); + this->file_size = json["file_size"].asInt64(); +} diff --git a/src/TelegramBot.cc b/src/TelegramBot.cc new file mode 100644 index 0000000..ec19a3a --- /dev/null +++ b/src/TelegramBot.cc @@ -0,0 +1,179 @@ +#include "TelegramBot.h" + +#include + +#include +#include +#include +#include + +#include "http_build_query.h" +#include "json_encode.h" +#include "std.h" + +#include "Message.h" +#include "MessageEntity.h" + +#define API_URL "https://api.telegram.org/bot" + +// Constructor of Bot +Telegram::TelegramBot::TelegramBot() { + + this->api_url = ""; + this->init(); +} + +Telegram::TelegramBot::TelegramBot(std::string token) { + + this->api_url = API_URL + token + "/"; + this->init(); +} + +void Telegram::TelegramBot::addCommand(TCommand cmd) { + + if (cmd.command[0] != '/') { + cmd.command = "/" + cmd.command; + } + this->command_map[cmd.command] = cmd; +} + +/** + * Set the webhook + * The web hook URL is like https:///cgi-bin/mybot.cgi + * A web hook must be set before you can get any messages from the Telegram + * network! + */ +void Telegram::TelegramBot::setWebhook(std::string url) { + + std::map params; + + params["url"] = url; + this->apiRequest("setWebhook", params); +} + +// Process incoming message +void Telegram::TelegramBot::processMessage(std::string message) { + + this->msg = new Telegram::Message(message); + + Telegram::TMessageEntities entities = this->msg->getEntities(); + + if (entities.size() && (entities[0]->getType() == "bot_command")) { + this->sendMessage(this->processCommand(this->msg->getText()), this->msg->getChat()->getId()); + } else { + this->sendMessage("Hello " + this->msg->getChat()->getUsername() + ", you told me: '" + msg->getText() + "'", this->msg->getChat()->getId()); + } +} + +// Send a text message to a user +void Telegram::TelegramBot::sendMessage(std::string message, Json::Int64 chat_id) { + + this->sendMessage(message, SSTR(chat_id)); +} + +void Telegram::TelegramBot::sendMessage(std::string message, std::string chat_id) { + + std::map params; + params["chat_id"] = chat_id; + params["text"] = message; + + this->apiRequestJson("sendMessage", params); +} + +Telegram::Message *Telegram::TelegramBot::getMessage() { + + return(this->msg); +} + +Telegram::TCommandMap Telegram::TelegramBot::getCommandMap() { + + return(this->command_map); +} + +// Private methods +void Telegram::TelegramBot::init() { + + std::cout << "Content-type: text/html\r\n\r\n" << std::endl; +} + +// A generic API request +void Telegram::TelegramBot::apiRequest(std::string method, std::map parameters) { + + parameters["method"] = method; + + Json::Value jValues; + Json::StyledWriter w; + + for(std::map::iterator it = parameters.begin(); it != parameters.end(); ++it) { + jValues[(*it).first] = (*it).second; + } + + try { + cURLpp::Easy handle; + std::string url = this->api_url + method + "?" + http_build_query(parameters); + + handle.setOpt(cURLpp::Options::Url(url)); + handle.setOpt(cURLpp::Options::ConnectTimeout(5)); + handle.setOpt(cURLpp::Options::Timeout(60)); + handle.perform(); // Do the curl request + + int code; + code = cURLpp::Infos::ResponseCode::get(handle); + } + catch(cURLpp::LogicError &e) { + Log(e.what()); + } + catch(cURLpp::RuntimeError &e) { + Log(e.what()); + } + catch(std::exception &e) { + Log(e.what()); + } +} + +// An API request, posting JSON data +void Telegram::TelegramBot::apiRequestJson(std::string method, std::map parameters) { + + parameters["method"] = method; + + try { + cURLpp::Easy handle; + std::list header; + header.push_back("Content-Type: application/json"); + + handle.setOpt(cURLpp::Options::Url(this->api_url)); + handle.setOpt(cURLpp::Options::ConnectTimeout(5)); + handle.setOpt(cURLpp::Options::Timeout(60)); + handle.setOpt(cURLpp::Options::HttpHeader(header)); + handle.setOpt(cURLpp::Options::PostFields(json_encode(parameters))); + handle.perform(); // Do the curl request + } + catch(cURLpp::LogicError &e) { + Log(e.what()); + } + catch(cURLpp::RuntimeError &e) { + Log(e.what()); + } + catch(std::exception &e) { + Log(e.what()); + } +} + +std::string Telegram::TelegramBot::processCommand(std::string cmd) { + + // Process command + std::string sCommand; + std::string sResult; + std::vector vCmdLine = split(cmd, ' '); + + if((vCmdLine.size() > 0) && (this->command_map.find(vCmdLine[0]) != this->command_map.end())) { + sCommand = vCmdLine[0]; + vCmdLine.erase(vCmdLine.begin()); // First value is the command itself + TCommand cs = this->command_map[sCommand]; + sResult = (*cs.callback)(this, vCmdLine); + } else { + sResult = "Unknown command"; + } + + return(sResult); +} diff --git a/src/User.cc b/src/User.cc new file mode 100644 index 0000000..3511782 --- /dev/null +++ b/src/User.cc @@ -0,0 +1,9 @@ +#include "User.h" + +Telegram::User::User(Json::Value json) { + + this->id = json["id"].asUInt64(); + this->first_name = json["first_name"].asString(); + this->last_name = json["last_name"].asString(); + this->username = json["username"].asString(); +} diff --git a/src/Venue.cc b/src/Venue.cc new file mode 100644 index 0000000..6517e8a --- /dev/null +++ b/src/Venue.cc @@ -0,0 +1,9 @@ +#include "Venue.h" + +Telegram::Venue::Venue(Json::Value json) { + + this->location = new Location(json["location"]); + this->title = json["title"].asString(); + this->address = json["address"].asString(); + this->foursquare_id = json["foursquare_id"].asString(); +} diff --git a/src/Video.cc b/src/Video.cc new file mode 100644 index 0000000..cd3fcfa --- /dev/null +++ b/src/Video.cc @@ -0,0 +1,12 @@ +#include "Video.h" + +Telegram::Video::Video(Json::Value json) { + + this->file_id = json["file_id"].asString(); + this->width = json["width"].asInt64(); + this->height = json["height"].asInt64(); + this->duration = json["duration"].asInt64(); + this->thumb = new PhotoSize(json["thumb"]); + this->mime_type = json["mime_type"].asString(); + this->file_size = json["file_size"].asInt64(); +} diff --git a/src/Voice.cc b/src/Voice.cc new file mode 100644 index 0000000..0560b81 --- /dev/null +++ b/src/Voice.cc @@ -0,0 +1,9 @@ +#include "Voice.h" + +Telegram::Voice::Voice(Json::Value json) { + + this->file_id = json["file_id"].asString(); + this->duration = json["duration"].asInt64(); + this->mime_type = json["mime_type"].asString(); + this->file_size = json["file_size"].asInt64(); +} diff --git a/src/exec.cc b/src/exec.cc new file mode 100644 index 0000000..4faad42 --- /dev/null +++ b/src/exec.cc @@ -0,0 +1,21 @@ +#include "exec.h" + +#include +#include + +std::string exec(const char* cmd) { + + FILE* pipe = popen(cmd, "r"); + if (!pipe) + return "ERROR"; + + char buffer[128]; + std::string result = ""; + while (!feof(pipe)) { + if (fgets(buffer, 128, pipe) != NULL) + result += buffer; + } + pclose(pipe); + + return result; +} diff --git a/src/explode.cc b/src/explode.cc new file mode 100644 index 0000000..009b5ec --- /dev/null +++ b/src/explode.cc @@ -0,0 +1,28 @@ +#include "explode.h" + +std::vector explode( const std::string &delimiter, const std::string &str) { + + std::vector arr; + + int strleng = str.length(); + int delleng = delimiter.length(); + if (delleng == 0) + return arr;//no change + + int i = 0; + int k = 0; + while(i < strleng) { + int j = 0; + while ((i+j < strleng) && (j < delleng) && (str[i+j] == delimiter[j])) + j++; + if (j == delleng) { + arr.push_back(str.substr(k, i-k)); + i += delleng; + k = i; + } else { + i++; + } + } + arr.push_back(str.substr(k, i-k)); + return arr; +} diff --git a/src/http_build_query.cc b/src/http_build_query.cc new file mode 100644 index 0000000..51ed26b --- /dev/null +++ b/src/http_build_query.cc @@ -0,0 +1,14 @@ +#include "http_build_query.h" + +std::string http_build_query(std::map data) { + + std::string result = ""; + + std::map::iterator it; + + for (it = data.begin(); it != data.end(); it++) { + result = result + it->first + "=" + it->second + "&"; + } + + return result; +} diff --git a/src/json_encode.cc b/src/json_encode.cc new file mode 100644 index 0000000..2b12a9f --- /dev/null +++ b/src/json_encode.cc @@ -0,0 +1,13 @@ +#include "json_encode.h" + +std::string json_encode(std::map parameters) { + + Json::Value jValues; + Json::StyledWriter w; + + for(std::map::iterator it = parameters.begin(); it != parameters.end(); ++it) { + jValues[(*it).first] = (*it).second; + } + + return(w.write(jValues)); +} diff --git a/src/std.cc b/src/std.cc new file mode 100644 index 0000000..7a94401 --- /dev/null +++ b/src/std.cc @@ -0,0 +1,97 @@ +#include "std.h" + +#include +#include +#include + +#include +#include +#include + +uint64 stoi(std::string st) { + + uint64 ret; + + if (st == "") { + st = "0"; + } + + std::istringstream convert(st); + convert >> ret; + + return(ret); +} + +std::string itos(uint64 i) { + + return(static_cast(&(std::ostringstream() << i))->str()); +} + +std::string currentDate() { + + time_t now = time(0); + struct tm tstruct; + char buf[32]; + tstruct = *localtime(&now); + + strftime(buf, sizeof(buf), "%Y-%m-%d", &tstruct); + + return(buf); +} + +std::vector split(const std::string &text, char sep) { + + std::vector tokens; + int start = 0, end = 0; + while ((int)(end = text.find(sep, start)) != (int)std::string::npos) { + std::string temp = text.substr(start, end - start); + if(temp != "") + tokens.push_back(temp); + start = end + 1; + } + std::string temp=text.substr(start); + if(temp != "") + tokens.push_back(temp); + + return tokens; +} + +float stof(std::string st) { + + // Conver , to . first + replace(st.begin(), st.end(), ',', '.'); + + return(atof(st.c_str())); +} + +std::string trim(const std::string &s) { + + std::string::const_iterator it = s.begin(); + while (it != s.end() && isspace(*it)) + it++; + + std::string::const_reverse_iterator rit = s.rbegin(); + while (rit.base() != it && isspace(*rit)) + rit++; + + return std::string(it, rit.base()); +} + +std::string gethome() { + + std::string homedir = getenv("HOME"); + if (homedir == "") { + homedir = getpwuid(getuid())->pw_dir; + } + + return(homedir); +} + +// A simple logger +void Log(std::string msg) { + + std::ofstream datei; + datei.open("/tmp/bot.log", std::ios::out | std::ios::app); + datei << "Msg: " << msg << std::endl; + datei.close(); +}