Toast/TriviaBot/bot/ProtocolHandler.h
2016-07-05 00:51:53 +01:00

168 lines
5.4 KiB
C++

#include "json/json.hpp"
#include <websocketpp/client.hpp>
#include <iostream>
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
using json = nlohmann::json;
/************ Opcodes **************************************************************************************************
* Code | Name | Description *
* --------------------------------------------------------------------------------------------------------------------------*
* 0 | Dispatch | dispatches an event *
* 1 | Heartbeat | used for ping checking *
* 2 | Identify | used for client handshake *
* 3 | Status Update | used to update the client status *
* 4 | Voice State Update | used to join/move/leave voice channels *
* 5 | Voice Server Ping | used for voice ping checking *
* 6 | Resume | used to resume a closed connection *
* 7 | Reconnect | used to tell clients to reconnect to the gateway *
* 8 | Request Guild Members | used to request guild members *
* 9 | Invalid Session | used to notify client they have an invalid session id *
* 10 | Hello | sent immediately after connecting, contains heartbeat and server debug information *
* 11 | Heartback ACK | sent immediately following a client heartbeat that was received *
*****************************************************************************************************************************/
class ProtocolHandler {
public:
ProtocolHandler() {
last_seq = 0;
}
void handle_data(std::string data, client &c, websocketpp::connection_hdl &hdl) {
json decoded = json::parse(data);
int op = decoded["op"];
switch (op) {
case 0: // Event dispatch
on_dispatch(decoded, c, hdl);
break;
case 10: // Hello
on_hello(decoded, c, hdl);
break;
case 11:
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat acknowledged.");
break;
default:
std::cout << data << std::endl;
}
}
void heartbeat(websocketpp::lib::error_code const & ec, client *c, websocketpp::connection_hdl *hdl) {
json heartbeat = {
{ "op", 1 },
{ "d", last_seq }
};
c->send(*hdl, heartbeat.dump(), websocketpp::frame::opcode::text);
c->set_timer(heartbeat_interval, websocketpp::lib::bind(
&ProtocolHandler::heartbeat,
this,
websocketpp::lib::placeholders::_1,
c,
hdl
));
c->get_alog().write(websocketpp::log::alevel::app, "Sent heartbeat. (seq: " + std::to_string(last_seq) + ")");
}
void on_hello(json decoded, client &c, websocketpp::connection_hdl &hdl) {
heartbeat_interval = decoded["d"]["heartbeat_interval"];
c.get_alog().write(websocketpp::log::alevel::app, "Heartbeat interval: " + std::to_string((float)heartbeat_interval / 1000) + " seconds");
c.set_timer(heartbeat_interval, websocketpp::lib::bind(
&ProtocolHandler::heartbeat,
this,
websocketpp::lib::placeholders::_1,
&c,
&hdl
));
identify(c, hdl);
}
void on_dispatch(json decoded, client &c, websocketpp::connection_hdl &hdl) {
last_seq = decoded["s"];
std::string event_name = decoded["t"];
json data = decoded["d"];
c.get_alog().write(websocketpp::log::alevel::app, "Received event: " + event_name + " (new seq value: " + std::to_string(last_seq) + ")");
if (event_name == "READY") {
user_object = data["user"];
std::string username = user_object["username"];
std::string discriminator = user_object["discriminator"];
c.get_alog().write(websocketpp::log::alevel::app, "Sign-on confirmed. (@" + username + "#" + discriminator + ")");
c.get_alog().write(websocketpp::log::alevel::app, data.dump(4));
}
else if (event_name == "GUILD_CREATE") {
std::string guild_name = data["name"];
std::string guild_id = data["id"];
guilds[guild_id] = data;
for (json &element : data["channels"]) {
if (element["type"] == "text"){
channels[element["id"]] = element;
}
}
c.get_alog().write(websocketpp::log::alevel::app, "Guild joined: " + guild_name);
}
else if (event_name == "TYPING_START") {}
else if (event_name == "MESSAGE_CREATE") {
std::string message = data["content"];
json channel = channels[data["channel_id"]];
std::string channel_name = channel["name"];
std::string channel_id = data["channel_id"];
c.get_alog().write(websocketpp::log::alevel::app, "Message received: " + message + " $" + channel_name + " ^" + channel_id);
if (message == "`trivia" || message == "`t") {
}
}
//c.get_alog().write(websocketpp::log::alevel::app, decoded.dump(2));
}
json create_message(json user, std::string channel_id) {
}
void identify(client &c, websocketpp::connection_hdl &hdl) {
json identify = {
{ "op", 2 },
{ "d", {
{ "token", bot_token },
{ "properties", {
{ "$browser", "Microsoft Windows 10" },
{ "$device", "TriviaBot-0.0" },
{ "$referrer", "" },
{ "$referring_domain", "" }
} },
{ "compress", false },
{ "large_threshold", 250 },
{ "shard", { 0, 1 } }
} }
};
c.send(hdl, identify.dump(), websocketpp::frame::opcode::text);
c.get_alog().write(websocketpp::log::alevel::app, "Sent identify payload.");
}
private:
int last_seq;
int heartbeat_interval;
const int protocol_version = 5;
const std::string bot_token = "MTk5NjU3MDk1MjU4MTc3NTM5.ClyBNQ.15qTa-XBKRtGNMMYeXCrU50GhWE";
std::map<std::string, json> guilds;
std::map<std::string, json> channels;
json user_object;
};