Basic JS implementation
This commit is contained in:
parent
d49c502869
commit
005dad899b
@ -10,7 +10,7 @@ extern std::string bot_token;
|
|||||||
GatewayHandler::GatewayHandler() {
|
GatewayHandler::GatewayHandler() {
|
||||||
last_seq = 0;
|
last_seq = 0;
|
||||||
|
|
||||||
ah = new APIHelper();
|
ah = std::make_shared<APIHelper>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GatewayHandler::handle_data(std::string data, client &c, websocketpp::connection_hdl &hdl) {
|
void GatewayHandler::handle_data(std::string data, client &c, websocketpp::connection_hdl &hdl) {
|
||||||
@ -68,14 +68,7 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
|||||||
}
|
}
|
||||||
else if (event_name == "GUILD_CREATE") {
|
else if (event_name == "GUILD_CREATE") {
|
||||||
std::string guild_id = data["id"];
|
std::string guild_id = data["id"];
|
||||||
try {
|
guilds[guild_id] = std::make_unique<DiscordObjects::Guild>(data);
|
||||||
guilds[guild_id] = std::make_unique<DiscordObjects::Guild>(data);
|
|
||||||
}
|
|
||||||
catch (std::domain_error err) {
|
|
||||||
// this doesn't even work
|
|
||||||
c.get_alog().write(websocketpp::log::elevel::rerror, "Domain error");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
c.get_alog().write(websocketpp::log::alevel::app, "Loaded guild: " + guilds[guild_id]->name);
|
c.get_alog().write(websocketpp::log::alevel::app, "Loaded guild: " + guilds[guild_id]->name);
|
||||||
|
|
||||||
@ -87,6 +80,11 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
|||||||
// add ptr to said channel list to guild's channel list
|
// add ptr to said channel list to guild's channel list
|
||||||
guilds[guild_id]->channels.push_back(std::shared_ptr<DiscordObjects::Channel>(channels[channel_id]));
|
guilds[guild_id]->channels.push_back(std::shared_ptr<DiscordObjects::Channel>(channels[channel_id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v8_instances.count(guild_id) == 0) {
|
||||||
|
v8_instances[guild_id] = std::make_unique<V8Instance>(ah);
|
||||||
|
c.get_alog().write(websocketpp::log::alevel::app, "Created v8 instance for guild " + guild_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (event_name == "TYPING_START") {}
|
else if (event_name == "TYPING_START") {}
|
||||||
else if (event_name == "MESSAGE_CREATE") {
|
else if (event_name == "MESSAGE_CREATE") {
|
||||||
@ -156,6 +154,13 @@ void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connectio
|
|||||||
else if (words[0] == "`info") {
|
else if (words[0] == "`info") {
|
||||||
ah->send_message(channel->id, ":information_source: trivia-bot by Jack. <http://github.com/jackb-p/TriviaDiscord>");
|
ah->send_message(channel->id, ":information_source: trivia-bot by Jack. <http://github.com/jackb-p/TriviaDiscord>");
|
||||||
}
|
}
|
||||||
|
else if (words[0] == "`js") {
|
||||||
|
std::string js = message.erase(0, 3);
|
||||||
|
auto it = v8_instances.find(channel->guild_id);
|
||||||
|
if (it != v8_instances.end()) {
|
||||||
|
it->second->exec_js(js, channel->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (games.find(channel->id) != games.end()) { // message received in channel with ongoing game
|
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);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "json/json.hpp"
|
#include "json/json.hpp"
|
||||||
|
|
||||||
#include "TriviaGame.hpp"
|
#include "TriviaGame.hpp"
|
||||||
|
#include "js/V8Instance.hpp"
|
||||||
#include "data_structures/User.hpp"
|
#include "data_structures/User.hpp"
|
||||||
#include "data_structures/Guild.hpp"
|
#include "data_structures/Guild.hpp"
|
||||||
#include "data_structures/Channel.hpp"
|
#include "data_structures/Channel.hpp"
|
||||||
@ -68,10 +69,12 @@ private:
|
|||||||
|
|
||||||
// <channel_id, game obj>
|
// <channel_id, game obj>
|
||||||
std::map<std::string, std::unique_ptr<TriviaGame>> games;
|
std::map<std::string, std::unique_ptr<TriviaGame>> games;
|
||||||
|
// <guild_id, v8 instance>
|
||||||
|
std::map<std::string, std::unique_ptr<V8Instance>> v8_instances;
|
||||||
|
|
||||||
std::unique_ptr<boost::thread> heartbeat_thread;
|
std::unique_ptr<boost::thread> heartbeat_thread;
|
||||||
|
|
||||||
APIHelper *ah;
|
std::shared_ptr<APIHelper> ah;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,4 +1,6 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <include/libplatform/libplatform.h>
|
||||||
|
#include <include/v8.h>
|
||||||
|
|
||||||
#include "ClientConnection.hpp"
|
#include "ClientConnection.hpp"
|
||||||
|
|
||||||
@ -7,6 +9,12 @@ std::string bot_token;
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
|
||||||
|
v8::V8::InitializeICUDefaultLocation(argv[0]);
|
||||||
|
v8::V8::InitializeExternalStartupData(argv[0]);
|
||||||
|
v8::Platform* platform = v8::platform::CreateDefaultPlatform();
|
||||||
|
v8::V8::InitializePlatform(platform);
|
||||||
|
v8::V8::Initialize();
|
||||||
|
|
||||||
if (argc == 2) {
|
if (argc == 2) {
|
||||||
bot_token = argv[1];
|
bot_token = argv[1];
|
||||||
}
|
}
|
||||||
@ -34,6 +42,10 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
std::getchar();
|
std::getchar();
|
||||||
|
|
||||||
|
v8::V8::Dispose();
|
||||||
|
v8::V8::ShutdownPlatform();
|
||||||
|
delete platform;
|
||||||
|
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "APIHelper.hpp"
|
#include "APIHelper.hpp"
|
||||||
#include "data_structures/User.hpp"
|
#include "data_structures/User.hpp"
|
||||||
|
|
||||||
TriviaGame::TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id, int total_questions, int delay) : interval(delay) {
|
TriviaGame::TriviaGame(GatewayHandler *gh, std::shared_ptr<APIHelper> ah, std::string channel_id, int total_questions, int delay) : interval(delay) {
|
||||||
this->gh = gh;
|
this->gh = gh;
|
||||||
this->ah = ah;
|
this->ah = ah;
|
||||||
this->channel_id = channel_id;
|
this->channel_id = channel_id;
|
||||||
|
@ -19,7 +19,7 @@ namespace DiscordObjects {
|
|||||||
|
|
||||||
class TriviaGame {
|
class TriviaGame {
|
||||||
public:
|
public:
|
||||||
TriviaGame(GatewayHandler *gh, APIHelper *ah, std::string channel_id, int total_questions, int delay);
|
TriviaGame(GatewayHandler *gh, std::shared_ptr<APIHelper> ah, std::string channel_id, int total_questions, int delay);
|
||||||
~TriviaGame();
|
~TriviaGame();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
@ -38,7 +38,7 @@ private:
|
|||||||
|
|
||||||
std::string channel_id;
|
std::string channel_id;
|
||||||
GatewayHandler *gh;
|
GatewayHandler *gh;
|
||||||
APIHelper *ah;
|
std::shared_ptr<APIHelper> ah;
|
||||||
|
|
||||||
const char hide_char = '#';
|
const char hide_char = '#';
|
||||||
|
|
||||||
|
101
TriviaBot/bot/js/V8Instance.cpp
Normal file
101
TriviaBot/bot/js/V8Instance.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "V8Instance.hpp"
|
||||||
|
#include "../APIHelper.hpp"
|
||||||
|
|
||||||
|
using namespace v8;
|
||||||
|
|
||||||
|
V8Instance::V8Instance(std::shared_ptr<APIHelper> ah) {
|
||||||
|
this->ah = ah;
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
V8Instance::~V8Instance() {
|
||||||
|
clean_up();
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8Instance::create() {
|
||||||
|
Isolate::CreateParams create_params;
|
||||||
|
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
|
||||||
|
|
||||||
|
isolate = Isolate::New(create_params);
|
||||||
|
isolate->Enter();
|
||||||
|
std::cout << "Created isolate." << std::endl;
|
||||||
|
|
||||||
|
Isolate::Scope isolate_scope(isolate);
|
||||||
|
HandleScope handle_scope(isolate);
|
||||||
|
|
||||||
|
// set global context
|
||||||
|
Local<Context> context = create_context();
|
||||||
|
context->Enter();
|
||||||
|
Context::Scope context_scope(context);
|
||||||
|
std::cout << "Created context and context scope." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Context> V8Instance::create_context() {
|
||||||
|
Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
|
||||||
|
// bind print() function
|
||||||
|
Local<External> self = External::New(isolate, (void *) this);
|
||||||
|
global->Set(String::NewFromUtf8(isolate, "print", NewStringType::kNormal).ToLocalChecked(), FunctionTemplate::New(isolate, V8Instance::js_print, self));
|
||||||
|
std::cout << "Created global, assigned print function." << std::endl;
|
||||||
|
|
||||||
|
return Context::New(isolate, NULL, global);
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8Instance::clean_up() {
|
||||||
|
std::cout << "Cleaning up." << std::endl;
|
||||||
|
isolate->Exit();
|
||||||
|
isolate->Dispose();
|
||||||
|
delete array_buffer_allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8Instance::reload() {
|
||||||
|
clean_up();
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8Instance::exec_js(std::string js, std::string channel_id) {
|
||||||
|
std::cout << "Isolate nullptr? " << (isolate == nullptr) << std::endl;
|
||||||
|
|
||||||
|
HandleScope handle_scope(isolate);
|
||||||
|
Local<Context> context(isolate->GetCurrentContext());
|
||||||
|
|
||||||
|
std::cout << "Executing js: " << js << std::endl;
|
||||||
|
|
||||||
|
Local<String> source = String::NewFromUtf8(isolate, js.c_str(), NewStringType::kNormal).ToLocalChecked();
|
||||||
|
std::cout << "String coverted" << std::endl;
|
||||||
|
|
||||||
|
// compile
|
||||||
|
std::cout << "Context empty? " << context.IsEmpty() << std::endl;
|
||||||
|
|
||||||
|
TryCatch try_catch(isolate);
|
||||||
|
Local<Script> script;
|
||||||
|
|
||||||
|
if (!Script::Compile(context, source).ToLocal(&script)) {
|
||||||
|
String::Utf8Value error(try_catch.Exception());
|
||||||
|
std::cerr << "Error: " << *error << std::endl;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::cout << "Compiled" << std::endl;
|
||||||
|
|
||||||
|
// run
|
||||||
|
script->Run(context);
|
||||||
|
std::cout << "Ran" << std::endl;
|
||||||
|
|
||||||
|
ah->send_message(channel_id, print_text);
|
||||||
|
print_text = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void V8Instance::js_print(const v8::FunctionCallbackInfo<v8::Value> &args) {
|
||||||
|
auto data = args.Data().As<v8::External>();
|
||||||
|
V8Instance *self = static_cast<V8Instance *>(data->Value());
|
||||||
|
|
||||||
|
std::string output = "";
|
||||||
|
for (int i = 0; i < args.Length(); i++) {
|
||||||
|
v8::HandleScope handle_scope(args.GetIsolate());
|
||||||
|
v8::String::Utf8Value str(args[i]);
|
||||||
|
self->print_text += *str;
|
||||||
|
}
|
||||||
|
}
|
31
TriviaBot/bot/js/V8Instance.hpp
Normal file
31
TriviaBot/bot/js/V8Instance.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef BOT_JS_V8INSTANCE
|
||||||
|
#define BOT_JS_V8INSTANCE
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <include/v8.h>
|
||||||
|
#include <include/libplatform/libplatform.h>
|
||||||
|
|
||||||
|
class APIHelper;
|
||||||
|
|
||||||
|
class V8Instance {
|
||||||
|
public:
|
||||||
|
V8Instance(std::shared_ptr<APIHelper> ah);
|
||||||
|
~V8Instance();
|
||||||
|
void reload();
|
||||||
|
void exec_js(std::string js, std::string channel_id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void clean_up();
|
||||||
|
void create();
|
||||||
|
v8::Local<v8::Context> create_context();
|
||||||
|
static void js_print(const v8::FunctionCallbackInfo<v8::Value> &args);
|
||||||
|
|
||||||
|
v8::ArrayBuffer::Allocator *array_buffer_allocator;
|
||||||
|
v8::Isolate *isolate;
|
||||||
|
|
||||||
|
std::shared_ptr<APIHelper> ah;
|
||||||
|
std::string print_text;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user