diff --git a/TriviaBot/bot/APIHelper.cpp b/TriviaBot/bot/APIHelper.cpp index 5df8e88..a6633ee 100644 --- a/TriviaBot/bot/APIHelper.cpp +++ b/TriviaBot/bot/APIHelper.cpp @@ -17,6 +17,22 @@ APIHelper::APIHelper() : BASE_URL("https://discordapp.com/api"), CHANNELS_URL(BA void APIHelper::send_message(std::string channel_id, std::string message) { if (message == "") { Logger::write("[send_message] Tried to send empty message", Logger::LogLevel::Warning); + return; + } + + if (message.length() > 4000) { + Logger::write("[send_message] Tried to send a message over 4000 characters", Logger::LogLevel::Warning); + return; + } + else if (message.length() > 2000) { + std::cout << message.length() << std::endl; + + std::string first = message.substr(0, 2000); + std::string second = message.substr(2000); + send_message(channel_id, first); + std::this_thread::sleep_for(50ms); + send_message(channel_id, second); + return; } const std::string url = CHANNELS_URL + "/" + channel_id + "/messages"; diff --git a/TriviaBot/bot/GatewayHandler.cpp b/TriviaBot/bot/GatewayHandler.cpp index 9f359af..092f10c 100644 --- a/TriviaBot/bot/GatewayHandler.cpp +++ b/TriviaBot/bot/GatewayHandler.cpp @@ -152,11 +152,11 @@ void GatewayHandler::on_event_guild_create(json data) { guild_member.roles.push_back(&roles[role_id]); } - guilds[guild.id].members.push_back(guild_member); + guilds[guild.id].members[user_id] = guild_member; } if (v8_instances.count(guild.id) == 0) { - v8_instances[guild.id] = std::make_unique(ah); + v8_instances[guild.id] = std::make_unique(guild.id, ah, &guilds, &channels, &users, &roles); Logger::write("Created v8 instance for guild " + guild.id, Logger::LogLevel::Debug); } @@ -209,36 +209,32 @@ void GatewayHandler::on_event_guild_member_add(json data) { guild_member.roles.push_back(&roles[role_id]); } - guilds[guild_id].members.push_back(guild_member); + guilds[guild_id].members[user_id] = guild_member; Logger::write("Added new member " + guild_member.user->id + " to guild " + guild_id, Logger::LogLevel::Debug); } void GatewayHandler::on_event_guild_member_update(json data) { - std::cout << data.dump(4) << std::endl; - std::string user_id = data["user"]["id"]; DiscordObjects::Guild &guild = guilds[data["guild_id"]]; - auto it = std::find_if(guild.members.begin(), guild.members.begin(), [user_id](const DiscordObjects::GuildMember &gm) { - return gm.user->id == user_id; - }); + auto it = guild.members.find(user_id); if (it != guild.members.end()) { bool nick_changed = false; size_t roles_change = 0; - std::string nick = data.value("nick", it->nick); - if (it->nick != nick) { - it->nick = nick; + std::string nick = data.value("nick", "null"); + if (it->second.nick != nick) { + it->second.nick = nick; nick_changed = true; } - roles_change = it->roles.size(); - it->roles.clear(); // reset and re-fill, changing the differences is probably more expensive anyway. + roles_change = it->second.roles.size(); + it->second.roles.clear(); // reset and re-fill, changing the differences is probably more expensive anyway. for (std::string role_id : data["roles"]) { - it->roles.push_back(&roles[role_id]); + it->second.roles.push_back(&roles[role_id]); } - roles_change = it->roles.size() - roles_change; + roles_change = it->second.roles.size() - roles_change; std::string debug_string = "Updated member " + user_id + " of guild " + guild.id; if (nick_changed) debug_string += ". Nick changed to " + nick; @@ -256,15 +252,12 @@ void GatewayHandler::on_event_guild_member_remove(json data) { DiscordObjects::Guild &guild = guilds[data["guild_id"]]; std::string user_id = data["user"]["id"]; - auto it = std::find_if(guild.members.begin(), guild.members.begin(), [user_id](const DiscordObjects::GuildMember &gm) { - return gm.user->id == user_id; - }); - + auto it = guild.members.find(user_id); if (it != guilds[guild.id].members.end()) { guild.members.erase(it); DiscordObjects::User &user = users[user_id]; - user.guilds.erase(std::remove(user.guilds.begin(), user.guilds.end(), user.id)); + user.guilds.erase(std::remove(user.guilds.begin(), user.guilds.end(), guild.id)); if (user.guilds.size() == 0) { users.erase(users.find(user_id)); @@ -275,7 +268,7 @@ void GatewayHandler::on_event_guild_member_remove(json data) { } } else { - Logger::write("Tried to remove guild member " + user_id + " which doesn't exist", Logger::LogLevel::Warning); + Logger::write("Tried to remove guild member " + user_id + " who doesn't exist", Logger::LogLevel::Warning); } } @@ -373,9 +366,12 @@ void GatewayHandler::on_event_channel_delete(json data) { void GatewayHandler::on_event_message_create(json data) { std::string message = data["content"]; - auto channel = channels[data["channel_id"]]; - DiscordObjects::User sender(data["author"]); + DiscordObjects::Channel &channel = channels[data["channel_id"]]; + DiscordObjects::Guild &guild = guilds[channel.guild_id]; + DiscordObjects::GuildMember &sender = guild.members[data["author"]["id"]]; + + if (sender.user->bot) return; // ignore bots to prevent looping std::vector words; boost::split(words, message, boost::is_any_of(" ")); @@ -431,14 +427,14 @@ void GatewayHandler::on_event_message_create(json data) { else if (words[0] == "`info") { ah->send_message(channel.id, ":information_source: trivia-bot by Jack. "); } - else if (words[0] == "`js" && message.length() > 4) { + else if (words[0] == "~js" && message.length() > 4) { std::string js = message.substr(4); auto it = v8_instances.find(channel.guild_id); if (it != v8_instances.end() && js.length() > 0) { - it->second->exec_js(js, channel.id); + it->second->exec_js(js, &channel, &sender); } } - else if (words[0] == "`createjs" && message.length() > 8) { + else if (words[0] == "~createjs" && message.length() > 8) { std::string args = message.substr(10); size_t seperator_loc = args.find("|"); if (seperator_loc != std::string::npos) { @@ -455,7 +451,7 @@ void GatewayHandler::on_event_message_create(json data) { } } } - else if (words[0] == "`shutdown" && sender.id == "82232146579689472") { // it me + else if (words[0] == "`shutdown" && sender.user->id == "82232146579689472") { // it me ah->send_message(channel.id, ":zzz: Goodbye!"); // TODO: without needing c, hdl - c.close(hdl, websocketpp::close::status::going_away, "`shutdown command used."); } @@ -482,12 +478,10 @@ void GatewayHandler::on_event_message_create(json data) { auto it = guilds.find(words[2]); if (it != guilds.end()) { std::string user_id = words[3]; - auto it2 = std::find_if(it->second.members.begin(), it->second.members.end(), [user_id](const DiscordObjects::GuildMember &gm) { - return user_id == gm.user->id; - }); + auto it2 = it->second.members.find(user_id); if (it2 != it->second.members.end()) { - ah->send_message(channel.id, it2->to_debug_string()); + ah->send_message(channel.id, it2->second.to_debug_string()); } else { ah->send_message(channel.id, ":question: Unrecognised user."); @@ -532,13 +526,18 @@ void GatewayHandler::on_event_message_create(json data) { } } else if (command_helper->get_command(channel.guild_id, words[0], custom_command)) { + std::string args = ""; + if (message.length() > (words[0].length() + 1)) { + args = message.substr(words[0].length() + 1); + } + auto it = v8_instances.find(channel.guild_id); if (it != v8_instances.end() && custom_command.script.length() > 0) { - it->second->exec_js(custom_command.script, channel.id); + it->second->exec_js(custom_command.script, &channel, &sender, args); } } else if (games.find(channel.id) != games.end()) { // message received in channel with ongoing game - games[channel.id]->handle_answer(message, sender); + games[channel.id]->handle_answer(message, *sender.user); } } diff --git a/TriviaBot/bot/data_structures/Guild.hpp b/TriviaBot/bot/data_structures/Guild.hpp index 78ab956..aa90a44 100644 --- a/TriviaBot/bot/data_structures/Guild.hpp +++ b/TriviaBot/bot/data_structures/Guild.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "../json/json.hpp" @@ -72,7 +73,7 @@ namespace DiscordObjects { bool unavailable; std::vector channels; - std::vector members; + std::map members; std::vector roles; //std::vector> users; }; diff --git a/TriviaBot/bot/data_structures/Role.hpp b/TriviaBot/bot/data_structures/Role.hpp index 3776e06..1e88a72 100644 --- a/TriviaBot/bot/data_structures/Role.hpp +++ b/TriviaBot/bot/data_structures/Role.hpp @@ -58,13 +58,9 @@ namespace DiscordObjects { } inline std::string Role::to_debug_string() { - std::stringstream colour_ss; - colour_ss << std::setw(6) << std::setfill('0') << colour; - std::string colour_str = colour_ss.str(); - return "**__Role " + id + "__**" + "\n**name:** " + name - + "\n**colour:** #" + colour_str + + "\n**colour:** " + std::to_string(colour) + "\n**hoist:** " + std::to_string(hoist) + "\n**position:** " + std::to_string(position) + "\n**permissions:** " + std::to_string(permissions) diff --git a/TriviaBot/bot/data_structures/Text.txt b/TriviaBot/bot/data_structures/Text.txt deleted file mode 100644 index c1e31ab..0000000 --- a/TriviaBot/bot/data_structures/Text.txt +++ /dev/null @@ -1,125 +0,0 @@ -Example data: - -!!!!!!!!!!!!!!!!! GUILD_CREATE Event -{ - "afk_channel_id": null, - "afk_timeout": 300, - "channels": [ - { - "id": "200398901767962624", - "is_private": false, - "last_message_id": "201355522635595776", - "name": "general", - "permission_overwrites": [], - "position": 0, - "topic": "", - "type": "text" - }, - { - "bitrate": 64000, - "id": "200398901767962625", - "is_private": false, - "name": "General", - "permission_overwrites": [], - "position": 0, - "type": "voice", - "user_limit": 0 - } - ], - "default_message_notifications": 0, - "emojis": [], - "features": [], - "icon": null, - "id": "200398901767962624", - "joined_at": "2016-07-06T23:54:20.824000+00:00", - "large": false, - "member_count": 2, - "members": [ - { - "deaf": false, - "joined_at": "2016-07-06T23:53:41.425000+00:00", - "mute": false, - "roles": [ - "200399346498273280" - ], - "user": { - "avatar": "1dc076d2d273615dd23546c86dbdfd9c", - "discriminator": "8212", - "id": "82232146579689472", - "username": "Jack" - } - }, - { - "deaf": false, - "joined_at": "2016-07-06T23:54:20.824000+00:00", - "mute": false, - "roles": [ - "200399601507893248" - ], - "user": { - "avatar": "e871ceecaa362718af6d3174bc941977", - "bot": true, - "discriminator": "8194", - "id": "199657095258177539", - "username": "trivia-bot" - } - } - ], - "mfa_level": 0, - "name": "EleGiggle", - "owner_id": "82232146579689472", - "presences": [ - { - "game": null, - "status": "online", - "user": { - "id": "82232146579689472" - } - }, - { - "game": null, - "status": "online", - "user": { - "id": "199657095258177539" - } - } - ], - "region": "london", - "roles": [ - { - "color": 0, - "hoist": false, - "id": "200398901767962624", - "managed": false, - "mentionable": false, - "name": "@everyone", - "permissions": 36953089, - "position": 0 - }, - { - "color": 3066993, - "hoist": true, - "id": "200399346498273280", - "managed": false, - "mentionable": false, - "name": "All Perms", - "permissions": 506715199, - "position": 1 - }, - { - "color": 15844367, - "hoist": true, - "id": "200399601507893248", - "managed": false, - "mentionable": false, - "name": "Robot", - "permissions": 536083519, - "position": 1 - } - ], - "splash": null, - "unavailable": false, - "verification_level": 0, - "voice_states": [] -} - diff --git a/TriviaBot/bot/js/V8Instance.cpp b/TriviaBot/bot/js/V8Instance.cpp index 78ba8cf..04ed7c3 100644 --- a/TriviaBot/bot/js/V8Instance.cpp +++ b/TriviaBot/bot/js/V8Instance.cpp @@ -1,14 +1,20 @@ -#include +#include #include #include "V8Instance.hpp" #include "../APIHelper.hpp" #include "../Logger.hpp" -using namespace v8; +V8Instance::V8Instance(std::string guild_id, std::shared_ptr ah, std::map *guilds, std::map *channels, + std::map *users, std::map *roles) { -V8Instance::V8Instance(std::shared_ptr ah) { + this->guild_id = guild_id; this->ah = ah; + this->guilds = guilds; + this->channels = channels; + this->users = users; + this->roles = roles; + create(); } @@ -38,17 +44,91 @@ v8::Local V8Instance::create_context() { Local global = ObjectTemplate::New(isolate); // bind print() function Local self = External::New(isolate, (void *) this); - global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print, self)); - Logger::write("[v8] Created global obj, linked print function", Logger::LogLevel::Debug); + + global->Set( + String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), + FunctionTemplate::New(isolate, V8Instance::js_print, self) + ); + global->SetAccessor( + String::NewFromUtf8(isolate, "server", NewStringType::kNormal).ToLocalChecked(), + V8Instance::js_get_server, + (AccessorSetterCallback) 0, + self + ); + global->SetAccessor( + String::NewFromUtf8(isolate, "channel", NewStringType::kNormal).ToLocalChecked(), + V8Instance::js_get_channel, + (AccessorSetterCallback) 0, + self + ); + global->SetAccessor( + String::NewFromUtf8(isolate, "user", NewStringType::kNormal).ToLocalChecked(), + V8Instance::js_get_user, + (AccessorSetterCallback) 0, + self + ); + global->SetAccessor( + String::NewFromUtf8(isolate, "input", NewStringType::kNormal).ToLocalChecked(), + V8Instance::js_get_input, + (AccessorSetterCallback) 0, + self + ); + + Logger::write("[v8] Created global obj, linked data and functions", Logger::LogLevel::Debug); return Context::New(isolate, NULL, global); } +void V8Instance::js_get_server(Local property, const PropertyCallbackInfo &info) { + auto data = info.Data().As(); + V8Instance *self = static_cast(data->Value()); + + Local obj = Object::New(info.GetIsolate()); + self->add_to_obj(obj, (*self->guilds)[self->guild_id]); + info.GetReturnValue().Set(obj); +} + +void V8Instance::js_get_channel(Local property, const PropertyCallbackInfo &info) { + auto data = info.Data().As(); + V8Instance *self = static_cast(data->Value()); + + if (!self->current_channel) { + Logger::write("[v8] current_channel is null pointer", Logger::LogLevel::Severe); + info.GetReturnValue().SetNull(); + return; + } + + Local obj = Object::New(info.GetIsolate()); + self->add_to_obj(obj, (*self->current_channel)); + info.GetReturnValue().Set(obj); +} + +void V8Instance::js_get_user(Local property, const PropertyCallbackInfo &info) { + auto data = info.Data().As(); + V8Instance *self = static_cast(data->Value()); + + if (!self->current_sender) { + Logger::write("[v8] current_sender is null pointer", Logger::LogLevel::Severe); + info.GetReturnValue().SetNull(); + return; + } + + Local obj = Object::New(info.GetIsolate()); + self->add_to_obj(obj, (*self->current_sender)); + info.GetReturnValue().Set(obj); +} + +void V8Instance::js_get_input(Local property, const PropertyCallbackInfo &info) { + auto data = info.Data().As(); + V8Instance *self = static_cast(data->Value()); + + info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), self->current_input.c_str(), NewStringType::kNormal).ToLocalChecked()); +} + void V8Instance::clean_up() { Logger::write("[v8] Cleaning up", Logger::LogLevel::Debug); isolate->Exit(); isolate->Dispose(); - delete array_buffer_allocator; } void V8Instance::reload() { @@ -56,11 +136,15 @@ void V8Instance::reload() { create(); } -void V8Instance::exec_js(std::string js, std::string channel_id) { +void V8Instance::exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args) { HandleScope handle_scope(isolate); Local context(isolate->GetCurrentContext()); - Logger::write("[v8] Executing JS: " + js, Logger::LogLevel::Debug); + current_sender = sender; + current_channel = channel; + current_input = args; + + Logger::write("[v8] Preparing JS: " + js, Logger::LogLevel::Debug); Local source = String::NewFromUtf8(isolate, js.c_str(), NewStringType::kNormal).ToLocalChecked(); @@ -75,7 +159,7 @@ void V8Instance::exec_js(std::string js, std::string channel_id) { std::string err_msg = *error; Logger::write("[v8] Compilation error: " + err_msg, Logger::LogLevel::Debug); - ah->send_message(channel_id, ":warning: **Compilation error:** `" + err_msg + "`"); + ah->send_message(channel->id, ":warning: **Compilation error:** `" + err_msg + "`"); return; } @@ -87,21 +171,23 @@ void V8Instance::exec_js(std::string js, std::string channel_id) { std::string err_msg = *error; Logger::write("[v8] Runtime error: " + err_msg, Logger::LogLevel::Debug); - ah->send_message(channel_id, ":warning: **Runtime error:** `" + err_msg + "`"); - - return; + ah->send_message(channel->id, ":warning: **Runtime error:** `" + err_msg + "`"); } Logger::write("[v8] Script compiled and run", Logger::LogLevel::Debug); + current_sender = nullptr; + current_channel = nullptr; + current_input = ""; + if (print_text != "") { - ah->send_message(channel_id, print_text); + ah->send_message(channel->id, print_text); print_text = ""; } } void V8Instance::js_print(const v8::FunctionCallbackInfo &args) { - auto data = args.Data().As(); + auto data = args.Data().As(); V8Instance *self = static_cast(data->Value()); std::string output = ""; @@ -110,4 +196,130 @@ void V8Instance::js_print(const v8::FunctionCallbackInfo &args) { v8::String::Utf8Value str(args[i]); self->print_text += *str; } +} + +void V8Instance::add_to_obj(Local &object, std::string field_name, std::string value) { + add_to_obj(object, field_name, value.c_str()); +} + +void V8Instance::add_to_obj(Local &object, std::string field_name, const char value[]) { + if (value == "null") { + object->Set(String::NewFromUtf8(isolate, field_name.c_str(), NewStringType::kNormal).ToLocalChecked(), Null(isolate)); + return; + } + + object->Set(String::NewFromUtf8(isolate, field_name.c_str(), NewStringType::kNormal).ToLocalChecked(), + String::NewFromUtf8(isolate, value, NewStringType::kNormal).ToLocalChecked()); +} + +void V8Instance::add_to_obj(Local &object, std::string field_name, int32_t value) { + object->Set(String::NewFromUtf8(isolate, field_name.c_str(), NewStringType::kNormal).ToLocalChecked(), + Integer::New(isolate, value)); +} + +void V8Instance::add_to_obj(Local &object, std::string field_name, bool value) { + object->Set(String::NewFromUtf8(isolate, field_name.c_str(), NewStringType::kNormal).ToLocalChecked(), + Boolean::New(isolate, value)); +} + +void V8Instance::add_to_obj(Local &object, std::string field_name, Local value) { + object->Set(String::NewFromUtf8(isolate, field_name.c_str(), NewStringType::kNormal).ToLocalChecked(), value); +} + +void V8Instance::add_to_obj(Local &object, std::string field_name, Local value) { + object->Set(String::NewFromUtf8(isolate, field_name.c_str(), NewStringType::kNormal).ToLocalChecked(), value); +} + +void V8Instance::add_to_obj(Local &object, DiscordObjects::Guild guild) { + /* Boobot fields */ + add_to_obj(object, "Id", guild.id); + add_to_obj(object, "Name", guild.name); + add_to_obj(object, "IconUrl", "https://discordapp.com/api/guilds/" + guild.id + "/icons/" + guild.icon + ".jpg"); + + Local owner_obj = Object::New(isolate); + DiscordObjects::GuildMember &owner = guild.members[guild.owner_id]; + add_to_obj(owner_obj, owner); + add_to_obj(object, "Owner", owner_obj); + + Local roles_arr = Array::New(isolate, guild.roles.size()); + for (uint32_t i = 0; i < guild.roles.size(); i++) { + Local obj = Object::New(isolate); + DiscordObjects::Role &role = *guild.roles[i]; + add_to_obj(obj, role); + + roles_arr->Set(i, obj); + } + add_to_obj(object, "Roles", roles_arr); + + Local members_arr = Array::New(isolate, guild.members.size()); + int i = 0; + for (auto it : guild.members) { + Local obj = Object::New(isolate); + DiscordObjects::GuildMember &member = it.second; + add_to_obj(obj, member); + + members_arr->Set(i, obj); + i++; + } + add_to_obj(object, "Users", members_arr); +} + +void V8Instance::add_to_obj(Local &object, DiscordObjects::Channel channel) { + /* Boobot fields */ + add_to_obj(object, "Id", channel.id); + add_to_obj(object, "Name", channel.name); + add_to_obj(object, "Topic", channel.topic); + add_to_obj(object, "IsVoice", channel.type == "voice"); + + Local users = Array::New(isolate, 1); + users->Set(0, String::NewFromUtf8(isolate, "NOT IMPLEMENTED", NewStringType::kNormal).ToLocalChecked()); + add_to_obj(object, "Users", users); + + /* Additional fields */ + add_to_obj(object, "LastMessageId", channel.last_message_id); + add_to_obj(object, "Bitrate", channel.bitrate); + add_to_obj(object, "UserLimit", channel.user_limit); +} + +void V8Instance::add_to_obj(Local &object, DiscordObjects::Role role) { + /* Boobot fields */ + add_to_obj(object, "Id", role.id); + add_to_obj(object, "Name", role.name); + add_to_obj(object, "Position", role.position); + add_to_obj(object, "Red", "NOT IMPLEMENTED"); + add_to_obj(object, "Blue", "NOT IMPLEMENTED"); + add_to_obj(object, "Green", "NOT IMPLEMENTED"); + + /* Additional fields */ + add_to_obj(object, "Mentionable", role.mentionable); + add_to_obj(object, "Mention", "<@&" + role.id + ">"); + add_to_obj(object, "Hoist", role.hoist); +} + +void V8Instance::add_to_obj(Local &object, DiscordObjects::GuildMember member) { + /* Boobot fields */ + add_to_obj(object, "Id", member.user->id); + add_to_obj(object, "Name", member.user->username); + add_to_obj(object, "Mention", "<@!" + member.user->id + ">"); + add_to_obj(object, "AvatarUrl", "https://discordapp.com/api/users/" + member.user->id + "/avatars/" + member.user->avatar + ".jpg"); + + Local roles = Array::New(isolate, member.roles.size()); + int i = 0; + for (DiscordObjects::Role *role : member.roles) { + Local role_obj = Object::New(isolate); + add_to_obj(role_obj, *role); + + roles->Set(i, role_obj); + i++; + } + add_to_obj(object, "Roles", roles); + + add_to_obj(object, "State", "NOT IMPLEMENTED"); + add_to_obj(object, "CurrentGame", "NOT IMPLEMENTED"); + + /* Additional fields */ + add_to_obj(object, "Nick", member.nick); + add_to_obj(object, "Deaf", member.deaf); + add_to_obj(object, "Mute", member.mute); + add_to_obj(object, "JoinedAt", member.joined_at); } \ No newline at end of file diff --git a/TriviaBot/bot/js/V8Instance.hpp b/TriviaBot/bot/js/V8Instance.hpp index 3bb0615..eb7fb3f 100644 --- a/TriviaBot/bot/js/V8Instance.hpp +++ b/TriviaBot/bot/js/V8Instance.hpp @@ -2,30 +2,66 @@ #define BOT_JS_V8INSTANCE #include +#include #include #include +#include "../data_structures/Guild.hpp" +#include "../data_structures/Channel.hpp" +#include "../data_structures/Role.hpp" +#include "../data_structures/GuildMember.hpp" +#include "../data_structures/User.hpp" + class APIHelper; +using namespace v8; + class V8Instance { public: - V8Instance(std::shared_ptr ah); + V8Instance(std::string guild_id, std::shared_ptr ah, std::map *guilds, + std::map *channels, std::map *users, std::map *roles); ~V8Instance(); void reload(); - void exec_js(std::string js, std::string channel_id); + void exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args = ""); private: void clean_up(); void create(); - v8::Local create_context(); - static void js_print(const v8::FunctionCallbackInfo &args); + Local create_context(); - v8::ArrayBuffer::Allocator *array_buffer_allocator; - v8::Isolate *isolate; + void add_to_obj(Local &object, std::string field_name, std::string value); + void add_to_obj(Local &object, std::string field_name, const char value[]); + void add_to_obj(Local &object, std::string field_name, int32_t value); + void add_to_obj(Local &object, std::string field_name, bool value); + void add_to_obj(Local &object, std::string field_name, Local value); + void add_to_obj(Local &object, std::string field_name, Local value); + void add_to_obj(Local &object, DiscordObjects::Guild guild); + void add_to_obj(Local &object, DiscordObjects::Channel channel); + void add_to_obj(Local &object, DiscordObjects::Role role); + void add_to_obj(Local &object, DiscordObjects::GuildMember member); + + static void js_print(const FunctionCallbackInfo &args); + static void js_get_server(Local property, const PropertyCallbackInfo &info); + static void js_get_channel(Local property, const PropertyCallbackInfo &info); + static void js_get_user(Local property, const PropertyCallbackInfo &info); + static void js_get_input(Local property, const PropertyCallbackInfo &info); + + std::map *guilds; + std::map *channels; + std::map *users; + std::map *roles; + + std::string guild_id; + Isolate *isolate; std::shared_ptr ah; + + /* variables which change when a new command is executed */ std::string print_text; + std::string current_input; + DiscordObjects::Channel *current_channel; + DiscordObjects::GuildMember *current_sender; }; #endif \ No newline at end of file