#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 isBot; int intents; std::string token; ix::WebSocket webSocket; json payload = { {"op", 1},{"d", nullptr} }, id; std::unordered_map> eventHandlers; WebSocket& operator=(const WebSocket&) = delete; WebSocket(const WebSocket&) = delete; WebSocket(const std::string& token, const int& intents, bool& isBot) { WebSocket::token = token; WebSocket::intents = 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} }} }} }; ix::initNetSystem(); webSocket.setUrl("wss://gateway.discord.gg/?v=10&encoding=json"); webSocket.setOnMessageCallback([this, res = json(""), heartbeat_interval = 0, connected = false](const ix::WebSocketMessagePtr& msg) mutable { if (msg->type == ix::WebSocketMessageType::Message) { res = json::parse(msg->str); chngcol(std::string("WEBSOCKET: " + 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()) : 0; std::thread([this, &heartbeat_interval, &connected]() { while (connected && heartbeat_interval != -1) { std::this_thread::sleep_for(milliseconds(heartbeat_interval)); webSocket.send(payload.dump()); } }).detach(); 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) { static WebSocket instance(token, intents, bot); return instance; } ~WebSocket() { webSocket.close(); ix::uninitNetSystem(); } std::string getToken() const { return isBot ? std::string("Bot " + WebSocket::token) : WebSocket::token; } int getIntents() const { return WebSocket::intents; } void on(const int event, std::function handler) { eventHandlers[events[event].second] = [handler](const json& message) { handler(message.get()); }; } void once(const int event, std::function handler) { eventHandlers[events[event].second] = [event, handler, isCalled = false](const json& message) mutable { isCalled == false ? isCalled = true : 0, handler(message.get()); }; } void start(void) { while (1) std::this_thread::sleep_for(1ms); } }; #endif