DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
WebSocketClient.cpp
Go to the documentation of this file.
1/*
2 MIT License
3
4 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
5
6 Copyright 2022, 2023 Chris M. (RealTimeChris)
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in all
16 copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 SOFTWARE.
25*/
26/// WebsocketClient.cpp - Source file for the webSocket related classes and structs.
27/// May 13, 2021
28/// https://discordcoreapi.com
29/// \file WebsocketClient.cpp
30
31
38#include <random>
39#include <stack>
40
41namespace discord_core_api {
42
43 extern voice_connections_map voiceConnectionMap;
44
45 namespace discord_core_internal {
46
47 event_converter::event_converter(jsonifier::string newEvent) {
48 eventValue = newEvent;
49 }
50
51 event_converter::operator uint64_t() {
52 if (eventValue == "READY") {
53 return 1;
54 } else if (eventValue == "RESUMED") {
55 return 2;
56 } else if (eventValue == "APPLICATION_COMMAND_PERMISSIONS_UPDATE") {
57 return 3;
58 } else if (eventValue == "AUTO_MODERATION_RULE_CREATE") {
59 return 4;
60 } else if (eventValue == "AUTO_MODERATION_RULE_UPDATE") {
61 return 5;
62 } else if (eventValue == "AUTO_MODERATION_RULE_DELETE") {
63 return 6;
64 } else if (eventValue == "AUTO_MODERATION_ACTION_EXECUTION") {
65 return 7;
66 } else if (eventValue == "CHANNEL_CREATE") {
67 return 8;
68 } else if (eventValue == "CHANNEL_UPDATE") {
69 return 9;
70 } else if (eventValue == "CHANNEL_DELETE") {
71 return 10;
72 } else if (eventValue == "CHANNEL_PINS_UPDATE") {
73 return 11;
74 } else if (eventValue == "THREAD_CREATE") {
75 return 12;
76 } else if (eventValue == "THREAD_UPDATE") {
77 return 13;
78 } else if (eventValue == "THREAD_DELETE") {
79 return 14;
80 } else if (eventValue == "THREAD_LIST_SYNC") {
81 return 15;
82 } else if (eventValue == "THREAD_MEMBER_UPDATE") {
83 return 16;
84 } else if (eventValue == "THREAD_MEMBERS_UPDATE") {
85 return 17;
86 } else if (eventValue == "GUILD_CREATE") {
87 return 18;
88 } else if (eventValue == "GUILD_UPDATE") {
89 return 19;
90 } else if (eventValue == "GUILD_DELETE") {
91 return 20;
92 } else if (eventValue == "GUILD_BAN_ADD") {
93 return 21;
94 } else if (eventValue == "GUILD_BAN_REMOVE") {
95 return 22;
96 } else if (eventValue == "GUILD_EMOJIS_UPDATE") {
97 return 23;
98 } else if (eventValue == "GUILD_STICKERS_UPDATE") {
99 return 24;
100 } else if (eventValue == "GUILD_INTEGRATIONS_UPDATE") {
101 return 25;
102 } else if (eventValue == "GUILD_MEMBER_ADD") {
103 return 26;
104 } else if (eventValue == "GUILD_MEMBER_REMOVE") {
105 return 27;
106 } else if (eventValue == "GUILD_MEMBER_UPDATE") {
107 return 28;
108 } else if (eventValue == "GUILD_MEMBERS_CHUNK") {
109 return 29;
110 } else if (eventValue == "GUILD_ROLE_CREATE") {
111 return 30;
112 } else if (eventValue == "GUILD_ROLE_UPDATE") {
113 return 31;
114 } else if (eventValue == "GUILD_ROLE_DELETE") {
115 return 32;
116 } else if (eventValue == "GUILD_SCHEDULED_EVENT_CREATE") {
117 return 33;
118 } else if (eventValue == "GUILD_SCHEDULED_EVENT_UPDATE") {
119 return 34;
120 } else if (eventValue == "GUILD_SCHEDULED_EVENT_DELETE") {
121 return 35;
122 } else if (eventValue == "GUILD_SCHEDULED_EVENT_USER_ADD") {
123 return 36;
124 } else if (eventValue == "GUILD_SCHEDULED_EVENT_USER_REMOVE") {
125 return 37;
126 } else if (eventValue == "INTEGRATION_CREATE") {
127 return 38;
128 } else if (eventValue == "INTEGRATION_UPDATE") {
129 return 39;
130 } else if (eventValue == "INTEGRATION_DELETE") {
131 return 40;
132 } else if (eventValue == "INTERACTION_CREATE") {
133 return 41;
134 } else if (eventValue == "INVITE_CREATE") {
135 return 42;
136 } else if (eventValue == "INVITE_DELETE") {
137 return 43;
138 } else if (eventValue == "MESSAGE_CREATE") {
139 return 44;
140 } else if (eventValue == "MESSAGE_UPDATE") {
141 return 45;
142 } else if (eventValue == "MESSAGE_DELETE") {
143 return 46;
144 } else if (eventValue == "MESSAGE_DELETE_BULK") {
145 return 47;
146 } else if (eventValue == "MESSAGE_REACTION_ADD") {
147 return 48;
148 } else if (eventValue == "MESSAGE_REACTION_REMOVE") {
149 return 49;
150 } else if (eventValue == "MESSAGE_REACTION_REMOVE_ALL") {
151 return 50;
152 } else if (eventValue == "MESSAGE_REACTION_REMOVE_EMOJI") {
153 return 51;
154 } else if (eventValue == "PRESENCE_UPDATE") {
155 return 52;
156 } else if (eventValue == "STAGE_INSTANCE_CREATE") {
157 return 53;
158 } else if (eventValue == "STAGE_INSTANCE_UPDATE") {
159 return 54;
160 } else if (eventValue == "STAGE_INSTANCE_DELETE") {
161 return 55;
162 } else if (eventValue == "TYPING_START") {
163 return 56;
164 } else if (eventValue == "USER_UPDATE") {
165 return 57;
166 } else if (eventValue == "VOICE_STATE_UPDATE") {
167 return 58;
168 } else if (eventValue == "VOICE_SERVER_UPDATE") {
169 return 59;
170 } else if (eventValue == "WEBHOOKS_UPDATE") {
171 return 60;
172 } else {
173 return 0;
174 }
175 }
176
177 websocket_core::websocket_core(config_manager* configManagerNew, websocket_type typeOfWebSocketNew) : etf_parser{} {
178 configManager = configManagerNew;
179 wsType = typeOfWebSocketNew;
180 }
181
182 websocket_core& websocket_core::operator=(websocket_core&& other) noexcept {
183 areWeCollectingData.store(other.areWeCollectingData.load(std::memory_order_acquire), std::memory_order_release);
184 currentState.store(other.currentState.load(std::memory_order_acquire), std::memory_order_release);
185 heartBeatStopWatch = std::move(other.heartBeatStopWatch);
186 haveWeReceivedHeartbeatAck = other.haveWeReceivedHeartbeatAck;
187 currentMessage = std::move(other.currentMessage);
188 tcpConnection = std::move(other.tcpConnection);
189 finalString = std::move(other.finalString);
190 currentReconnectTries = other.currentReconnectTries;
191 dataBuffer = std::move(other.dataBuffer);
192 lastNumberReceived = other.lastNumberReceived;
193 maxReconnectTries = other.maxReconnectTries;
194 areWeHeartBeating = other.areWeHeartBeating;
195 areWeResuming = other.areWeResuming;
196 configManager = other.configManager;
197 dataOpCode = other.dataOpCode;
198 shard.at(0) = other.shard.at(0);
199 shard.at(1) = other.shard.at(1);
200 dataSize = other.dataSize;
201 offSet = other.offSet;
202 wsType = other.wsType;
203 return *this;
204 }
205
206 websocket_core::websocket_core(websocket_core&& other) noexcept : etf_parser{} {
207 *this = std::move(other);
208 }
209
210 bool websocket_core::connect(const jsonifier::string& baseUrlNew, jsonifier::string_view relativePath, const uint16_t portNew) {
211 tcpConnection = websocket_tcpconnection{ baseUrlNew, portNew, this };
212 if (tcpConnection.currentStatus != connection_status::NO_Error) {
213 std::this_thread::sleep_for(1s);
214 return false;
215 }
216 currentState.store(websocket_state::upgrading, std::memory_order_release);
217 jsonifier::string sendString{ "GET " + relativePath + " HTTP/1.1\r\nHost: " + baseUrlNew +
218 "\r\nUpgrade: webSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: " + generateBase64EncodedKey() + "\r\nSec-WebSocket-Version: 13\r\n\r\n" };
219 tcpConnection.writeData(static_cast<jsonifier::string_view>(sendString), true);
220
221 if (tcpConnection.currentStatus != connection_status::NO_Error) {
222 std::this_thread::sleep_for(1s);
223 return false;
224 }
225 return true;
226 }
227
228 websocket_tcpconnection::websocket_tcpconnection(const jsonifier::string& baseUrlNew, uint16_t portNew, websocket_core* ptrNew) : tcp_connection{ baseUrlNew, portNew } {
229 ptr = ptrNew;
230 }
231
232 bool websocket_core::sendMessage(jsonifier::string_base<uint8_t>& dataToSend, bool priority) {
233 if (dataToSend.size() == 0) {
234 return false;
235 }
236 jsonifier::string webSocketTitle{ wsType == websocket_type::voice ? "voice websocket" : "WebSocket" };
237 message_printer::printSuccess<print_message_type::websocket>(jsonifier::string{ "sending " + webSocketTitle + " [" + jsonifier::toString(shard.at(0)) + "," +
238 jsonifier::toString(shard.at(1)) + "]" + jsonifier::string{ "'s message: " } } +
239 dataToSend);
240 std::unique_lock lock{ accessMutex };
241 if (areWeConnected()) {
242 tcpConnection.writeData(static_cast<jsonifier::string_view_base<uint8_t>>(dataToSend), priority);
243 if (tcpConnection.currentStatus != connection_status::NO_Error) {
244 onClosed();
245 return false;
246 }
247 }
248 return true;
249 }
250
251 void websocket_core::parseConnectionHeaders() {
252 if (areWeConnected() && currentState.load(std::memory_order_acquire) == websocket_state::upgrading) {
253 jsonifier::string_base<uint8_t> newString{};
254 newString.resize(4);
255 std::memcpy(newString.data(), "\r\n\r\n", 4);
256 auto theFindValue = currentMessage.find(newString);
257 if (theFindValue != jsonifier::string::npos) {
258 currentMessage.clear();
259 currentState.store(websocket_state::Collecting_Hello, std::memory_order_release);
260 return;
261 }
262 }
263 }
264
265 bool websocket_core::checkForAndSendHeartBeat(bool isImmediate) {
266 if ((currentState.load(std::memory_order_acquire) == websocket_state::authenticated && heartBeatStopWatch.hasTimeElapsed() && haveWeReceivedHeartbeatAck) ||
267 isImmediate) {
268 jsonifier::string_base<uint8_t> string{};
269 if (dataOpCode == websocket_op_code::Op_Binary) {
270 etf_serializer data{};
271 data["d"] = lastNumberReceived;
272 data["op"] = 1;
273 string = data.operator jsonifier::string_base<uint8_t>();
274 } else {
275 websocket_message_data<uint64_t> message{};
276 message.d = lastNumberReceived;
277 message.op = 1;
278 parser.serializeJson<true>(message, string);
279 }
280 haveWeReceivedHeartbeatAck = false;
281 heartBeatStopWatch.reset();
282 createHeader(string, dataOpCode);
283 return sendMessage(string, true);
284 }
285 return false;
286 }
287
288 bool websocket_core::parseMessage() {
289 if (currentMessage.size() < 4) {
290 return false;
291 } else {
292 websocket_op_code opcode = static_cast<websocket_op_code>(currentMessage.at(0) & ~webSocketMaskBit);
293 switch (opcode) {
294 case websocket_op_code::Op_Continuation:
295 [[fallthrough]];
296 case websocket_op_code::Op_Text:
297 [[fallthrough]];
298 case websocket_op_code::Op_Binary:
299 [[fallthrough]];
300 case websocket_op_code::Op_Ping:
301 [[fallthrough]];
302 case websocket_op_code::Op_Pong: {
303 uint8_t length00 = currentMessage.at(1);
304 uint32_t messageOffset = 2;
305
306 if (length00 & webSocketMaskBit) {
307 return true;
308 }
309
310 uint64_t lengthFinal = length00;
311
312 if (length00 == webSocketPayloadLengthMagicLarge) {
313 if (currentMessage.size() < 8) {
314 return false;
315 }
316
317 uint8_t length01 = static_cast<uint8_t>(currentMessage.at(2));
318 uint8_t length02 = static_cast<uint8_t>(currentMessage.at(3));
319 lengthFinal = static_cast<uint64_t>((length01 << 8ULL) | length02);
320
321 messageOffset += 2;
322 } else if (length00 == webSocketPayloadLengthMagicHuge) {
323 if (currentMessage.size() < 10) {
324 return false;
325 }
326 lengthFinal = 0;
327 for (uint64_t x = 2, shift = 56; x < 10; ++x, shift -= 8) {
328 uint8_t length03 = static_cast<uint8_t>(currentMessage.at(x));
329 lengthFinal |= static_cast<uint64_t>(length03 & 0xff) << shift;
330 }
331 messageOffset += 8;
332 }
333
334 if (currentMessage.size() < messageOffset + lengthFinal) {
335 return false;
336 }
337
338 if (opcode == websocket_op_code::Op_Ping || opcode == websocket_op_code::Op_Pong) {
339 return false;
340 } else {
341 onMessageReceived({ currentMessage.data() + messageOffset, lengthFinal });
342 currentMessage.erase(messageOffset + lengthFinal);
343 }
344 return true;
345 } break;
346 case websocket_op_code::Op_Close: {
347 uint16_t closeValue = static_cast<uint16_t>(currentMessage.at(2) & 0xff);
348 closeValue <<= 8;
349 closeValue |= currentMessage.at(3) & 0xff;
350 jsonifier::string closeString{};
351 if (wsType == websocket_type::voice) {
352 voice_websocket_close voiceClose{ closeValue };
353 closeString = static_cast<jsonifier::string>(voiceClose.operator jsonifier::string_view());
354 } else {
355 websocket_close wsClose{ closeValue };
356 closeString = static_cast<jsonifier::string>(wsClose.operator jsonifier::string_view());
357 }
358 jsonifier::string webSocketTitle = wsType == websocket_type::voice ? "voice websocket" : "WebSocket";
359 message_printer::printError<print_message_type::websocket>(jsonifier::string{ webSocketTitle + " [" + jsonifier::toString(shard.at(0)) + "," +
360 jsonifier::toString(shard.at(1)) + "]" + " closed; code: " + jsonifier::toString(closeValue) + ", " + closeString });
361 return false;
362 } break;
363
364 default: {
365 return false;
366 } break;
367 }
368 }
369 }
370
371 bool websocket_core::areWeConnected() {
372 return tcpConnection.areWeStillConnected();
373 }
374
375 void websocket_tcpconnection::handleBuffer() {
376 auto inputBufferNew = getInputBuffer();
377 auto oldSize = ptr->currentMessage.size();
378 if (ptr->currentMessage.size() < oldSize + inputBufferNew.size()) {
379 ptr->currentMessage.resize(oldSize + inputBufferNew.size());
380 }
381 std::memcpy(ptr->currentMessage.data() + oldSize, inputBufferNew.data(), inputBufferNew.size());
382 if (ptr->currentState.load(std::memory_order_acquire) == websocket_state::upgrading) {
383 ptr->parseConnectionHeaders();
384 } else {
385 while (ptr->parseMessage()) {
386 };
387 }
388 }
389
390 websocket_client::websocket_client(uint64_t currentShardNew, std::atomic_bool* doWeQuitNew)
391 : websocket_core(&discord_core_client::getInstance()->configManager, websocket_type::normal) {
392 configManager = &discord_core_client::getInstance()->configManager;
393 shard.at(0) = currentShardNew;
394 doWeQuit = doWeQuitNew;
395 if (discord_core_client::getInstance()) {
396 shard.at(1) = discord_core_client::getInstance()->configManager.getTotalShardCount();
397 if (discord_core_client::getInstance()->configManager.getTextFormat() == text_format::etf) {
398 dataOpCode = websocket_op_code::Op_Binary;
399 } else {
400 dataOpCode = websocket_op_code::Op_Text;
401 }
402 }
403 }
404
405 void websocket_client::getVoiceConnectionData(const voice_connect_init_data& doWeCollect) {
406 while (currentState.load(std::memory_order_acquire) != websocket_state::authenticated) {
407 std::this_thread::sleep_for(1ms);
408 }
409 websocket_message_data<update_voice_state_data_dc> data01{};
410 data01.excludedKeys.emplace("t");
411 data01.excludedKeys.emplace("s");
412 data01.d.channelId = std::nullptr_t{};
413 data01.d.guildId = doWeCollect.guildId;
414 data01.d.selfDeaf = doWeCollect.selfDeaf;
415 data01.d.selfMute = doWeCollect.selfMute;
416 data01.op = 4;
417 userId = doWeCollect.userId;
418
419 websocket_message_data<update_voice_state_data> data02{};
420 data02.excludedKeys.emplace("t");
421 data02.excludedKeys.emplace("s");
422 data02.d.channelId = doWeCollect.channelId;
423 data02.d.guildId = doWeCollect.guildId;
424 data02.d.selfDeaf = doWeCollect.selfDeaf;
425 data02.d.selfMute = doWeCollect.selfMute;
426 data02.op = 4;
427 jsonifier::string_base<uint8_t> string{};
428 auto serializer = data01.operator etf_serializer();
429 if (dataOpCode == websocket_op_code::Op_Binary) {
430 string = serializer.operator jsonifier::string_base<uint8_t>();
431 } else {
432 parser.serializeJson<true>(data01, string);
433 }
434 createHeader(string, dataOpCode);
435 if (!sendMessage(string, true)) {
436 return;
437 }
438 if (snowflake{ doWeCollect.channelId } == 0) {
439 return;
440 }
441 serializer = data02.operator etf_serializer();
442 if (dataOpCode == websocket_op_code::Op_Binary) {
443 string = serializer.operator jsonifier::string_base<uint8_t>();
444 } else {
445 parser.serializeJson<true>(data02, string);
446 }
447 createHeader(string, dataOpCode);
448 areWeCollectingData.store(true, std::memory_order_release);
449 if (!sendMessage(string, true)) {
450 return;
451 }
452 }
453
454 uint64_t countBackSlashes(jsonifier::string_base<uint8_t>::iterator& iter, jsonifier::string_base<uint8_t>::iterator end, uint64_t currentCount = 0) {
455 if (iter < end) {
456 if (*iter == '\\') {
457 ++currentCount;
458 ++iter;
459 return countBackSlashes(iter, end, currentCount);
460 }
461 }
462 ++iter;
463 return currentCount;
464 }
465
466 uint64_t findInvalidJSONIndex(jsonifier::string_view_base<uint8_t> jsonStr) {
467 std::stack<uint8_t> stack;
468 bool areWeInAString{ false };
469 jsonifier::string_base<uint8_t> stringNew{ jsonStr + '\0' };
470 uint64_t backslashCount{};
471 for (jsonifier::string_base<uint8_t>::iterator iter{ stringNew.begin() }; iter != stringNew.end(); ++iter) {
472 if (iter > stringNew.begin()) {
473 uint8_t cMinus1 = *(iter - 1);
474 uint8_t c = *iter;
475 backslashCount = 0;
476 if (c == '\\') {
477 backslashCount = countBackSlashes(iter, stringNew.end());
478 }
479 cMinus1 = *(iter - 1);
480 c = *iter;
481
482 if ((c == '{' || c == '[' || c == '"') && cMinus1 != '\\' && !areWeInAString && backslashCount % 1 == 0) {
483 if (c == '"') {
484 areWeInAString = true;
485 }
486 stack.push(c);
487 } else if (areWeInAString && c == '"' && cMinus1 != '\\' && backslashCount % 1 == 0) {
488 areWeInAString = false;
489 stack.pop();
490 } else if ((c == '}' || c == ']' || c == '"') && !areWeInAString) {
491
492 uint8_t top = stack.top();
493 stack.pop();
494
495 if ((c == '}' && top != '{') || (c == ']' && top != '[') || (c == '"' && top != '"')) {
496 return static_cast<uint64_t>(iter - stringNew.begin());
497 }
498 }
499 } else {
500 uint8_t c = *iter;
501 if ((c == '{' || c == '[' || c == '"') && !areWeInAString) {
502 if (c == '"') {
503 areWeInAString = true;
504 }
505 stack.push(c);
506 } else if (areWeInAString && c == '"' ) {
507 areWeInAString = false;
508 stack.pop();
509 } else if ((c == '}' || c == ']' || c == '"') && !areWeInAString) {
510 uint8_t top = stack.top();
511 stack.pop();
512
513 if ((c == '}' && top != '{') || (c == ']' && top != '[') || (c == '"' && top != '"')) {
514 return static_cast<uint64_t>(iter - stringNew.begin());
515 }
516 }
517 }
518 }
519
520 if (stack.empty()) {
521 return std::numeric_limits<uint64_t>::max();
522 } else {
523 return jsonStr.size();
524 }
525 }
526
527 bool websocket_client::onMessageReceived(jsonifier::string_view_base<uint8_t> dataNew) {
528 try {
529 if (areWeConnected() && currentMessage.size() > 0 && dataNew.size() > 0) {
530 websocket_message message{};
531 if (configManager->getTextFormat() == text_format::etf) {
532 try {
533 dataNew = etf_parser::parseEtfToJson(dataNew);
534 auto newString = jsonifier::string{ dataNew };
535 parser.parseJson<true, true>(message, newString);
536 if (auto result = parser.getErrors(); result.size() > 0) {
537 for (auto& valueNew: result) {
538 message_printer::printError<print_message_type::websocket>(valueNew.reportError() + ", for data:" + dataNew);
539 }
540 }
541 } catch (const dca_exception& error) {
542 message_printer::printError<print_message_type::websocket>(error.what());
543 tcpConnection.getInputBuffer();
544 currentMessage.clear();
545 return false;
546 }
547 } else {
548#if !defined(NDEBUG)
549 if (auto result = findInvalidJSONIndex(dataNew); result != std::numeric_limits<uint64_t>::max()) {
550 throw dca_exception{ "Sorry, but that json data is invalid at index: " + jsonifier::toString(result) + " and it is: " + dataNew };
551 }
552#endif
553 parser.parseJson<true, true>(message, dataNew);
554 if (auto result = parser.getErrors(); result.size() > 0) {
555 for (auto& valueNew: result) {
556 message_printer::printError<print_message_type::websocket>(valueNew.reportError() + ", for data:" + dataNew);
557 }
558 }
559 }
560
561 if (message.s != 0) {
562 lastNumberReceived = static_cast<uint32_t>(message.s);
563 }
564 message_printer::printSuccess<print_message_type::websocket>(jsonifier::string{ "Message received from websocket [" + jsonifier::toString(shard.at(0)) + "," +
565 jsonifier::toString(shard.at(1)) + jsonifier::string("]: ") + jsonifier::string{ dataNew } });
566 switch (static_cast<websocket_op_codes>(message.op)) {
567 case websocket_op_codes::dispatch: {
568 if (message.t != "") {
569 switch (event_converter{ message.t }) {
570 case 1: {
571 websocket_message_data<ready_data> data{};
572 if (dataOpCode == websocket_op_code::Op_Text) {
573 data.d.excludedKeys.emplace("shard");
574 }
575 currentState.store(websocket_state::authenticated, std::memory_order_release);
576 parser.parseJson<true, true>(data, dataNew);
577 if (auto result = parser.getErrors(); result.size() > 0) {
578 for (auto& valueNew: result) {
579 message_printer::printError<print_message_type::websocket>(valueNew.reportError());
580 }
581 }
582 sessionId = data.d.sessionId;
583 if (data.d.resumeGatewayUrl.find("wss://") != jsonifier::string::npos) {
584 resumeUrl = data.d.resumeGatewayUrl.substr(data.d.resumeGatewayUrl.find("wss://") + jsonifier::string{ "wss://" }.size());
585 }
586 discord_core_client::getInstance()->currentUser = bot_user{ data.d.user,
587 discord_core_client::getInstance()
588 ->baseSocketAgentsMap[static_cast<uint64_t>(floor(
589 static_cast<uint64_t>(shard.at(0)) % static_cast<uint64_t>(discord_core_client::getInstance()->baseSocketAgentsMap.size())))]
590 .get() };
591 users::insertUser(static_cast<user_cache_data>(std::move(data.d.user)));
592 currentReconnectTries = 0;
593 break;
594 }
595 case 2: {
596 currentState.store(websocket_state::authenticated, std::memory_order_release);
597 currentReconnectTries = 0;
598 break;
599 }
600 case 3: {
601 if (discord_core_client::getInstance()->eventManager.onApplicationCommandPermissionsUpdateEvent.functions.size() > 0) {
602 unique_ptr<on_application_command_permissions_update_data> dataPackage{ makeUnique<on_application_command_permissions_update_data>(
603 parser, dataNew) };
604 discord_core_client::getInstance()->eventManager.onApplicationCommandPermissionsUpdateEvent(*dataPackage);
605 }
606 break;
607 }
608 case 4: {
609 if (discord_core_client::getInstance()->eventManager.onAutoModerationRuleCreationEvent.functions.size() > 0) {
610 unique_ptr<on_auto_moderation_rule_creation_data> dataPackage{ makeUnique<on_auto_moderation_rule_creation_data>(parser, dataNew) };
611 discord_core_client::getInstance()->eventManager.onAutoModerationRuleCreationEvent(*dataPackage);
612 }
613 break;
614 }
615 case 5: {
616 if (discord_core_client::getInstance()->eventManager.onAutoModerationRuleUpdateEvent.functions.size() > 0) {
617 unique_ptr<on_auto_moderation_rule_update_data> dataPackage{ makeUnique<on_auto_moderation_rule_update_data>(parser, dataNew) };
618 discord_core_client::getInstance()->eventManager.onAutoModerationRuleUpdateEvent(*dataPackage);
619 }
620 break;
621 }
622 case 6: {
623 if (discord_core_client::getInstance()->eventManager.onAutoModerationRuleDeletionEvent.functions.size() > 0) {
624 unique_ptr<on_auto_moderation_rule_deletion_data> dataPackage{ makeUnique<on_auto_moderation_rule_deletion_data>(parser, dataNew) };
625 discord_core_client::getInstance()->eventManager.onAutoModerationRuleDeletionEvent(*dataPackage);
626 }
627 break;
628 }
629 case 7: {
630 if (discord_core_client::getInstance()->eventManager.onAutoModerationActionExecutionEvent.functions.size() > 0) {
631 unique_ptr<on_auto_moderation_action_execution_data> dataPackage{ makeUnique<on_auto_moderation_action_execution_data>(parser,
632 dataNew) };
633 discord_core_client::getInstance()->eventManager.onAutoModerationActionExecutionEvent(*dataPackage);
634 }
635 break;
636 }
637 case 8: {
638 unique_ptr<on_channel_creation_data> dataPackage{ makeUnique<on_channel_creation_data>(parser, dataNew) };
639 if (discord_core_client::getInstance()->eventManager.onChannelCreationEvent.functions.size() > 0) {
640 discord_core_client::getInstance()->eventManager.onChannelCreationEvent(*dataPackage);
641 }
642 break;
643 }
644 case 9: {
645 unique_ptr<on_channel_update_data> dataPackage{ makeUnique<on_channel_update_data>(parser, dataNew) };
646 if (discord_core_client::getInstance()->eventManager.onChannelUpdateEvent.functions.size() > 0) {
647 discord_core_client::getInstance()->eventManager.onChannelUpdateEvent(*dataPackage);
648 }
649 break;
650 }
651 case 10: {
652 unique_ptr<on_channel_deletion_data> dataPackage{ makeUnique<on_channel_deletion_data>(parser, dataNew) };
653 if (discord_core_client::getInstance()->eventManager.onChannelDeletionEvent.functions.size() > 0) {
654 discord_core_client::getInstance()->eventManager.onChannelDeletionEvent(*dataPackage);
655 }
656 break;
657 }
658 case 11: {
659 if (discord_core_client::getInstance()->eventManager.onChannelPinsUpdateEvent.functions.size() > 0) {
660 unique_ptr<on_channel_pins_update_data> dataPackage{ makeUnique<on_channel_pins_update_data>(parser, dataNew) };
661 discord_core_client::getInstance()->eventManager.onChannelPinsUpdateEvent(*dataPackage);
662 }
663 break;
664 }
665 case 12: {
666 if (discord_core_client::getInstance()->eventManager.onThreadCreationEvent.functions.size() > 0) {
667 unique_ptr<on_thread_creation_data> dataPackage{ makeUnique<on_thread_creation_data>(parser, dataNew) };
668 discord_core_client::getInstance()->eventManager.onThreadCreationEvent(*dataPackage);
669 }
670 break;
671 }
672 case 13: {
673 if (discord_core_client::getInstance()->eventManager.onThreadUpdateEvent.functions.size() > 0) {
674 unique_ptr<on_thread_update_data> dataPackage{ makeUnique<on_thread_update_data>(parser, dataNew) };
675 discord_core_client::getInstance()->eventManager.onThreadUpdateEvent(*dataPackage);
676 }
677 break;
678 }
679 case 14: {
680 if (discord_core_client::getInstance()->eventManager.onThreadDeletionEvent.functions.size() > 0) {
681 unique_ptr<on_thread_deletion_data> dataPackage{ makeUnique<on_thread_deletion_data>(parser, dataNew) };
682 discord_core_client::getInstance()->eventManager.onThreadDeletionEvent(*dataPackage);
683 }
684 break;
685 }
686 case 15: {
687 if (discord_core_client::getInstance()->eventManager.onThreadListSyncEvent.functions.size() > 0) {
688 unique_ptr<on_thread_list_sync_data> dataPackage{ makeUnique<on_thread_list_sync_data>(parser, dataNew) };
689 discord_core_client::getInstance()->eventManager.onThreadListSyncEvent(*dataPackage);
690 }
691 break;
692 }
693 case 16: {
694 if (discord_core_client::getInstance()->eventManager.onThreadMemberUpdateEvent.functions.size() > 0) {
695 unique_ptr<on_thread_member_update_data> dataPackage{ makeUnique<on_thread_member_update_data>(parser, dataNew) };
696 discord_core_client::getInstance()->eventManager.onThreadMemberUpdateEvent(*dataPackage);
697 }
698 break;
699 }
700 case 17: {
701 if (discord_core_client::getInstance()->eventManager.onThreadMembersUpdateEvent.functions.size() > 0) {
702 unique_ptr<on_thread_members_update_data> dataPackage{ makeUnique<on_thread_members_update_data>(parser, dataNew) };
703 discord_core_client::getInstance()->eventManager.onThreadMembersUpdateEvent(*dataPackage);
704 }
705 break;
706 }
707 case 18: {
708 unique_ptr<on_guild_creation_data> dataPackage{ makeUnique<on_guild_creation_data>(parser, dataNew) };
709 if (discord_core_client::getInstance()->eventManager.onGuildCreationEvent.functions.size() > 0) {
710 discord_core_client::getInstance()->eventManager.onGuildCreationEvent(*dataPackage);
711 }
712 break;
713 }
714 case 19: {
715 unique_ptr<on_guild_update_data> dataPackage{ makeUnique<on_guild_update_data>(parser, dataNew) };
716 if (discord_core_client::getInstance()->eventManager.onGuildUpdateEvent.functions.size() > 0) {
717 discord_core_client::getInstance()->eventManager.onGuildUpdateEvent(*dataPackage);
718 }
719 break;
720 }
721 case 20: {
722 unique_ptr<on_guild_deletion_data> dataPackage{ makeUnique<on_guild_deletion_data>(parser, dataNew) };
723 if (discord_core_client::getInstance()->eventManager.onGuildDeletionEvent.functions.size() > 0) {
724 discord_core_client::getInstance()->eventManager.onGuildDeletionEvent(*dataPackage);
725 }
726 break;
727 }
728 case 21: {
729 if (discord_core_client::getInstance()->eventManager.onGuildBanAddEvent.functions.size() > 0) {
730 unique_ptr<on_guild_ban_add_data> dataPackage{ makeUnique<on_guild_ban_add_data>(parser, dataNew) };
731 discord_core_client::getInstance()->eventManager.onGuildBanAddEvent(*dataPackage);
732 }
733 break;
734 }
735 case 22: {
736 if (discord_core_client::getInstance()->eventManager.onGuildBanRemoveEvent.functions.size() > 0) {
737 unique_ptr<on_guild_ban_remove_data> dataPackage{ makeUnique<on_guild_ban_remove_data>(parser, dataNew) };
738 discord_core_client::getInstance()->eventManager.onGuildBanRemoveEvent(*dataPackage);
739 }
740 break;
741 }
742 case 23: {
743 if (discord_core_client::getInstance()->eventManager.onGuildEmojisUpdateEvent.functions.size() > 0) {
744 unique_ptr<on_guild_emojis_update_data> dataPackage{ makeUnique<on_guild_emojis_update_data>(parser, dataNew) };
745 discord_core_client::getInstance()->eventManager.onGuildEmojisUpdateEvent(*dataPackage);
746 }
747 break;
748 }
749 case 24: {
750 if (discord_core_client::getInstance()->eventManager.onGuildStickersUpdateEvent.functions.size() > 0) {
751 unique_ptr<on_guild_stickers_update_data> dataPackage{ makeUnique<on_guild_stickers_update_data>(parser, dataNew) };
752 discord_core_client::getInstance()->eventManager.onGuildStickersUpdateEvent(*dataPackage);
753 }
754 break;
755 }
756 case 25: {
757 if (discord_core_client::getInstance()->eventManager.onGuildIntegrationsUpdateEvent.functions.size() > 0) {
758 unique_ptr<on_guild_integrations_update_data> dataPackage{ makeUnique<on_guild_integrations_update_data>(parser, dataNew) };
759 discord_core_client::getInstance()->eventManager.onGuildIntegrationsUpdateEvent(*dataPackage);
760 }
761 break;
762 }
763 case 26: {
764 unique_ptr<on_guild_member_add_data> dataPackage{ makeUnique<on_guild_member_add_data>(parser, dataNew) };
765 if (discord_core_client::getInstance()->eventManager.onGuildMemberAddEvent.functions.size() > 0) {
766 discord_core_client::getInstance()->eventManager.onGuildMemberAddEvent(*dataPackage);
767 }
768 break;
769 }
770 case 27: {
771 unique_ptr<on_guild_member_remove_data> dataPackage{ makeUnique<on_guild_member_remove_data>(parser, dataNew) };
772 if (discord_core_client::getInstance()->eventManager.onGuildMemberRemoveEvent.functions.size() > 0) {
773 discord_core_client::getInstance()->eventManager.onGuildMemberRemoveEvent(*dataPackage);
774 }
775 break;
776 }
777 case 28: {
778 unique_ptr<on_guild_member_update_data> dataPackage{ makeUnique<on_guild_member_update_data>(parser, dataNew) };
779 if (discord_core_client::getInstance()->eventManager.onGuildMemberUpdateEvent.functions.size() > 0) {
780 discord_core_client::getInstance()->eventManager.onGuildMemberUpdateEvent(*dataPackage);
781 }
782 break;
783 }
784 case 29: {
785 if (discord_core_client::getInstance()->eventManager.onGuildMembersChunkEvent.functions.size() > 0) {
786 unique_ptr<on_guild_members_chunk_data> dataPackage{ makeUnique<on_guild_members_chunk_data>(parser, dataNew) };
787 discord_core_client::getInstance()->eventManager.onGuildMembersChunkEvent(*dataPackage);
788 }
789 break;
790 }
791 case 30: {
792 unique_ptr<on_role_creation_data> dataPackage{ makeUnique<on_role_creation_data>(parser, dataNew) };
793 if (discord_core_client::getInstance()->eventManager.onRoleCreationEvent.functions.size() > 0) {
794 discord_core_client::getInstance()->eventManager.onRoleCreationEvent(*dataPackage);
795 }
796 break;
797 }
798 case 31: {
799 unique_ptr<on_role_update_data> dataPackage{ makeUnique<on_role_update_data>(parser, dataNew) };
800 if (discord_core_client::getInstance()->eventManager.onRoleUpdateEvent.functions.size() > 0) {
801 discord_core_client::getInstance()->eventManager.onRoleUpdateEvent(*dataPackage);
802 }
803 break;
804 }
805 case 32: {
806 unique_ptr<on_role_deletion_data> dataPackage{ makeUnique<on_role_deletion_data>(parser, dataNew) };
807 if (discord_core_client::getInstance()->eventManager.onRoleDeletionEvent.functions.size() > 0) {
808 discord_core_client::getInstance()->eventManager.onRoleDeletionEvent(*dataPackage);
809 }
810 break;
811 }
812 case 33: {
813 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventCreationEvent.functions.size() > 0) {
814 unique_ptr<on_guild_scheduled_event_creation_data> dataPackage{ makeUnique<on_guild_scheduled_event_creation_data>(parser, dataNew) };
815 discord_core_client::getInstance()->eventManager.onGuildScheduledEventCreationEvent(*dataPackage);
816 }
817 break;
818 }
819 case 34: {
820 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventUpdateEvent.functions.size() > 0) {
821 unique_ptr<on_guild_scheduled_event_update_data> dataPackage{ makeUnique<on_guild_scheduled_event_update_data>(parser, dataNew) };
822 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUpdateEvent(*dataPackage);
823 }
824 break;
825 }
826 case 35: {
827 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventDeletionEvent.functions.size() > 0) {
828 unique_ptr<on_guild_scheduled_event_deletion_data> dataPackage{ makeUnique<on_guild_scheduled_event_deletion_data>(parser, dataNew) };
829 discord_core_client::getInstance()->eventManager.onGuildScheduledEventDeletionEvent(*dataPackage);
830 }
831 break;
832 }
833 case 36: {
834 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserAddEvent.functions.size() > 0) {
835 unique_ptr<on_guild_scheduled_event_user_add_data> dataPackage{ makeUnique<on_guild_scheduled_event_user_add_data>(parser, dataNew) };
836 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserAddEvent(*dataPackage);
837 }
838 break;
839 }
840 case 37: {
841 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserRemoveEvent.functions.size() > 0) {
842 unique_ptr<on_guild_scheduled_event_user_remove_data> dataPackage{ makeUnique<on_guild_scheduled_event_user_remove_data>(parser,
843 dataNew) };
844 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserRemoveEvent(*dataPackage);
845 }
846 break;
847 }
848 case 38: {
849 if (discord_core_client::getInstance()->eventManager.onIntegrationCreationEvent.functions.size() > 0) {
850 unique_ptr<on_integration_creation_data> dataPackage{ makeUnique<on_integration_creation_data>(parser, dataNew) };
851 discord_core_client::getInstance()->eventManager.onIntegrationCreationEvent(*dataPackage);
852 }
853 break;
854 }
855 case 39: {
856 if (discord_core_client::getInstance()->eventManager.onIntegrationUpdateEvent.functions.size() > 0) {
857 unique_ptr<on_integration_update_data> dataPackage{ makeUnique<on_integration_update_data>(parser, dataNew) };
858 discord_core_client::getInstance()->eventManager.onIntegrationUpdateEvent(*dataPackage);
859 }
860 break;
861 }
862 case 40: {
863 if (discord_core_client::getInstance()->eventManager.onIntegrationDeletionEvent.functions.size() > 0) {
864 unique_ptr<on_integration_deletion_data> dataPackage{ makeUnique<on_integration_deletion_data>(parser, dataNew) };
865 discord_core_client::getInstance()->eventManager.onIntegrationDeletionEvent(*dataPackage);
866 }
867 break;
868 }
869 case 41: {
870 unique_ptr<on_interaction_creation_data> dataPackage{ makeUnique<on_interaction_creation_data>(parser, dataNew) };
871 if (discord_core_client::getInstance()->eventManager.onInteractionCreationEvent.functions.size() > 0) {
872 discord_core_client::getInstance()->eventManager.onInteractionCreationEvent(*dataPackage);
873 }
874 break;
875 }
876 case 42: {
877 if (discord_core_client::getInstance()->eventManager.onInviteCreationEvent.functions.size() > 0) {
878 unique_ptr<on_invite_creation_data> dataPackage{ makeUnique<on_invite_creation_data>(parser, dataNew) };
879 discord_core_client::getInstance()->eventManager.onInviteCreationEvent(*dataPackage);
880 }
881 break;
882 }
883 case 43: {
884 if (discord_core_client::getInstance()->eventManager.onInviteDeletionEvent.functions.size() > 0) {
885 unique_ptr<on_invite_deletion_data> dataPackage{ makeUnique<on_invite_deletion_data>(parser, dataNew) };
886 discord_core_client::getInstance()->eventManager.onInviteDeletionEvent(*dataPackage);
887 }
888 break;
889 }
890 case 44: {
891 unique_ptr<on_message_creation_data> dataPackage{ makeUnique<on_message_creation_data>(parser, dataNew) };
892 if (discord_core_client::getInstance()->eventManager.onMessageCreationEvent.functions.size() > 0) {
893 discord_core_client::getInstance()->eventManager.onMessageCreationEvent(*dataPackage);
894 }
895 break;
896 }
897 case 45: {
898 unique_ptr<on_message_update_data> dataPackage{ makeUnique<on_message_update_data>(parser, dataNew) };
899 if (discord_core_client::getInstance()->eventManager.onMessageUpdateEvent.functions.size() > 0) {
900 discord_core_client::getInstance()->eventManager.onMessageUpdateEvent(*dataPackage);
901 }
902 break;
903 }
904 case 46: {
905 if (discord_core_client::getInstance()->eventManager.onMessageDeletionEvent.functions.size() > 0) {
906 unique_ptr<on_message_deletion_data> dataPackage{ makeUnique<on_message_deletion_data>(parser, dataNew) };
907 discord_core_client::getInstance()->eventManager.onMessageDeletionEvent(*dataPackage);
908 }
909 break;
910 }
911 case 47: {
912 if (discord_core_client::getInstance()->eventManager.onMessageDeleteBulkEvent.functions.size() > 0) {
913 unique_ptr<on_message_delete_bulk_data> dataPackage{ makeUnique<on_message_delete_bulk_data>(parser, dataNew) };
914 discord_core_client::getInstance()->eventManager.onMessageDeleteBulkEvent(*dataPackage);
915 }
916 break;
917 }
918 case 48: {
919 if (discord_core_client::getInstance()->eventManager.onReactionAddEvent.functions.size() > 0) {
920 unique_ptr<on_reaction_add_data> dataPackage{ makeUnique<on_reaction_add_data>(parser, dataNew) };
921 discord_core_client::getInstance()->eventManager.onReactionAddEvent(*dataPackage);
922 }
923 break;
924 }
925 case 49: {
926 if (discord_core_client::getInstance()->eventManager.onReactionRemoveEvent.functions.size() > 0) {
927 unique_ptr<on_reaction_remove_data> dataPackage{ makeUnique<on_reaction_remove_data>(parser, dataNew) };
928 discord_core_client::getInstance()->eventManager.onReactionRemoveEvent(*dataPackage);
929 }
930 break;
931 }
932 case 50: {
933 if (discord_core_client::getInstance()->eventManager.onReactionRemoveAllEvent.functions.size() > 0) {
934 unique_ptr<on_reaction_remove_all_data> dataPackage{ makeUnique<on_reaction_remove_all_data>(parser, dataNew) };
935 discord_core_client::getInstance()->eventManager.onReactionRemoveAllEvent(*dataPackage);
936 }
937 break;
938 }
939 case 51: {
940 if (discord_core_client::getInstance()->eventManager.onReactionRemoveEmojiEvent.functions.size() > 0) {
941 unique_ptr<on_reaction_remove_emoji_data> dataPackage{ makeUnique<on_reaction_remove_emoji_data>(parser, dataNew) };
942 discord_core_client::getInstance()->eventManager.onReactionRemoveEmojiEvent(*dataPackage);
943 }
944 break;
945 }
946 case 52: {
947 unique_ptr<on_presence_update_data> dataPackage{ makeUnique<on_presence_update_data>(parser, dataNew) };
948 if (discord_core_client::getInstance()->eventManager.onPresenceUpdateEvent.functions.size() > 0) {
949 discord_core_client::getInstance()->eventManager.onPresenceUpdateEvent(*dataPackage);
950 }
951 break;
952 }
953 case 53: {
954 if (discord_core_client::getInstance()->eventManager.onStageInstanceCreationEvent.functions.size() > 0) {
955 unique_ptr<on_stage_instance_creation_data> dataPackage{ makeUnique<on_stage_instance_creation_data>(parser, dataNew) };
956 discord_core_client::getInstance()->eventManager.onStageInstanceCreationEvent(*dataPackage);
957 }
958 break;
959 }
960 case 54: {
961 if (discord_core_client::getInstance()->eventManager.onStageInstanceUpdateEvent.functions.size() > 0) {
962 unique_ptr<on_stage_instance_update_data> dataPackage{ makeUnique<on_stage_instance_update_data>(parser, dataNew) };
963 discord_core_client::getInstance()->eventManager.onStageInstanceUpdateEvent(*dataPackage);
964 }
965 break;
966 }
967 case 55: {
968 if (discord_core_client::getInstance()->eventManager.onStageInstanceDeletionEvent.functions.size() > 0) {
969 unique_ptr<on_stage_instance_deletion_data> dataPackage{ makeUnique<on_stage_instance_deletion_data>(parser, dataNew) };
970 discord_core_client::getInstance()->eventManager.onStageInstanceDeletionEvent(*dataPackage);
971 }
972 break;
973 }
974 case 56: {
975 if (discord_core_client::getInstance()->eventManager.onTypingStartEvent.functions.size() > 0) {
976 unique_ptr<on_typing_start_data> dataPackage{ makeUnique<on_typing_start_data>(parser, dataNew) };
977 discord_core_client::getInstance()->eventManager.onTypingStartEvent(*dataPackage);
978 }
979 break;
980 }
981 case 57: {
982 if (discord_core_client::getInstance()->eventManager.onUserUpdateEvent.functions.size() > 0) {
983 unique_ptr<on_user_update_data> dataPackage{ makeUnique<on_user_update_data>(parser, dataNew) };
984 discord_core_client::getInstance()->eventManager.onUserUpdateEvent(*dataPackage);
985 }
986 break;
987 }
988 case 58: {
989 unique_ptr<on_voice_state_update_data> dataPackage{ makeUnique<on_voice_state_update_data>(parser, dataNew, this) };
990 if (discord_core_client::getInstance()->eventManager.onVoiceStateUpdateEvent.functions.size() > 0) {
991 discord_core_client::getInstance()->eventManager.onVoiceStateUpdateEvent(*dataPackage);
992 }
993 break;
994 }
995 case 59: {
996 unique_ptr<on_voice_server_update_data> dataPackage{ makeUnique<on_voice_server_update_data>(parser, dataNew, this) };
997 if (discord_core_client::getInstance()->eventManager.onVoiceServerUpdateEvent.functions.size() > 0) {
998 discord_core_client::getInstance()->eventManager.onVoiceServerUpdateEvent(*dataPackage);
999 }
1000 break;
1001 }
1002 case 60: {
1003 if (discord_core_client::getInstance()->eventManager.onWebhookUpdateEvent.functions.size() > 0) {
1004 unique_ptr<on_webhook_update_data> dataPackage{ makeUnique<on_webhook_update_data>(parser, dataNew) };
1005 discord_core_client::getInstance()->eventManager.onWebhookUpdateEvent(*dataPackage);
1006 }
1007 break;
1008 }
1009 }
1010 }
1011 break;
1012 }
1013 case websocket_op_codes::heartbeat: {
1014 if (!checkForAndSendHeartBeat(true)) {
1015 return false;
1016 }
1017 break;
1018 }
1019 case websocket_op_codes::reconnect: {
1020 message_printer::printError<print_message_type::websocket>(
1021 jsonifier::string{ "Shard [" + jsonifier::toString(shard.at(0)) + "," + jsonifier::toString(shard.at(1)) + "]" + " reconnecting (type 7)!" });
1022 areWeResuming = true;
1023 tcpConnection.disconnect();
1024 return true;
1025 }
1026 case websocket_op_codes::Invalid_Session: {
1027 websocket_message_data<bool> data{};
1028 parser.parseJson<true, true>(data, dataNew);
1029 if (auto result = parser.getErrors(); result.size() > 0) {
1030 for (auto& valueNew: result) {
1031 message_printer::printError<print_message_type::websocket>(valueNew.reportError());
1032 }
1033 }
1034 message_printer::printError<print_message_type::websocket>(
1035 jsonifier::string{ "Shard [" + jsonifier::toString(shard.at(0)) + "," + jsonifier::toString(shard.at(1)) + "]" + " reconnecting (type 9)!" });
1036 std::mt19937_64 randomEngine{ static_cast<uint64_t>(hrclock::now().time_since_epoch().count()) };
1037 uint64_t numOfMsToWait =
1038 static_cast<uint64_t>(1000.0f + ((static_cast<double>(randomEngine()) / static_cast<double>(randomEngine.max())) * static_cast<double>(4000.0f)));
1039 if (numOfMsToWait <= 5000 && numOfMsToWait > 0) {
1040 std::this_thread::sleep_for(milliseconds{ numOfMsToWait });
1041 }
1042 if (data.d == true) {
1043 areWeResuming = true;
1044 } else {
1045 areWeResuming = false;
1046 }
1047 onClosed();
1048 return true;
1049 }
1050 case websocket_op_codes::hello: {
1051 websocket_message_data<hello_data> data{};
1052 parser.parseJson<true, true>(data, dataNew);
1053 if (auto result = parser.getErrors(); result.size() > 0) {
1054 for (auto& valueNew: result) {
1055 message_printer::printError<print_message_type::websocket>(valueNew.reportError());
1056 }
1057 }
1058 if (data.d.heartbeatInterval != 0) {
1059 areWeHeartBeating = true;
1060 heartBeatStopWatch = stop_watch<milliseconds>{ milliseconds{ data.d.heartbeatInterval } };
1061 heartBeatStopWatch.reset();
1062 haveWeReceivedHeartbeatAck = true;
1063 }
1064 if (areWeResuming) {
1065 websocket_message_data<websocket_resume_data> dataNewer{};
1066 dataNewer.d.botToken = configManager->getBotToken();
1067 dataNewer.d.lastNumberReceived = lastNumberReceived;
1068 dataNewer.d.sessionId = sessionId;
1069 dataNewer.op = 6;
1070 jsonifier::string_base<uint8_t> string{};
1071 if (dataOpCode == websocket_op_code::Op_Binary) {
1072 auto serializer = dataNewer.operator etf_serializer();
1073 string = serializer.operator jsonifier::string_base<uint8_t>();
1074 } else {
1075 parser.serializeJson<true>(dataNewer, string);
1076 }
1077 createHeader(string, dataOpCode);
1078 currentState.store(websocket_state::Sending_Identify, std::memory_order_release);
1079 if (!sendMessage(string, true)) {
1080 return false;
1081 }
1082 } else {
1083 websocket_message_data<websocket_identify_data> dataNewer{};
1084 dataNewer.d.botToken = configManager->getBotToken();
1085 dataNewer.d.shard.at(0) = shard.at(0);
1086 dataNewer.d.shard.at(1) = shard.at(1);
1087 dataNewer.d.intents = static_cast<int64_t>(configManager->getGatewayIntents());
1088 dataNewer.d.presence = configManager->getPresenceData();
1089 for (auto& value: dataNewer.d.presence.activities) {
1090 if (value.url == "") {
1091 value.excludedKeys.emplace("url");
1092 }
1093 }
1094 dataNewer.op = 2;
1095 jsonifier::string_base<uint8_t> string{};
1096 if (dataOpCode == websocket_op_code::Op_Binary) {
1097 auto serializer = dataNewer.operator etf_serializer();
1098 string = serializer.operator jsonifier::string_base<uint8_t>();
1099 } else {
1100 parser.serializeJson<true>(dataNewer, string);
1101 }
1102 createHeader(string, dataOpCode);
1103 currentState.store(websocket_state::Sending_Identify, std::memory_order_release);
1104 if (!sendMessage(string, true)) {
1105 return false;
1106 }
1107 }
1108 break;
1109 }
1110 case websocket_op_codes::Heartbeat_ACK: {
1111 haveWeReceivedHeartbeatAck = true;
1112 break;
1113 }
1114 case websocket_op_codes::identify: {
1115 [[fallthrough]];
1116 }
1117 case websocket_op_codes::Presence_Update: {
1118 [[fallthrough]];
1119 }
1120 case websocket_op_codes::Voice_State_Update: {
1121 [[fallthrough]];
1122 }
1123 case websocket_op_codes::resume: {
1124 [[fallthrough]];
1125 }
1126 case websocket_op_codes::Request_Guild_Members: {
1127 [[fallthrough]];
1128 }
1129 default: {
1130 break;
1131 }
1132 }
1133 return true;
1134 }
1135
1136 } catch (const dca_exception& error) {
1137 message_printer::printError<print_message_type::websocket>(error.what());
1138 }
1139 return false;
1140 }
1141
1142 void websocket_core::disconnect() {
1143 if (areWeConnected()) {
1144 jsonifier::string dataNew{ "\x03\xE8" };
1145 createHeader(dataNew, websocket_op_code::Op_Close);
1146 tcpConnection.writeData(static_cast<jsonifier::string_view>(dataNew), true);
1147 tcpConnection.disconnect();
1148 currentState.store(websocket_state::disconnected, std::memory_order_release);
1149 areWeHeartBeating = false;
1150 }
1151 }
1152
1153 void websocket_client::disconnect() {
1154 websocket_core::disconnect();
1155 }
1156
1157 void websocket_client::onClosed() {
1158 if (maxReconnectTries > currentReconnectTries) {
1159 disconnect();
1160 } else {
1161 if (doWeQuit) {
1162 doWeQuit->store(true, std::memory_order_release);
1163 }
1164 }
1165 }
1166
1167 websocket_client::~websocket_client() {
1168 disconnect();
1169 }
1170
1171 base_socket_agent::base_socket_agent(std::atomic_bool* doWeQuitNew) {
1172 doWeQuit = doWeQuitNew;
1173 taskThread = std::jthread([this](std::stop_token token) {
1174 run(token);
1175 });
1176 }
1177
1178 void base_socket_agent::connect(websocket_client& value) {
1179 jsonifier::string connectionUrl{ value.areWeResuming ? value.resumeUrl : discord_core_client::getInstance()->configManager.getConnectionAddress() };
1180 message_printer::printSuccess<print_message_type::general>(jsonifier::string{ "Connecting shard " + jsonifier::toString(value.shard.at(0) + 1) + " of " +
1181 jsonifier::toString(discord_core_client::getInstance()->configManager.getShardCountForThisProcess()) + jsonifier::string{ " shards for this process. (" } +
1182 jsonifier::toString(value.shard.at(0) + 1) + " of " + jsonifier::toString(discord_core_client::getInstance()->configManager.getTotalShardCount()) +
1183 jsonifier::string{ " shards total across all processes)" } });
1184 jsonifier::string relativePath{ "/?v=10&encoding=" +
1185 jsonifier::string{ discord_core_client::getInstance()->configManager.getTextFormat() == text_format::etf ? "etf" : "json" } };
1186
1187 value = websocket_client{ value.shard.at(0), doWeQuit };
1188 value.connect(connectionUrl, relativePath, discord_core_client::getInstance()->configManager.getConnectionPort());
1189 if (value.tcpConnection.currentStatus != connection_status::NO_Error) {
1190 std::cout << "WERE HERE THIS IS TI!" << std::endl;
1191 value.onClosed();
1192 }
1193 value.tcpConnection.processIO(0);
1194 discord_core_client::getInstance()->connectionStopWatch01.reset();
1195 }
1196
1197 void base_socket_agent::run(std::stop_token token) {
1198 unordered_map<uint64_t, websocket_tcpconnection*> processIOMapNew{};
1199 while (!discord_core_client::getInstance()->areWeReadyToConnect.load(std::memory_order_acquire)) {
1200 std::this_thread::sleep_for(1ms);
1201 }
1202 for (auto& [key, value]: shardMap) {
1203 while (key != discord_core_client::getInstance()->currentlyConnectingShard.load(std::memory_order_acquire) ||
1204 !discord_core_client::getInstance()->connectionStopWatch01.hasTimeElapsed()) {
1205 processIOMapNew.reserve(shardMap.size());
1206 for (auto& [keyNew, valueNew]: shardMap) {
1207 if (valueNew.areWeConnected()) {
1208 processIOMapNew.emplace(keyNew, &valueNew.tcpConnection);
1209 }
1210 }
1211 tcp_connection<websocket_tcpconnection>::processIO(processIOMapNew);
1212 processIOMapNew.clear();
1213 std::this_thread::sleep_for(1ms);
1214 }
1215 connect(value);
1216 discord_core_client::getInstance()->currentlyConnectingShard.fetch_add(1, std::memory_order_release);
1217 }
1218 processIOMapNew.clear();
1219 while (!token.stop_requested() && !doWeQuit->load(std::memory_order_acquire)) {
1220 try {
1221 for (auto& [key, value]: shardMap) {
1222 if (value.areWeConnected()) {
1223 processIOMapNew.emplace(key, &value.tcpConnection);
1224 }
1225 }
1226 tcp_connection<websocket_tcpconnection>::processIO(processIOMapNew);
1227 processIOMapNew.clear();
1228 bool areWeConnected{};
1229 for (auto& [key, value]: shardMap) {
1230 if (value.areWeConnected()) {
1231 if (value.checkForAndSendHeartBeat()) {
1232 on_gateway_ping_data dataNew{};
1233 dataNew.timeUntilNextPing = static_cast<int32_t>(value.heartBeatStopWatch.getTotalWaitTime().count());
1234 discord_core_client::getInstance()->eventManager.onGatewayPingEvent(dataNew);
1235 }
1236 areWeConnected = true;
1237 } else {
1238 message_printer::printError<print_message_type::websocket>(
1239 jsonifier::string{ "Connection lost for websocket [" + jsonifier::toString(value.shard.at(0)) + "," +
1240 jsonifier::toString(discord_core_client::getInstance()->configManager.getTotalShardCount()) + "]... reconnecting." });
1241 std::this_thread::sleep_for(1s);
1242 if (discord_core_client::getInstance()->connectionStopWatch01.hasTimeElapsed()) {
1243 connect(value);
1244 }
1245 }
1246 }
1247 if (!areWeConnected) {
1248 std::this_thread::sleep_for(1ms);
1249 }
1250 } catch (const dca_exception& error) {
1251 message_printer::printError<print_message_type::websocket>(error.what());
1252 }
1253 }
1254 }
1255
1256 base_socket_agent::~base_socket_agent(){}
1257 }// namespace discord_core_internal
1258}// namespace discord_core_api
websocket_op_codes
For the opcodes that could be sent/received via discord's websockets.
@ connect
Allows for joining of a voice channel.
The main namespace for the forward-facing interfaces.