#ifndef GATEWAY_WEBSOCKET_HPP_ #define GATEWAY_WEBSOCKET_HPP_ #include #include #include #include #include using std::string, std::cout, std::endl, nlohmann::json; using namespace std::chrono; using namespace std::chrono_literals; class WebSocket { private: bool isBot; int intents; std::string token; ix::WebSocket webSocket; json payload = { {"op", 1},{"d", nullptr} }, id; std::unordered_map> eventHandlers; WebSocket& operator=(const WebSocket&) = delete; WebSocket(const WebSocket&) = delete; WebSocket(const std::string& token, const int& intents, bool& isBot) { WebSocket::token = token; WebSocket::intents = intents; WebSocket::isBot = isBot; id = { {"op", 2}, {"d", { {"token", token}, {"intents", intents}, {"properties", { {"os", "linux"}, {"browser", "firefox"}, {"device", "firefox"} }}, //{"compress", 1}, {"presence", { {"activities", json::array({ { //{"name", "asdsadsadsadsa"}, //{"type", 2} } })}, {"status", "idle"}, {"since", 91879201}, {"afk", false} }} }} }; ix::initNetSystem(); webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json"); webSocket.setHandshakeTimeout(5); Log::create(INFO, WEBSOCKET, "ixwebsocket init"); webSocket.setOnMessageCallback([this, res = json(), heartbeat_interval = 0, connected = false](const ix::WebSocketMessagePtr& msg) mutable { if (msg->type == ix::WebSocketMessageType::Message) { res = json::parse(msg->str); Log::create(INFO, WEBSOCKET, res["op"].dump() + " " + res["t"].dump()); switch (res["op"].get()) { case 10: heartbeat_interval = res["d"]["heartbeat_interval"].get(); !connected ? connected = true, webSocket.send(id.dump()) : 0; std::thread([this, &heartbeat_interval, &connected]() { while (connected && heartbeat_interval != -1) { Log::create(INFO, WEBSOCKET, "Heartbeat " + std::to_string(heartbeat_interval)); std::this_thread::sleep_for(milliseconds(heartbeat_interval)); webSocket.send(payload.dump()); } }).detach(); break; case 0: if (eventHandlers.find(res["t"].get()) != eventHandlers.end()) { eventHandlers[res["t"].get()](res); } break; } } }); webSocket.start(); } public: /* void sendPresenceUpdate(int statusType, const std::string& activityName) { json prsUpdate = { {"op", 3}, {"d", { {"since", 0}, {"activities", json::array({{"name", activityName}, {"type", 2}})}, {"status", statusType == 1 ? "online" : "idle"}, {"afk", false} }} }; webSocket.send(prsUpdate.dump()); } */ static WebSocket& getInstance(const std::string& token = "", const int intents = 0, bool bot = true) { Log::create(WARNING, WEBSOCKET, "Instance event"); static WebSocket instance(token, intents, bot); return instance; } ~WebSocket() { webSocket.close(); ix::uninitNetSystem(); } std::string getToken() const { return isBot ? std::string("Bot " + WebSocket::token) : WebSocket::token; } int getIntents() const { return WebSocket::intents; } void on(const string& event, std::function handler) { eventHandlers[event] = [handler](const json& message) { handler(message.get()); }; } void once(const string& event, std::function handler) { eventHandlers[event] = [event, handler, isCalled = false](const json& message) mutable { isCalled == false ? isCalled = true : 0, handler(message.get()); }; } void start() { while (1) std::this_thread::sleep_for(1ms); } }; #endif