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
c.connect(con);
c.run();
Logger::write("Finished running", Logger::LogLevel::Debug);
}
// Event handlers
@ -120,4 +122,5 @@ void ClientConnection::on_message(websocketpp::connection_hdl hdl, message_ptr m
void ClientConnection::on_close(websocketpp::connection_hdl) {
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);
}
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"];
std::string event_name = decoded["t"];
json data = decoded["d"];
@ -145,7 +145,7 @@ void GatewayHandler::on_dispatch(json decoded, client &, websocketpp::connection
on_event_channel_delete(data);
}
else if (event_name == "MESSAGE_CREATE") {
on_event_message_create(data);
on_event_message_create(data, c, hdl);
}
else if (event_name == "PRESENCE_UPDATE") {
on_event_presence_update(data);
@ -306,7 +306,7 @@ void GatewayHandler::on_event_guild_member_update(json data) {
});
if (it != guild.members.end()) {
bool nick_changed = false;
size_t roles_change = 0;
int roles_change = 0;
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"];
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") {
if (games.find(channel.id) != games.end()) {
delete_game(channel.id);
return;
}
else {
DiscordAPI::send_message(channel.id, ":warning: Couldn't find an ongoing trivia game for this channel.");
}
return;
}
else {
try {
@ -502,14 +505,14 @@ void GatewayHandler::on_event_message_create(json data) {
games[channel.id]->start();
}
else if (words[0] == "`guilds") {
std::string m = "Guild List:\n";
std::string m = "**Guild List:**\n";
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);
}
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) {
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) {
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);
size_t seperator_loc = args.find("|");
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
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") {
if (words[1] == "channel" && words.size() == 3) {
auto it = channels.find(words[2]);
if (it != channels.end()) {
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
}
else {
if (it == channels.end()) {
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) {
auto it = guilds.find(words[2]);
if (it != guilds.end()) {
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
}
else {
if (it == guilds.end()) {
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) {
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](DiscordObjects::GuildMember *member) {
return user_id == member->user->id;
});
if (it2 != it->second.members.end()) {
DiscordAPI::send_message(channel.id, (*it2)->to_debug_string());
}
else {
DiscordAPI::send_message(channel.id, ":question: Unrecognised user.");
}
}
else {
if (it == guilds.end()) {
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) {
return user_id == member->user->id;
});
if (it2 == it->second.members.end()) {
DiscordAPI::send_message(channel.id, ":question: Unrecognised user.");
return;
}
DiscordAPI::send_message(channel.id, (*it2)->to_debug_string());
}
else if (words[1] == "role" && words.size() == 3) {
auto it = roles.find(words[2]);
if (it != roles.end()) {
DiscordAPI::send_message(channel.id, it->second.to_debug_string());
}
else {
if (it == roles.end()) {
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) {
std::string role_name = words[3];
auto it = guilds.find(words[2]);
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 {
if (it == guilds.end()) {
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 {
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);
}
auto it = v8_instances.find(channel.guild_id);
if (it != v8_instances.end() && custom_command.script.length() > 0) {
DiscordObjects::GuildMember *member = *std::find_if(guild.members.begin(), guild.members.end(), [sender](DiscordObjects::GuildMember *m) {
return sender.id == m->user->id;
});
it->second->exec_js(custom_command.script, &channel, member, args);
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);
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) {
return sender.id == m->user->id;
});
it->second->exec_js(custom_command.script, &channel, member, args);
}
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 trivia game
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
/* 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;

View File

@ -34,13 +34,13 @@ namespace Logger {
void write(std::string text, LogLevel log_level) {
time_t rawtime;
struct tm *timeinfo;
char buffer[80];
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
std::string time_str(buffer);
strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", timeinfo);
std::string time_str(buffer);
get_ostream(log_level) << "[" << time_str << "] [" << log_level << "] " << text << std::endl;
}

View File

@ -1,3 +1,6 @@
#include <thread>
#include <chrono>
#include <curl/curl.h>
#include <include/libplatform/libplatform.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");
bool retry = true;
int exit_code = 0;
while (retry) {
retry = false;
try {
ClientConnection conn;
conn.start(url + args);
}
catch (const std::exception &e) {
Logger::write("std exception: " + std::string(e.what()), Logger::LogLevel::Severe);
retry = false;
exit_code = 1;
}
catch (websocketpp::lib::error_code e) {
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 (...) {
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);
std::cout << "Press enter to exit" << std::endl;
std::getchar();
return 0;
return exit_code;
}

View File

@ -20,16 +20,11 @@ V8Instance::V8Instance(std::string guild_id, std::map<std::string, DiscordObject
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();
Logger::write("[v8] Created isolate", Logger::LogLevel::Debug);
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) {
HandleScope handle_scope(isolate);
Local<Context> context = Local<Context>::New(isolate, context_);

View File

@ -22,12 +22,9 @@ class V8Instance {
public:
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);
~V8Instance();
void reload();
void exec_js(std::string js, DiscordObjects::Channel *channel, DiscordObjects::GuildMember *sender, std::string args = "");
private:
void clean_up();
void create();
Local<Context> create_context();