#ifndef GATEWAY_WEBSOCKET_HPP_ #define GATEWAY_WEBSOCKET_HPP_ #include #include #include #include #include #include #include #include #include using json = nlohmann::json; using std::cout; using std::endl; using namespace std::chrono; using namespace std::chrono_literals; class WebSocket { private: std::array, 73> 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 bool initialized, isBot; static WebSocket* instance; static int i; static std::string t; ix::WebSocket webSocket; int heartbeat_interval, lastS; json payload = { {"op", 1},{"d", nullptr} }, id, res; std::unordered_map> eventHandlers; WebSocket(const std::string& token, const int intents, bool isBot) : lastS(0), heartbeat_interval(-1) { WebSocket::t = token; WebSocket::i = intents; WebSocket::isBot = isBot; 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()), 0, 0, 120); switch (res["op"].get()) { case 10: heartbeat_interval = res["d"]["heartbeat_interval"].get(); !connected ? connected = true, webSocket.send(id.dump()) : false; start_heartbeat(); break; case 0: if (eventHandlers.find(res["t"].get()) != eventHandlers.end()) { eventHandlers[res["t"].get()](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) { if (!instance) { if (token.empty() || intents == 0) { throw std::invalid_argument("Token and intents is empty."); } instance = new WebSocket(token, intents, bot); initialized = true; } return instance; } ~WebSocket() { webSocket.close(); ix::uninitNetSystem(); } std::string getToken() const { return isBot ? std::string("Bot " + WebSocket::t) : WebSocket::t; } int getIntents() const { return WebSocket::i; } void on(const int event, std::function handler) { eventHandlers[events[event].second] = [handler](const json& message) { json eventData = message.get(); handler(eventData); }; } void once(const int event, std::function handler) { eventHandlers[events[event].second] = [event, this, handler, isCalled = false](const json& message) mutable { if (isCalled == false) { isCalled = true; const json& eventData = message.get(); handler(eventData); } }; } 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() { connected = false; } void start() { while (1) std::this_thread::sleep_for(1ms); } }; WebSocket* WebSocket::instance = nullptr; std::string WebSocket::t = ""; int WebSocket::i = 0; bool WebSocket::initialized = false; bool WebSocket::isBot = true; #endif