Fix shutting down, other minor cleanups

This commit is contained in:
Jack Bond-Preston 2016-08-14 17:46:29 +01:00
parent 8ebe6c2c4e
commit da93eda0be
7 changed files with 98 additions and 88 deletions

View File

@ -66,6 +66,8 @@ void ClientConnection::start(std::string uri) {
// Open the connection // Open the connection
c.connect(con); c.connect(con);
c.run(); c.run();
Logger::write("Finished running", Logger::LogLevel::Debug);
} }
// Event handlers // Event handlers
@ -120,4 +122,5 @@ void ClientConnection::on_message(websocketpp::connection_hdl hdl, message_ptr m
void ClientConnection::on_close(websocketpp::connection_hdl) { void ClientConnection::on_close(websocketpp::connection_hdl) {
Logger::write("Connection closed", Logger::LogLevel::Info); Logger::write("Connection closed", Logger::LogLevel::Info);
c.stop();
} }

View File

@ -100,7 +100,7 @@ void GatewayHandler::on_hello(json decoded, client &c, websocketpp::connection_h
send_identify(c, hdl); send_identify(c, hdl);
} }
void GatewayHandler::on_dispatch(json decoded, client &, websocketpp::connection_hdl &) { void GatewayHandler::on_dispatch(json decoded, client &c, websocketpp::connection_hdl &hdl) {
last_seq = decoded["s"]; last_seq = decoded["s"];
std::string event_name = decoded["t"]; std::string event_name = decoded["t"];
json data = decoded["d"]; json data = decoded["d"];
@ -145,7 +145,7 @@ void GatewayHandler::on_dispatch(json decoded, client &, websocketpp::connection
on_event_channel_delete(data); on_event_channel_delete(data);
} }
else if (event_name == "MESSAGE_CREATE") { else if (event_name == "MESSAGE_CREATE") {
on_event_message_create(data); on_event_message_create(data, c, hdl);
} }
else if (event_name == "PRESENCE_UPDATE") { else if (event_name == "PRESENCE_UPDATE") {
on_event_presence_update(data); on_event_presence_update(data);
@ -306,7 +306,7 @@ void GatewayHandler::on_event_guild_member_update(json data) {
}); });
if (it != guild.members.end()) { if (it != guild.members.end()) {
bool nick_changed = false; bool nick_changed = false;
size_t roles_change = 0; int roles_change = 0;
DiscordObjects::GuildMember *member = (*it); DiscordObjects::GuildMember *member = (*it);
@ -448,7 +448,7 @@ void GatewayHandler::on_event_channel_delete(json data) {
} }
} }
void GatewayHandler::on_event_message_create(json data) { void GatewayHandler::on_event_message_create(json data, client &c, websocketpp::connection_hdl &hdl) {
std::string message = data["content"]; std::string message = data["content"];
DiscordObjects::Channel &channel = channels[data["channel_id"]]; DiscordObjects::Channel &channel = channels[data["channel_id"]];
@ -481,8 +481,11 @@ void GatewayHandler::on_event_message_create(json data) {
else if (words[1] == "stop" || words[1] == "s") { else if (words[1] == "stop" || words[1] == "s") {
if (games.find(channel.id) != games.end()) { if (games.find(channel.id) != games.end()) {
delete_game(channel.id); delete_game(channel.id);
return;
} }
else {
DiscordAPI::send_message(channel.id, ":warning: Couldn't find an ongoing trivia game for this channel.");
}
return;
} }
else { else {
try { try {
@ -502,14 +505,14 @@ void GatewayHandler::on_event_message_create(json data) {
games[channel.id]->start(); games[channel.id]->start();
} }
else if (words[0] == "`guilds") { else if (words[0] == "`guilds") {
std::string m = "Guild List:\n"; std::string m = "**Guild List:**\n";
for (auto &gu : guilds) { for (auto &gu : guilds) {
m += "> " + gu.second.name + " (" + gu.second.id + ") Channels: " + std::to_string(gu.second.channels.size()) + "\n"; m += ":small_orange_diamond: " + gu.second.name + " (" + gu.second.id + ") Channels: " + std::to_string(gu.second.channels.size()) + "\n";
} }
DiscordAPI::send_message(channel.id, m); DiscordAPI::send_message(channel.id, m);
} }
else if (words[0] == "`info") { else if (words[0] == "`info") {
DiscordAPI::send_message(channel.id, ":information_source: trivia-bot by Jack. <http://github.com/jackb-p/TriviaDiscord>"); DiscordAPI::send_message(channel.id, ":information_source: **trivia-bot** by Jack. <http://github.com/jackb-p/TriviaDiscord>");
} }
else if (words[0] == "~js" && words.size() > 1) { else if (words[0] == "~js" && words.size() > 1) {
DiscordObjects::GuildMember *member = *std::find_if(guild.members.begin(), guild.members.end(), [sender](DiscordObjects::GuildMember *m) { DiscordObjects::GuildMember *member = *std::find_if(guild.members.begin(), guild.members.end(), [sender](DiscordObjects::GuildMember *m) {
@ -522,6 +525,16 @@ void GatewayHandler::on_event_message_create(json data) {
} }
} }
else if (words[0] == "~createjs" && words.size() > 1) { else if (words[0] == "~createjs" && words.size() > 1) {
auto &member = *std::find_if(guild.members.begin(), guild.members.end(), [sender](DiscordObjects::GuildMember *m) { return sender.id == m->user->id; });
bool allowed = std::find_if(member->roles.begin(), member->roles.end(), [](DiscordObjects::Role *r) {
return r->name == "Admin" || r->name == "Moderator" || r->name == "Coder"; // TODO: customisation here
}) == member->roles.end(); // checks if the user has the required roles
if (!allowed) {
DiscordAPI::send_message(channel.id, ":warning: You do not have permission to use this command.");
return;
}
std::string args = message.substr(10); std::string args = message.substr(10);
size_t seperator_loc = args.find("|"); size_t seperator_loc = args.find("|");
if (seperator_loc != std::string::npos) { if (seperator_loc != std::string::npos) {
@ -540,75 +553,76 @@ void GatewayHandler::on_event_message_create(json data) {
} }
else if (words[0] == "`shutdown" && sender.id == "82232146579689472") { // it me else if (words[0] == "`shutdown" && sender.id == "82232146579689472") { // it me
DiscordAPI::send_message(channel.id, ":zzz: Goodbye!"); DiscordAPI::send_message(channel.id, ":zzz: Goodbye!");
// TODO: without needing c, hdl - c.close(hdl, websocketpp::close::status::going_away, "`shutdown command used."); for (auto &game : games) {
delete_game(game.first);
}
v8_instances.clear();
c.close(hdl, websocketpp::close::status::going_away, "");
} }
else if (words[0] == "`debug") { else if (words[0] == "`debug") {
if (words[1] == "channel" && words.size() == 3) { if (words[1] == "channel" && words.size() == 3) {
auto it = channels.find(words[2]); auto it = channels.find(words[2]);
if (it != channels.end()) { if (it == channels.end()) {
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised channel."); DiscordAPI::send_message(channel.id, ":question: Unrecognised channel.");
return;
} }
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
} }
else if (words[1] == "guild" && words.size() == 3) { else if (words[1] == "guild" && words.size() == 3) {
auto it = guilds.find(words[2]); auto it = guilds.find(words[2]);
if (it != guilds.end()) { if (it == guilds.end()) {
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised guild."); DiscordAPI::send_message(channel.id, ":question: Unrecognised guild.");
return;
} }
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
} }
else if (words[1] == "member" && words.size() == 4) { else if (words[1] == "member" && words.size() == 4) {
auto it = guilds.find(words[2]); auto it = guilds.find(words[2]);
if (it != guilds.end()) { if (it == guilds.end()) {
std::string user_id = words[3]; DiscordAPI::send_message(channel.id, ":question: Unrecognised guild.");
return;
}
std::string user_id = words[3];
auto it2 = std::find_if(it->second.members.begin(), it->second.members.end(), [user_id](DiscordObjects::GuildMember *member) { auto it2 = std::find_if(it->second.members.begin(), it->second.members.end(), [user_id](DiscordObjects::GuildMember *member) {
return user_id == member->user->id; return user_id == member->user->id;
}); });
if (it2 != it->second.members.end()) { if (it2 == it->second.members.end()) {
DiscordAPI::send_message(channel.id, (*it2)->to_debug_string());
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised user."); DiscordAPI::send_message(channel.id, ":question: Unrecognised user.");
return;
} }
}
else { DiscordAPI::send_message(channel.id, (*it2)->to_debug_string());
DiscordAPI::send_message(channel.id, ":question: Unrecognised guild.");
}
} }
else if (words[1] == "role" && words.size() == 3) { else if (words[1] == "role" && words.size() == 3) {
auto it = roles.find(words[2]); auto it = roles.find(words[2]);
if (it != roles.end()) { if (it == roles.end()) {
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised role."); DiscordAPI::send_message(channel.id, ":question: Unrecognised role.");
return;
} }
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
} }
else if (words[1] == "role" && words.size() == 4) { else if (words[1] == "role" && words.size() == 4) {
std::string role_name = words[3]; std::string role_name = words[3];
auto it = guilds.find(words[2]); auto it = guilds.find(words[2]);
if (it != guilds.end()) { if (it == guilds.end()) {
auto check_lambda = [role_name](DiscordObjects::Role *r) {
return role_name == r->name;
};
auto it2 = std::find_if(it->second.roles.begin(), it->second.roles.end(), check_lambda);
if (it2 != it->second.roles.end()) {
DiscordAPI::send_message(channel.id, (*it2)->to_debug_string());
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised role.");
}
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised guild."); DiscordAPI::send_message(channel.id, ":question: Unrecognised guild.");
return;
} }
auto it2 = std::find_if(it->second.roles.begin(), it->second.roles.end(), [role_name](DiscordObjects::Role *r) {
return role_name == r->name;
});
if (it2 == it->second.roles.end()) {
DiscordAPI::send_message(channel.id, ":question: Unrecognised role.");
return;
}
DiscordAPI::send_message(channel.id, (*it2)->to_debug_string());
} }
else { else {
DiscordAPI::send_message(channel.id, ":question: Unknown parameters."); DiscordAPI::send_message(channel.id, ":question: Unknown parameters.");
@ -620,15 +634,23 @@ void GatewayHandler::on_event_message_create(json data) {
args = message.substr(words[0].length() + 1); args = message.substr(words[0].length() + 1);
} }
if (custom_command.script.length() == 0) {
DiscordAPI::send_message(channel.id, ":warning: Script has 0 length.");
return;
}
auto it = v8_instances.find(channel.guild_id); auto it = v8_instances.find(channel.guild_id);
if (it != v8_instances.end() && custom_command.script.length() > 0) { if (it == v8_instances.end()) {
DiscordAPI::send_message(channel.id, ":warning: No V8 instance exists for this server - it's our fault not yours!");
return;
}
DiscordObjects::GuildMember *member = *std::find_if(guild.members.begin(), guild.members.end(), [sender](DiscordObjects::GuildMember *m) { DiscordObjects::GuildMember *member = *std::find_if(guild.members.begin(), guild.members.end(), [sender](DiscordObjects::GuildMember *m) {
return sender.id == m->user->id; return sender.id == m->user->id;
}); });
it->second->exec_js(custom_command.script, &channel, member, args); it->second->exec_js(custom_command.script, &channel, member, args);
} }
} else if (games.find(channel.id) != games.end()) { // message received in channel with ongoing trivia 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);
} }
} }

View File

@ -81,7 +81,7 @@ private:
void on_event_channel_delete(json data); // https://discordapp.com/developers/docs/topics/gateway#channel-delete void on_event_channel_delete(json data); // https://discordapp.com/developers/docs/topics/gateway#channel-delete
/* message events */ /* message events */
void on_event_message_create(json data); // https://discordapp.com/developers/docs/topics/gateway#message-create void on_event_message_create(json data, client &c, websocketpp::connection_hdl &hdl); // https://discordapp.com/developers/docs/topics/gateway#message-create
const int protocol_version = 5; const int protocol_version = 5;

View File

@ -1,3 +1,6 @@
#include <thread>
#include <chrono>
#include <curl/curl.h> #include <curl/curl.h>
#include <include/libplatform/libplatform.h> #include <include/libplatform/libplatform.h>
#include <include/v8.h> #include <include/v8.h>
@ -31,21 +34,26 @@ int main(int argc, char *argv[]) {
std::string url = DiscordAPI::get_gateway().value("url", "wss://gateway.discord.gg"); std::string url = DiscordAPI::get_gateway().value("url", "wss://gateway.discord.gg");
bool retry = true; bool retry = true;
int exit_code = 0;
while (retry) { while (retry) {
retry = false;
try { try {
ClientConnection conn; ClientConnection conn;
conn.start(url + args); conn.start(url + args);
} }
catch (const std::exception &e) { catch (const std::exception &e) {
Logger::write("std exception: " + std::string(e.what()), Logger::LogLevel::Severe); Logger::write("std exception: " + std::string(e.what()), Logger::LogLevel::Severe);
retry = false; exit_code = 1;
} }
catch (websocketpp::lib::error_code e) { catch (websocketpp::lib::error_code e) {
Logger::write("websocketpp exception: " + e.message(), Logger::LogLevel::Severe); Logger::write("websocketpp exception: " + e.message(), Logger::LogLevel::Severe);
std::this_thread::sleep_for(std::chrono::seconds(10));
retry = true; // should just be an occasional connection issue
} }
catch (...) { catch (...) {
Logger::write("other exception.", Logger::LogLevel::Severe); Logger::write("other exception.", Logger::LogLevel::Severe);
retry = false; exit_code = 2;
} }
} }
@ -57,8 +65,5 @@ int main(int argc, char *argv[]) {
Logger::write("Cleaned up", Logger::LogLevel::Info); Logger::write("Cleaned up", Logger::LogLevel::Info);
std::cout << "Press enter to exit" << std::endl; return exit_code;
std::getchar();
return 0;
} }

View File

@ -20,16 +20,11 @@ V8Instance::V8Instance(std::string guild_id, std::map<std::string, DiscordObject
create(); create();
} }
V8Instance::~V8Instance() {
clean_up();
}
void V8Instance::create() { void V8Instance::create() {
Isolate::CreateParams create_params; Isolate::CreateParams create_params;
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator(); create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
isolate = Isolate::New(create_params); isolate = Isolate::New(create_params);
isolate->Enter();
Logger::write("[v8] Created isolate", Logger::LogLevel::Debug); Logger::write("[v8] Created isolate", Logger::LogLevel::Debug);
Isolate::Scope isolate_scope(isolate); Isolate::Scope isolate_scope(isolate);
@ -661,18 +656,6 @@ void V8Instance::js_shuffle(const v8::FunctionCallbackInfo<v8::Value> &args) {
} }
} }
void V8Instance::clean_up() {
Logger::write("[v8] Cleaning up", Logger::LogLevel::Debug);
isolate->Exit();
isolate->Dispose();
}
void V8Instance::reload() {
clean_up();
create();
}
void V8Instance::exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args) { void V8Instance::exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args) {
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
Local<Context> context = Local<Context>::New(isolate, context_); Local<Context> context = Local<Context>::New(isolate, context_);

View File

@ -22,12 +22,9 @@ class V8Instance {
public: public:
V8Instance(std::string guild_id, std::map<std::string, DiscordObjects::Guild> *guilds, V8Instance(std::string guild_id, std::map<std::string, DiscordObjects::Guild> *guilds,
std::map<std::string, DiscordObjects::Channel> *channels, std::map<std::string, DiscordObjects::User> *users, std::map<std::string, DiscordObjects::Role> *roles); std::map<std::string, DiscordObjects::Channel> *channels, std::map<std::string, DiscordObjects::User> *users, std::map<std::string, DiscordObjects::Role> *roles);
~V8Instance();
void reload();
void exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args = ""); void exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args = "");
private: private:
void clean_up();
void create(); void create();
Local<Context> create_context(); Local<Context> create_context();