sparkle/libs/gateway/Websocket.hpp
2025-01-25 14:21:16 +05:00

121 lines
4.8 KiB
C++

#ifndef GATEWAY_WEBSOCKET_HPP_
#define GATEWAY_WEBSOCKET_HPP_
#include <includes.hpp>
#include <thread>
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
class WebSocket {
private:
bool isBot;
int intents;
std::string token;
ix::WebSocket webSocket;
nlohmann::json payload = { {"op", 1},{"d", nullptr} }, id;
std::unordered_map<std::string, std::function<void(const nlohmann::json&)>> eventHandlers;
WebSocket& operator=(const WebSocket&) = delete;
WebSocket& operator=(WebSocket&&) = delete;
WebSocket(WebSocket&&) = delete;
WebSocket(const WebSocket&) = delete;
explicit WebSocket(const std::string& token, const int& intents, const 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", nlohmann::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 = nlohmann::json(), heartbeat_interval = 0, connected = false](const ix::WebSocketMessagePtr& msg) mutable {
if (msg->type == ix::WebSocketMessageType::Message) {
res = nlohmann::json::parse(msg->str);
Log::create(INFO, WEBSOCKET, res["op"].dump() + " " + res["t"].dump());
switch (res["op"].get<int>()) {
case 10:
heartbeat_interval = res["d"]["heartbeat_interval"].get<int>();
!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(std::chrono::milliseconds(heartbeat_interval));
webSocket.send(payload.dump());
}
}).detach();
break;
case 0:
if (eventHandlers.find(res["t"].get<std::string>()) != eventHandlers.end()) {
eventHandlers[res["t"].get<std::string>()](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 std::string& event, std::function<void(const nlohmann::json&)> handler) {
eventHandlers[event] = [handler](const nlohmann::json& message) {
handler(message.get<nlohmann::json>());
};
}
void once(const std::string& event, std::function<void(const nlohmann::json&)> handler) {
eventHandlers[event] = [event, handler, isCalled = false](const nlohmann::json& message) mutable {
isCalled == false ? isCalled = true : 0, handler(message.get<nlohmann::json>());
};
}
void start() {
while (1) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
};
#endif