DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
Utilities.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/// Utilities.cpp - Source file for the utilities.
27/// Jun 28, 2022
28/// https://discordcoreapi.com
29/// \file Utilities.cpp
30
43#include <fstream>
44#include <time.h>
45
46namespace discord_core_api {
47
48 update_presence_data::update_presence_data(presence_update_state state) {
49 status = state;
50 switch (status) {
51 case presence_update_state::online: {
52 statusReal = "online";
53 return;
54 }
55 case presence_update_state::Do_Not_Disturb: {
56 statusReal = "dnd";
57 return;
58 }
59 case presence_update_state::idle: {
60 statusReal = "idle";
61 return;
62 }
63 case presence_update_state::invisible: {
64 statusReal = "invisible";
65 return;
66 }
67 case presence_update_state::offline: {
68 statusReal = "offline";
69 return;
70 }
71 }
72 }
73
74 std::basic_ostream<char>& operator<<(std::basic_ostream<char>& outputSttream, jsonifier::string_view (*function)(void)) {
75 outputSttream << function();
76 return outputSttream;
77 }
78
79 config_manager::config_manager(const discord_core_client_config& configNew) {
80 config = configNew;
81 }
82
83 bool config_manager::doWePrintWebSocketSuccessMessages() const {
84 return config.logOptions.logWebSocketSuccessMessages;
85 }
86
87 bool config_manager::doWePrintWebSocketErrorMessages() const {
88 return config.logOptions.logWebSocketErrorMessages;
89 }
90
91 bool config_manager::doWePrintHttpsSuccessMessages() const {
92 return config.logOptions.logHttpsSuccessMessages;
93 }
94
95 bool config_manager::doWePrintHttpsErrorMessages() const {
96 return config.logOptions.logHttpsErrorMessages;
97 }
98
99 bool config_manager::doWePrintGeneralSuccessMessages() const {
100 return config.logOptions.logGeneralSuccessMessages;
101 }
102
103 bool config_manager::doWePrintGeneralErrorMessages() const {
104 return config.logOptions.logGeneralErrorMessages;
105 }
106
107 bool config_manager::doWeCacheGuildMembers() const {
108 return config.cacheOptions.cacheGuildMembers;
109 }
110
111 bool config_manager::doWeCacheChannels() const {
112 return config.cacheOptions.cacheChannels;
113 }
114
115 bool config_manager::doWeCacheUsers() const {
116 return config.cacheOptions.cacheUsers;
117 }
118
119 bool config_manager::doWeCacheVoiceStates() const {
120 return config.cacheOptions.cacheVoiceStates;
121 }
122
123 bool config_manager::doWeCacheGuilds() const {
124 return config.cacheOptions.cacheGuilds;
125 }
126
127 bool config_manager::doWeCacheRoles() const {
128 return config.cacheOptions.cacheRoles;
129 }
130
131 update_presence_data config_manager::getPresenceData() const {
132 return config.presenceData;
133 }
134
135 jsonifier::string config_manager::getBotToken() const {
136 return config.botToken;
137 }
138
139 std::ostream* config_manager::getErrorStream() const {
140 return config.logOptions.errorStream;
141 }
142
143 std::ostream* config_manager::getOutputStream() const {
144 return config.logOptions.outputStream;
145 }
146
147 uint64_t config_manager::getTotalShardCount() const {
148 return config.shardOptions.totalNumberOfShards;
149 }
150
151 uint64_t config_manager::getStartingShard() const {
152 return config.shardOptions.startingShard;
153 }
154
155 uint64_t config_manager::getShardCountForThisProcess() const {
156 return config.shardOptions.numberOfShardsForThisProcess;
157 }
158
159 jsonifier::string config_manager::getConnectionAddress() const {
160 return config.connectionAddress;
161 }
162
163 void config_manager::setConnectionAddress(jsonifier::string_view connectionAddressNew) {
164 config.connectionAddress = connectionAddressNew;
165 }
166
167 uint16_t config_manager::getConnectionPort() const {
168 return config.connectionPort;
169 }
170
171 void config_manager::setConnectionPort(const uint16_t connectionPortNew) {
172 config.connectionPort = connectionPortNew;
173 }
174
175 jsonifier::vector<repeated_function_data> config_manager::getFunctionsToExecute() const {
176 return config.functionsToExecute;
177 }
178
179 text_format config_manager::getTextFormat() const {
180 return config.textFormat;
181 }
182
183 gateway_intents config_manager::getGatewayIntents() {
184 return config.intents;
185 }
186
187 audio_frame_data::audio_frame_data(audio_frame_type frameTypeNew) {
188 type = frameTypeNew;
189 }
190
191 audio_frame_data& audio_frame_data::operator+=(jsonifier::string_view_base<uint8_t> other) {
192 if (other.size() > 0) {
193 if (data.size() < other.size()) {
194 data.resize(other.size());
195 }
196 std::memcpy(data.data(), other.data(), other.size());
197 }
198 currentSize = static_cast<int64_t>(other.size());
199 return *this;
200 }
201
202 audio_frame_data& audio_frame_data::operator+=(jsonifier::vector<uint8_t> other) {
203 if (other.size() > 0) {
204 if (data.size() < other.size()) {
205 data.resize(other.size());
206 }
207 std::memcpy(data.data(), other.data(), other.size());
208 }
209 currentSize = static_cast<int64_t>(other.size());
210 return *this;
211 }
212
213 void audio_frame_data::clearData() {
215 currentSize = 0;
216 data.clear();
217 }
218
219 color_value::color_value(uint32_t colorValue) {
220 color = colorValue;
221 }
222
223 color_value::color_value(jsonifier::string_view hexColorValue) {
224 jsonifier::string returnString{};
225 if (hexColorValue == "") {
226 returnString = jsonifier::string{ "fefefe" };
227 } else {
228 returnString = hexColorValue;
229 }
230 color = static_cast<uint32_t>(jsonifier::strToInt64<16>(returnString));
231 }
232
233 rgbcolor_value color_value::getRgbColorValue() {
234 uint8_t red = static_cast<uint8_t>(color >> 16);
235 uint8_t green = static_cast<uint8_t>(color >> 8);
236 uint8_t blue = static_cast<uint8_t>(color);
237 rgbcolor_value colorNew{};
238 colorNew.green = green;
239 colorNew.blue = blue;
240 colorNew.red = red;
241 return colorNew;
242 }
243
244 hex_color_value color_value::getHexColorValue() {
245 std::stringstream stream{};
246 stream << std::hex << color;
247 return jsonifier::string{ stream.str() };
248 }
249
250 uint32_t color_value::getIntColorValue() {
251 return color;
252 }
253
254 icon_hash& icon_hash::operator=(jsonifier::string_view string) {
255 jsonifier::string newHash{ string };
256 if (newHash.empty() || newHash == "0") {
257 highBits = 0;
258 lowBits = 0;
259 return *this;
260 }
261 if (newHash.size() >= 32 && newHash.find("a_") != jsonifier::string::npos) {
262 newHash = newHash.substr(newHash.find("a_") + 2);
263 }
264 if (newHash.size() != 32) {
265 throw dca_exception{ "Sorry, but that is an incorrect icon_hash length, it must be 32 characters long." };
266 }
267 lowBits = fromString<uint64_t>(newHash.substr(0, 16), std::hex);
268 highBits = fromString<uint64_t>(newHash.substr(16, 16), std::hex);
269 return *this;
270 }
271
272 icon_hash::icon_hash(jsonifier::string_view string) {
273 *this = string;
274 }
275
276 icon_hash::operator jsonifier::string() const {
277 if (highBits == 0 || lowBits == 0) {
278 return {};
279 } else {
280 return toHex(lowBits) + toHex(highBits);
281 }
282 }
283
284 jsonifier::string operator+(const icon_hash& lhs, jsonifier::string_view rhs) {
285 jsonifier::string newString = lhs.operator jsonifier::string() += rhs;
286 return newString;
287 }
288
289 bool icon_hash::operator==(const icon_hash& rhs) const {
290 return highBits == rhs.highBits && lowBits == rhs.lowBits;
291 }
292
293 bool icon_hash::operator==(jsonifier::string_view rhs) const {
294 return operator jsonifier::string() == rhs;
295 }
296
297 template<>
298 jsonifier::string permissions_base<permissions>::computeOverwrites(jsonifier::string_view basePermissions, const guild_member_data& guildMember, const channel_data& channel) {
299 if ((jsonifier::strToUint64(basePermissions.data()) & static_cast<uint64_t>(permission::administrator)) & static_cast<uint64_t>(permission::administrator)) {
300 return getAllPermissions();
301 }
302
303 uint64_t permissions = jsonifier::strToUint64(basePermissions.data());
304 for (uint64_t x = 0; x < channel.permissionOverwrites.size(); ++x) {
305 if (channel.permissionOverwrites.at(x).id == guildMember.guildId) {
306 permissions &= ~channel.permissionOverwrites.at(x).deny;
307 permissions |= channel.permissionOverwrites.at(x).allow;
308 break;
309 }
310 }
311 jsonifier::vector<role_data> guildMemberRoles{};
312 for (auto& value: guildMember.roles) {
313 guildMemberRoles.emplace_back(roles::getCachedRole({ .guildId = guildMember.guildId, .roleId = value }));
314 }
315 uint64_t allow{};
316 uint64_t deny{};
317 for (auto& value: guildMemberRoles) {
318 for (uint64_t x = 0; x < channel.permissionOverwrites.size(); ++x) {
319 if (value.id == channel.permissionOverwrites.at(x).id) {
320 allow |= channel.permissionOverwrites.at(x).allow;
321 deny |= channel.permissionOverwrites.at(x).deny;
322 }
323 }
324 }
325 permissions &= ~deny;
326 permissions |= allow;
327 for (uint64_t x = 0; x < channel.permissionOverwrites.size(); ++x) {
328 if (channel.permissionOverwrites.at(x).id == guildMember.user.id) {
329 permissions &= ~channel.permissionOverwrites.at(x).deny;
330 permissions |= channel.permissionOverwrites.at(x).allow;
331 break;
332 }
333 }
334 return jsonifier::toString(permissions);
335 }
336
337 template<> jsonifier::string permissions_base<permissions>::computeBasePermissions(const guild_member_data& guildMember) {
338 const guild_cache_data guild = guilds::getCachedGuild({ .guildId = guildMember.guildId });
339 if (guild.ownerId == guildMember.user.id) {
340 return getAllPermissions();
341 }
342 jsonifier::vector<role_data> guildRoles{};
343 if (roles::doWeCacheRoles()) {
344 for (auto& value: guild.roles) {
345 guildRoles.emplace_back(roles::getCachedRole({ .roleId = value }));
346 }
347 } else {
348 guildRoles = roles::getGuildRolesAsync({ .guildId = guildMember.guildId }).get();
349 }
350 role_data roleEveryone{};
351 for (auto& value: guildRoles) {
352 if (value.id == guild.id) {
353 roleEveryone = value;
354 }
355 }
356 uint64_t permissions{};
357 if (roleEveryone.permissions.operator std::basic_string_view<char, std::char_traits<char>>() != "0") {
358 permissions = roleEveryone.permissions;
359 }
360 get_guild_member_roles_data getRolesData{};
361 getRolesData.guildMember = guildMember;
362 getRolesData.guildId = guildMember.guildId;
363 jsonifier::vector<role_data> guildMemberRoles{};
364 if (roles::doWeCacheRoles()) {
365 for (auto& value: guildMember.roles) {
366 guildMemberRoles.emplace_back(roles::getCachedRole({ .roleId = value }));
367 }
368 } else {
369 guildMemberRoles = roles::getGuildMemberRolesAsync({ .guildMember = guildMember, .guildId = guildMember.guildId }).get();
370 }
371 for (auto& value: guildMemberRoles) {
372 permissions |= value.permissions.operator uint64_t();
373 }
374 if (permissions & static_cast<uint64_t>(permission::administrator)) {
375 return getAllPermissions();
376 }
377
378 return jsonifier::toString(permissions);
379 }
380
381 template<> jsonifier::string permissions_base<permissions_parse>::computeOverwrites(jsonifier::string_view basePermissions, const guild_member_data& guildMember,
382 const channel_data& channel) {
383 if ((jsonifier::strToUint64(basePermissions.data()) & static_cast<uint64_t>(permission::administrator)) & static_cast<uint64_t>(permission::administrator)) {
384 return getAllPermissions();
385 }
386
387 uint64_t permissions = jsonifier::strToUint64(basePermissions.data());
388 for (uint64_t x = 0; x < channel.permissionOverwrites.size(); ++x) {
389 if (channel.permissionOverwrites.at(x).id == guildMember.guildId) {
390 permissions &= ~channel.permissionOverwrites.at(x).deny;
391 permissions |= channel.permissionOverwrites.at(x).allow;
392 break;
393 }
394 }
395 jsonifier::vector<role_data> guildMemberRoles{};
396 if (roles::doWeCacheRoles()) {
397 for (auto& value: guildMember.roles) {
398 guildMemberRoles.emplace_back(roles::getCachedRole({ .roleId = value }));
399 }
400 } else {
401 guildMemberRoles = roles::getGuildMemberRolesAsync({ .guildMember = guildMember, .guildId = guildMember.guildId }).get();
402 }
403 uint64_t allow{};
404 uint64_t deny{};
405 for (auto& value: guildMemberRoles) {
406 for (uint64_t x = 0; x < channel.permissionOverwrites.size(); ++x) {
407 if (value.id == channel.permissionOverwrites.at(x).id) {
408 allow |= channel.permissionOverwrites.at(x).allow;
409 deny |= channel.permissionOverwrites.at(x).deny;
410 }
411 }
412 }
413 permissions &= ~deny;
414 permissions |= allow;
415 for (uint64_t x = 0; x < channel.permissionOverwrites.size(); ++x) {
416 if (channel.permissionOverwrites.at(x).id == guildMember.user.id) {
417 permissions &= ~channel.permissionOverwrites.at(x).deny;
418 permissions |= channel.permissionOverwrites.at(x).allow;
419 break;
420 }
421 }
422 return jsonifier::toString(permissions);
423 }
424
425 template<> jsonifier::string permissions_base<permissions_parse>::computeBasePermissions(const guild_member_data& guildMember) {
426 const guild_data guild = guilds::getCachedGuild({ .guildId = guildMember.guildId });
427 if (guild.ownerId == guildMember.user.id) {
428 return getAllPermissions();
429 }
430 jsonifier::vector<role_data> guildRoles{};
431 for (auto& value: guild.roles) {
432 guildRoles.emplace_back(value);
433 }
434 role_data roleEveryone{};
435 for (auto& value: guildRoles) {
436 if (value.id == guild.id) {
437 roleEveryone = value;
438 }
439 }
440 uint64_t permissions{};
441 if (roleEveryone.permissions.operator std::basic_string_view<char, std::char_traits<char>>() != "0") {
442 permissions = roleEveryone.permissions;
443 }
444 get_guild_member_roles_data getRolesData{};
445 getRolesData.guildMember = guildMember;
446 getRolesData.guildId = guildMember.guildId;
447 jsonifier::vector<role_data> guildMemberRoles{};
448 for (auto& value: guildMember.roles) {
449 guildMemberRoles.emplace_back(value);
450 }
451 for (auto& value: guildMemberRoles) {
452 permissions |= value.permissions.operator uint64_t();
453 }
454
455 if (permissions & static_cast<uint64_t>(permission::administrator)) {
456 return getAllPermissions();
457 }
458
459 return jsonifier::toString(permissions);
460 }
461
462 jsonifier::string constructMultiPartData(jsonifier::string_view data, const jsonifier::vector<file>& files) {
463 static constexpr jsonifier::string_view boundary{ "boundary25" };
464 static constexpr jsonifier::string_view partStart("--boundary25\r\nContent-type: application/octet-stream\r\nContent-disposition: form-data; ");
465
466 jsonifier::string content("--" + boundary);
467
468 content += "\r\nContent-type: application/json\r\nContent-disposition: form-data; "
469 "name=\"payload_json\"\r\n\r\n";
470 content += data + "\r\n";
471 if (files.size() == 1) {
472 content += partStart + "name=\"file\"; filename=\"" + files.at(0).fileName + "\"" + "\r\n\r\n";
473 content += files.at(0).data;
474 } else {
475 for (uint64_t x = 0; x < files.size(); ++x) {
476 content += partStart + "name=\"files[" + jsonifier::toString(x) + "]\"; filename=\"" + files.at(x).fileName + "\"\r\n\r\n";
477 content += files.at(x).data;
478 content += "\r\n";
479 }
480 }
481 content += "\r\n--" + boundary + "--";
482 return content;
483 }
484
485 jsonifier::string convertToLowerCase(jsonifier::string_view stringToConvert) {
486 jsonifier::string newString;
487 for (auto& value: stringToConvert) {
488 if (isupper(static_cast<uint8_t>(value))) {
489 newString += static_cast<char>(tolower(static_cast<uint8_t>(value)));
490 } else {
491 newString += value;
492 }
493 }
494 return newString;
495 }
496
497 jsonifier::string base64Encode(jsonifier::string_view string, bool url) {
498 static constexpr const char* base64CharsArray[2] = { "abcdefghijklmnopqrstuvwxyz"
499 "abcdefghijklmnopqrstuvwxyz"
500 "0123456789"
501 "+/",
502
503 "abcdefghijklmnopqrstuvwxyz"
504 "abcdefghijklmnopqrstuvwxyz"
505 "0123456789"
506 "-_" };
507
508 uint64_t encodedLength = (string.size() + 2) / 3 * 4;
509
510 char trailing_char = url ? '.' : '=';
511
512 const char* base64Chars = base64CharsArray[url];
513
514 jsonifier::string returnString{};
515 returnString.reserve(encodedLength);
516 stop_watch<milliseconds> stopWatch{ 1500ms };
517 stopWatch.reset();
518 uint64_t pos = 0;
519 while (pos < string.size()) {
520 if (stopWatch.hasTimeElapsed()) {
521 break;
522 }
523 returnString.emplace_back(base64Chars[(string[static_cast<uint64_t>(pos + 0)] & 0xfc) >> 2]);
524
525 if (static_cast<uint64_t>(pos + 1) < string.size()) {
526 returnString.emplace_back(base64Chars[((string[static_cast<uint64_t>(pos + 0)] & 0x03) << 4) + ((string[static_cast<uint64_t>(pos + 1)] & 0xf0) >> 4)]);
527
528 if (static_cast<uint64_t>(pos + 2) < string.size()) {
529 returnString.emplace_back(base64Chars[((string[static_cast<uint64_t>(pos + 1)] & 0x0f) << 2) + ((string[static_cast<uint64_t>(pos + 2)] & 0xc0) >> 6)]);
530 returnString.emplace_back(base64Chars[string[static_cast<uint64_t>(pos + 2)] & 0x3f]);
531 } else {
532 returnString.emplace_back(base64Chars[(string[static_cast<uint64_t>(pos + 1)] & 0x0f) << 2]);
533 returnString.emplace_back(trailing_char);
534 }
535 } else {
536 returnString.emplace_back(base64Chars[(string[static_cast<uint64_t>(pos + 0)] & 0x03) << 4]);
537 returnString.emplace_back(trailing_char);
538 returnString.emplace_back(trailing_char);
539 }
540
541 pos += 3;
542 }
543
544 return returnString;
545 }
546
547 jsonifier::string loadFileContents(jsonifier::string_view filePath) {
548 std::ifstream file(filePath.data(), std::ios::in | std::ios::binary);
549 std::ostringstream stream{};
550 stream << file.rdbuf();
551 return jsonifier::string{ stream.str() };
552 }
553
554 jsonifier::string utf8MakeValid(jsonifier::string_view inputString) {
555 jsonifier::string returnString{};
556 for (auto& value: inputString) {
557 if (static_cast<uint8_t>(value) >= 128 || value < 0) {
558 uint64_t difference = 0ULL - value;
559 if (value + difference == '\0') {
560 continue;
561 } else {
562 returnString.emplace_back(value + static_cast<char>(difference));
563 }
564 } else {
565 returnString.emplace_back(value);
566 }
567 }
568 return returnString;
569 }
570
571 jsonifier::string urlEncode(jsonifier::string_view inputString) {
572 std::ostringstream escaped{};
573 escaped.fill('0');
574 escaped << std::hex;
575
576 for (jsonifier::string::const_iterator x = inputString.begin(), n = inputString.end(); x != n; ++x) {
577 jsonifier::string::value_type c = (*x);
578
579 if (isalnum(static_cast<uint8_t>(c)) || c == '-' || c == '_' || c == '.' || c == '~') {
580 escaped << c;
581 continue;
582 }
583
584 escaped << std::uppercase;
585 escaped << '%' << std::setw(2) << uint64_t(static_cast<uint8_t>(c));
586 escaped << std::nouppercase;
587 }
588 return jsonifier::string{ escaped.str() };
589 }
590
591 void spinLock(uint64_t timeInNsToSpinLockFor) {
592 int64_t startTime = std::chrono::duration_cast<nanoseconds>(sys_clock::now().time_since_epoch()).count();
593 int64_t timePassed{};
594 while (timePassed < static_cast<int64_t>(timeInNsToSpinLockFor)) {
595 timePassed = std::chrono::duration_cast<nanoseconds>(sys_clock::now().time_since_epoch()).count() - startTime;
596 }
597 }
598
599 jsonifier::string generateBase64EncodedKey() {
600 jsonifier::string returnString{};
601 returnString.resize(16);
602 std::mt19937_64 randomEngine{ static_cast<uint64_t>(sys_clock::now().time_since_epoch().count()) };
603 for (uint64_t x = 0; x < 16; ++x) {
604 returnString.at(x) = static_cast<char>((static_cast<double>(randomEngine()) / static_cast<double>(randomEngine.max())) * 255.0f);
605 }
606 returnString = base64Encode(returnString, false);
607 return returnString;
608 }
609
610 bool nanoSleep(int64_t ns) {
611#if defined _WIN32
612 HANDLE timer = CreateWaitableTimerExW(nullptr, nullptr, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
613 LARGE_INTEGER largeInt{ .QuadPart = -ns / 100 };
614 if (!timer) {
615 return false;
616 }
617
618 if (!SetWaitableTimerEx(timer, &largeInt, 0, nullptr, nullptr, nullptr, 0)) {
619 CloseHandle(timer);
620 return false;
621 }
622 WaitForSingleObjectEx(timer, INFINITE, false);
623 CloseHandle(timer);
624#else
625 std::this_thread::sleep_for(nanoseconds{ ns });
626#endif
627 return true;
628 }
629
630 jsonifier::string getTimeAndDate() {
631 std::time_t time = std::time({});
632 time = std::chrono::current_zone()->to_sys(std::chrono::local_time<std::chrono::seconds>(std::chrono::seconds{ time })).time_since_epoch().count();
633 char timeString[std::size("yyyy-mm-ddThh:mm:ss")];
634 tm timeNew{ getTime(time) };
635 std::strftime(std::data(timeString), std::size(timeString), "%FT%T", &timeNew);
636 return timeString;
637 }
638};
Data structure representing a single guild, for the purposes of populating the cache.
A discord guild. used to connect to/disconnect from voice.
Data structure representing a single guild_member_data.
snowflake guildId
The guild that this member belongs to.
static guild_cache_data getCachedGuild(get_guild_data dataPackage)
Collects a guild from the library's cache.
static co_routine< jsonifier::vector< role_data > > getGuildMemberRolesAsync(get_guild_member_roles_data dataPackage)
Collects the roles that a guild_member has.
static role_cache_data getCachedRole(get_role_data dataPackage)
Collects a given role from the library's cache.
static co_routine< jsonifier::vector< role_data > > getGuildRolesAsync(get_guild_roles_data dataPackage)
Collects the roles that a guild has.
text_format
Represents which text format to use for websocket transfer.
gateway_intents
Gateway intents.
DiscordCoreAPI_Dll jsonifier::string getTimeAndDate()
Acquires a timeStamp with the current time and date - suitable for use in message-embeds.
@ administrator
Allows all permissions and bypasses channel permission overwrites.
@ stream
Allows the user to go live.
audio_frame_type
Audio frame types.
The main namespace for the forward-facing interfaces.
Represents a single frame of audio data.
audio_frame_type type
The type of audio frame.
jsonifier::vector< uint8_t > data
The audio data.
int64_t currentSize
The current size of the allocated memory.
Configuration data for the library's main class, discord_core_client.
Data representing a file to be sent via multipart-form data.
For getting a chosen guild_member_data's roles.
guild_member_data guildMember
Which guild member to collect the roles from.
For updating a user's presence.
presence_update_state status
current status.