2024-12-31 02:20:56 +05:00
|
|
|
#ifndef GATEWAY_WEBSOCKET_HPP_
|
|
|
|
#define GATEWAY_WEBSOCKET_HPP_
|
|
|
|
#include <utils/enums.hpp>
|
|
|
|
#include <string>
|
|
|
|
#include <utils/json.hpp>
|
|
|
|
#include <thread>
|
|
|
|
#include <iostream>
|
|
|
|
#include <chrono>
|
|
|
|
#include <utils/types.hpp>
|
2025-01-14 05:18:08 +05:00
|
|
|
#include <utils/logs.hpp>
|
2024-12-31 02:20:56 +05:00
|
|
|
#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:
|
2025-01-14 05:18:08 +05:00
|
|
|
const std::array<std::pair<const int, std::string_view>, 73> events = { {
|
2024-12-31 02:20:56 +05:00
|
|
|
{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"}
|
2024-12-31 05:58:15 +05:00
|
|
|
}};
|
2025-01-13 22:30:24 +05:00
|
|
|
bool isBot;
|
2025-01-13 14:40:21 +05:00
|
|
|
int intents;
|
|
|
|
std::string token;
|
2024-12-31 02:20:56 +05:00
|
|
|
ix::WebSocket webSocket;
|
2025-01-13 22:30:24 +05:00
|
|
|
json payload = { {"op", 1},{"d", nullptr} }, id;
|
2024-12-31 05:58:15 +05:00
|
|
|
std::unordered_map<std::string_view, std::function<void(const json&)>> eventHandlers;
|
2025-01-13 14:40:21 +05:00
|
|
|
WebSocket& operator=(const WebSocket&) = delete;
|
|
|
|
WebSocket(const WebSocket&) = delete;
|
2025-01-13 22:30:24 +05:00
|
|
|
WebSocket(const std::string& token, const int& intents, bool& isBot) {
|
2025-01-13 14:40:21 +05:00
|
|
|
WebSocket::token = token;
|
|
|
|
WebSocket::intents = intents;
|
2024-12-31 04:46:39 +05:00
|
|
|
WebSocket::isBot = isBot;
|
2024-12-31 02:20:56 +05:00
|
|
|
id = {
|
|
|
|
{"op", 2},
|
|
|
|
{"d", {
|
|
|
|
{"token", token},
|
|
|
|
{"intents", intents},
|
|
|
|
{"properties", {
|
|
|
|
{"os", "linux"},
|
|
|
|
{"browser", "firefox"},
|
|
|
|
{"device", "firefox"}
|
|
|
|
}},
|
2025-01-01 18:23:07 +05:00
|
|
|
//{"compress", 1},
|
2024-12-31 02:20:56 +05:00
|
|
|
{"presence", {
|
|
|
|
{"activities", json::array({
|
|
|
|
{
|
2025-01-01 18:23:07 +05:00
|
|
|
//{"name", "asdsadsadsadsa"},
|
|
|
|
//{"type", 2}
|
2024-12-31 02:20:56 +05:00
|
|
|
}
|
|
|
|
})},
|
|
|
|
{"status", "idle"},
|
|
|
|
{"since", 91879201},
|
|
|
|
{"afk", false}
|
|
|
|
}}
|
|
|
|
}}
|
|
|
|
};
|
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-14 05:18:08 +05:00
|
|
|
webSocket.setHandshakeTimeout(5);
|
|
|
|
Logs::create(INFO, WEBSOCKET, "ixwebsocket init");
|
2025-01-13 22:34:42 +05:00
|
|
|
webSocket.setOnMessageCallback([this, res = json(), heartbeat_interval = 0, connected = false](const ix::WebSocketMessagePtr& msg) mutable {
|
2025-01-06 22:18:30 +05:00
|
|
|
if (msg->type == ix::WebSocketMessageType::Message) {
|
2024-12-31 02:20:56 +05:00
|
|
|
res = json::parse(msg->str);
|
2025-01-14 05:18:08 +05:00
|
|
|
//#ifdef DEBUG
|
|
|
|
Logs::create(INFO, WEBSOCKET, res["op"].dump() + " " + res["t"].dump());
|
|
|
|
//#endif
|
2024-12-31 02:20:56 +05:00
|
|
|
switch (res["op"].get<int>()) {
|
|
|
|
case 10:
|
|
|
|
heartbeat_interval = res["d"]["heartbeat_interval"].get<int>();
|
2025-01-13 22:30:24 +05:00
|
|
|
!connected ? connected = true, webSocket.send(id.dump()) : 0;
|
|
|
|
std::thread([this, &heartbeat_interval, &connected]() {
|
2025-01-13 14:40:21 +05:00
|
|
|
while (connected && heartbeat_interval != -1) {
|
2025-01-14 05:18:08 +05:00
|
|
|
Logs::create(INFO, WEBSOCKET, "Heartbeat " + std::to_string(heartbeat_interval));
|
2025-01-13 14:40:21 +05:00
|
|
|
std::this_thread::sleep_for(milliseconds(heartbeat_interval));
|
|
|
|
webSocket.send(payload.dump());
|
|
|
|
}
|
|
|
|
}).detach();
|
2024-12-31 02:20:56 +05:00
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
if (eventHandlers.find(res["t"].get<std::string>()) != eventHandlers.end()) {
|
|
|
|
eventHandlers[res["t"].get<std::string>()](res);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
webSocket.start();
|
|
|
|
}
|
|
|
|
public:
|
2025-01-13 14:40:21 +05:00
|
|
|
/*
|
2024-12-31 05:58:15 +05:00
|
|
|
void sendPresenceUpdate(int statusType, const std::string& activityName) {
|
|
|
|
json prsUpdate = {
|
|
|
|
{"op", 3},
|
|
|
|
{"d", {
|
2024-12-31 06:32:29 +05:00
|
|
|
{"since", 0},
|
|
|
|
{"activities", 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-13 14:40:21 +05:00
|
|
|
*/
|
|
|
|
static WebSocket& getInstance(const std::string& token = "", const int intents = 0, bool bot = true) {
|
2025-01-14 05:18:08 +05:00
|
|
|
Logs::create(WARNING, 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
|
|
|
}
|
|
|
|
void on(const int event, std::function<void(const json&)> handler) {
|
2024-12-31 05:58:15 +05:00
|
|
|
eventHandlers[events[event].second] = [handler](const json& message) {
|
2025-01-13 22:30:24 +05:00
|
|
|
handler(message.get<json>());
|
2024-12-31 02:20:56 +05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
void once(const int event, std::function<void(const json&)> handler) {
|
2025-01-13 22:30:24 +05:00
|
|
|
eventHandlers[events[event].second] = [event, handler, isCalled = false](const json& message) mutable {
|
|
|
|
isCalled == false ? isCalled = true : 0, handler(message.get<json>());
|
2024-12-31 02:20:56 +05:00
|
|
|
};
|
|
|
|
}
|
2025-01-14 05:18:08 +05:00
|
|
|
void start() {
|
2024-12-31 02:20:56 +05:00
|
|
|
while (1) std::this_thread::sleep_for(1ms);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|