43 extern voice_connections_map voiceConnectionMap;
45 namespace discord_core_internal {
47 event_converter::event_converter(
const jsonifier::string& newEvent) {
48 eventValue = newEvent;
51 event_converter::operator uint64_t() {
52 if (eventValue ==
"READY") {
54 }
else if (eventValue ==
"RESUMED") {
56 }
else if (eventValue ==
"APPLICATION_COMMAND_PERMISSIONS_UPDATE") {
58 }
else if (eventValue ==
"AUTO_MODERATION_RULE_CREATE") {
60 }
else if (eventValue ==
"AUTO_MODERATION_RULE_UPDATE") {
62 }
else if (eventValue ==
"AUTO_MODERATION_RULE_DELETE") {
64 }
else if (eventValue ==
"AUTO_MODERATION_ACTION_EXECUTION") {
66 }
else if (eventValue ==
"CHANNEL_CREATE") {
68 }
else if (eventValue ==
"CHANNEL_UPDATE") {
70 }
else if (eventValue ==
"CHANNEL_DELETE") {
72 }
else if (eventValue ==
"CHANNEL_PINS_UPDATE") {
74 }
else if (eventValue ==
"THREAD_CREATE") {
76 }
else if (eventValue ==
"THREAD_UPDATE") {
78 }
else if (eventValue ==
"THREAD_DELETE") {
80 }
else if (eventValue ==
"THREAD_LIST_SYNC") {
82 }
else if (eventValue ==
"THREAD_MEMBER_UPDATE") {
84 }
else if (eventValue ==
"THREAD_MEMBERS_UPDATE") {
86 }
else if (eventValue ==
"GUILD_CREATE") {
88 }
else if (eventValue ==
"GUILD_UPDATE") {
90 }
else if (eventValue ==
"GUILD_DELETE") {
92 }
else if (eventValue ==
"GUILD_BAN_ADD") {
94 }
else if (eventValue ==
"GUILD_BAN_REMOVE") {
96 }
else if (eventValue ==
"GUILD_EMOJIS_UPDATE") {
98 }
else if (eventValue ==
"GUILD_STICKERS_UPDATE") {
100 }
else if (eventValue ==
"GUILD_INTEGRATIONS_UPDATE") {
102 }
else if (eventValue ==
"GUILD_MEMBER_ADD") {
104 }
else if (eventValue ==
"GUILD_MEMBER_REMOVE") {
106 }
else if (eventValue ==
"GUILD_MEMBER_UPDATE") {
108 }
else if (eventValue ==
"GUILD_MEMBERS_CHUNK") {
110 }
else if (eventValue ==
"GUILD_ROLE_CREATE") {
112 }
else if (eventValue ==
"GUILD_ROLE_UPDATE") {
114 }
else if (eventValue ==
"GUILD_ROLE_DELETE") {
116 }
else if (eventValue ==
"GUILD_SCHEDULED_EVENT_CREATE") {
118 }
else if (eventValue ==
"GUILD_SCHEDULED_EVENT_UPDATE") {
120 }
else if (eventValue ==
"GUILD_SCHEDULED_EVENT_DELETE") {
122 }
else if (eventValue ==
"GUILD_SCHEDULED_EVENT_USER_ADD") {
124 }
else if (eventValue ==
"GUILD_SCHEDULED_EVENT_USER_REMOVE") {
126 }
else if (eventValue ==
"INTEGRATION_CREATE") {
128 }
else if (eventValue ==
"INTEGRATION_UPDATE") {
130 }
else if (eventValue ==
"INTEGRATION_DELETE") {
132 }
else if (eventValue ==
"INTERACTION_CREATE") {
134 }
else if (eventValue ==
"INVITE_CREATE") {
136 }
else if (eventValue ==
"INVITE_DELETE") {
138 }
else if (eventValue ==
"MESSAGE_CREATE") {
140 }
else if (eventValue ==
"MESSAGE_UPDATE") {
142 }
else if (eventValue ==
"MESSAGE_DELETE") {
144 }
else if (eventValue ==
"MESSAGE_DELETE_BULK") {
146 }
else if (eventValue ==
"MESSAGE_REACTION_ADD") {
148 }
else if (eventValue ==
"MESSAGE_REACTION_REMOVE") {
150 }
else if (eventValue ==
"MESSAGE_REACTION_REMOVE_ALL") {
152 }
else if (eventValue ==
"MESSAGE_REACTION_REMOVE_EMOJI") {
154 }
else if (eventValue ==
"PRESENCE_UPDATE") {
156 }
else if (eventValue ==
"STAGE_INSTANCE_CREATE") {
158 }
else if (eventValue ==
"STAGE_INSTANCE_UPDATE") {
160 }
else if (eventValue ==
"STAGE_INSTANCE_DELETE") {
162 }
else if (eventValue ==
"TYPING_START") {
164 }
else if (eventValue ==
"USER_UPDATE") {
166 }
else if (eventValue ==
"VOICE_STATE_UPDATE") {
168 }
else if (eventValue ==
"VOICE_SERVER_UPDATE") {
170 }
else if (eventValue ==
"WEBHOOKS_UPDATE") {
177 websocket_core::websocket_core(config_manager* configManagerNew, websocket_type typeOfWebSocketNew) {
178 configManager = configManagerNew;
179 wsType = typeOfWebSocketNew;
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;
202 websocket_core::websocket_core(websocket_core&& other)
noexcept {
203 *
this = std::move(other);
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);
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);
217 if (tcpConnection.currentStatus != connection_status::NO_Error) {
218 std::this_thread::sleep_for(1s);
224 websocket_tcpconnection::websocket_tcpconnection(
const jsonifier::string& baseUrlNew, uint16_t portNew, websocket_core* ptrNew) : tcp_connection{ baseUrlNew, portNew } {
228 bool websocket_core::sendMessage(jsonifier::string_base<uint8_t>& dataToSend,
bool priority) {
229 if (dataToSend.size() == 0) {
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) {
246 void websocket_core::parseConnectionHeaders() {
247 if (areWeConnected() && currentState.load(std::memory_order_acquire) == websocket_state::upgrading) {
248 jsonifier::string_base<uint8_t> newString{};
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);
260 bool websocket_core::checkForAndSendHeartBeat(
bool isImmediate) {
261 if ((currentState.load(std::memory_order_acquire) == websocket_state::authenticated && heartBeatStopWatch.hasTimeElapsed() && haveWeReceivedHeartbeatAck) ||
263 jsonifier::string_base<uint8_t>
string{};
264 if (dataOpCode == websocket_op_code::Op_Binary) {
265 etf_serializer data{};
266 data[
"d"] = lastNumberReceived;
268 string = data.operator jsonifier::string_base<uint8_t>();
270 websocket_message_data<uint64_t> message{};
271 message.d = lastNumberReceived;
273 parser.serializeJson(message,
string);
275 haveWeReceivedHeartbeatAck =
false;
276 heartBeatStopWatch.reset();
277 createHeader(
string, dataOpCode);
278 return sendMessage(
string,
true);
283 bool websocket_core::parseMessage() {
284 if (currentMessage.size() < 4) {
287 websocket_op_code opcode =
static_cast<websocket_op_code
>(currentMessage.at(0) & ~webSocketMaskBit);
289 case websocket_op_code::Op_Continuation:
291 case websocket_op_code::Op_Text:
293 case websocket_op_code::Op_Binary:
295 case websocket_op_code::Op_Ping:
297 case websocket_op_code::Op_Pong: {
298 uint8_t length00 = currentMessage.at(1);
299 uint32_t messageOffset = 2;
301 if (length00 & webSocketMaskBit) {
305 uint64_t lengthFinal = length00;
307 if (length00 == webSocketPayloadLengthMagicLarge) {
308 if (currentMessage.size() < 8) {
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);
317 }
else if (length00 == webSocketPayloadLengthMagicHuge) {
318 if (currentMessage.size() < 10) {
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;
329 if (currentMessage.size() < messageOffset + lengthFinal) {
333 if (opcode == websocket_op_code::Op_Ping || opcode == websocket_op_code::Op_Pong) {
336 onMessageReceived({ currentMessage.data() + messageOffset, lengthFinal });
337 currentMessage.erase(messageOffset + lengthFinal);
341 case websocket_op_code::Op_Close: {
342 uint16_t closeValue =
static_cast<uint16_t
>(currentMessage.at(2) & 0xff);
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());
350 websocket_close wsClose{ closeValue };
351 closeString =
static_cast<jsonifier::string
>(wsClose.operator jsonifier::string_view());
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);
366 bool websocket_core::areWeConnected() {
367 return tcpConnection.areWeStillConnected();
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());
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();
380 while (ptr->parseMessage()) {
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;
395 dataOpCode = websocket_op_code::Op_Text;
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);
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;
412 userId = doWeCollect.userId;
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;
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>();
427 parser.serializeJson(data01,
string);
429 createHeader(
string, dataOpCode);
430 if (!sendMessage(
string,
true)) {
433 if (snowflake{ doWeCollect.channelId } == 0) {
436 serializer = data02.operator etf_serializer();
437 if (dataOpCode == websocket_op_code::Op_Binary) {
438 string = serializer.operator jsonifier::string_base<uint8_t>();
440 parser.serializeJson(data02,
string);
442 createHeader(
string, dataOpCode);
443 areWeCollectingData.store(
true, std::memory_order_release);
444 if (!sendMessage(
string,
true)) {
449 uint64_t countBackSlashes(jsonifier::string_base<uint8_t>::iterator& iter, jsonifier::string_base<uint8_t>::iterator end, uint64_t currentCount = 0) {
454 return countBackSlashes(iter, end, currentCount);
461 bool websocket_client::onMessageReceived(jsonifier::string_view_base<uint8_t> dataNew) {
463 if (areWeConnected() && currentMessage.size() > 0 && dataNew.size() > 0) {
464 websocket_message message{};
465 if (configManager->getTextFormat() == text_format::etf) {
468 parser.parseJson(message, dataNew);
469 for (
auto& valueNew: parser.getErrors()) {
470 message_printer::printError<print_message_type::websocket>(valueNew.reportError() +
", for data:" + dataNew);
472 }
catch (
const dca_exception& error) {
473 message_printer::printError<print_message_type::websocket>(error.what());
474 tcpConnection.getInputBuffer();
475 currentMessage.clear();
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);
487 if (message.s != 0) {
488 lastNumberReceived =
static_cast<uint32_t
>(message.s);
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 });
493 case websocket_op_codes::dispatch: {
494 if (message.t !=
"") {
495 switch (event_converter{ message.t }) {
497 websocket_message_data<ready_data> data{};
498 if (dataOpCode == websocket_op_code::Op_Text) {
499 data.d.jsonifierExcludedKeys.emplace(
"shard");
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());
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());
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())))]
517 users::insertUser(
static_cast<user_cache_data
>(std::move(data.d.user)));
518 currentReconnectTries = 0;
522 currentState.store(websocket_state::authenticated, std::memory_order_release);
523 currentReconnectTries = 0;
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>(
530 discord_core_client::getInstance()->eventManager.onApplicationCommandPermissionsUpdateEvent(*dataPackage);
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);
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);
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);
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,
559 discord_core_client::getInstance()->eventManager.onAutoModerationActionExecutionEvent(*dataPackage);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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,
770 discord_core_client::getInstance()->eventManager.onGuildScheduledEventUserRemoveEvent(*dataPackage);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
939 case websocket_op_codes::heartbeat: {
940 if (!checkForAndSendHeartBeat(
true)) {
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();
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());
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 });
968 if (data.d ==
true) {
969 areWeResuming =
true;
971 areWeResuming =
false;
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());
984 if (data.d.heartbeatInterval != 0) {
985 areWeHeartBeating =
true;
986 heartBeatStopWatch = stop_watch<milliseconds>{ milliseconds{ data.d.heartbeatInterval } };
987 heartBeatStopWatch.reset();
988 haveWeReceivedHeartbeatAck =
true;
991 websocket_message_data<websocket_resume_data> dataNewer{};
992 dataNewer.d.botToken = configManager->getBotToken();
993 dataNewer.d.lastNumberReceived = lastNumberReceived;
994 dataNewer.d.sessionId = sessionId;
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>();
1001 parser.serializeJson(dataNewer,
string);
1003 createHeader(
string, dataOpCode);
1004 currentState.store(websocket_state::Sending_Identify, std::memory_order_release);
1005 if (!sendMessage(
string,
true)) {
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");
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>();
1027 parser.serializeJson(dataNewer, stringNew);
1029 createHeader(
string, dataOpCode);
1030 currentState.store(websocket_state::Sending_Identify, std::memory_order_release);
1031 if (!sendMessage(
string,
true)) {
1037 case websocket_op_codes::Heartbeat_ACK: {
1038 haveWeReceivedHeartbeatAck =
true;
1041 case websocket_op_codes::identify: {
1044 case websocket_op_codes::Presence_Update: {
1047 case websocket_op_codes::Voice_State_Update: {
1050 case websocket_op_codes::resume: {
1053 case websocket_op_codes::Request_Guild_Members: {
1063 }
catch (
const dca_exception& error) {
1064 message_printer::printError<print_message_type::websocket>(error.what());
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;
1080 void websocket_client::disconnect() {
1081 websocket_core::disconnect();
1084 void websocket_client::onClosed() {
1085 if (maxReconnectTries > currentReconnectTries) {
1089 doWeQuit->store(
true, std::memory_order_release);
1094 websocket_client::~websocket_client() {
1098 base_socket_agent::base_socket_agent(std::atomic_bool* doWeQuitNew) {
1099 doWeQuit = doWeQuitNew;
1100 taskThread = std::jthread([
this](std::stop_token token) {
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" } };
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) {
1119 value.tcpConnection.processIO(0);
1120 discord_core_client::getInstance()->connectionStopWatch01.reset();
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);
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);
1137 tcp_connection<websocket_tcpconnection>::processIO(processIOMapNew);
1138 processIOMapNew.clear();
1139 std::this_thread::sleep_for(1ms);
1142 discord_core_client::getInstance()->currentlyConnectingShard.fetch_add(1, std::memory_order_release);
1144 processIOMapNew.clear();
1145 while (!token.stop_requested() && !doWeQuit->load(std::memory_order_acquire)) {
1147 for (
auto& [key, value]: shardMap) {
1148 if (value.areWeConnected()) {
1149 processIOMapNew.emplace(key, &value.tcpConnection);
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);
1162 areWeConnected =
true;
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()) {
1172 if (!areWeConnected) {
1173 std::this_thread::sleep_for(1ms);
1175 }
catch (
const dca_exception& error) {
1176 message_printer::printError<print_message_type::websocket>(error.what());
1181 base_socket_agent::~base_socket_agent(){}
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.
@ connect
Allows for joining of a voice channel.
The main namespace for the forward-facing interfaces.