DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
Utilities.hpp
Go to the documentation of this file.
1/*
2 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
3
4 Copyright 2021, 2022 Chris M. (RealTimeChris)
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA
20*/
21/// Utilities.cpp - Header file for the Utilities.
22/// Jun 28, 2022
23/// https://discordcoreapi.com
24/// \file Utilities.hpp
25
26#pragma once
27
28#pragma warning(push)
29#pragma warning(disable : 4275)
30#pragma warning(disable : 4244)
31#pragma warning(disable : 4251)
32#pragma warning(disable : 4996)
33
34#ifdef _WIN32
35 #ifdef DiscordCoreAPI_EXPORTS
36 #define DiscordCoreAPI_Dll __declspec(dllexport)
37 #else
38 #define DiscordCoreAPI_Dll __declspec(dllimport)
39 #endif
40 #ifndef WIN32_LEAN_AND_MEAN
41 #define WIN32_LEAN_AND_MEAN
42 #endif
43 #ifndef WINRT_LEAN_AND_MEAN
44 #define WINRT_LEAN_AND_MEAN
45 #endif
46 #include <WinSock2.h>
47#elif __linux__
48 #ifndef DiscordCoreAPI_Dll
49 #define DiscordCoreAPI_Dll
50 #endif
51 #include <arpa/inet.h>
52 #include <sys/time.h>
53 #include <pthread.h>
54 #include <cstdint>
55 #include <cstring>
56 #include <time.h>
57 #include <ctime>
58#endif
59
60#include <source_location>
61#include <unordered_map>
62#include <unordered_set>
63#include <shared_mutex>
64#include <immintrin.h>
65#include <functional>
66#include <concepts>
67#include <iostream>
68#include <sstream>
69#include <iomanip>
70#include <vector>
71#include <atomic>
72#include <random>
73#include <string>
74#include <thread>
75#include <mutex>
76#include <queue>
77#include <array>
78#include <map>
79
80#ifdef max
81 #undef max
82#endif
83
84#ifdef min
85 #undef min
86#endif
87
88/**
89 * \defgroup main_endpoints Main Endpoints
90 * \brief For all of the Discord API's endpoints.
91 */
92
93/**
94 * \defgroup voice_connection Voice Connection
95 * \brief For all of the voice connection related stuff.
96 */
97
98/**
99 * \defgroup discord_events Discord Events
100 * \brief For all of the events that could be sent by the Discord API.
101 */
102
103/**
104 * \defgroup utilities Utilities
105 * \brief For utility classes/functions.
106 */
107
108/**
109 * \defgroup foundation_entities Foundation Entities
110 * \brief For all of the building blocks of the main endpoints.
111 */
112
113/**
114 * \defgroup discord_events Discord Events
115 * \brief For all of events that could be sent by Discord's Websockets.
116 */
117
118namespace DiscordCoreAPI {
119
120 /**
121 * \addtogroup foundation_entities
122 * @{
123 */
124
125 class DiscordCoreAPI_Dll Snowflake {
126 public:
127 Snowflake() noexcept = default;
128
129 Snowflake& operator=(const std::string&) noexcept;
130 Snowflake(const std::string&) noexcept;
131
132 Snowflake& operator=(const uint64_t) noexcept;
133 Snowflake(const uint64_t) noexcept;
134
135 operator std::string() const noexcept;
136
137 explicit operator uint64_t() const noexcept;
138
139 DiscordCoreAPI_Dll friend inline std::string operator+(const std::string&, const Snowflake&) noexcept;
140
141 DiscordCoreAPI_Dll friend inline std::string operator+(const char*, const Snowflake&) noexcept;
142
143 bool operator==(const Snowflake& rhs) const noexcept;
144
145 protected:
146 uint64_t id{};
147 };
148
149 DiscordCoreAPI_Dll inline std::string operator+(const char* lhs, const Snowflake& rhs) noexcept {
150 std::string string{};
151 string += lhs;
152 string += std::to_string(rhs.id);
153 return string;
154 }
155
156 DiscordCoreAPI_Dll inline std::string operator+(const std::string& lhs, const Snowflake& rhs) noexcept {
157 std::string string{};
158 string += lhs;
159 string += std::to_string(rhs.id);
160 return string;
161 }
162
163 template<typename RTy> void reverseByteOrder(RTy& net) {
164 if constexpr (std::endian::native == std::endian::little) {
165 switch (sizeof(RTy)) {
166 case 1: {
167 return;
168 }
169 case 2: {
170 net =
171 _mm256_extract_epi16(_mm256_shuffle_epi8(_mm256_insert_epi16(__m256i{}, net, 0), _mm256_insert_epi16(__m256i{}, 0x01, 0)), 0);
172 return;
173 }
174 case 4: {
175 net = _mm256_extract_epi32(
176 _mm256_shuffle_epi8(_mm256_insert_epi32(__m256i{}, net, 0), _mm256_insert_epi32(__m256i{}, 0x10203, 0)), 0);
177 return;
178 }
179 case 8: {
180 net = _mm256_extract_epi64(
181 _mm256_shuffle_epi8(_mm256_insert_epi64(__m256i{}, net, 0), _mm256_insert_epi64(__m256i{}, 0x102030405060708, 0)), 0);
182 return;
183 }
184 }
185 }
186 }
187
188 template<typename ReturnType> void storeBits(char* to, ReturnType num) {
189 const uint8_t byteSize{ 8 };
190 reverseByteOrder<ReturnType>(num);
191 for (int32_t x = 0; x < sizeof(ReturnType); ++x) {
192 to[x] = static_cast<uint8_t>(num >> (byteSize * x));
193 }
194 }
195
196 template<typename TTy> class StopWatch {
197 public:
198 using HRClock = std::chrono::high_resolution_clock;
199
200 StopWatch() = delete;
201
202 StopWatch<TTy>& operator=(StopWatch<TTy>&& data) {
203 this->maxNumberOfTimeUnits.store(data.maxNumberOfTimeUnits.load());
204 this->startTime.store(data.startTime.load());
205 return *this;
206 }
207
208 StopWatch(StopWatch<TTy>&& data) {
209 *this = std::move(data);
210 }
211
212 StopWatch(TTy maxNumberOfMsNew) {
213 this->maxNumberOfTimeUnits.store(maxNumberOfMsNew);
214 this->startTime.store(std::chrono::duration_cast<TTy>(HRClock::now().time_since_epoch()));
215 }
216
217 TTy totalTimePassed() {
218 TTy currentTime = std::chrono::duration_cast<TTy>(HRClock::now().time_since_epoch());
219 TTy elapsedTime = currentTime - this->startTime.load();
220 return elapsedTime;
221 }
222
223 TTy getTotalWaitTime() {
224 return this->maxNumberOfTimeUnits.load();
225 }
226
227 bool hasTimePassed() {
228 TTy currentTime = std::chrono::duration_cast<TTy>(HRClock::now().time_since_epoch());
229 TTy elapsedTime = currentTime - this->startTime.load();
230 return elapsedTime >= this->maxNumberOfTimeUnits.load();
231 }
232
233 void resetTimer() {
234 this->startTime.store(std::chrono::duration_cast<TTy>(HRClock::now().time_since_epoch()));
235 }
236
237 protected:
238 std::atomic<TTy> maxNumberOfTimeUnits{ TTy{} };
239 std::atomic<TTy> startTime{ TTy{} };
240 };
241
242 const uint8_t formatVersion{ 131 };
243
244 enum class EtfType : uint8_t {
245 New_Float_Ext = 70,
246 Small_Integer_Ext = 97,
247 Integer_Ext = 98,
248 Atom_Ext = 100,
249 Nil_Ext = 106,
250 String_Ext = 107,
251 List_Ext = 108,
252 Binary_Ext = 109,
253 Small_Big_Ext = 110,
254 Small_Atom_Ext = 115,
255 Map_Ext = 116,
256 };
257
258 template<typename Ty>
259 concept IsEnum = std::is_enum<Ty>::value;
260
261 struct DiscordCoreAPI_Dll EnumConverter {
262 template<IsEnum EnumType> EnumConverter& operator=(const std::vector<EnumType>& data) {
263 for (auto& value: data) {
264 this->vector.emplace_back(std::move(static_cast<uint64_t>(value)));
265 }
266 return *this;
267 };
268
269 template<IsEnum EnumType> EnumConverter(const std::vector<EnumType>& data) {
270 *this = data;
271 };
272
273 template<IsEnum EnumType> EnumConverter& operator=(EnumType data) {
274 this->integer = static_cast<uint64_t>(data);
275 return *this;
276 };
277
278 template<IsEnum EnumType> EnumConverter(EnumType data) {
279 *this = data;
280 };
281
282 operator std::vector<uint64_t>() const noexcept;
283
284 operator uint64_t() const noexcept;
285
286 bool isItAVector() const noexcept;
287
288 protected:
289 std::vector<uint64_t> vector{};
290 bool vectorType{};
291 uint64_t integer{};
292 };
293
294 enum class JsonType : uint8_t { Object = 1, Array = 2, String = 3, Float = 4, Uint64 = 5, Int64 = 6, Bool = 7, Null = 8 };
295
296 enum class JsonifierSerializeType { Etf = 0, Json = 1 };
297
298 class DiscordCoreAPI_Dll Jsonifier;
299
300 template<typename Ty>
301 concept IsConvertibleToJsonifier = std::convertible_to<Ty, Jsonifier>;
302
303 class DiscordCoreAPI_Dll Jsonifier {
304 public:
305 using MapAllocatorType = std::allocator<std::pair<const std::string, Jsonifier>>;
306 template<typename OTy> using AllocatorType = std::allocator<OTy>;
307 template<typename OTy> using AllocatorTraits = std::allocator_traits<AllocatorType<OTy>>;
308 using ObjectType = std::map<std::string, Jsonifier, std::less<>, MapAllocatorType>;
309 using ArrayType = std::vector<Jsonifier, AllocatorType<Jsonifier>>;
310 using StringType = std::string;
311 using FloatType = double;
312 using UintType = uint64_t;
313 using IntType = int64_t;
314 using BoolType = bool;
315
316 union JsonValue {
317 JsonValue() noexcept = default;
318 JsonValue& operator=(JsonValue&&) noexcept = delete;
319 JsonValue(JsonValue&&) noexcept = delete;
320 JsonValue& operator=(const JsonValue&) noexcept = delete;
321 JsonValue(const JsonValue&) noexcept = delete;
322 ObjectType* object;
323 StringType* string;
324 ArrayType* array;
325 FloatType numberDouble;
326 UintType numberUint;
327 IntType numberInt;
328 BoolType boolean;
329 };
330
331 Jsonifier() noexcept = default;
332
333 template<IsConvertibleToJsonifier OTy> Jsonifier& operator=(std::vector<OTy>&& data) noexcept {
334 this->setValue(JsonType::Array);
335 for (auto& value: data) {
336 this->jsonValue.array->push_back(std::move(value));
337 }
338 return *this;
339 }
340
341 template<IsConvertibleToJsonifier OTy> Jsonifier(std::vector<OTy>&& data) noexcept {
342 *this = std::move(data);
343 }
344
345 template<IsConvertibleToJsonifier OTy> Jsonifier& operator=(std::vector<OTy>& data) noexcept {
346 this->setValue(JsonType::Array);
347 for (auto& value: data) {
348 this->jsonValue.array->push_back(value);
349 }
350 return *this;
351 }
352
353 template<IsConvertibleToJsonifier OTy> Jsonifier(std::vector<OTy>& data) noexcept {
354 *this = data;
355 }
356
357 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier& operator=(std::unordered_map<KTy, OTy>&& data) noexcept {
358 this->setValue(JsonType::Object);
359 for (auto& [key, value]: data) {
360 (*this->jsonValue.object)[key] = std::move(value);
361 }
362 return *this;
363 }
364
365 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier(std::unordered_map<KTy, OTy>&& data) noexcept {
366 *this = std::move(data);
367 };
368
369 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier& operator=(std::unordered_map<KTy, OTy>& data) noexcept {
370 this->setValue(JsonType::Object);
371 for (auto& [key, value]: data) {
372 (*this->jsonValue.object)[key] = value;
373 }
374 return *this;
375 }
376
377 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier(std::unordered_map<KTy, OTy>& data) noexcept {
378 *this = data;
379 };
380
381 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier& operator=(std::map<KTy, OTy>&& data) noexcept {
382 this->setValue(JsonType::Object);
383 for (auto& [key, value]: data) {
384 (*this->jsonValue.object)[key] = std::move(value);
385 }
386 return *this;
387 }
388
389 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier(std::map<KTy, OTy>&& data) noexcept {
390 *this = std::move(data);
391 };
392
393 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier& operator=(std::map<KTy, OTy>& data) noexcept {
394 this->setValue(JsonType::Object);
395 for (auto& [key, value]: data) {
396 (*this->jsonValue.object)[key] = value;
397 }
398 return *this;
399 }
400
401 template<IsConvertibleToJsonifier KTy, IsConvertibleToJsonifier OTy> Jsonifier(std::map<KTy, OTy>& data) noexcept {
402 *this = data;
403 };
404
405 template<IsEnum Ty> Jsonifier& operator=(Ty data) noexcept {
406 this->jsonValue.numberUint = static_cast<uint64_t>(data);
407 this->type = JsonType::Uint64;
408 return *this;
409 }
410
411 template<IsEnum Ty> Jsonifier(Ty data) noexcept {
412 *this = data;
413 }
414
415 Jsonifier& operator=(Jsonifier&& data) noexcept;
416
417 Jsonifier(Jsonifier&& data) noexcept;
418
419 Jsonifier& operator=(const Jsonifier& data) noexcept;
420
421 Jsonifier(const Jsonifier& data) noexcept;
422
423 operator std::string&&() noexcept;
424
425 operator std::string() noexcept;
426
427 void refreshString(JsonifierSerializeType OpCode);
428
429 Jsonifier& operator=(EnumConverter&& data) noexcept;
430 Jsonifier(EnumConverter&& data) noexcept;
431
432 Jsonifier& operator=(const EnumConverter& data) noexcept;
433 Jsonifier(const EnumConverter& data) noexcept;
434
435 Jsonifier& operator=(std::string&& data) noexcept;
436 Jsonifier(std::string&& data) noexcept;
437
438 Jsonifier& operator=(const std::string& data) noexcept;
439 Jsonifier(const std::string& data) noexcept;
440
441 Jsonifier& operator=(const char* data) noexcept;
442 Jsonifier(const char* data) noexcept;
443
444 Jsonifier& operator=(double data) noexcept;
445 Jsonifier(double data) noexcept;
446
447 Jsonifier& operator=(float data) noexcept;
448 Jsonifier(float data) noexcept;
449
450 Jsonifier& operator=(uint64_t data) noexcept;
451 Jsonifier(uint64_t data) noexcept;
452
453 Jsonifier& operator=(uint32_t data) noexcept;
454 Jsonifier(uint32_t data) noexcept;
455
456 Jsonifier& operator=(uint16_t data) noexcept;
457 Jsonifier(uint16_t data) noexcept;
458
459 Jsonifier& operator=(uint8_t data) noexcept;
460 Jsonifier(uint8_t data) noexcept;
461
462 Jsonifier& operator=(int64_t data) noexcept;
463 Jsonifier(int64_t data) noexcept;
464
465 Jsonifier& operator=(int32_t data) noexcept;
466 Jsonifier(int32_t data) noexcept;
467
468 Jsonifier& operator=(int16_t data) noexcept;
469 Jsonifier(int16_t data) noexcept;
470
471 Jsonifier& operator=(int8_t data) noexcept;
472 Jsonifier(int8_t data) noexcept;
473
474 Jsonifier& operator=(bool data) noexcept;
475 Jsonifier(bool data) noexcept;
476
477 Jsonifier& operator=(JsonType TypeNew) noexcept;
478 Jsonifier(JsonType type) noexcept;
479
480 Jsonifier& operator=(std::nullptr_t) noexcept;
481 Jsonifier(std::nullptr_t data) noexcept;
482
483 Jsonifier& operator[](typename ObjectType::key_type key);
484
485 Jsonifier& operator[](uint64_t index);
486
487 template<typename Ty> const Ty& getValue() const {
488 return Ty{};
489 }
490
491 template<typename Ty> Ty& getValue() {
492 return Ty{};
493 }
494
495 JsonType getType() noexcept;
496
497 void emplaceBack(Jsonifier&& data) noexcept;
498 void emplaceBack(Jsonifier& data) noexcept;
499
500 ~Jsonifier() noexcept;
501
502 protected:
503 JsonType type{ JsonType::Null };
504 JsonValue jsonValue{};
505 std::string string{};
506
507 void serializeJsonToEtfString(const Jsonifier* dataToParse);
508
509 void serializeJsonToJsonString(const Jsonifier* dataToParse);
510
511 void writeJsonObject(const ObjectType& ObjectNew);
512
513 void writeJsonArray(const ArrayType& Array);
514
515 void writeJsonString(const StringType& StringNew);
516
517 void writeJsonFloat(const FloatType x);
518
519 template<typename NumberType,
520 std::enable_if_t<
521 std::is_integral<NumberType>::value || std::is_same<NumberType, uint64_t>::value || std::is_same<NumberType, int64_t>::value, int> =
522 0>
523 void writeJsonInt(NumberType Int) {
524 auto IntNew = std::to_string(Int);
525 this->writeString(IntNew.data(), IntNew.size());
526 }
527
528 void writeJsonBool(const BoolType ValueNew);
529
530 void writeJsonNull();
531
532 void writeEtfObject(const ObjectType& jsonData);
533
534 void writeEtfArray(const ArrayType& jsonData);
535
536 void writeEtfString(const StringType& jsonData);
537
538 void writeEtfUint(const UintType jsonData);
539
540 void writeEtfInt(const IntType jsonData);
541
542 void writeEtfFloat(const FloatType jsonData);
543
544 void writeEtfBool(const BoolType jsonData);
545
546 void writeEtfNull();
547
548 void writeString(const char* data, size_t length);
549
550 void writeCharacter(const char Char);
551
552 void appendBinaryExt(const std::string& bytes, const uint32_t sizeNew);
553
554 void appendUnsignedLongLong(const uint64_t value);
555
556 void appendNewFloatExt(const double FloatValue);
557
558 void appendSmallIntegerExt(const uint8_t value);
559
560 void appendListHeader(const uint32_t sizeNew);
561
562 void appendMapHeader(const uint32_t sizeNew);
563
564 void appendIntegerExt(const uint32_t value);
565
566 void appendBool(bool data);
567
568 void appendVersion();
569
570 void appendNilExt();
571
572 void appendNil();
573
574 void setValue(JsonType TypeNew);
575
576 void destroy() noexcept;
577
578 friend bool operator==(const Jsonifier& lhs, const Jsonifier& rhs);
579 };
580
581 template<> inline const Jsonifier::ObjectType& Jsonifier::getValue() const {
582 return *this->jsonValue.object;
583 }
584
585 template<> inline const Jsonifier::ArrayType& Jsonifier::getValue() const {
586 return *this->jsonValue.array;
587 }
588
589 template<> inline const Jsonifier::StringType& Jsonifier::getValue() const {
590 return *this->jsonValue.string;
591 }
592
593 template<> inline const Jsonifier::FloatType& Jsonifier::getValue() const {
594 return this->jsonValue.numberDouble;
595 }
596
597 template<> inline const Jsonifier::UintType& Jsonifier::getValue() const {
598 return this->jsonValue.numberUint;
599 }
600
601 template<> inline const Jsonifier::IntType& Jsonifier::getValue() const {
602 return this->jsonValue.numberInt;
603 }
604
605 template<> inline const Jsonifier::BoolType& Jsonifier::getValue() const {
606 return this->jsonValue.boolean;
607 }
608
609 template<> inline Jsonifier::ObjectType& Jsonifier::getValue() {
610 return *this->jsonValue.object;
611 }
612
613 template<> inline Jsonifier::ArrayType& Jsonifier::getValue() {
614 return *this->jsonValue.array;
615 }
616
617 template<> inline Jsonifier::StringType& Jsonifier::getValue() {
618 return *this->jsonValue.string;
619 }
620
621 template<> inline Jsonifier::FloatType& Jsonifier::getValue() {
622 return this->jsonValue.numberDouble;
623 }
624
625 template<> inline Jsonifier::UintType& Jsonifier::getValue() {
626 return this->jsonValue.numberUint;
627 }
628
629 template<> inline Jsonifier::IntType& Jsonifier::getValue() {
630 return this->jsonValue.numberInt;
631 }
632
633 template<> inline Jsonifier::BoolType& Jsonifier::getValue() {
634 return this->jsonValue.boolean;
635 }
636
637 struct DiscordCoreAPI_Dll ActivityData;
638
639 /// \brief For selecting the type of streamer that the given bot is, one must be one server and one of client per connection.
640 enum class StreamType { None = 0, Client = 1, Server = 2 };
641
642 /// \brief For connecting two bots to stream the VC contents between the two.
643 struct DiscordCoreAPI_Dll StreamInfo {
644 bool streamBotAudio{};///< Do we stream the audio coming from other bots?
645 std::string address{};///< The address to connect to.
646 StreamType type{};///< The type of streamer that this is. Set one to client and one to server.
647 uint16_t port{};///< The port to connect to.
648 };
649
650};
651
652namespace DiscordCoreInternal {
653
654 using HRClock = std::chrono::high_resolution_clock;
655 using Milliseconds = std::chrono::milliseconds;
656 using Microseconds = std::chrono::microseconds;
657 using Nanoseconds = std::chrono::nanoseconds;
658 using SysClock = std::chrono::system_clock;
659 using Seconds = std::chrono::seconds;
660 using namespace std::literals;
661 using std::cout;
662 using std::endl;
663
664 class DiscordCoreAPI_Dll SoundCloudRequestBuilder;
665 class DiscordCoreAPI_Dll YouTubeRequestBuilder;
666 class DiscordCoreAPI_Dll WebSocketClient;
667 class DiscordCoreAPI_Dll BaseSocketAgent;
668 class DiscordCoreAPI_Dll SoundCloudAPI;
669 class DiscordCoreAPI_Dll YouTubeAPI;
670
671 enum class WebSocketOpCode : uint8_t {
672 Op_Continuation = 0x00,
673 Op_Text = 0x01,
674 Op_Binary = 0x02,
675 Op_Close = 0x08,
676 Op_Ping = 0x09,
677 Op_Pong = 0x0a
678 };
679
680 /// \brief Websocket close codes.
681 class DiscordCoreAPI_Dll WebSocketClose {
682 public:
683 /// \brief Websocket close codes.
684 enum class WebSocketCloseCode : uint16_t {
685 Unset = 1 << 0,///< Unset.
686 Normal_Close = 1 << 1,///< Normal close.
687 Unknown_Error = 1 << 2,///< We're not sure what went wrong. Try reconnecting?
688 Unknown_Opcode = 1 << 3,///< You sent an invalid Gateway opcode or an invalid payload for an opcode. Don't do that!
689 Decode_Error = 1 << 4,///< You sent an invalid payload to us. Don't do that!
690 Not_Authenticated = 1 << 5,///< You sent us a payload prior to identifying.
691 Authentication_Failed = 1 << 6,///< The account token sent with your identify payload is incorrect.
692 Already_Authenticated = 1 << 7,///< You sent more than one identify payload. Don't do that!
693 Invalid_Seq = 1 << 8,///< The sequence sent when resuming the session was invalid. Reconnect and start a new session.
694 Rate_Limited =
695 1 << 9,///< Woah nelly! You're sending payloads to us too quickly. Slow it down! You will be disconnected on receiving this.
696 Session_Timed = 1 << 10,///< Your session timed out. Reconnect and start a new one.
697 Invalid_Shard = 1 << 11,///< You sent us an invalid shard when identifying.
698 Sharding_Required =
699 1 << 12,///< The session would have handled too many guilds - you are required to shard your connection in order to connect.
700 Invalid_API_Version = 1 << 13,///< You sent an invalid version for the gateway.
701 Invalid_Intent = 1 << 14,///< You sent an invalid intent for a Gateway Intent. You may have incorrectly calculated the bitwise value.
702 Disallowed_Intent = 1
703 << 15,///< You sent a disallowed intent for a Gateway Intent. You may have tried to specify an intent that you have not enabled or are not approved for.
704 We_Do_Reconnect = Normal_Close | Unknown_Error | Unknown_Opcode | Decode_Error | Not_Authenticated | Already_Authenticated | Invalid_Seq |
705 Rate_Limited | Session_Timed,
706 We_Do_Not_Reconnect = Authentication_Failed | Invalid_Shard | Sharding_Required | Invalid_API_Version | Invalid_Intent | Disallowed_Intent
707 };
708
709 std::unordered_map<uint16_t, WebSocketCloseCode> mappingValues{ { 0, WebSocketCloseCode::Unset }, { 1000, WebSocketCloseCode::Normal_Close },
710 { 4000, WebSocketCloseCode::Unknown_Error }, { 4001, WebSocketCloseCode::Unknown_Opcode }, { 4002, WebSocketCloseCode::Decode_Error },
711 { 4003, WebSocketCloseCode::Not_Authenticated }, { 4004, WebSocketCloseCode::Authentication_Failed },
712 { 4005, WebSocketCloseCode::Already_Authenticated }, { 4007, WebSocketCloseCode::Invalid_Seq },
713 { 4008, WebSocketCloseCode::Rate_Limited }, { 4009, WebSocketCloseCode::Session_Timed }, { 4010, WebSocketCloseCode::Invalid_Shard },
714 { 4011, WebSocketCloseCode::Sharding_Required }, { 4012, WebSocketCloseCode::Invalid_API_Version },
715 { 4013, WebSocketCloseCode::Invalid_Intent }, { 4014, WebSocketCloseCode::Disallowed_Intent } };
716
717 std::unordered_map<WebSocketCloseCode, std::string> outputErrorValues{ {
718 WebSocketCloseCode::Unknown_Error,
719 "4000; We're not sure what went wrong.",
720 },
721 { WebSocketCloseCode::Unknown_Opcode, "4001; You sent an invalid Gateway opcode or an invalid payload for an opcode. Don't do that!" },
722 { WebSocketCloseCode::Decode_Error, "4002; You sent an invalid payload to Discord. Don't do that!" },
723 { WebSocketCloseCode::Not_Authenticated, "4003; You sent us a payload prior to identifying." },
724 { WebSocketCloseCode::Authentication_Failed, "4004; The account token sent with your identify payload is incorrect." },
725 { WebSocketCloseCode::Already_Authenticated, "4005; You sent more than one identify payload. Don't do that!" },
726 { WebSocketCloseCode::Invalid_Seq, "4006; The sequence sent when resuming the session was invalid. Reconnect and start a new session." },
727 { WebSocketCloseCode::Rate_Limited,
728 "4008; Woah nelly! You're sending payloads to us too quickly. Slow it down! You will be disconnected on receiving this." },
729 { WebSocketCloseCode::Session_Timed, "4009; Your session timed out. Reconnect and start a new one." },
730 { WebSocketCloseCode::Invalid_Shard, "4010; You sent us an invalid shard when identifying." },
731 { WebSocketCloseCode::Sharding_Required,
732 "4011; The session would have handled too many guilds - you are required to shard your connection in order to connect." },
733 { WebSocketCloseCode::Invalid_API_Version, "4012; You sent an invalid version for the gateway." },
734 { WebSocketCloseCode::Invalid_Intent,
735 "4013; You sent an invalid intent for a Gateway Intent. You may have incorrectly calculated the bitwise value." },
736 { WebSocketCloseCode::Disallowed_Intent,
737 "4014; You sent a disallowed intent for a Gateway Intent. You may have tried to specify an intent that you have not enabled or are "
738 "not "
739 "approved for." } };
740
741 WebSocketCloseCode value{};
742
743 WebSocketClose& operator=(uint16_t valueNew);
744
745 explicit WebSocketClose(uint16_t valueNew);
746
747 operator std::string();
748
749 operator bool();
750 };
751
752 /// \brief Voice Websocket close codes.
753 class DiscordCoreAPI_Dll VoiceWebSocketClose {
754 public:
755 /// \brief Voice Websocket close codes.
756 enum class VoiceWebSocketCloseCode : uint16_t {
757 Unset = 1 << 0,///< Unset.
758 Normal_Close = 1 << 1,///< Normal close.
759 Unknown_Opcode = 1 << 2,///< You sent an invalid opcode.
760 Failed_To_Decode = 1 << 3,///< You sent an invalid payload in your identifying to the Gateway.
761 Not_Authenticated = 1 << 4,///< You sent a payload before identifying with the Gateway.
762 Authentication_Failed = 1 << 5,///< The token you sent in your identify payload is incorrect.
763 Already_Authenticated = 1 << 6,///< You sent more than one identify payload. Stahp.
764 Session_No_Longer_Valid = 1 << 7,///< Your session is no longer valid.
765 Session_Timeout = 1 << 8,///< Your session has timed out.
766 Server_Not_Found = 1 << 9,///< We can't find the server you're trying to connect to.
767 Unknown_Protocol = 1 << 10,///< We didn't recognize the protocol you sent.
768 Disconnected = 1
769 << 11,///< Channel was deleted, you were kicked, voice server changed, or the main gateway session was dropped. Should not reconnect.
770 Voice_Server_Crashed = 1 << 12,///< The server crashed. Our bad! Try resuming.
771 Unknown_Encryption_Mode = 1 << 13///< We didn't recognize your encryption.
772 };
773
774 std::unordered_map<uint16_t, VoiceWebSocketCloseCode> mappingValues{ { 0, VoiceWebSocketCloseCode::Unset },
775 { 1000, VoiceWebSocketCloseCode::Normal_Close }, { 4001, VoiceWebSocketCloseCode::Unknown_Opcode },
776 { 4002, VoiceWebSocketCloseCode::Failed_To_Decode }, { 4003, VoiceWebSocketCloseCode::Not_Authenticated },
777 { 4004, VoiceWebSocketCloseCode ::Authentication_Failed }, { 4005, VoiceWebSocketCloseCode::Already_Authenticated },
778 { 4006, VoiceWebSocketCloseCode ::Session_No_Longer_Valid }, { 4009, VoiceWebSocketCloseCode::Session_Timeout },
779 { 4011, VoiceWebSocketCloseCode::Server_Not_Found }, { 4012, VoiceWebSocketCloseCode::Unknown_Protocol },
780 { 4014, VoiceWebSocketCloseCode ::Disconnected }, { 4015, VoiceWebSocketCloseCode ::Voice_Server_Crashed },
781 { 4016, VoiceWebSocketCloseCode ::Unknown_Encryption_Mode } };
782
783 std::unordered_map<VoiceWebSocketCloseCode, std::string> outputErrorValues{ { VoiceWebSocketCloseCode::Unset, "0; Unset." },
784 { VoiceWebSocketCloseCode::Normal_Close, "1000; Normal close." },
785 { VoiceWebSocketCloseCode::Unknown_Opcode, "4001; You sent an invalid opcode." },
786 { VoiceWebSocketCloseCode::Failed_To_Decode, "4002; You sent an invalid payload in your identifying to the Gateway." },
787 { VoiceWebSocketCloseCode::Not_Authenticated, "4003; You sent a payload before identifying with the Gateway." },
788 { VoiceWebSocketCloseCode::Authentication_Failed, "4004; The token you sent in your identify payload is incorrect." },
789 { VoiceWebSocketCloseCode::Already_Authenticated, "4005; You sent more than one identify payload. Stahp." },
790 { VoiceWebSocketCloseCode::Session_No_Longer_Valid, "4006; Your session is no longer valid." },
791 { VoiceWebSocketCloseCode::Session_Timeout, "4009; Your session has timed out." },
792 { VoiceWebSocketCloseCode::Server_Not_Found, "4011; We can't find the server you're trying to connect to." },
793 { VoiceWebSocketCloseCode::Unknown_Protocol, "4012; We didn't recognize the protocol you sent." },
794 { VoiceWebSocketCloseCode::Disconnected,
795 "4014; Channel was deleted, you were kicked, voice server changed, or the main gateway session was dropped. Should not reconnect." },
796 { VoiceWebSocketCloseCode::Voice_Server_Crashed, "4015; The server crashed. Our bad! Try resuming." },
797 { VoiceWebSocketCloseCode::Unknown_Encryption_Mode, "4016; We didn't recognize your encryption." } };
798
799 VoiceWebSocketCloseCode value{};
800
801 VoiceWebSocketClose& operator=(uint16_t valueNew);
802
803 VoiceWebSocketClose(uint16_t valueNew);
804
805 operator std::string();
806
807 operator bool();
808 };
809
810 /// \brief Voice Websocket close codes.
811 class DiscordCoreAPI_Dll HttpsResponseCode {
812 public:
813 /// \brief Voice Websocket close codes.
814 enum class HttpsResponseCodes : uint32_t {
815 Ok = 200,///< The request completed successfully.
816 Created = 201,///< The entity was created successfully.
817 No_Content = 204,///< The request completed successfully but returned no content.
818 Not_Modifies = 304,///< The entity was not modified (no action was taken).
819 Bad_Request = 400,///< The request was improperly formatted, or the server couldn't understand it.
820 Unauthorized = 401,///< The Authorization header was missing or invalid.
821 Forbidden = 403,///< The Authorization token you passed did not have permission to the resource.
822 Not_Found = 404,///< The resource at the location specified doesn't exist.
823 Method_Not_Allowed = 405,///< The HTTPS method used is not valid for the location specified.
824 Too_Many_Requests = 429,///< You are being rate limited, see Rate Limits.
825 Gatewat_Unavailable = 502,///< There was not a gateway available to process your request. Wait a bit and retry.
826 };
827
828 std::unordered_map<HttpsResponseCodes, std::string> outputErrorValues{ { static_cast<HttpsResponseCodes>(200),
829 "200; The request completed successfully" },
830 { static_cast<HttpsResponseCodes>(201), "201; The entity was created successfully" },
831 { static_cast<HttpsResponseCodes>(204), "204; The request completed successfully but returned no content" },
832 { static_cast<HttpsResponseCodes>(304), "304; The entity was not modified (no action was taken)" },
833 { static_cast<HttpsResponseCodes>(400), "400; The request was improperly formatted, or the server couldn't understand it" },
834 { static_cast<HttpsResponseCodes>(401), "401; The Authorization header was missing or invalid" },
835 { static_cast<HttpsResponseCodes>(403), "403; The Authorization token you passed did not have permission to the resource" },
836 { static_cast<HttpsResponseCodes>(404), "404; The resource at the location specified doesn't exist" },
837 { static_cast<HttpsResponseCodes>(405), "405; The HTTPS method used is not valid for the location specified" },
838 { static_cast<HttpsResponseCodes>(429), "429; You are being rate limited, see Rate Limits" },
839 { static_cast<HttpsResponseCodes>(502), "502; There was not a gateway available to process your request.Wait a bit and retry" } };
840
841 HttpsResponseCodes value{};
842
843 HttpsResponseCode& operator=(uint32_t valueNew);
844
845 HttpsResponseCode(uint32_t valueNew);
846
847 operator uint32_t();
848
849 operator std::string();
850 };
851
852}// namespace DiscordCoreInternal
853
854
855namespace DiscordCoreAPI {
856
857 using HRClock = std::chrono::high_resolution_clock;
858 using Milliseconds = std::chrono::milliseconds;
859 using Microseconds = std::chrono::microseconds;
860 using Nanoseconds = std::chrono::nanoseconds;
861 using SysClock = std::chrono::system_clock;
862 using Seconds = std::chrono::seconds;
863 using namespace std::literals;
864 using std::cout;
865 using std::endl;
866
867 struct DiscordCoreAPI_Dll OnVoiceServerUpdateData;
868 struct DiscordCoreAPI_Dll OnVoiceStateUpdateData;
869 struct DiscordCoreAPI_Dll File;
870
871 class DiscordCoreAPI_Dll DiscordCoreClient;
872 class DiscordCoreAPI_Dll VoiceConnection;
873 class DiscordCoreAPI_Dll GuildMember;
874 class DiscordCoreAPI_Dll ChannelData;
875 class DiscordCoreAPI_Dll Reactions;
876 class DiscordCoreAPI_Dll BotUser;
877
878 struct DiscordCoreAPI_Dll DCAException : public std::runtime_error, std::string {
879 DCAException(const std::string&, std::source_location = std::source_location::current()) noexcept;
880 };
881
882 template<typename RTy> class CoRoutine;
883
884 /// \brief Update-presence status types.
886 online = 0,///< Online.
887 dnd = 1,///< Do Not Disturb.
888 idle = 2,///< AFK.
889 invisible = 3,///< Invisible and shown as offline.
890 offline = 4,///< Offline
891 };
892
893 /// \brief For updating a User's presence.
894 struct DiscordCoreAPI_Dll UpdatePresenceData {
895 std::vector<ActivityData> activities{};///< A vector of activities.
896 UpdatePresenceStatusTypes status{};///< Current status.
897 int64_t since{};///< When was the activity started?
898 bool afk{};///< Are we afk.
899
900 operator Jsonifier();
901 };
902
903 std::basic_ostream<char>& operator<<(std::basic_ostream<char>& outputSttream, const std::string& (*function)( void ));
904
905 /// \brief Input event response types.
906 enum class InputEventResponseType : uint8_t {
907 Unset = 0,///< Unset.
908 Deferred_Response = 1,
909 Ephemeral_Deferred_Response = 2,///< Deferred ephemeral response.
910 Interaction_Response = 3,///< Interaction response.
911 Ephemeral_Interaction_Response = 4,///< Ephemeral Interaction response.
912 Edit_Interaction_Response = 5,///< Interaction response edit.
913 Follow_Up_Message = 6,///< Follow-up Message.
914 Ephemeral_Follow_Up_Message = 7,///< Ephemeral follow-up Message.
915 Edit_Follow_Up_Message = 8,///< Follow-up Message edit.
916 Application_Command_AutoComplete_Result = 9,///< Respond to an autocomplete interaction with suggested choices.
917 Modal_Interaction_Response = 10,///< Respond to an interaction with a popup modal.
918 };
919
920 /// \brief Gateway intents.
921 enum class GatewayIntents : uint32_t {
922 Guilds = 1 << 0,///< Intent for receipt of Guild information.
923 Guild_Members = 1 << 1,///< Intent for receipt of Guild members.
924 Guild_Bans = 1 << 2,///< Intent for receipt of Guild bans.
925 Guild_Emojis = 1 << 3,///< Intent for receipt of Guild emojis.
926 Guild_Integrations = 1 << 4,///< Intent for receipt of Guild integrations.
927 Guild_Webhooks = 1 << 5,///< Intent for receipt of Guild webhooks.
928 Guild_Invites = 1 << 6,///< Intent for receipt of Guild invites.
929 Guild_VoiceStates = 1 << 7,///< Intent for receipt of Guild voice states.
930 Guild_Presences = 1 << 8,///< Intent for receipt of Guild presences.
931 Guild_Messages = 1 << 9,///< Intent for receipt of Guild messages.
932 Guild_Message_Reactions = 1 << 10,///< Intent for receipt of Guild message reactions.
933 Guild_Message_Typing = 1 << 11,///< Intent for receipt of Guild message typing notifications.
934 Direct_Messages = 1 << 12,///< Intent for receipt of direct messages (DMs).
935 Direct_Message_Reactions = 1 << 13,///< Intent for receipt of direct message reactions.
936 Direct_Message_Typing = 1 << 14,///< Intent for receipt of direct message typing notifications.
937 Message_Content = 1 << 15,///< Intent for receipt of message content.
938 Guild_Scheduled_Events = 1 << 16,///< Scheduled events.
941 Guild_Scheduled_Events,///< Default intents (all non-privileged intents).
942 Privileged_Intents = Guild_Members | Guild_Presences | Message_Content,///< Privileged intents requiring ID.
943 All_Intents = Default_Intents | Privileged_Intents///< Every single intent.
944 };
945
946 /// \brief Function data for repeated functions to be loaded.
947 struct DiscordCoreAPI_Dll RepeatedFunctionData {
948 std::function<void(DiscordCoreClient*)> function{ nullptr };///< The std::function pointer to be loaded.
949 uint32_t intervalInMs{};///< The time interval at which to call the std::function.
950 bool repeated{};///< Whether or not the std::function is repeating.
951 int64_t dummyArg{};
952 };
953
954 /// \brief Represents which text format to use for websocket transfer.
955 enum class TextFormat : uint8_t {
956 Etf = 0x00,///< Etf format.
957 Json = 0x01///< Json format.
958 };
959
960 /// \brief Sharding options for the library.
961 struct DiscordCoreAPI_Dll ShardingOptions {
962 uint32_t numberOfShardsForThisProcess{ 1 };///< The number of shards to launch on the current process.
963 uint32_t totalNumberOfShards{ 1 };///< The total number of shards that will be launched across all processes.
964 uint32_t startingShard{};///< The first shard to start on this process.
965 };
966
967 /**@}*/
968
969 /// \brief Loggin options for the library.
970 struct DiscordCoreAPI_Dll LoggingOptions {
971 bool logWebSocketSuccessMessages{};///< Do we log the websocket success messages to cout?
972 bool logWebSocketErrorMessages{};///< Do we log the websocket error messages to cout?
973 bool logGeneralSuccessMessages{};///< Do we log general success messages to cout?
974 bool logFFMPEGSuccessMessages{};///< Do we log FFMPEG success messages to cout?
975 bool logGeneralErrorMessages{};///< Do we log general error messages to cout?
976 bool logHttpsSuccessMessages{};///< Do we log Https response success messages to cout?
977 bool logFFMPEGErrorMessages{};///< Do we log FFMPEG error messages to cout?
978 bool logHttpsErrorMessages{};///< Do we log Https response error messages to cout?
979 };
980
981 /// \brief For selecting the caching style of the library.
982 struct DiscordCoreAPI_Dll CacheOptions {
983 bool cacheChannels{ true };///< Do we cache Channels?
984 bool cacheGuilds{ true };///< Do we cache Guilds?
985 bool cacheRoles{ true };///< Do we cache Roles?
986 bool cacheUsers{ true };///< Do we cache Users/GuildMembers?
987 };
988
989 /// \brief Configuration data for the library's main class, DiscordCoreClient.
990 struct DiscordCoreAPI_Dll DiscordCoreClientConfig {
991 std::vector<RepeatedFunctionData> functionsToExecute{};///< Functions to execute after a timer, or on a repetition.
992 GatewayIntents intents{ GatewayIntents::All_Intents };///< The gateway intents to be used for this instance.
993 TextFormat textFormat{ TextFormat::Etf };///< Use ETF or JSON format for websocket transfer?
994 UpdatePresenceData presenceData{};///< Presence data to initialize your bot with.
995 std::string connectionAddress{};///< A potentially alternative connection address for the websocket.
996 ShardingOptions shardOptions{};///< Options for the sharding of your bot.
997 LoggingOptions logOptions{};///< Options for the output/logging of the library.
998 CacheOptions cacheOptions{};///< Options for the cache of the library.
999 uint16_t connectionPort{};///< A potentially alternative connection port for the websocket.
1000 std::string botToken{};///< Your bot's token.
1001 };
1002
1003 struct DiscordCoreAPI_Dll JsonStringValue {
1004 std::string value{};
1005 JsonType type{};
1006 };
1007
1008 class DiscordCoreAPI_Dll ConfigManager {
1009 public:
1010 ConfigManager() noexcept = default;
1011
1012 explicit ConfigManager(const DiscordCoreClientConfig&);
1013
1014 const bool doWePrintWebSocketSuccessMessages() const;
1015
1016 const bool doWePrintWebSocketErrorMessages() const;
1017
1018 const bool doWePrintHttpsSuccessMessages() const;
1019
1020 const bool doWePrintHttpsErrorMessages() const;
1021
1022 const bool doWePrintFFMPEGSuccessMessages() const;
1023
1024 const bool doWePrintFFMPEGErrorMessages() const;
1025
1026 const bool doWePrintGeneralSuccessMessages() const;
1027
1028 const bool doWePrintGeneralErrorMessages() const;
1029
1030 const bool doWeCacheChannels() const;
1031
1032 const bool doWeCacheUsers() const;
1033
1034 const bool doWeCacheGuilds() const;
1035
1036 const bool doWeCacheRoles() const;
1037
1038 const UpdatePresenceData getPresenceData() const;
1039
1040 const std::string getBotToken() const;
1041
1042 const uint32_t getTotalShardCount() const;
1043
1044 const uint32_t getStartingShard() const;
1045
1046 const uint32_t getShardCountForThisProcess() const;
1047
1048 const std::string getConnectionAddress() const;
1049
1050 void setConnectionAddress(const std::string& connectionAddressNew);
1051
1052 const uint16_t getConnectionPort() const;
1053
1054 void setConnectionPort(const uint16_t connectionPortNew);
1055
1056 const std::vector<RepeatedFunctionData> getFunctionsToExecute() const;
1057
1058 const TextFormat getTextFormat() const;
1059
1060 const GatewayIntents getGatewayIntents();
1061
1062 protected:
1063 DiscordCoreClientConfig config{};
1064 };
1065
1066 /**
1067 * \addtogroup utilities
1068 * @{
1069 */
1070
1071 /// \brief Color constants for use in the EmbedData color values.
1072 namespace Colors {
1073 const std::string White = "FFFFFF",///< White.
1074 DiscordWhite = "FFFFFE",///< Discord white.
1075 LightGray = "C0C0C0",///< Light gray.
1076 Gray = "808080",///< Gray.
1077 DarkGray = "404040",///< Dark gray.
1078 Black = "000000",///< Black.
1079 DiscordBlack = "000001",///< Discord black.
1080 Red = "FF0000",///< Red.
1081 Pink = "FFAFAF",///< Pink.
1082 Orange = "FFC800",///< Orange.
1083 Yellow = "FFFF00",///< Yellow.
1084 Green = "00FF00",///< Green.
1085 Magenta = "FF00FF",///< Magenta.
1086 Cyan = "00FFFF",///< Cyan.
1087 Blue = "0000FF",///< Blue.
1088 LightSeaGreen = "1ABC9C",///< Light sea green.
1089 MediumSeaGreen = "2ECC71",///< Medium sea green.
1090 SummerSky = "3498DB",///< Summer skye.
1091 DeepLilac = "9B59B6",///< Deep lilac.
1092 Ruby = "E91E63",///< Ruby.
1093 MoonYellow = "F1C40F",///< Moon yellow.
1094 TahitiGold = "E67E22",///< Tahiti gold.
1095 Cinnabar = "E74C3C",///< Cinnabar.
1096 Submarine = "95A5A6",///< Submarine.
1097 BlueAquamarine = "607D8B",///< Blue aquamarine.
1098 DeepSea = "11806A",///< Deep sea.
1099 SeaGreen = "1F8B4C",///< Sea green.
1100 Endeavour = "206694",///< Endeavor.
1101 VividViolet = "71368A",///< Vivid violet.
1102 JazzberryJam = "AD1457",///< Jazzberry jam.
1103 DarkGoldenrod = "C27C0E",///< Dark goldenrod.
1104 Rust = "A84300",///< Rust.
1105 Brown = "992D22",///< Brown.
1106 GrayChateau = "979C9F",///< Gray chateau.
1107 Bismark = "546E7A",///< Bismark.
1108 StiBlue = "0E4BEF",///< Sti blue.
1109 WrxBlue = "00247D",///< Wrx blue.
1110 RalliArtCrimson = "E60012",///< Ralliart crimson.
1111 Lime = "00FF00",///< Lime.
1112 ForestGreen = "228B22",///< Forest green.
1113 CadmiumGreen = "097969",///< Cadmium green.
1114 Aquamarine = "7FFFD4",///< Aquamarine.
1115 BlueGreen = "088F8F",///< Blue green.
1116 Raspberry = "E30B5C",///< Raspberry.
1117 ScarletRed = "FF2400";///< Scarlet red.
1118 };
1119
1120 template<typename OTy> class ObjectCache {
1121 public:
1122 ObjectCache() noexcept {};
1123
1124 void emplace(OTy&& data) noexcept {
1125 std::unique_lock lock{ this->accessMutex };
1126 this->set.emplace(std::move(data));
1127 }
1128
1129 void emplace(OTy& data) noexcept {
1130 std::unique_lock lock{ this->accessMutex };
1131 this->set.emplace(data);
1132 }
1133
1134 const OTy& readOnly(OTy& key) noexcept {
1135 std::shared_lock lock{ this->accessMutex };
1136 return *this->set.find(key);
1137 }
1138
1139 OTy& at(OTy&& key) noexcept {
1140 std::shared_lock lock{ this->accessMutex };
1141 return ( OTy& )*this->set.find(key);
1142 }
1143
1144 OTy& at(OTy& key) noexcept {
1145 std::shared_lock lock{ this->accessMutex };
1146 return ( OTy& )*this->set.find(key);
1147 }
1148
1149 auto begin() {
1150 std::unique_lock lock{ this->accessMutex };
1151 return this->set.begin();
1152 }
1153
1154 auto end() {
1155 std::unique_lock lock{ this->accessMutex };
1156 return this->set.end();
1157 }
1158
1159 const bool contains(OTy& key) noexcept {
1160 std::shared_lock lock{ this->accessMutex };
1161 return this->set.contains(key);
1162 }
1163
1164 void erase(OTy& key) {
1165 if (this->set.contains(key)) {
1166 std::unique_lock lock{ this->accessMutex };
1167 this->set.erase(key);
1168 }
1169 }
1170
1171 OTy& operator[](OTy& key) {
1172 if (!this->contains(key)) {
1173 std::shared_lock lock{ this->accessMutex };
1174 this->set.emplace(key);
1175 }
1176 return ( OTy& )*this->set.find(key);
1177 }
1178
1179 OTy& operator[](OTy&& key) {
1180 if (!this->contains(key)) {
1181 std::shared_lock lock{ this->accessMutex };
1182 this->set.emplace(std::move(key));
1183 }
1184 return ( OTy& )*this->set.find(key);
1185 }
1186
1187 uint64_t size() noexcept {
1188 std::unique_lock lock{ this->accessMutex };
1189 return this->set.size();
1190 }
1191
1192 protected:
1193 std::shared_mutex accessMutex{};
1194 std::unordered_set<OTy> set{};
1195 };
1196
1197 class DiscordCoreAPI_Dll StringWrapper {
1198 public:
1199 StringWrapper() noexcept = default;
1200
1201 StringWrapper& operator=(StringWrapper&& other) noexcept;
1202
1203 StringWrapper(StringWrapper&& other) noexcept;
1204
1205 StringWrapper& operator=(const StringWrapper& other);
1206
1207 StringWrapper(const StringWrapper& other);
1208
1209 StringWrapper& operator=(const std::string& string);
1210
1211 explicit StringWrapper(const std::string& string);
1212
1213 StringWrapper& operator=(const char* string);
1214
1215 StringWrapper(const char* string);
1216
1217 operator std::string();
1218
1219 void emplace_back(char value);
1220
1221 uint64_t size();
1222
1223 const char* data();
1224
1225 protected:
1226 std::unique_ptr<char[]> ptr{};
1227 };
1228
1229 DiscordCoreAPI_Dll inline std::basic_ostream<char>& operator<<(std::basic_ostream<char, std::char_traits<char>>& lhs, const StringWrapper& rhs) {
1230 for (auto& value: static_cast<std::string>(static_cast<StringWrapper>(rhs))) {
1231 lhs.put(value);
1232 }
1233 return lhs;
1234 }
1235
1236 DiscordCoreAPI_Dll inline std::basic_string<char> operator+(const std::basic_string<char, std::char_traits<char>, std::allocator<char>>& lhs,
1237 StringWrapper rhs) {
1238 std::stringstream stream{};
1239 stream << lhs << rhs;
1240 return stream.str();
1241 }
1242
1243 DiscordCoreAPI_Dll inline std::basic_string<char> operator+(const char* lhs, StringWrapper rhs) {
1244 std::stringstream stream{};
1245 stream << lhs << rhs;
1246 return stream.str();
1247 }
1248
1249 DiscordCoreAPI_Dll inline bool operator==(StringWrapper lhs, const char* rhs) {
1250 return static_cast<std::string>(lhs) == static_cast<std::string>(rhs);
1251 }
1252
1253 DiscordCoreAPI_Dll inline bool operator!=(StringWrapper lhs, const char* rhs) {
1254 return static_cast<std::string>(lhs) != rhs;
1255 }
1256
1257 DiscordCoreAPI_Dll inline bool operator==(std::string& lhs, StringWrapper& rhs) {
1258 if (lhs.size() != rhs.size()) {
1259 return false;
1260 }
1261 for (size_t x = 0; x < lhs.size(); ++x) {
1262 if (lhs[x] != rhs.data()[x]) {
1263 return false;
1264 }
1265 }
1266 return true;
1267 }
1268
1269 /**@}*/
1270
1271 /**
1272 * \addtogroup voice_connection
1273 * @{
1274 */
1275
1276 /// \brief Audio frame types.
1277 enum class AudioFrameType : uint8_t {
1278 Unset = 0,///< Unset.
1279 RawPCM = 1,///< Raw PCM.
1280 Skip = 2///< Skip.
1281 };
1282
1283 /// \brief Represents a single frame of audio data.
1284 struct DiscordCoreAPI_Dll AudioFrameData {
1285 AudioFrameType type{ AudioFrameType::Unset };///< The type of audio frame.
1286 std::basic_string<std::byte> data{};///< The audio data.
1287 uint64_t guildMemberId{};///< GuildMemberId for the sending GuildMember.
1288 int64_t currentSize{};///< The current size of the allocated memory.
1289
1290 AudioFrameData() noexcept = default;
1291
1292 AudioFrameData& operator=(AudioFrameData&&) noexcept;
1293
1294 AudioFrameData(AudioFrameData&&) noexcept;
1295
1296 AudioFrameData& operator=(const AudioFrameData&) noexcept = delete;
1297
1298 AudioFrameData(const AudioFrameData&) noexcept = delete;
1299
1300 AudioFrameData& operator+=(std::basic_string_view<std::byte>) noexcept;
1301
1302 AudioFrameData& operator+=(std::byte);
1303
1304 friend bool operator==(const AudioFrameData& lhs, const AudioFrameData& rhs);
1305
1306 void clearData() noexcept;
1307 };
1308
1309 /// For connecting to a voice-channel. "streamInfo" is used when a socket is created to connect this bot to another bot, for transmitting audio back and forth.
1310 /// \brief For connecting to a voice-channel. "streamInfo" is used when a socket is created to connect this bot to another bot, for transmitting audio back and forth.
1311 struct DiscordCoreAPI_Dll VoiceConnectInitData {
1312 StreamInfo streamInfo{};///< The info for the stream-socekt, if applicable.
1313 int32_t currentShard{};///< The current websocket shard, if applicable.
1314 Snowflake channelId{};///< The channel id to connect to.
1315 Snowflake guildId{};///< The guild id to connect to.
1316 Snowflake userId{};///< This bot's user id.
1317 bool selfDeaf{};///< Self-deafen the bot?
1318 bool selfMute{};///< Self-mute the bot?
1319 };
1320
1321 /**@}*/
1322
1323 /**
1324 * \addtogroup utilities
1325 * @{
1326 */
1327
1328 /// \brief Time formatting methods.
1329 enum class TimeFormat : char {
1330 LongDate = 'D',///< "20 April 2021" - Long Date
1331 LongDateTime = 'F',///< "Tuesday, 20 April 2021 16:20" - Long Date/Time
1332 LongTime = 'T',///< "16:20:30" - Long Time
1333 ShortDate = 'd',///< "20/04/2021" - Short Date
1334 ShortDateTime = 'f',///< "20 April 2021 16:20" - Short Date/Time
1335 ShortTime = 't',///< "16:20" - Short Time
1336 };
1337
1338 DiscordCoreAPI_Dll uint64_t strtoull(std::string_view string);
1339
1340 template<typename RTy> RTy fromString(const std::string& string, std::ios_base& (*type)( std::ios_base& )) {
1341 RTy value{};
1342 std::istringstream stream(string);
1343 stream >> type, stream >> value;
1344 return value;
1345 }
1346
1347 template<typename RTy> std::string toHex(RTy inputValue) {
1348 std::stringstream stream{};
1349 stream << std::setfill('0') << std::setw(sizeof(RTy) * 2) << std::hex << inputValue;
1350 return stream.str();
1351 }
1352
1353 class DiscordCoreAPI_Dll RGBColorValue {
1354 public:
1355 uint8_t green{};
1356 uint8_t blue{};
1357 uint8_t red{};
1358 };
1359
1360 using HexColorValue = std::string;
1361
1362 class DiscordCoreAPI_Dll ColorValue {
1363 public:
1364 ColorValue(std::string hexColorValue);
1365
1366 ColorValue(uint32_t colorValue);
1367
1368 RGBColorValue getRgbColorValue();
1369
1370 HexColorValue getHexColorValue();
1371
1372 uint32_t getIntColorValue();
1373
1374 protected:
1375 uint32_t color{};
1376 };
1377
1378 enum class HashType {
1379 User_Avatar = 0,
1380 Channel_Icon = 1,
1381 GuildMember_Avatar = 2,
1382 Guild_Icon = 3,
1383 Guild_Splash = 4,
1384 Guild_Banner = 5,
1385 Guild_Discovery = 6
1386 };
1387
1388 class DiscordCoreAPI_Dll IconHash {
1389 public:
1390 IconHash() noexcept = default;
1391
1392 IconHash& operator=(const std::string& string);
1393
1394 IconHash(const std::string& string) noexcept;
1395
1396 bool operator==(const IconHash& other);
1397
1398 std::string getIconHash() noexcept;
1399
1400 ~IconHash() noexcept = default;
1401
1402 protected:
1403 uint64_t highBits{};
1404 uint64_t lowBits{};
1405 };
1406
1407 /**@}*/
1408
1409 /**
1410 * \addtogroup foundation_entities
1411 * @{
1412 */
1413
1414 /// \brief Permission values, for a given Channel, by Role or GuildMember.
1415 enum class Permission : uint64_t {
1416 Create_Instant_Invite = 1ull << 0,///< Create Instant Invite.
1417 Kick_Members = 1ull << 1,///< Kick Members.
1418 Ban_Members = 1ull << 2,///< Ban Members.
1419 Administrator = 1ull << 3,///< Administrator.
1420 Manage_Channels = 1ull << 4,///< Manage Channels.
1421 Manage_Guild = 1ull << 5,///< Manage Guild.
1422 Add_Reactions = 1ull << 6,///< Add Reactions.
1423 View_Audit_Log = 1ull << 7,///< View Audit Log.
1424 Priority_Speaker = 1ull << 8,///< Priority Speaker.
1425 Stream = 1ull << 9,///< Stream.
1426 View_Channel = 1ull << 10,///< View Channel.
1427 Send_Messages = 1ull << 11,///< Send Messages.
1428 Send_Tts_Messages = 1ull << 12,///< Send TTS Messages.
1429 Manage_Messages = 1ull << 13,///< Manage Messages.
1430 Embed_Links = 1ull << 14,///< Embed Links.
1431 Attach_Files = 1ull << 15,///< Attach Files.
1432 Read_Message_History = 1ull << 16,///< Read Message History.
1433 Mention_Everyone = 1ull << 17,///< Mention Everyone.
1434 Use_External_Emojis = 1ull << 18,///< Use External Emoji.
1435 View_Guild_Insights = 1ull << 19,///< View Guild Insights.
1436 Connect = 1ull << 20,///< Connect.
1437 Speak = 1ull << 21,///< Speak.
1438 Mute_Members = 1ull << 22,///< Mute Members.
1439 Deafen_Members = 1ull << 23,///< Deafen Members.
1440 Move_Members = 1ull << 24,///< Move Members.
1441 Use_Vad = 1ull << 25,///< Use VAD.
1442 Change_Nickname = 1ull << 26,///< Change Nickname.
1443 Manage_Nicknames = 1ull << 27,///< Manage Nicknames.
1444 Manage_Roles = 1ull << 28,///< Manage Roles.
1445 Manage_Webhooks = 1ull << 29,///< Manage Webhooks.
1446 Manage_Emojis_And_Stickers = 1ull << 30,///< Manage Emojis And Stickers.
1447 Use_Application_Commands = 1ull << 31,///< Use Application Commands.
1448 Request_To_Speak = 1ull << 32,///< Request To Speak.
1449 Manage_Events = 1ull << 33,///< Manage Events.
1450 Manage_Threads = 1ull << 34,///< Manage Threads.
1451 Create_Public_Threads = 1ull << 35,///< Create Public Threads.
1452 Create_Private_Threads = 1ull << 36,///< Create Private Threads.
1453 Use_External_Stickers = 1ull << 37,///< Use External Stickers.
1454 Send_Messages_In_Threads = 1ull << 38,///< Send Messages In Threads.
1455 Start_Embedded_Activities = 1ull << 39,///< Start Embedded Activities.
1456 Moderate_Members = 1ull << 40///< Moderate Members.
1457 };
1458
1459 /// \brief Permissions class, for representing and manipulating Permission values.
1460 class DiscordCoreAPI_Dll Permissions {
1461 public:
1462 Permissions() noexcept = default;
1463
1464 Permissions& operator=(Permission&& other);
1465
1466 Permissions(Permission&& permsNew);
1467
1468 Permissions& operator=(const Permission& other);
1469
1470 explicit Permissions(const Permission& permsNew);
1471
1472 Permissions& operator=(std::string&& other);
1473
1474 explicit Permissions(std::string&& permsNew);
1475
1476 Permissions& operator=(const std::string& other);
1477
1478 explicit Permissions(const std::string& permsNew);
1479
1480 Permissions& operator=(const uint64_t other);
1481
1482 explicit Permissions(const uint64_t permsNew);
1483
1484 operator uint64_t();
1485
1486 operator std::string();
1487
1488 /// \brief Returns a string containing all of a given User's Permissions for a given Channel.
1489 /// \param guildMember The GuildMember who's Permissions to analyze.
1490 /// \param channel The Channel withint which to check for Permissions.
1491 /// \returns std::string A string containing the final Permission's value for a given Channel.
1492 static std::string getCurrentChannelPermissions(const GuildMember& guildMember, const ChannelData& channel);
1493
1494 /// \brief Checks for a given Permission in a chosen Channel, for a specific User.
1495 /// \param guildMember The GuildMember who to check the Permissions of.
1496 /// \param channel The Channel within which to check for the Permission's presence.
1497 /// \param permission A Permission to check the current Channel for.
1498 /// \returns bool A bool suggesting the presence of the chosen Permission.
1499 bool checkForPermission(const GuildMember& guildMember, const ChannelData& channel, Permission permission);
1500
1501 /// \brief Returns a string containing the currently held Permissions in a given Guild.
1502 /// \param guildMember The GuildMember who's Permissions are to be evaluated.
1503 /// \returns std::string A string containing the current Permissions.
1504 static std::string getCurrentGuildPermissions(const GuildMember& guildMember);
1505
1506 /// \brief Removes one or more Permissions from the current Permissions value.
1507 /// \param permissionsToRemove A vector containing the Permissions you wish to remove.
1508 void removePermissions(const std::vector<Permission>& permissionsToRemove);
1509
1510 /// \brief Adds one or more Permissions to the current Permissions value.
1511 /// \param permissionsToAdd A vector containing the Permissions you wish to add.
1512 void addPermissions(const std::vector<Permission>& permissionsToAdd);
1513
1514 /// \brief Displays the currently present Permissions in a string, and returns a vector with each of them stored in string format.
1515 /// \returns std::vector A vector full of strings of the Permissions that are in the input std::string's value.
1516 std::vector<std::string> displayPermissions();
1517
1518 /// \brief Returns a string containing the currently held Permissions.
1519 /// \returns std::string A string containing the current Permissions.
1520 std::string getCurrentPermissionString();
1521
1522 /// \brief Returns a string containing ALL of the possible Permissions.
1523 /// \returns std::string A string containing all of the possible Permissions.
1524 static std::string getAllPermissions();
1525
1526 protected:
1527 uint64_t permissions{};
1528
1529 static std::string computeOverwrites(const std::string& basePermissions, const GuildMember& guildMember, const ChannelData& channel);
1530
1531 static std::string computePermissions(const GuildMember& guildMember, const ChannelData& channel);
1532
1533 static std::string computeBasePermissions(const GuildMember& guildMember);
1534 };
1535
1536 /// \brief Prints the current file, line, and column from which the function is being called - typically from within an exception's "catch" block.
1537 /// \param currentFunctionName A string to display the current function's name.
1538 /// \param location For deriving the current file, line, and column - do not set this value.
1539 DiscordCoreAPI_Dll void reportException(const std::string& currentFunctionName, std::source_location location = std::source_location::current());
1540
1541 DiscordCoreAPI_Dll void rethrowException(const std::string& currentFunctionName, std::source_location location = std::source_location::current());
1542
1543 DiscordCoreAPI_Dll std::string constructMultiPartData(const std::string& data, const std::vector<File>& files);
1544
1545 DiscordCoreAPI_Dll std::string convertToLowerCase(const std::string& stringToConvert);
1546
1547 DiscordCoreAPI_Dll std::string base64Encode(const std::string&, bool = false);
1548
1549 DiscordCoreAPI_Dll std::string loadFileContents(const std::string& filePath);
1550
1551 DiscordCoreAPI_Dll std::string utf8MakeValid(const std::string& inputString);
1552
1553 DiscordCoreAPI_Dll std::string urlEncode(const std::string& inputString);
1554
1555 DiscordCoreAPI_Dll std::string escapeCharacters(std::string_view string);
1556
1557 DiscordCoreAPI_Dll void spinLock(uint64_t timeInNsToSpinLockFor);
1558
1559 DiscordCoreAPI_Dll std::string generateBase64EncodedKey();
1560
1561 DiscordCoreAPI_Dll std::string shiftToBrightGreen();
1562
1563 DiscordCoreAPI_Dll std::string shiftToBrightBlue();
1564
1565 DiscordCoreAPI_Dll std::string shiftToBrightRed();
1566
1567 DiscordCoreAPI_Dll bool nanoSleep(int64_t ns);
1568
1569 DiscordCoreAPI_Dll std::string reset();
1570
1571 /// \brief Acquires a timeStamp with the current time and date - suitable for use in message-embeds.
1572 /// \returns std::string A string containing the current date-time stamp.
1573 DiscordCoreAPI_Dll std::string getTimeAndDate();
1574
1575 /// \brief Class for representing a timeStamp, as well as working with time-related values.
1576 class DiscordCoreAPI_Dll TimeStamp {
1577 public:
1578 explicit TimeStamp(TimeFormat formatNew = TimeFormat::LongDateTime);
1579
1580 TimeStamp(std::string year, std::string month, std::string day, std::string hour, std::string minute, std::string second,
1581 TimeFormat formatNew);
1582
1583 operator std::string();
1584
1585 operator uint64_t();
1586
1587 TimeStamp& operator=(std::string&& originalTimeStampNew);
1588
1589 explicit TimeStamp(std::string&& originalTimeStampNew);
1590
1591 TimeStamp& operator=(std::string& originalTimeStampNew);
1592
1593 explicit TimeStamp(std::string& originalTimeStampNew);
1594
1595 TimeStamp& operator=(const TimeStamp& other);
1596
1597 TimeStamp(const TimeStamp& other);
1598
1599 TimeStamp(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t minute, int32_t second, TimeFormat formatNew);
1600
1601 TimeStamp(uint64_t timeInTimeUnits, TimeFormat formatNew);
1602
1603 static std::string convertToFutureISO8601TimeStamp(int32_t minutesToAdd, int32_t hoursToAdd, int32_t daysToAdd, int32_t monthsToAdd,
1604 int32_t yearsToAdd, TimeFormat formatNew);
1605
1606 static std::string convertToCurrentISO8601TimeStamp(TimeFormat timeFormat);
1607
1608 bool hasTimeElapsed(uint64_t days, uint64_t hours, uint64_t minutes);
1609
1610 static std::string convertMsToDurationString(uint64_t durationInMs);
1611
1612 protected:
1613 uint64_t timeStampInTimeUnits{};
1614
1615 void getTimeSinceEpoch(int64_t year, int64_t month, int64_t day, int64_t hour, int64_t minute, int64_t second);
1616
1617 void convertTimeStampToTimeUnits(TimeFormat formatNew, std::string originalTimeStamp);
1618
1619 std::string getISO8601TimeStamp(TimeFormat timeFormat);
1620 };
1621
1622 template<typename ITy>
1623 concept IsInteger = std::is_integral<ITy>::value;
1624
1625 template<IsInteger StoredAs, IsEnum OTy> auto setBool(StoredAs theFlags, OTy theFlagToSet, bool enabled) {
1626 auto theValue{ theFlags };
1627 if (enabled) {
1628 theValue |= std::to_underlying(theFlagToSet);
1629 } else {
1630 theValue &= ~std::to_underlying(theFlagToSet);
1631 }
1632 return theValue;
1633 }
1634
1635 template<IsEnum OTy> bool getBool(OTy theFlags, OTy theFlagToCheckFor) {
1636 return std::to_underlying(theFlags) & std::to_underlying(theFlagToCheckFor);
1637 }
1638
1639 template<typename OTy>
1640 concept CopyableOrMovable = std::copyable<OTy> || std::movable<OTy>;
1641
1642 /// \brief A thread-safe messaging block for data-structures.
1643 /// \tparam OTy The type of object that will be sent over
1644 /// message block.
1645 template<CopyableOrMovable OTy> class UnboundedMessageBlock {
1646 public:
1647 UnboundedMessageBlock<OTy>& operator=(UnboundedMessageBlock<OTy>&& other) noexcept {
1648 if (this != &other) {
1649 this->queue = std::move(other.queue);
1650 other.queue = std::deque<OTy>{};
1651 }
1652 return *this;
1653 }
1654
1656 *this = std::move(other);
1657 }
1658
1659 UnboundedMessageBlock<OTy>& operator=(const UnboundedMessageBlock<OTy>&) = delete;
1660
1662
1663 UnboundedMessageBlock() noexcept {};
1664
1665 /// \brief Sends an object of type OTy to the "recipient", ahead of other already queued items.
1666 /// \param object An object of OTy.
1667 void sendFront(OTy&& object) {
1668 std::unique_lock lock{ this->accessMutex };
1669 this->queue.emplace_front(std::move(object));
1670 }
1671
1672 /// \brief Sends an object of type OTy to the "recipient", ahead of other already queued items.
1673 /// \param object An object of OTy.
1674 void sendFront(OTy& object) {
1675 std::unique_lock lock{ this->accessMutex };
1676 this->queue.emplace_front(object);
1677 }
1678
1679 /// \brief Sends an object of type OTy to the "recipient".
1680 /// \param object An object of OTy.
1681 void send(OTy&& object) {
1682 std::unique_lock lock{ this->accessMutex };
1683 this->queue.emplace_back(std::move(object));
1684 }
1685
1686 /// \brief Sends an object of type OTy to the "recipient".
1687 /// \param object An object of OTy.
1688 void send(OTy& object) {
1689 std::unique_lock lock{ this->accessMutex };
1690 this->queue.emplace_back(object);
1691 }
1692
1693 /// \brief Sends an object of type OTy to the "recipient".
1694 /// \param object An object of OTy.
1695 void send(const OTy& object) {
1696 std::unique_lock lock{ this->accessMutex };
1697 this->queue.emplace_back(object);
1698 }
1699
1700 /// \brief Clears the contents of the messaging block.
1702 std::unique_lock lock{ this->accessMutex };
1703 this->queue.clear();
1704 }
1705
1706 /// \brief Tries to receive an object of type OTy to be placed into a reference.
1707 /// \param object A reference of type OTy for placing the potentially received object.
1708 /// \returns bool A bool, denoting whether or not we received an object.
1709 bool tryReceive(OTy& object) {
1710 std::unique_lock lock{ this->accessMutex };
1711 if (this->queue.size() > 0) {
1712 object = std::move(this->queue.front());
1713 this->queue.pop_front();
1714 return true;
1715 } else {
1716 return false;
1717 }
1718 }
1719
1720 size_t size() {
1721 return this->queue.size();
1722 }
1723
1724 protected:
1725 std::deque<OTy> queue{};
1726 std::mutex accessMutex{};
1727 };
1728
1729 template<typename RTy> class NewThreadAwaiter;
1730
1731 /// \brief An awaitable that can be used to launch the CoRoutine onto a new thread - as well as return the handle for stoppping its execution.
1732 /// \tparam RTy The type of value returned by the containing CoRoutine.
1733 template<typename RTy> auto NewThreadAwaitable() {
1734 return NewThreadAwaiter<RTy>{};
1735 }
1736
1737 /// \brief Typedef for the message filter.
1738 template<typename OTy> using ObjectFilter = std::function<bool(OTy)>;
1739
1740 template<typename OTy> bool waitForTimeToPass(UnboundedMessageBlock<OTy>& outBuffer, OTy& argOne, int32_t timeInMsNew) {
1741 StopWatch stopWatch{ Milliseconds{ timeInMsNew } };
1742 while (!outBuffer.tryReceive(argOne)) {
1743 std::this_thread::sleep_for(1ms);
1744 if (stopWatch.hasTimePassed()) {
1745 return true;
1746 }
1747 };
1748 return false;
1749 }
1750
1751 /**@}*/
1752};
1753
1754namespace DiscordCoreInternal {
1755
1756 struct DiscordCoreAPI_Dll LengthData {
1757 uint64_t offSet{};
1758 uint64_t length{};
1759 };
1760
1761 class DiscordCoreAPI_Dll StringBuffer {
1762 public:
1763 StringBuffer() noexcept;
1764
1765 std::string_view operator[](LengthData);
1766
1767 char operator[](uint64_t);
1768
1769 void writeData(const char* ptr, uint64_t size);
1770
1771 std::string::iterator begin();
1772
1773 std::string::iterator end();
1774
1775 void erase(uint64_t);
1776
1777 uint64_t size();
1778
1779 char* data();
1780
1781 void clear();
1782
1783 protected:
1784 std::string string{};
1785 uint64_t sizeValue{};
1786 };
1787
1788 enum class RingBufferAccessType { Read = 0, Write = 1 };
1789
1790 template<typename OTy, uint64_t Size> class RingBufferInterface {
1791 public:
1792 void modifyReadOrWritePosition(RingBufferAccessType type, uint64_t size) noexcept {
1793 if (type == RingBufferAccessType::Read) {
1794 this->tail += size;
1795 this->areWeFull = false;
1796 } else {
1797 this->head += size;
1798 if (this->head == this->tail) {
1799 this->areWeFull = true;
1800 }
1801 if (this->head != this->tail) {
1802 this->areWeFull = false;
1803 }
1804 }
1805 }
1806
1807 uint64_t getUsedSpace() noexcept {
1808 if (this->areWeFull) {
1809 return this->arrayValue.size();
1810 }
1811 if ((this->head % this->arrayValue.size()) >= (this->tail % this->arrayValue.size())) {
1812 return (this->head % this->arrayValue.size()) - (this->tail % this->arrayValue.size());
1813 } else {
1814 return this->arrayValue.size() + (this->head % this->arrayValue.size()) - (this->tail % this->arrayValue.size());
1815 }
1816 }
1817
1818 uint64_t getFreeSpace() noexcept {
1819 return this->arrayValue.size() - this->getUsedSpace();
1820 }
1821
1822 OTy* getCurrentTail() noexcept {
1823 return (this->arrayValue.data() + (this->tail % (this->arrayValue.size())));
1824 }
1825
1826 OTy* getCurrentHead() noexcept {
1827 return (this->arrayValue.data() + (this->head % (this->arrayValue.size())));
1828 }
1829
1830 bool isItFull() noexcept {
1831 return this->areWeFull;
1832 }
1833
1834 virtual void clear() noexcept {
1835 this->areWeFull = false;
1836 this->tail = 0;
1837 this->head = 0;
1838 }
1839
1840 protected:
1841 std::array<OTy, Size> arrayValue{};
1842 bool areWeFull{};
1843 uint64_t tail{};
1844 uint64_t head{};
1845 };
1846
1847 template<typename OTy, uint64_t SliceCount> class RingBuffer : public RingBufferInterface<RingBufferInterface<OTy, 1024 * 16>, SliceCount> {
1848 public:
1849 void clear() noexcept override {
1850 for (uint64_t x = 0; x < this->arrayValue.size(); ++x) {
1851 this->arrayValue[x].clear();
1852 }
1853 this->areWeFull = false;
1854 this->tail = 0;
1855 this->head = 0;
1856 }
1857 };
1858}
1859
1860template<> struct DiscordCoreAPI_Dll std::hash<DiscordCoreAPI::Snowflake> {
1861 uint64_t operator()(DiscordCoreAPI::Snowflake const& object) const noexcept {
1862 return object.operator size_t();
1863 }
1864};
AudioFrameType
Audio frame types.
Definition: Utilities.hpp:1277
TimeFormat
Time formatting methods.
Definition: Utilities.hpp:1329
@ ShortTime
"16:20" - Short Time
@ LongDate
"20 April 2021" - Long Date
@ ShortDate
"20/04/2021" - Short Date
@ LongDateTime
"Tuesday, 20 April 2021 16:20" - Long Date/Time
@ LongTime
"16:20:30" - Long Time
@ ShortDateTime
"20 April 2021 16:20" - Short Date/Time
GatewayIntents
Gateway intents.
Definition: Utilities.hpp:921
DiscordCoreAPI_Dll std::string getTimeAndDate()
Acquires a timeStamp with the current time and date - suitable for use in message-embeds.
Definition: Utilities.cpp:1718
TextFormat
Represents which text format to use for websocket transfer.
Definition: Utilities.hpp:955
auto NewThreadAwaitable()
An awaitable that can be used to launch the CoRoutine onto a new thread - as well as return the handl...
Definition: Utilities.hpp:1733
InputEventResponseType
Input event response types.
Definition: Utilities.hpp:906
HttpsResponseCodes
Voice Websocket close codes.
Definition: Utilities.hpp:814
DiscordCoreAPI_Dll void reportException(const std::string &currentFunctionName, std::source_location location=std::source_location::current())
Prints the current file, line, and column from which the function is being called - typically from wi...
Definition: Utilities.cpp:1498
std::function< bool(OTy)> ObjectFilter
Typedef for the message filter.
Definition: Utilities.hpp:1738
UpdatePresenceStatusTypes
Update-presence status types.
Definition: Utilities.hpp:885
VoiceWebSocketCloseCode
Voice Websocket close codes.
Definition: Utilities.hpp:756
StreamType
For selecting the type of streamer that the given bot is, one must be one server and one of client pe...
Definition: Utilities.hpp:640
Permission
Permission values, for a given Channel, by Role or GuildMember.
Definition: Utilities.hpp:1415
WebSocketCloseCode
Websocket close codes.
Definition: Utilities.hpp:684
@ Guild_Scheduled_Events
Scheduled events.
@ Privileged_Intents
Privileged intents requiring ID.
@ Guild_Integrations
Intent for receipt of Guild integrations.
@ Guild_Message_Typing
Intent for receipt of Guild message typing notifications.
@ Message_Content
Intent for receipt of message content.
@ All_Intents
Every single intent.
@ Default_Intents
Default intents (all non-privileged intents).
@ Guild_Bans
Intent for receipt of Guild bans.
@ Guild_Message_Reactions
Intent for receipt of Guild message reactions.
@ Direct_Message_Typing
Intent for receipt of direct message typing notifications.
@ Guild_Invites
Intent for receipt of Guild invites.
@ Guild_Emojis
Intent for receipt of Guild emojis.
@ Guild_Presences
Intent for receipt of Guild presences.
@ Guild_Webhooks
Intent for receipt of Guild webhooks.
@ Guild_VoiceStates
Intent for receipt of Guild voice states.
@ Direct_Message_Reactions
Intent for receipt of direct message reactions.
@ Guild_Messages
Intent for receipt of Guild messages.
@ Guild_Members
Intent for receipt of Guild members.
@ Direct_Messages
Intent for receipt of direct messages (DMs).
@ Ephemeral_Interaction_Response
Ephemeral Interaction response.
@ Ephemeral_Deferred_Response
Deferred ephemeral response.
@ Interaction_Response
Interaction response.
@ Modal_Interaction_Response
Respond to an interaction with a popup modal.
@ Edit_Interaction_Response
Interaction response edit.
@ Application_Command_AutoComplete_Result
Respond to an autocomplete interaction with suggested choices.
@ Edit_Follow_Up_Message
Follow-up Message edit.
@ Ephemeral_Follow_Up_Message
Ephemeral follow-up Message.
@ invisible
Invisible and shown as offline.
@ View_Channel
View Channel.
@ Manage_Events
Manage Events.
@ Use_Application_Commands
Use Application Commands.
@ Manage_Messages
Manage Messages.
@ Manage_Nicknames
Manage Nicknames.
@ Change_Nickname
Change Nickname.
@ Create_Instant_Invite
Create Instant Invite.
@ Manage_Emojis_And_Stickers
Manage Emojis And Stickers.
@ Move_Members
Move Members.
@ Priority_Speaker
Priority Speaker.
@ Administrator
Administrator.
@ Read_Message_History
Read Message History.
@ Manage_Webhooks
Manage Webhooks.
@ Mute_Members
Mute Members.
@ Manage_Roles
Manage Roles.
@ Send_Messages_In_Threads
Send Messages In Threads.
@ Create_Private_Threads
Create Private Threads.
@ Use_External_Emojis
Use External Emoji.
@ Send_Tts_Messages
Send TTS Messages.
@ Kick_Members
Kick Members.
@ View_Audit_Log
View Audit Log.
@ Manage_Threads
Manage Threads.
@ Create_Public_Threads
Create Public Threads.
@ Use_External_Stickers
Use External Stickers.
@ Manage_Channels
Manage Channels.
@ Mention_Everyone
Mention Everyone.
@ Attach_Files
Attach Files.
@ Manage_Guild
Manage Guild.
@ Moderate_Members
Moderate Members.
@ Add_Reactions
Add Reactions.
@ Send_Messages
Send Messages.
@ Start_Embedded_Activities
Start Embedded Activities.
@ View_Guild_Insights
View Guild Insights.
@ Deafen_Members
Deafen Members.
@ Request_To_Speak
Request To Speak.
The main namespace for this library.
const std::string GrayChateau
Gray chateau.
Definition: Utilities.hpp:1106
const std::string WrxBlue
Wrx blue.
Definition: Utilities.hpp:1109
const std::string LightSeaGreen
Light sea green.
Definition: Utilities.hpp:1088
const std::string Pink
Pink.
Definition: Utilities.hpp:1081
const std::string Red
Red.
Definition: Utilities.hpp:1080
const std::string StiBlue
Sti blue.
Definition: Utilities.hpp:1108
const std::string ScarletRed
Scarlet red.
Definition: Utilities.hpp:1117
const std::string SummerSky
Summer skye.
Definition: Utilities.hpp:1090
const std::string Cinnabar
Cinnabar.
Definition: Utilities.hpp:1095
const std::string Rust
Rust.
Definition: Utilities.hpp:1104
const std::string DarkGoldenrod
Dark goldenrod.
Definition: Utilities.hpp:1103
const std::string DiscordWhite
Discord white.
Definition: Utilities.hpp:1074
const std::string Brown
Brown.
Definition: Utilities.hpp:1105
const std::string Black
Black.
Definition: Utilities.hpp:1078
const std::string MediumSeaGreen
Medium sea green.
Definition: Utilities.hpp:1089
const std::string BlueAquamarine
Blue aquamarine.
Definition: Utilities.hpp:1097
const std::string MoonYellow
Moon yellow.
Definition: Utilities.hpp:1093
const std::string Blue
Blue.
Definition: Utilities.hpp:1087
const std::string TahitiGold
Tahiti gold.
Definition: Utilities.hpp:1094
const std::string Endeavour
Endeavor.
Definition: Utilities.hpp:1100
const std::string ForestGreen
Forest green.
Definition: Utilities.hpp:1112
const std::string Aquamarine
Aquamarine.
Definition: Utilities.hpp:1114
const std::string JazzberryJam
Jazzberry jam.
Definition: Utilities.hpp:1102
const std::string CadmiumGreen
Cadmium green.
Definition: Utilities.hpp:1113
const std::string LightGray
Light gray.
Definition: Utilities.hpp:1075
const std::string Magenta
Magenta.
Definition: Utilities.hpp:1085
const std::string DeepLilac
Deep lilac.
Definition: Utilities.hpp:1091
const std::string DiscordBlack
Discord black.
Definition: Utilities.hpp:1079
const std::string RalliArtCrimson
Ralliart crimson.
Definition: Utilities.hpp:1110
const std::string Submarine
Submarine.
Definition: Utilities.hpp:1096
const std::string White
White.
Definition: Utilities.hpp:1073
const std::string Yellow
Yellow.
Definition: Utilities.hpp:1083
const std::string Raspberry
Raspberry.
Definition: Utilities.hpp:1116
const std::string DeepSea
Deep sea.
Definition: Utilities.hpp:1098
const std::string VividViolet
Vivid violet.
Definition: Utilities.hpp:1101
const std::string SeaGreen
Sea green.
Definition: Utilities.hpp:1099
const std::string Gray
Gray.
Definition: Utilities.hpp:1076
const std::string Cyan
Cyan.
Definition: Utilities.hpp:1086
const std::string BlueGreen
Blue green.
Definition: Utilities.hpp:1115
const std::string Green
Green.
Definition: Utilities.hpp:1084
const std::string Orange
Orange.
Definition: Utilities.hpp:1082
const std::string Lime
Lime.
Definition: Utilities.hpp:1111
const std::string Ruby
Ruby.
Definition: Utilities.hpp:1092
const std::string DarkGray
Dark gray.
Definition: Utilities.hpp:1077
const std::string Bismark
Bismark.
Definition: Utilities.hpp:1107
An awaitable that can be used to launch the CoRoutine onto a new thread - as well as return the handl...
Definition: CoRoutine.hpp:356
DiscordCoreClient - The main class for this library.
Data structure representing a single Channel.
An interface class for the Guild related Discord endpoints.
For connecting two bots to stream the VC contents between the two.
Definition: Utilities.hpp:643
Voice Websocket close codes.
Definition: Utilities.hpp:753
Voice Websocket close codes.
Definition: Utilities.hpp:811
For updating a User's presence.
Definition: Utilities.hpp:894
Function data for repeated functions to be loaded.
Definition: Utilities.hpp:947
Sharding options for the library.
Definition: Utilities.hpp:961
Loggin options for the library.
Definition: Utilities.hpp:970
For selecting the caching style of the library.
Definition: Utilities.hpp:982
Configuration data for the library's main class, DiscordCoreClient.
Definition: Utilities.hpp:990
Represents a single frame of audio data.
Definition: Utilities.hpp:1284
For connecting to a voice-channel. "streamInfo" is used when a socket is created to connect this bot ...
Definition: Utilities.hpp:1311
Permissions class, for representing and manipulating Permission values.
Definition: Utilities.hpp:1460
Class for representing a timeStamp, as well as working with time-related values.
Definition: Utilities.hpp:1576
A thread-safe messaging block for data-structures.
Definition: Utilities.hpp:1645
void send(const OTy &object)
Sends an object of type OTy to the "recipient".
Definition: Utilities.hpp:1695
bool tryReceive(OTy &object)
Tries to receive an object of type OTy to be placed into a reference.
Definition: Utilities.hpp:1709
void send(OTy &object)
Sends an object of type OTy to the "recipient".
Definition: Utilities.hpp:1688
void send(OTy &&object)
Sends an object of type OTy to the "recipient".
Definition: Utilities.hpp:1681
void sendFront(OTy &&object)
Sends an object of type OTy to the "recipient", ahead of other already queued items.
Definition: Utilities.hpp:1667
void clearContents()
Clears the contents of the messaging block.
Definition: Utilities.hpp:1701
void sendFront(OTy &object)
Sends an object of type OTy to the "recipient", ahead of other already queued items.
Definition: Utilities.hpp:1674