128 lines
4.9 KiB
C++
128 lines
4.9 KiB
C++
#include "websocket.hpp"
|
|
void EventEmitter::emit(const std::string& event, const nlohmann::json& data) {
|
|
if (auto it = handlers.find(event); it != handlers.end()) {
|
|
std::for_each(it->second.begin(), it->second.end(), [&data](const auto& handler) {
|
|
handler(data);
|
|
});
|
|
}
|
|
}
|
|
void EventEmitter::getEvents() const {
|
|
Log::create(CRITICAL, WEBSOCKET, "Event list");
|
|
for (const auto& handler : handlers) {
|
|
Log::create(INFO, WEBSOCKET, handler.first);
|
|
}
|
|
Log::create(CRITICAL, WEBSOCKET, "End of list");
|
|
}
|
|
void EventEmitter::start() const {
|
|
while (true) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
void EventEmitter::on(const std::string& event, eventHandlers handler) {
|
|
handlers[event].emplace_back(std::move(handler));
|
|
}
|
|
void EventEmitter::once(const std::string& event, const eventHandlers& handler) {
|
|
auto wrappedHandler = [this, event, handler](const nlohmann::json& data) {
|
|
handler(data);
|
|
off(event, handler);
|
|
};
|
|
handlers[event].emplace_back(std::move(wrappedHandler));
|
|
}
|
|
void EventEmitter::off(const std::string& event, eventHandlers handler) {
|
|
if (auto it = handlers.find(event); it != handlers.end()) {
|
|
auto& vec = it->second;
|
|
vec.erase(std::ranges::remove_if(vec, [&handler](const eventHandlers& h) {
|
|
return h.target<eventHandlers>() == handler.target<eventHandlers>();
|
|
}).begin(), vec.end());
|
|
}
|
|
}
|
|
WebSocket::WebSocket(const std::string& token, int intents, bool isBot) : token(token), intents(intents), isBot(isBot) {
|
|
nlohmann::json id = {
|
|
{"op", GatewayOpcodes::Identify},
|
|
{"d", {
|
|
{"token", token},
|
|
{"intents", intents},
|
|
{"properties", {
|
|
{"os", "linux"},
|
|
{"browser", "firefox"},
|
|
{"device", "firefox"}
|
|
}},
|
|
{"compress", 1},
|
|
{"presence", {
|
|
{"activities", nlohmann::json::array({
|
|
{
|
|
{"name", "meow"},
|
|
{"type", 2}
|
|
}
|
|
})},
|
|
{"status", "idle"},
|
|
{"since", 0},
|
|
{"afk", false}
|
|
}}
|
|
}}
|
|
};
|
|
ix::initNetSystem();
|
|
webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json");
|
|
webSocket.disableAutomaticReconnection();
|
|
Log::create(INFO, WEBSOCKET, "ixwebsocket init");
|
|
webSocket.setOnMessageCallback([this, res = nlohmann::json(), heartbeat_interval = 0, connected = false, id](const ix::WebSocketMessagePtr& msg) mutable {
|
|
switch (msg->type) {
|
|
case ix::WebSocketMessageType::Message:
|
|
res = nlohmann::json::parse(msg->str);
|
|
Log::create(INFO, WEBSOCKET, std::to_string(res["op"].get<int>()) + " " + res["t"].dump());
|
|
switch (res["op"].get<GatewayOpcodes>()) {
|
|
case GatewayOpcodes::Hello:
|
|
heartbeat_interval = res["d"]["heartbeat_interval"].get<int>();
|
|
!connected ? connected = true, webSocket.send(id.dump()) : false;
|
|
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 GatewayOpcodes::Dispatch:
|
|
Log::create(INFO, WEBSOCKET, res.dump());
|
|
emit(res["t"].get<std::string>(), res);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case ix::WebSocketMessageType::Error:
|
|
Log::force_create(ERROR, WEBSOCKET, msg->errorInfo.reason);
|
|
exit(-1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
});
|
|
webSocket.start();
|
|
}
|
|
auto WebSocket::getInstance(const std::string& token, int intents, bool bot) -> WebSocket& {
|
|
Log::create(INFO, WEBSOCKET, "Instance event");
|
|
static WebSocket instance(token, intents, bot);
|
|
return instance;
|
|
}
|
|
WebSocket::~WebSocket() {
|
|
webSocket.close();
|
|
ix::uninitNetSystem();
|
|
}
|
|
auto WebSocket::getToken() const -> std::string {
|
|
return this->isBot ? std::string("Bot " + this->token) : this->token;
|
|
}
|
|
auto WebSocket::getIntents() const -> int {
|
|
return this->intents;
|
|
}
|
|
_maybe_unused void WebSocket::sendPresenceUpdate(const char* statusType, const std::string& activityName, const int& activityType) {
|
|
nlohmann::json prsUpdate = {
|
|
{"op", 3},
|
|
{"d", {
|
|
{"since", 0},
|
|
{"activities", nlohmann::json::array({{"name", activityName}, {"type", activityType}})},
|
|
{"status", statusType},
|
|
{"afk", false}
|
|
}}
|
|
};
|
|
webSocket.send(prsUpdate.dump());
|
|
} |