sparkle/libs/gateway/websocket.hpp
ZZMOaG(vj3GeCEpn7k76EZFEj_PL$%u@9)Oxp;BrMykYFFxC
 1fb42627b1 added
2024-12-31 02:20:56 +05:00

216 lines
9.1 KiB
C++

#ifndef GATEWAY_WEBSOCKET_HPP_
#define GATEWAY_WEBSOCKET_HPP_
#include <utils/enums.hpp>
#include <string>
#include <unordered_map>
#include <utils/json.hpp>
#include <thread>
#include <iostream>
#include <chrono>
#include <utils/types.hpp>
#include <ixwebsocket/IXNetSystem.h>
#include <ixwebsocket/IXWebSocket.h>
using json = nlohmann::json;
using std::cout;
using std::endl;
using namespace std::chrono;
using namespace std::chrono_literals;
class WebSocket {
private:
std::unordered_map<int, std::string> events = {
{APPLICATION_COMMAND_PERMISSIONS_UPDATE, "APPLICATION_COMMAND_PERMISSIONS_UPDATE"},
{AUTO_MODERATION_ACTION_EXECUTION, "AUTO_MODERATION_ACTION_EXECUTION"},
{AUTO_MODERATION_RULE_CREATE, "AUTO_MODERATION_RULE_CREATE"},
{AUTO_MODERATION_RULE_DELETE, "AUTO_MODERATION_RULE_DELETE"},
{AUTO_MODERATION_RULE_UPDATE, "AUTO_MODERATION_RULE_UPDATE"},
{CHANNEL_CREATE, "CHANNEL_CREATE"},
{CHANNEL_DELETE, "CHANNEL_DELETE"},
{CHANNEL_PINS_UPDATE, "CHANNEL_PINS_UPDATE"},
{CHANNEL_UPDATE, "CHANNEL_UPDATE"},
{ENTITLEMENT_CREATE, "ENTITLEMENT_CREATE"},
{ENTITLEMENT_DELETE, "ENTITLEMENT_DELETE"},
{ENTITLEMENT_UPDATE, "ENTITLEMENT_UPDATE"},
{GUILD_AUDIT_LOG_ENTRY_CREATE, "GUILD_AUDIT_LOG_ENTRY_CREATE"},
{GUILD_BAN_ADD, "GUILD_BAN_ADD"},
{GUILD_BAN_REMOVE, "GUILD_BAN_REMOVE"},
{GUILD_CREATE, "GUILD_CREATE"},
{GUILD_DELETE, "GUILD_DELETE"},
{GUILD_EMOJIS_UPDATE, "GUILD_EMOJIS_UPDATE"},
{GUILD_INTEGRATIONS_UPDATE, "GUILD_INTEGRATIONS_UPDATE"},
{GUILD_MEMBER_ADD, "GUILD_MEMBER_ADD"},
{GUILD_MEMBER_REMOVE, "GUILD_MEMBER_REMOVE"},
{GUILD_MEMBERS_CHUNK, "GUILD_MEMBERS_CHUNK"},
{GUILD_MEMBER_UPDATE, "GUILD_MEMBER_UPDATE"},
{GUILD_ROLE_CREATE, "GUILD_ROLE_CREATE"},
{GUILD_ROLE_DELETE, "GUILD_ROLE_DELETE"},
{GUILD_ROLE_UPDATE, "GUILD_ROLE_UPDATE"},
{GUILD_SCHEDULED_EVENT_CREATE, "GUILD_SCHEDULED_EVENT_CREATE"},
{GUILD_SCHEDULED_EVENT_DELETE, "GUILD_SCHEDULED_EVENT_DELETE"},
{GUILD_SCHEDULED_EVENT_UPDATE, "GUILD_SCHEDULED_EVENT_UPDATE"},
{GUILD_SCHEDULED_EVENT_USER_REMOVE, "GUILD_SCHEDULED_EVENT_USER_REMOVE"},
{GUILD_SOUNDBOARD_SOUND_CREATE, "GUILD_SOUNDBOARD_SOUND_CREATE"},
{GUILD_SOUNDBOARD_SOUND_DELETE, "GUILD_SOUNDBOARD_SOUND_DELETE"},
{GUILD_SOUNDBOARD_SOUNDS_UPDATE, "GUILD_SOUNDBOARD_SOUNDS_UPDATE"},
{GUILD_SOUNDBOARD_SOUND_UPDATE, "GUILD_SOUNDBOARD_SOUND_UPDATE"},
{SOUNDBOARD_SOUNDS, "SOUNDBOARD_SOUNDS"},
{GUILD_STICKERS_UPDATE, "GUILD_STICKERS_UPDATE"},
{GUILD_UPDATE, "GUILD_UPDATE"},
{INTEGRATION_CREATE, "INTEGRATION_CREATE"},
{INTEGRATION_DELETE, "INTEGRATION_DELETE"},
{INTEGRATION_UPDATE, "INTEGRATION_UPDATE"},
{INVITE_CREATE, "INVITE_CREATE"},
{INVITE_DELETE, "INVITE_DELETE"},
{MESSAGE_CREATE, "MESSAGE_CREATE"},
{MESSAGE_DELETE, "MESSAGE_DELETE"},
{MESSAGE_DELETE_BULK, "MESSAGE_DELETE_BULK"},
{MESSAGE_POLL_VOTE_ADD, "MESSAGE_POLL_VOTE_ADD"},
{MESSAGE_POLL_VOTE_REMOVE, "MESSAGE_POLL_VOTE_REMOVE"},
{MESSAGE_REACTION_ADD, "MESSAGE_REACTION_ADD"},
{MESSAGE_REACTION_REMOVE, "MESSAGE_REACTION_REMOVE"},
{MESSAGE_REACTION_REMOVE_ALL, "MESSAGE_REACTION_REMOVE_ALL"},
{MESSAGE_REACTION_REMOVE_EMOJI, "MESSAGE_REACTION_REMOVE_EMOJI"},
{MESSAGE_UPDATE, "MESSAGE_UPDATE"},
{PRESENCE_UPDATE, "PRESENCE_UPDATE"},
{READY, "READY"},
{RESUMED, "RESUMED"},
{STAGE_INSTANCE_CREATE, "STAGE_INSTANCE_CREATE"},
{STAGE_INSTANCE_DELETE, "STAGE_INSTANCE_DELETE"},
{SUBSCRIPTION_CREATE, "SUBSCRIPTION_CREATE"},
{STAGE_INSTANCE_UPDATE, "STAGE_INSTANCE_UPDATE"},
{SUBSCRIPTION_DELETE, "SUBSCRIPTION_DELETE"},
{SUBSCRIPTION_UPDATE, "SUBSCRIPTION_UPDATE"},
{THREAD_CREATE, "THREAD_CREATE"},
{THREAD_DELETE, "THREAD_DELETE"},
{THREAD_LIST_SYNC, "THREAD_LIST_SYNC"},
{THREAD_MEMBERS_UPDATE, "THREAD_MEMBERS_UPDATE"},
{THREAD_MEMBER_UPDATE, "THREAD_MEMBER_UPDATE"},
{THREAD_UPDATE, "THREAD_UPDATE"},
{TYPING_START, "TYPING_START"},
{USER_UPDATE, "USER_UPDATE"},
{VOICE_CHANNEL_EFFECT_SEND, "VOICE_CHANNEL_EFFECT_SEND"},
{VOICE_SERVER_UPDATE, "VOICE_SERVER_UPDATE"},
{VOICE_STATE_UPDATE, "VOICE_STATE_UPDATE"},
{WEBHOOKS_UPDATE, "WEBHOOKS_UPDATE"}
};
bool connected = false;
static WebSocket* instance;
ix::WebSocket webSocket;
int heartbeat_interval, lastS, i;
json payload = { {"op", 1},{"d", nullptr} }, id, res;
std::string t;
std::unordered_map<std::string, std::function<void(const json&)>> eventHandlers;
void test() {
std::thread([this]() {
while (1) {
json prsUpdate = { {"op", 3},{"d", {{"since", 9187921},{"activities", json::array({{"name", "dsa"}, {"type", 1}})},{"status", "online"},{"afk", false}}} };
//json voice = { {"op", 4},{"d", {{"guild_id", "1322653635875967140"},{"channel_id", nullptr},{"self_mute", false},{"self_deaf", false}}} };
webSocket.send(prsUpdate.dump());
std::this_thread::sleep_for(10000ms);
json prsUpdate2 = { {"op", 3},{"d", {{"since", 9187921},{"activities", json::array({{"name", "asd"}, {"type", 1}})},{"status", "idle"},{"afk", false}}} };
webSocket.send(prsUpdate2.dump());
std::this_thread::sleep_for(10000ms);
}
}).detach();
}
WebSocket(const std::string& token, const int intents) : t(token), i(intents), lastS(0), heartbeat_interval(-1) {
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}
}}
}}
};
using namespace ix;
initNetSystem();
webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json");
webSocket.setOnMessageCallback([this](const WebSocketMessagePtr& msg) {
if (msg->type == WebSocketMessageType::Message) {
res = json::parse(msg->str);
res["s"].is_number() ? lastS = res["s"] : false;
chngcol(std::string("WEBSOCKET: " + std::to_string(lastS) + " " + res["op"].dump() + " " + res["t"].dump() + " " + res["d"]["content"].dump()), 0, 0, 120);
switch (res["op"].get<int>()) {
case 10:
heartbeat_interval = res["d"]["heartbeat_interval"].get<int>();
!connected ? connected = true, webSocket.send(id.dump()) : false;
start_heartbeat();
//test();
break;
case 0:
if (eventHandlers.find(res["t"].get<std::string>()) != eventHandlers.end()) {
eventHandlers[res["t"].get<std::string>()](res);
}
break;
}
}
});
webSocket.start();
}
public:
static WebSocket* getInstance(const std::string& token = "", const int intents = 0) {
if (!instance) {
instance = new WebSocket(token, intents);
}
return instance;
}
~WebSocket() {
webSocket.close();
ix::uninitNetSystem();
}
std::string getToken() const {
return t;
}
int getIntents() const {
return i;
}
void on(const int event, std::function<void(const json&)> handler) {
eventHandlers[events[event]] = [handler](const json& message) {
json eventData = message.get<json>();
handler(eventData);
};
}
void once(const int event, std::function<void(const json&)> handler) {
eventHandlers[events[event]] = [event, this, handler, isCalled = false](const json& message) mutable {
if (isCalled == false) {
isCalled = true;
const json& eventData = message.get<json>();
handler(eventData);
}
else {
eventHandlers.erase(events[event]);
}
};
}
void start_heartbeat() {
std::thread([this]() {
while (connected && heartbeat_interval != -1) {
std::this_thread::sleep_for(milliseconds(heartbeat_interval));
webSocket.send(payload.dump());
}
}).detach();
}
void stop() {
while (1) std::this_thread::sleep_for(1s);
}
void start() {
while (1) std::this_thread::sleep_for(1ms);
}
};
WebSocket* WebSocket::instance = nullptr;
#endif