sparkle/libs/gateway/Websocket.hpp

141 lines
5.5 KiB
C++
Raw Normal View History

2024-12-31 02:20:56 +05:00
#ifndef GATEWAY_WEBSOCKET_HPP_
#define GATEWAY_WEBSOCKET_HPP_
2025-01-25 13:22:59 +05:00
#include <includes.hpp>
2024-12-31 02:20:56 +05:00
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
2025-01-26 15:48:38 +05:00
class EventEmitter {
private:
using eventHandlers = std::function<void(const nlohmann::json&)>;
std::unordered_map<std::string, std::list<eventHandlers>> handlers;
2025-01-26 16:12:25 +05:00
protected:
void emit(const std::string& event, const nlohmann::json& data) {
if (handlers.find(event) != handlers.end()) {
for (const auto& handler : handlers[event]) {
handler(data);
}
}
}
2025-01-26 15:48:38 +05:00
public:
void on(const std::string& event, eventHandlers handler) {
handlers[event].emplace_back(handler);
}
void once(const std::string& event, eventHandlers handler) {
auto wrappedHandler = [this, event, handler](const nlohmann::json& data) {
handler(data);
off(event, handler);
};
handlers[event].emplace_back(wrappedHandler);
}
void off(const std::string& event, eventHandlers handler) {
if (handlers.find(event) != handlers.end()) {
auto& vec = handlers[event];
vec.erase(std::remove_if(vec.begin(), vec.end(), [&handler](const eventHandlers& h) {
return h.target<eventHandlers>() == handler.target<eventHandlers>();
}), vec.end());
}
}
};
class WebSocket : public EventEmitter {
2024-12-31 02:20:56 +05:00
private:
2025-01-13 14:40:21 +05:00
std::string token;
2025-01-26 15:48:38 +05:00
int intents;
bool isBot;
2024-12-31 02:20:56 +05:00
ix::WebSocket webSocket;
2025-01-26 15:48:38 +05:00
const nlohmann::json payload = { {"op", 1}, {"d", nullptr} };
2025-01-13 14:40:21 +05:00
WebSocket& operator=(const WebSocket&) = delete;
2025-01-25 14:21:16 +05:00
WebSocket& operator=(WebSocket&&) = delete;
WebSocket(WebSocket&&) = delete;
2025-01-13 14:40:21 +05:00
WebSocket(const WebSocket&) = delete;
2025-01-26 15:48:38 +05:00
WebSocket(const std::string& token = "", const int& intents = 0, const bool& isBot = true) : token(token), intents(intents), isBot(isBot) {
nlohmann::json id = {
2024-12-31 02:20:56 +05:00
{"op", 2},
{"d", {
{"token", token},
{"intents", intents},
{"properties", {
{"os", "linux"},
{"browser", "firefox"},
{"device", "firefox"}
}},
2025-01-26 15:48:38 +05:00
{"compress", 1},
2025-01-25 13:22:59 +05:00
{"presence", {
{"activities", nlohmann::json::array({
{
2025-01-26 16:12:25 +05:00
{"name", "meow"},
2025-01-26 15:48:38 +05:00
{"type", 2}
2025-01-25 13:22:59 +05:00
}
})},
{"status", "idle"},
{"since", 91879201},
{"afk", false}
2024-12-31 02:20:56 +05:00
}}
2025-01-25 13:22:59 +05:00
}}
2024-12-31 02:20:56 +05:00
};
2025-01-06 22:18:30 +05:00
ix::initNetSystem();
2024-12-31 02:20:56 +05:00
webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json");
2025-01-26 16:12:25 +05:00
//webSocket.disableAutomaticReconnection();
2025-01-19 04:35:20 +05:00
Log::create(INFO, WEBSOCKET, "ixwebsocket init");
2025-01-26 15:48:38 +05:00
webSocket.setOnMessageCallback([this, res = nlohmann::json(), heartbeat_interval = 0, connected = false, id](const ix::WebSocketMessagePtr& msg) mutable {
2025-01-26 16:12:25 +05:00
switch (msg->type) {
case 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: emit(res["t"].get<std::string>(), res); break;
}
break;
case ix::WebSocketMessageType::Error:
std::cout << msg->errorInfo.reason << std::endl;
exit(-1);
break;
default:
break;
2024-12-31 02:20:56 +05:00
}
});
webSocket.start();
}
public:
2025-01-26 16:12:25 +05:00
[[maybe_unused]]
void sendPresenceUpdate(const int& statusType, const std::string& activityName) {
nlohmann::json prsUpdate = {
2024-12-31 05:58:15 +05:00
{"op", 3},
{"d", {
2024-12-31 06:32:29 +05:00
{"since", 0},
2025-01-26 16:12:25 +05:00
{"activities", nlohmann::json::array({{"name", activityName}, {"type", 2}})},
2024-12-31 05:58:15 +05:00
{"status", statusType == 1 ? "online" : "idle"},
{"afk", false}
}}
};
webSocket.send(prsUpdate.dump());
}
2025-01-26 15:48:38 +05:00
static WebSocket& getInstance(const std::string& token = "", const int& intents = 0, const bool& bot = true) {
2025-01-25 18:40:57 +05:00
Log::create(INFO, WEBSOCKET, "Instance event");
2025-01-13 14:40:21 +05:00
static WebSocket instance(token, intents, bot);
2024-12-31 02:20:56 +05:00
return instance;
}
~WebSocket() {
webSocket.close();
ix::uninitNetSystem();
}
std::string getToken() const {
2025-01-13 14:40:21 +05:00
return isBot ? std::string("Bot " + WebSocket::token) : WebSocket::token;
2024-12-31 02:20:56 +05:00
}
int getIntents() const {
2025-01-13 14:40:21 +05:00
return WebSocket::intents;
2024-12-31 02:20:56 +05:00
}
2025-01-14 05:18:08 +05:00
void start() {
2025-01-26 15:48:38 +05:00
while (1) std::this_thread::sleep_for(std::chrono::milliseconds(1));
2024-12-31 02:20:56 +05:00
}
};
#endif