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(const 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) {
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 currentReconnectTries = other.currentReconnectTries;
190 lastNumberReceived = other.lastNumberReceived;
191 maxReconnectTries = other.maxReconnectTries;
192 areWeHeartBeating = other.areWeHeartBeating;
193 areWeResuming = other.areWeResuming;
194 configManager = other.configManager;
195 dataOpCode = other.dataOpCode;
196 shard.at(0) = other.shard.at(0);
197 shard.at(1) = other.shard.at(1);
198 wsType = other.wsType;
199 return *this;
200 }
201
202 websocket_core::websocket_core(websocket_core&& other) noexcept {
203 *this = std::move(other);
204 }
205
206 bool websocket_core::connect(const jsonifier::string& baseUrlNew, jsonifier::string_view relativePath, const uint16_t portNew) {
207 tcpConnection = websocket_tcpconnection{ baseUrlNew, portNew, this };
208 if (tcpConnection.currentStatus != connection_status::NO_Error) {
209 std::this_thread::sleep_for(1s);
210 return false;
211 }
212 currentState.store(websocket_state::upgrading, std::memory_order_release);
213 jsonifier::string sendString{ "GET " + relativePath + " HTTP/1.1\r\nHost: " + baseUrlNew +
214 "\r\nUpgrade: webSocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: " + generateBase64EncodedKey() + "\r\nSec-WebSocket-Version: 13\r\n\r\n" };
215 tcpConnection.writeData(static_cast<jsonifier::string_view>(sendString), true);
216
217 if (tcpConnection.currentStatus != connection_status::NO_Error) {
218 std::this_thread::sleep_for(1s);
219 return false;
220 }
221 return true;
222 }
223
224 websocket_tcpconnection::websocket_tcpconnection(const jsonifier::string& baseUrlNew, uint16_t portNew, websocket_core* ptrNew) : tcp_connection{ baseUrlNew, portNew } {
225 ptr = ptrNew;
226 }
227
228 bool websocket_core::sendMessage(jsonifier::string_base<uint8_t>& dataToSend, bool priority) {
229 if (dataToSend.size() == 0) {
230 return false;
231 }
232 jsonifier::string webSocketTitle{ wsType == websocket_type::voice ? "voice websocket" : "WebSocket" };
233 message_printer::printSuccess<print_message_type::websocket>("sending " + webSocketTitle + " [" + jsonifier::toString(shard.at(0)) + "," +
234 jsonifier::toString(shard.at(1)) + "]" + jsonifier::string{ "'s message: " } + dataToSend);
235 std::unique_lock lock{ accessMutex };
236 if (areWeConnected()) {
237 tcpConnection.writeData(static_cast<jsonifier::string_view_base<uint8_t>>(dataToSend), priority);
238 if (tcpConnection.currentStatus != connection_status::NO_Error) {
239 onClosed();
240 return false;
241 }
242 }
243 return true;
244 }
245
246 void websocket_core::parseConnectionHeaders() {
247 if (areWeConnected() && currentState.load(std::memory_order_acquire) == websocket_state::upgrading) {
248 jsonifier::string_base<uint8_t> newString{};
249 newString.resize(4);
250 std::memcpy(newString.data(), "\r\n\r\n", 4);
251 auto theFindValue = currentMessage.find(newString);
252 if (theFindValue != jsonifier::string::npos) {
253 currentMessage.clear();
254 currentState.store(websocket_state::Collecting_Hello, std::memory_order_release);
255 return;
256 }
257 }
258 }
259
260 bool websocket_core::checkForAndSendHeartBeat(bool isImmediate) {
261 if ((currentState.load(std::memory_order_acquire) == websocket_state::authenticated && heartBeatStopWatch.hasTimeElapsed() && haveWeReceivedHeartbeatAck) ||
262 isImmediate) {
263 jsonifier::string_base<uint8_t> string{};
264 if (dataOpCode == websocket_op_code::Op_Binary) {
265 etf_serializer data{};
266 data["d"] = lastNumberReceived;
267 data["op"] = 1;
268 string = data.operator jsonifier::string_base<uint8_t>();
269 } else {
270 websocket_message_data<uint64_t> message{};
271 message.d = lastNumberReceived;
272 message.op = 1;
273 parser.serializeJson(message, string);
274 }
275 haveWeReceivedHeartbeatAck = false;
276 heartBeatStopWatch.reset();
277 createHeader(string, dataOpCode);
278 return sendMessage(string, true);
279 }
280 return false;
281 }
282
283 bool websocket_core::parseMessage() {
284 if (currentMessage.size() < 4) {
285 return false;
286 } else {
287 websocket_op_code opcode = static_cast<websocket_op_code>(currentMessage.at(0) & ~webSocketMaskBit);
288 switch (opcode) {
289 case websocket_op_code::Op_Continuation:
290 [[fallthrough]];
291 case websocket_op_code::Op_Text:
292 [[fallthrough]];
293 case websocket_op_code::Op_Binary:
294 [[fallthrough]];
295 case websocket_op_code::Op_Ping:
296 [[fallthrough]];
297 case websocket_op_code::Op_Pong: {
298 uint8_t length00 = currentMessage.at(1);
299 uint32_t messageOffset = 2;
300
301 if (length00 & webSocketMaskBit) {
302 return true;
303 }
304
305 uint64_t lengthFinal = length00;
306
307 if (length00 == webSocketPayloadLengthMagicLarge) {
308 if (currentMessage.size() < 8) {
309 return false;
310 }
311
312 uint8_t length01 = static_cast<uint8_t>(currentMessage.at(2));
313 uint8_t length02 = static_cast<uint8_t>(currentMessage.at(3));
314 lengthFinal = static_cast<uint64_t>((length01 << 8ULL) | length02);
315
316 messageOffset += 2;
317 } else if (length00 == webSocketPayloadLengthMagicHuge) {
318 if (currentMessage.size() < 10) {
319 return false;
320 }
321 lengthFinal = 0;
322 for (uint64_t x = 2, shift = 56; x < 10; ++x, shift -= 8) {
323 uint8_t length03 = static_cast<uint8_t>(currentMessage.at(x));
324 lengthFinal |= static_cast<uint64_t>(length03 & 0xff) << shift;
325 }
326 messageOffset += 8;
327 }
328
329 if (currentMessage.size() < messageOffset + lengthFinal) {
330 return false;
331 }
332
333 if (opcode == websocket_op_code::Op_Ping || opcode == websocket_op_code::Op_Pong) {
334 return false;
335 } else {
336 onMessageReceived({ currentMessage.data() + messageOffset, lengthFinal });
337 currentMessage.erase(messageOffset + lengthFinal);
338 }
339 return true;
340 } break;
341 case websocket_op_code::Op_Close: {
342 uint16_t closeValue = static_cast<uint16_t>(currentMessage.at(2) & 0xff);
343 closeValue <<= 8;
344 closeValue |= currentMessage.at(3) & 0xff;
345 jsonifier::string closeString{};
346 if (wsType == websocket_type::voice) {
347 voice_websocket_close voiceClose{ closeValue };
348 closeString = static_cast<jsonifier::string>(voiceClose.operator jsonifier::string_view());
349 } else {
350 websocket_close wsClose{ closeValue };
351 closeString = static_cast<jsonifier::string>(wsClose.operator jsonifier::string_view());
352 }
353 jsonifier::string webSocketTitle = wsType == websocket_type::voice ? "voice websocket" : "WebSocket";
354 message_printer::printError<print_message_type::websocket>(webSocketTitle + " [" + jsonifier::toString(shard.at(0)) + "," +
355 jsonifier::toString(shard.at(1)) + "]" + " closed; code: " + jsonifier::toString(closeValue) + ", " + closeString);
356 return false;
357 } break;
358
359 default: {
360 return false;
361 } break;
362 }
363 }
364 }
365
366 bool websocket_core::areWeConnected() {
367 return tcpConnection.areWeStillConnected();
368 }
369
370 void websocket_tcpconnection::handleBuffer() {
371 auto inputBufferNew = getInputBuffer();
372 auto oldSize = ptr->currentMessage.size();
373 if (ptr->currentMessage.size() < oldSize + inputBufferNew.size()) {
374 ptr->currentMessage.resize(oldSize + inputBufferNew.size());
375 }
376 std::memcpy(ptr->currentMessage.data() + oldSize, inputBufferNew.data(), inputBufferNew.size());
377 if (ptr->currentState.load(std::memory_order_acquire) == websocket_state::upgrading) {
378 ptr->parseConnectionHeaders();
379 } else {
380 while (ptr->parseMessage()) {
381 };
382 }
383 }
384
385 websocket_client::websocket_client(uint64_t currentShardNew, std::atomic_bool* doWeQuitNew)
386 : websocket_core(&discord_core_client::getInstance()->configManager, websocket_type::normal) {
387 configManager = &discord_core_client::getInstance()->configManager;
388 shard.at(0) = currentShardNew;
389 doWeQuit = doWeQuitNew;
390 if (discord_core_client::getInstance()) {
391 shard.at(1) = discord_core_client::getInstance()->configManager.getTotalShardCount();
392 if (discord_core_client::getInstance()->configManager.getTextFormat() == text_format::etf) {
393 dataOpCode = websocket_op_code::Op_Binary;
394 } else {
395 dataOpCode = websocket_op_code::Op_Text;
396 }
397 }
398 }
399
400 void websocket_client::getVoiceConnectionData(const voice_connect_init_data& doWeCollect) {
401 while (currentState.load(std::memory_order_acquire) != websocket_state::authenticated) {
402 std::this_thread::sleep_for(1ms);
403 }
404 websocket_message_data<update_voice_state_data_dc> data01{};
405 data01.jsonifierExcludedKeys.emplace("t");
406 data01.jsonifierExcludedKeys.emplace("s");
407 data01.d.channelId = std::nullptr_t{};
408 data01.d.guildId = doWeCollect.guildId;
409 data01.d.selfDeaf = doWeCollect.selfDeaf;
410 data01.d.selfMute = doWeCollect.selfMute;
411 data01.op = 4;
412 userId = doWeCollect.userId;
413
414 websocket_message_data<update_voice_state_data> data02{};
415 data02.jsonifierExcludedKeys.emplace("t");
416 data02.jsonifierExcludedKeys.emplace("s");
417 data02.d.channelId = doWeCollect.channelId;
418 data02.d.guildId = doWeCollect.guildId;
419 data02.d.selfDeaf = doWeCollect.selfDeaf;
420 data02.d.selfMute = doWeCollect.selfMute;
421 data02.op = 4;
422 jsonifier::string_base<uint8_t> string{};
423 auto serializer = data01.operator etf_serializer();
424 if (dataOpCode == websocket_op_code::Op_Binary) {
425 string = serializer.operator jsonifier::string_base<uint8_t>();
426 } else {
427 parser.serializeJson(data01, string);
428 }
429 createHeader(string, dataOpCode);
430 if (!sendMessage(string, true)) {
431 return;
432 }
433 if (snowflake{ doWeCollect.channelId } == 0) {
434 return;
435 }
436 serializer = data02.operator etf_serializer();
437 if (dataOpCode == websocket_op_code::Op_Binary) {
438 string = serializer.operator jsonifier::string_base<uint8_t>();
439 } else {
440 parser.serializeJson(data02, string);
441 }
442 createHeader(string, dataOpCode);
443 areWeCollectingData.store(true, std::memory_order_release);
444 if (!sendMessage(string, true)) {
445 return;
446 }
447 }
448
449 uint64_t countBackSlashes(jsonifier::string_base<uint8_t>::iterator& iter, jsonifier::string_base<uint8_t>::iterator end, uint64_t currentCount = 0) {
450 if (iter < end) {
451 if (*iter == '\\') {
452 ++currentCount;
453 ++iter;
454 return countBackSlashes(iter, end, currentCount);
455 }
456 }
457 ++iter;
458 return currentCount;
459 }
460
461 bool websocket_client::onMessageReceived(jsonifier::string_view_base<uint8_t> dataNew) {
462 try {
463 if (areWeConnected() && currentMessage.size() > 0 && dataNew.size() > 0) {
464 websocket_message message{};
465 if (configManager->getTextFormat() == text_format::etf) {
466 try {
467 dataNew = etfParser.parseEtfToJson(dataNew);
468 parser.parseJson(message, dataNew);
469 for (auto& valueNew: parser.getErrors()) {
470 message_printer::printError<print_message_type::websocket>(valueNew.reportError() + ", for data:" + dataNew);
471 }
472 } catch (const dca_exception& error) {
473 message_printer::printError<print_message_type::websocket>(error.what());
474 tcpConnection.getInputBuffer();
475 currentMessage.clear();
476 return false;
477 }
478 } else {
479 parser.parseJson(message, dataNew);
480 if (auto result = parser.getErrors(); result.size() > 0) {
481 for (auto& valueNew: result) {
482 message_printer::printError<print_message_type::websocket>(valueNew.reportError() + ", for data:" + dataNew);
483 }
484 }
485 }
486
487 if (message.s != 0) {
488 lastNumberReceived = static_cast<uint32_t>(message.s);
489 }
490 message_printer::printSuccess<print_message_type::websocket>("Message received from websocket [" + jsonifier::toString(shard.at(0)) + "," +
491 jsonifier::toString(shard.at(1)) + jsonifier::string("]: ") + jsonifier::string{ dataNew });
492 switch (static_cast<websocket_op_codes>(message.op)) {
493 case websocket_op_codes::dispatch: {
494 if (message.t != "") {
495 switch (event_converter{ message.t }) {
496 case 1: {
497 websocket_message_data<ready_data> data{};
498 if (dataOpCode == websocket_op_code::Op_Text) {
499 data.d.jsonifierExcludedKeys.emplace("shard");
500 }
501 currentState.store(websocket_state::authenticated, std::memory_order_release);
502 parser.parseJson(data, dataNew);
503 if (auto result = parser.getErrors(); result.size() > 0) {
504 for (auto& valueNew: result) {
505 message_printer::printError<print_message_type::websocket>(valueNew.reportError());
506 }
507 }
508 sessionId = data.d.sessionId;
509 if (data.d.resumeGatewayUrl.find("wss://") != jsonifier::string::npos) {
510 resumeUrl = data.d.resumeGatewayUrl.substr(data.d.resumeGatewayUrl.find("wss://") + jsonifier::string{ "wss://" }.size());
511 }
512 discord_core_client::getInstance()->currentUser = bot_user{ data.d.user,
513 discord_core_client::getInstance()
514 ->baseSocketAgentsMap[static_cast<uint64_t>(floor(
515 static_cast<uint64_t>(shard.at(0)) % static_cast<uint64_t>(discord_core_client::getInstance()->baseSocketAgentsMap.size())))]
516 .get() };
517 users::insertUser(static_cast<user_cache_data>(std::move(data.d.user)));
518 currentReconnectTries = 0;
519 break;
520 }
521 case 2: {
522 currentState.store(websocket_state::authenticated, std::memory_order_release);
523 currentReconnectTries = 0;
524 break;
525 }
526 case 3: {
527 if (discord_core_client::getInstance()->eventManager.onApplicationCommandPermissionsUpdateEvent.functions.size() > 0) {
528 unique_ptr<on_application_command_permissions_update_data> dataPackage{ makeUnique<on_application_command_permissions_update_data>(
529 parser, dataNew) };
530 discord_core_client::getInstance()->eventManager.onApplicationCommandPermissionsUpdateEvent(*dataPackage);
531 }
532 break;
533 }
534 case 4: {
535 if (discord_core_client::getInstance()->eventManager.onAutoModerationRuleCreationEvent.functions.size() > 0) {
536 unique_ptr<on_auto_moderation_rule_creation_data> dataPackage{ makeUnique<on_auto_moderation_rule_creation_data>(parser, dataNew) };
537 discord_core_client::getInstance()->eventManager.onAutoModerationRuleCreationEvent(*dataPackage);
538 }
539 break;
540 }
541 case 5: {
542 if (discord_core_client::getInstance()->eventManager.onAutoModerationRuleUpdateEvent.functions.size() > 0) {
543 unique_ptr<on_auto_moderation_rule_update_data> dataPackage{ makeUnique<on_auto_moderation_rule_update_data>(parser, dataNew) };
544 discord_core_client::getInstance()->eventManager.onAutoModerationRuleUpdateEvent(*dataPackage);
545 }
546 break;
547 }
548 case 6: {
549 if (discord_core_client::getInstance()->eventManager.onAutoModerationRuleDeletionEvent.functions.size() > 0) {
550 unique_ptr<on_auto_moderation_rule_deletion_data> dataPackage{ makeUnique<on_auto_moderation_rule_deletion_data>(parser, dataNew) };
551 discord_core_client::getInstance()->eventManager.onAutoModerationRuleDeletionEvent(*dataPackage);
552 }
553 break;
554 }
555 case 7: {
556 if (discord_core_client::getInstance()->eventManager.onAutoModerationActionExecutionEvent.functions.size() > 0) {
557 unique_ptr<on_auto_moderation_action_execution_data> dataPackage{ makeUnique<on_auto_moderation_action_execution_data>(parser,
558 dataNew) };
559 discord_core_client::getInstance()->eventManager.onAutoModerationActionExecutionEvent(*dataPackage);
560 }
561 break;
562 }
563 case 8: {
564 unique_ptr<on_channel_creation_data> dataPackage{ makeUnique<on_channel_creation_data>(parser, dataNew) };
565 if (discord_core_client::getInstance()->eventManager.onChannelCreationEvent.functions.size() > 0) {
566 discord_core_client::getInstance()->eventManager.onChannelCreationEvent(*dataPackage);
567 }
568 break;
569 }
570 case 9: {
571 unique_ptr<on_channel_update_data> dataPackage{ makeUnique<on_channel_update_data>(parser, dataNew) };
572 if (discord_core_client::getInstance()->eventManager.onChannelUpdateEvent.functions.size() > 0) {
573 discord_core_client::getInstance()->eventManager.onChannelUpdateEvent(*dataPackage);
574 }
575 break;
576 }
577 case 10: {
578 unique_ptr<on_channel_deletion_data> dataPackage{ makeUnique<on_channel_deletion_data>(parser, dataNew) };
579 if (discord_core_client::getInstance()->eventManager.onChannelDeletionEvent.functions.size() > 0) {
580 discord_core_client::getInstance()->eventManager.onChannelDeletionEvent(*dataPackage);
581 }
582 break;
583 }
584 case 11: {
585 if (discord_core_client::getInstance()->eventManager.onChannelPinsUpdateEvent.functions.size() > 0) {
586 unique_ptr<on_channel_pins_update_data> dataPackage{ makeUnique<on_channel_pins_update_data>(parser, dataNew) };
587 discord_core_client::getInstance()->eventManager.onChannelPinsUpdateEvent(*dataPackage);
588 }
589 break;
590 }
591 case 12: {
592 if (discord_core_client::getInstance()->eventManager.onThreadCreationEvent.functions.size() > 0) {
593 unique_ptr<on_thread_creation_data> dataPackage{ makeUnique<on_thread_creation_data>(parser, dataNew) };
594 discord_core_client::getInstance()->eventManager.onThreadCreationEvent(*dataPackage);
595 }
596 break;
597 }
598 case 13: {
599 if (discord_core_client::getInstance()->eventManager.onThreadUpdateEvent.functions.size() > 0) {
600 unique_ptr<on_thread_update_data> dataPackage{ makeUnique<on_thread_update_data>(parser, dataNew) };
601 discord_core_client::getInstance()->eventManager.onThreadUpdateEvent(*dataPackage);
602 }
603 break;
604 }
605 case 14: {
606 if (discord_core_client::getInstance()->eventManager.onThreadDeletionEvent.functions.size() > 0) {
607 unique_ptr<on_thread_deletion_data> dataPackage{ makeUnique<on_thread_deletion_data>(parser, dataNew) };
608 discord_core_client::getInstance()->eventManager.onThreadDeletionEvent(*dataPackage);
609 }
610 break;
611 }
612 case 15: {
613 if (discord_core_client::getInstance()->eventManager.onThreadListSyncEvent.functions.size() > 0) {
614 unique_ptr<on_thread_list_sync_data> dataPackage{ makeUnique<on_thread_list_sync_data>(parser, dataNew) };
615 discord_core_client::getInstance()->eventManager.onThreadListSyncEvent(*dataPackage);
616 }
617 break;
618 }
619 case 16: {
620 if (discord_core_client::getInstance()->eventManager.onThreadMemberUpdateEvent.functions.size() > 0) {
621 unique_ptr<on_thread_member_update_data> dataPackage{ makeUnique<on_thread_member_update_data>(parser, dataNew) };
622 discord_core_client::getInstance()->eventManager.onThreadMemberUpdateEvent(*dataPackage);
623 }
624 break;
625 }
626 case 17: {
627 if (discord_core_client::getInstance()->eventManager.onThreadMembersUpdateEvent.functions.size() > 0) {
628 unique_ptr<on_thread_members_update_data> dataPackage{ makeUnique<on_thread_members_update_data>(parser, dataNew) };
629 discord_core_client::getInstance()->eventManager.onThreadMembersUpdateEvent(*dataPackage);
630 }
631 break;
632 }
633 case 18: {
634 unique_ptr<on_guild_creation_data> dataPackage{ makeUnique<on_guild_creation_data>(parser, dataNew) };
635 if (discord_core_client::getInstance()->eventManager.onGuildCreationEvent.functions.size() > 0) {
636 discord_core_client::getInstance()->eventManager.onGuildCreationEvent(*dataPackage);
637 }
638 break;
639 }
640 case 19: {
641 unique_ptr<on_guild_update_data> dataPackage{ makeUnique<on_guild_update_data>(parser, dataNew) };
642 if (discord_core_client::getInstance()->eventManager.onGuildUpdateEvent.functions.size() > 0) {
643 discord_core_client::getInstance()->eventManager.onGuildUpdateEvent(*dataPackage);
644 }
645 break;
646 }
647 case 20: {
648 unique_ptr<on_guild_deletion_data> dataPackage{ makeUnique<on_guild_deletion_data>(parser, dataNew) };
649 if (discord_core_client::getInstance()->eventManager.onGuildDeletionEvent.functions.size() > 0) {
650 discord_core_client::getInstance()->eventManager.onGuildDeletionEvent(*dataPackage);
651 }
652 break;
653 }
654 case 21: {
655 if (discord_core_client::getInstance()->eventManager.onGuildBanAddEvent.functions.size() > 0) {
656 unique_ptr<on_guild_ban_add_data> dataPackage{ makeUnique<on_guild_ban_add_data>(parser, dataNew) };
657 discord_core_client::getInstance()->eventManager.onGuildBanAddEvent(*dataPackage);
658 }
659 break;
660 }
661 case 22: {
662 if (discord_core_client::getInstance()->eventManager.onGuildBanRemoveEvent.functions.size() > 0) {
663 unique_ptr<on_guild_ban_remove_data> dataPackage{ makeUnique<on_guild_ban_remove_data>(parser, dataNew) };
664 discord_core_client::getInstance()->eventManager.onGuildBanRemoveEvent(*dataPackage);
665 }
666 break;
667 }
668 case 23: {
669 if (discord_core_client::getInstance()->eventManager.onGuildEmojisUpdateEvent.functions.size() > 0) {
670 unique_ptr<on_guild_emojis_update_data> dataPackage{ makeUnique<on_guild_emojis_update_data>(parser, dataNew) };
671 discord_core_client::getInstance()->eventManager.onGuildEmojisUpdateEvent(*dataPackage);
672 }
673 break;
674 }
675 case 24: {
676 if (discord_core_client::getInstance()->eventManager.onGuildStickersUpdateEvent.functions.size() > 0) {
677 unique_ptr<on_guild_stickers_update_data> dataPackage{ makeUnique<on_guild_stickers_update_data>(parser, dataNew) };
678 discord_core_client::getInstance()->eventManager.onGuildStickersUpdateEvent(*dataPackage);
679 }
680 break;
681 }
682 case 25: {
683 if (discord_core_client::getInstance()->eventManager.onGuildIntegrationsUpdateEvent.functions.size() > 0) {
684 unique_ptr<on_guild_integrations_update_data> dataPackage{ makeUnique<on_guild_integrations_update_data>(parser, dataNew) };
685 discord_core_client::getInstance()->eventManager.onGuildIntegrationsUpdateEvent(*dataPackage);
686 }
687 break;
688 }
689 case 26: {
690 unique_ptr<on_guild_member_add_data> dataPackage{ makeUnique<on_guild_member_add_data>(parser, dataNew) };
691 if (discord_core_client::getInstance()->eventManager.onGuildMemberAddEvent.functions.size() > 0) {
692 discord_core_client::getInstance()->eventManager.onGuildMemberAddEvent(*dataPackage);
693 }
694 break;
695 }
696 case 27: {
697 unique_ptr<on_guild_member_remove_data> dataPackage{ makeUnique<on_guild_member_remove_data>(parser, dataNew) };
698 if (discord_core_client::getInstance()->eventManager.onGuildMemberRemoveEvent.functions.size() > 0) {
699 discord_core_client::getInstance()->eventManager.onGuildMemberRemoveEvent(*dataPackage);
700 }
701 break;
702 }
703 case 28: {
704 unique_ptr<on_guild_member_update_data> dataPackage{ makeUnique<on_guild_member_update_data>(parser, dataNew) };
705 if (discord_core_client::getInstance()->eventManager.onGuildMemberUpdateEvent.functions.size() > 0) {
706 discord_core_client::getInstance()->eventManager.onGuildMemberUpdateEvent(*dataPackage);
707 }
708 break;
709 }
710 case 29: {
711 if (discord_core_client::getInstance()->eventManager.onGuildMembersChunkEvent.functions.size() > 0) {
712 unique_ptr<on_guild_members_chunk_data> dataPackage{ makeUnique<on_guild_members_chunk_data>(parser, dataNew) };
713 discord_core_client::getInstance()->eventManager.onGuildMembersChunkEvent(*dataPackage);
714 }
715 break;
716 }
717 case 30: {
718 unique_ptr<on_role_creation_data> dataPackage{ makeUnique<on_role_creation_data>(parser, dataNew) };
719 if (discord_core_client::getInstance()->eventManager.onRoleCreationEvent.functions.size() > 0) {
720 discord_core_client::getInstance()->eventManager.onRoleCreationEvent(*dataPackage);
721 }
722 break;
723 }
724 case 31: {
725 unique_ptr<on_role_update_data> dataPackage{ makeUnique<on_role_update_data>(parser, dataNew) };
726 if (discord_core_client::getInstance()->eventManager.onRoleUpdateEvent.functions.size() > 0) {
727 discord_core_client::getInstance()->eventManager.onRoleUpdateEvent(*dataPackage);
728 }
729 break;
730 }
731 case 32: {
732 unique_ptr<on_role_deletion_data> dataPackage{ makeUnique<on_role_deletion_data>(parser, dataNew) };
733 if (discord_core_client::getInstance()->eventManager.onRoleDeletionEvent.functions.size() > 0) {
734 discord_core_client::getInstance()->eventManager.onRoleDeletionEvent(*dataPackage);
735 }
736 break;
737 }
738 case 33: {
739 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventCreationEvent.functions.size() > 0) {
740 unique_ptr<on_guild_scheduled_event_creation_data> dataPackage{ makeUnique<on_guild_scheduled_event_creation_data>(parser, dataNew) };
741 discord_core_client::getInstance()->eventManager.onGuildScheduledEventCreationEvent(*dataPackage);
742 }
743 break;
744 }
745 case 34: {
746 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventUpdateEvent.functions.size() > 0) {
747 unique_ptr<on_guild_scheduled_event_update_data> dataPackage{ makeUnique<on_guild_scheduled_event_update_data>(parser, dataNew) };
748 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUpdateEvent(*dataPackage);
749 }
750 break;
751 }
752 case 35: {
753 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventDeletionEvent.functions.size() > 0) {
754 unique_ptr<on_guild_scheduled_event_deletion_data> dataPackage{ makeUnique<on_guild_scheduled_event_deletion_data>(parser, dataNew) };
755 discord_core_client::getInstance()->eventManager.onGuildScheduledEventDeletionEvent(*dataPackage);
756 }
757 break;
758 }
759 case 36: {
760 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserAddEvent.functions.size() > 0) {
761 unique_ptr<on_guild_scheduled_event_user_add_data> dataPackage{ makeUnique<on_guild_scheduled_event_user_add_data>(parser, dataNew) };
762 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserAddEvent(*dataPackage);
763 }
764 break;
765 }
766 case 37: {
767 if (discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserRemoveEvent.functions.size() > 0) {
768 unique_ptr<on_guild_scheduled_event_user_remove_data> dataPackage{ makeUnique<on_guild_scheduled_event_user_remove_data>(parser,
769 dataNew) };
770 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserRemoveEvent(*dataPackage);
771 }
772 break;
773 }
774 case 38: {
775 if (discord_core_client::getInstance()->eventManager.onIntegrationCreationEvent.functions.size() > 0) {
776 unique_ptr<on_integration_creation_data> dataPackage{ makeUnique<on_integration_creation_data>(parser, dataNew) };
777 discord_core_client::getInstance()->eventManager.onIntegrationCreationEvent(*dataPackage);
778 }
779 break;
780 }
781 case 39: {
782 if (discord_core_client::getInstance()->eventManager.onIntegrationUpdateEvent.functions.size() > 0) {
783 unique_ptr<on_integration_update_data> dataPackage{ makeUnique<on_integration_update_data>(parser, dataNew) };
784 discord_core_client::getInstance()->eventManager.onIntegrationUpdateEvent(*dataPackage);
785 }
786 break;
787 }
788 case 40: {
789 if (discord_core_client::getInstance()->eventManager.onIntegrationDeletionEvent.functions.size() > 0) {
790 unique_ptr<on_integration_deletion_data> dataPackage{ makeUnique<on_integration_deletion_data>(parser, dataNew) };
791 discord_core_client::getInstance()->eventManager.onIntegrationDeletionEvent(*dataPackage);
792 }
793 break;
794 }
795 case 41: {
796 unique_ptr<on_interaction_creation_data> dataPackage{ makeUnique<on_interaction_creation_data>(parser, dataNew) };
797 if (discord_core_client::getInstance()->eventManager.onInteractionCreationEvent.functions.size() > 0) {
798 discord_core_client::getInstance()->eventManager.onInteractionCreationEvent(*dataPackage);
799 }
800 break;
801 }
802 case 42: {
803 if (discord_core_client::getInstance()->eventManager.onInviteCreationEvent.functions.size() > 0) {
804 unique_ptr<on_invite_creation_data> dataPackage{ makeUnique<on_invite_creation_data>(parser, dataNew) };
805 discord_core_client::getInstance()->eventManager.onInviteCreationEvent(*dataPackage);
806 }
807 break;
808 }
809 case 43: {
810 if (discord_core_client::getInstance()->eventManager.onInviteDeletionEvent.functions.size() > 0) {
811 unique_ptr<on_invite_deletion_data> dataPackage{ makeUnique<on_invite_deletion_data>(parser, dataNew) };
812 discord_core_client::getInstance()->eventManager.onInviteDeletionEvent(*dataPackage);
813 }
814 break;
815 }
816 case 44: {
817 unique_ptr<on_message_creation_data> dataPackage{ makeUnique<on_message_creation_data>(parser, dataNew) };
818 if (discord_core_client::getInstance()->eventManager.onMessageCreationEvent.functions.size() > 0) {
819 discord_core_client::getInstance()->eventManager.onMessageCreationEvent(*dataPackage);
820 }
821 break;
822 }
823 case 45: {
824 unique_ptr<on_message_update_data> dataPackage{ makeUnique<on_message_update_data>(parser, dataNew) };
825 if (discord_core_client::getInstance()->eventManager.onMessageUpdateEvent.functions.size() > 0) {
826 discord_core_client::getInstance()->eventManager.onMessageUpdateEvent(*dataPackage);
827 }
828 break;
829 }
830 case 46: {
831 if (discord_core_client::getInstance()->eventManager.onMessageDeletionEvent.functions.size() > 0) {
832 unique_ptr<on_message_deletion_data> dataPackage{ makeUnique<on_message_deletion_data>(parser, dataNew) };
833 discord_core_client::getInstance()->eventManager.onMessageDeletionEvent(*dataPackage);
834 }
835 break;
836 }
837 case 47: {
838 if (discord_core_client::getInstance()->eventManager.onMessageDeleteBulkEvent.functions.size() > 0) {
839 unique_ptr<on_message_delete_bulk_data> dataPackage{ makeUnique<on_message_delete_bulk_data>(parser, dataNew) };
840 discord_core_client::getInstance()->eventManager.onMessageDeleteBulkEvent(*dataPackage);
841 }
842 break;
843 }
844 case 48: {
845 if (discord_core_client::getInstance()->eventManager.onReactionAddEvent.functions.size() > 0) {
846 unique_ptr<on_reaction_add_data> dataPackage{ makeUnique<on_reaction_add_data>(parser, dataNew) };
847 discord_core_client::getInstance()->eventManager.onReactionAddEvent(*dataPackage);
848 }
849 break;
850 }
851 case 49: {
852 if (discord_core_client::getInstance()->eventManager.onReactionRemoveEvent.functions.size() > 0) {
853 unique_ptr<on_reaction_remove_data> dataPackage{ makeUnique<on_reaction_remove_data>(parser, dataNew) };
854 discord_core_client::getInstance()->eventManager.onReactionRemoveEvent(*dataPackage);
855 }
856 break;
857 }
858 case 50: {
859 if (discord_core_client::getInstance()->eventManager.onReactionRemoveAllEvent.functions.size() > 0) {
860 unique_ptr<on_reaction_remove_all_data> dataPackage{ makeUnique<on_reaction_remove_all_data>(parser, dataNew) };
861 discord_core_client::getInstance()->eventManager.onReactionRemoveAllEvent(*dataPackage);
862 }
863 break;
864 }
865 case 51: {
866 if (discord_core_client::getInstance()->eventManager.onReactionRemoveEmojiEvent.functions.size() > 0) {
867 unique_ptr<on_reaction_remove_emoji_data> dataPackage{ makeUnique<on_reaction_remove_emoji_data>(parser, dataNew) };
868 discord_core_client::getInstance()->eventManager.onReactionRemoveEmojiEvent(*dataPackage);
869 }
870 break;
871 }
872 case 52: {
873 unique_ptr<on_presence_update_data> dataPackage{ makeUnique<on_presence_update_data>(parser, dataNew) };
874 if (discord_core_client::getInstance()->eventManager.onPresenceUpdateEvent.functions.size() > 0) {
875 discord_core_client::getInstance()->eventManager.onPresenceUpdateEvent(*dataPackage);
876 }
877 break;
878 }
879 case 53: {
880 if (discord_core_client::getInstance()->eventManager.onStageInstanceCreationEvent.functions.size() > 0) {
881 unique_ptr<on_stage_instance_creation_data> dataPackage{ makeUnique<on_stage_instance_creation_data>(parser, dataNew) };
882 discord_core_client::getInstance()->eventManager.onStageInstanceCreationEvent(*dataPackage);
883 }
884 break;
885 }
886 case 54: {
887 if (discord_core_client::getInstance()->eventManager.onStageInstanceUpdateEvent.functions.size() > 0) {
888 unique_ptr<on_stage_instance_update_data> dataPackage{ makeUnique<on_stage_instance_update_data>(parser, dataNew) };
889 discord_core_client::getInstance()->eventManager.onStageInstanceUpdateEvent(*dataPackage);
890 }
891 break;
892 }
893 case 55: {
894 if (discord_core_client::getInstance()->eventManager.onStageInstanceDeletionEvent.functions.size() > 0) {
895 unique_ptr<on_stage_instance_deletion_data> dataPackage{ makeUnique<on_stage_instance_deletion_data>(parser, dataNew) };
896 discord_core_client::getInstance()->eventManager.onStageInstanceDeletionEvent(*dataPackage);
897 }
898 break;
899 }
900 case 56: {
901 if (discord_core_client::getInstance()->eventManager.onTypingStartEvent.functions.size() > 0) {
902 unique_ptr<on_typing_start_data> dataPackage{ makeUnique<on_typing_start_data>(parser, dataNew) };
903 discord_core_client::getInstance()->eventManager.onTypingStartEvent(*dataPackage);
904 }
905 break;
906 }
907 case 57: {
908 if (discord_core_client::getInstance()->eventManager.onUserUpdateEvent.functions.size() > 0) {
909 unique_ptr<on_user_update_data> dataPackage{ makeUnique<on_user_update_data>(parser, dataNew) };
910 discord_core_client::getInstance()->eventManager.onUserUpdateEvent(*dataPackage);
911 }
912 break;
913 }
914 case 58: {
915 unique_ptr<on_voice_state_update_data> dataPackage{ makeUnique<on_voice_state_update_data>(parser, dataNew, this) };
916 if (discord_core_client::getInstance()->eventManager.onVoiceStateUpdateEvent.functions.size() > 0) {
917 discord_core_client::getInstance()->eventManager.onVoiceStateUpdateEvent(*dataPackage);
918 }
919 break;
920 }
921 case 59: {
922 unique_ptr<on_voice_server_update_data> dataPackage{ makeUnique<on_voice_server_update_data>(parser, dataNew, this) };
923 if (discord_core_client::getInstance()->eventManager.onVoiceServerUpdateEvent.functions.size() > 0) {
924 discord_core_client::getInstance()->eventManager.onVoiceServerUpdateEvent(*dataPackage);
925 }
926 break;
927 }
928 case 60: {
929 if (discord_core_client::getInstance()->eventManager.onWebhookUpdateEvent.functions.size() > 0) {
930 unique_ptr<on_webhook_update_data> dataPackage{ makeUnique<on_webhook_update_data>(parser, dataNew) };
931 discord_core_client::getInstance()->eventManager.onWebhookUpdateEvent(*dataPackage);
932 }
933 break;
934 }
935 }
936 }
937 break;
938 }
939 case websocket_op_codes::heartbeat: {
940 if (!checkForAndSendHeartBeat(true)) {
941 return false;
942 }
943 break;
944 }
945 case websocket_op_codes::reconnect: {
946 message_printer::printError<print_message_type::websocket>(
947 "Shard [" + jsonifier::toString(shard.at(0)) + "," + jsonifier::toString(shard.at(1)) + "]" + " reconnecting (type 7)!");
948 areWeResuming = true;
949 tcpConnection.disconnect();
950 return true;
951 }
952 case websocket_op_codes::Invalid_Session: {
953 websocket_message_data<bool> data{};
954 parser.parseJson(data, dataNew);
955 if (auto result = parser.getErrors(); result.size() > 0) {
956 for (auto& valueNew: result) {
957 message_printer::printError<print_message_type::websocket>(valueNew.reportError());
958 }
959 }
960 message_printer::printError<print_message_type::websocket>(
961 "Shard [" + jsonifier::toString(shard.at(0)) + "," + jsonifier::toString(shard.at(1)) + "]" + " reconnecting (type 9)!");
962 std::mt19937_64 randomEngine{ static_cast<uint64_t>(sys_clock::now().time_since_epoch().count()) };
963 uint64_t numOfMsToWait =
964 static_cast<uint64_t>(1000.0f + ((static_cast<double>(randomEngine()) / static_cast<double>(randomEngine.max())) * static_cast<double>(4000.0f)));
965 if (numOfMsToWait <= 5000 && numOfMsToWait > 0) {
966 std::this_thread::sleep_for(milliseconds{ numOfMsToWait });
967 }
968 if (data.d == true) {
969 areWeResuming = true;
970 } else {
971 areWeResuming = false;
972 }
973 onClosed();
974 return true;
975 }
976 case websocket_op_codes::hello: {
977 websocket_message_data<hello_data> data{};
978 parser.parseJson(data, dataNew);
979 if (auto result = parser.getErrors(); result.size() > 0) {
980 for (auto& valueNew: result) {
981 message_printer::printError<print_message_type::websocket>(valueNew.reportError());
982 }
983 }
984 if (data.d.heartbeatInterval != 0) {
985 areWeHeartBeating = true;
986 heartBeatStopWatch = stop_watch<milliseconds>{ milliseconds{ data.d.heartbeatInterval } };
987 heartBeatStopWatch.reset();
988 haveWeReceivedHeartbeatAck = true;
989 }
990 if (areWeResuming) {
991 websocket_message_data<websocket_resume_data> dataNewer{};
992 dataNewer.d.botToken = configManager->getBotToken();
993 dataNewer.d.lastNumberReceived = lastNumberReceived;
994 dataNewer.d.sessionId = sessionId;
995 dataNewer.op = 6;
996 jsonifier::string_base<uint8_t> string{};
997 if (dataOpCode == websocket_op_code::Op_Binary) {
998 auto serializer = dataNewer.operator etf_serializer();
999 string = serializer.operator jsonifier::string_base<uint8_t>();
1000 } else {
1001 parser.serializeJson(dataNewer, string);
1002 }
1003 createHeader(string, dataOpCode);
1004 currentState.store(websocket_state::Sending_Identify, std::memory_order_release);
1005 if (!sendMessage(string, true)) {
1006 return false;
1007 }
1008 } else {
1009 websocket_message_data<websocket_identify_data> dataNewer{};
1010 dataNewer.d.botToken = configManager->getBotToken();
1011 dataNewer.d.shard.at(0) = shard.at(0);
1012 dataNewer.d.shard.at(1) = shard.at(1);
1013 dataNewer.d.intents = static_cast<int64_t>(configManager->getGatewayIntents());
1014 dataNewer.d.presence = configManager->getPresenceData();
1015 for (auto& value: dataNewer.d.presence.activities) {
1016 if (value.url == "") {
1017 value.jsonifierExcludedKeys.emplace("url");
1018 }
1019 }
1020 dataNewer.op = 2;
1021 jsonifier::string_base<char> stringNew{};
1022 jsonifier::string_base<uint8_t> string{};
1023 if (dataOpCode == websocket_op_code::Op_Binary) {
1024 auto serializer = dataNewer.operator etf_serializer();
1025 string = serializer.operator jsonifier::string_base<uint8_t>();
1026 } else {
1027 parser.serializeJson(dataNewer, stringNew);
1028 }
1029 createHeader(string, dataOpCode);
1030 currentState.store(websocket_state::Sending_Identify, std::memory_order_release);
1031 if (!sendMessage(string, true)) {
1032 return false;
1033 }
1034 }
1035 break;
1036 }
1037 case websocket_op_codes::Heartbeat_ACK: {
1038 haveWeReceivedHeartbeatAck = true;
1039 break;
1040 }
1041 case websocket_op_codes::identify: {
1042 [[fallthrough]];
1043 }
1044 case websocket_op_codes::Presence_Update: {
1045 [[fallthrough]];
1046 }
1047 case websocket_op_codes::Voice_State_Update: {
1048 [[fallthrough]];
1049 }
1050 case websocket_op_codes::resume: {
1051 [[fallthrough]];
1052 }
1053 case websocket_op_codes::Request_Guild_Members: {
1054 [[fallthrough]];
1055 }
1056 default: {
1057 break;
1058 }
1059 }
1060 return true;
1061 }
1062
1063 } catch (const dca_exception& error) {
1064 message_printer::printError<print_message_type::websocket>(error.what());
1065 }
1066 return false;
1067 }
1068
1069 void websocket_core::disconnect() {
1070 if (areWeConnected()) {
1071 jsonifier::string dataNew{ "\x03\xE8" };
1072 createHeader(dataNew, websocket_op_code::Op_Close);
1073 tcpConnection.writeData(static_cast<jsonifier::string_view>(dataNew), true);
1074 tcpConnection.disconnect();
1075 currentState.store(websocket_state::disconnected, std::memory_order_release);
1076 areWeHeartBeating = false;
1077 }
1078 }
1079
1080 void websocket_client::disconnect() {
1081 websocket_core::disconnect();
1082 }
1083
1084 void websocket_client::onClosed() {
1085 if (maxReconnectTries > currentReconnectTries) {
1086 disconnect();
1087 } else {
1088 if (doWeQuit) {
1089 doWeQuit->store(true, std::memory_order_release);
1090 }
1091 }
1092 }
1093
1094 websocket_client::~websocket_client() {
1095 disconnect();
1096 }
1097
1098 base_socket_agent::base_socket_agent(std::atomic_bool* doWeQuitNew) {
1099 doWeQuit = doWeQuitNew;
1100 taskThread = std::jthread([this](std::stop_token token) {
1101 run(token);
1102 });
1103 }
1104
1105 void base_socket_agent::connect(websocket_client& value) {
1106 jsonifier::string connectionUrl{ value.areWeResuming ? value.resumeUrl : discord_core_client::getInstance()->configManager.getConnectionAddress() };
1107 message_printer::printSuccess<print_message_type::general>("Connecting shard " + jsonifier::toString(value.shard.at(0) + 1) + " of " +
1108 jsonifier::toString(discord_core_client::getInstance()->configManager.getShardCountForThisProcess()) + jsonifier::string{ " shards for this process. (" } +
1109 jsonifier::toString(value.shard.at(0) + 1) + " of " + jsonifier::toString(discord_core_client::getInstance()->configManager.getTotalShardCount()) +
1110 jsonifier::string{ " shards total across all processes)" });
1111 jsonifier::string relativePath{ "/?v=10&encoding=" +
1112 jsonifier::string{ discord_core_client::getInstance()->configManager.getTextFormat() == text_format::etf ? "etf" : "json" } };
1113
1114 value = websocket_client{ value.shard.at(0), doWeQuit };
1115 value.connect(connectionUrl, relativePath, discord_core_client::getInstance()->configManager.getConnectionPort());
1116 if (value.tcpConnection.currentStatus != connection_status::NO_Error) {
1117 value.onClosed();
1118 }
1119 value.tcpConnection.processIO(0);
1120 discord_core_client::getInstance()->connectionStopWatch01.reset();
1121 }
1122
1123 void base_socket_agent::run(std::stop_token token) {
1124 unordered_map<uint64_t, websocket_tcpconnection*> processIOMapNew{};
1125 while (!discord_core_client::getInstance()->areWeReadyToConnect.load(std::memory_order_acquire)) {
1126 std::this_thread::sleep_for(1ms);
1127 }
1128 for (auto& [key, value]: shardMap) {
1129 while (key != discord_core_client::getInstance()->currentlyConnectingShard.load(std::memory_order_acquire) ||
1130 !discord_core_client::getInstance()->connectionStopWatch01.hasTimeElapsed()) {
1131 processIOMapNew.reserve(shardMap.size());
1132 for (auto& [keyNew, valueNew]: shardMap) {
1133 if (valueNew.areWeConnected()) {
1134 processIOMapNew.emplace(keyNew, &valueNew.tcpConnection);
1135 }
1136 }
1137 tcp_connection<websocket_tcpconnection>::processIO(processIOMapNew);
1138 processIOMapNew.clear();
1139 std::this_thread::sleep_for(1ms);
1140 }
1141 connect(value);
1142 discord_core_client::getInstance()->currentlyConnectingShard.fetch_add(1, std::memory_order_release);
1143 }
1144 processIOMapNew.clear();
1145 while (!token.stop_requested() && !doWeQuit->load(std::memory_order_acquire)) {
1146 try {
1147 for (auto& [key, value]: shardMap) {
1148 if (value.areWeConnected()) {
1149 processIOMapNew.emplace(key, &value.tcpConnection);
1150 }
1151 }
1152 tcp_connection<websocket_tcpconnection>::processIO(processIOMapNew);
1153 processIOMapNew.clear();
1154 bool areWeConnected{};
1155 for (auto& [key, value]: shardMap) {
1156 if (value.areWeConnected()) {
1157 if (value.checkForAndSendHeartBeat()) {
1158 on_gateway_ping_data dataNew{};
1159 dataNew.timeUntilNextPing = static_cast<int32_t>(value.heartBeatStopWatch.getTotalWaitTime().count());
1160 discord_core_client::getInstance()->eventManager.onGatewayPingEvent(dataNew);
1161 }
1162 areWeConnected = true;
1163 } else {
1164 message_printer::printError<print_message_type::websocket>("Connection lost for websocket [" + jsonifier::toString(value.shard.at(0)) + "," +
1165 jsonifier::toString(discord_core_client::getInstance()->configManager.getTotalShardCount()) + "]... reconnecting.");
1166 std::this_thread::sleep_for(1s);
1167 if (discord_core_client::getInstance()->connectionStopWatch01.hasTimeElapsed()) {
1168 connect(value);
1169 }
1170 }
1171 }
1172 if (!areWeConnected) {
1173 std::this_thread::sleep_for(1ms);
1174 }
1175 } catch (const dca_exception& error) {
1176 message_printer::printError<print_message_type::websocket>(error.what());
1177 }
1178 }
1179 }
1180
1181 base_socket_agent::~base_socket_agent(){}
1182 }// namespace discord_core_internal
1183}// namespace discord_core_api
websocket_op_codes
For the opcodes that could be sent/received via discord's websockets.
DCA_INLINE jsonifier::string_view_base< uint8_t > parseEtfToJson(jsonifier::string_view_base< uint8_t > dataToParse)
Parse etf data to json format.
Definition Etf.hpp:132
@ connect
Allows for joining of a voice channel.
The main namespace for the forward-facing interfaces.