DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
Base.hpp
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/// Base.hpp - Header for the some of the base definitions and includes.
27/// Nov 8, 2021
28/// https://discordcoreapi.com
29/// \file Base.hpp
30#pragma once
31
32#if !defined(__GNUC__)
33 #pragma warning(disable : 4710)
34 #pragma warning(disable : 4711)
35 #pragma warning(disable : 4251)
36 #pragma warning(disable : 4371)
37 #pragma warning(disable : 4514)
38 #pragma warning(disable : 4623)
39 #pragma warning(disable : 4625)
40 #pragma warning(disable : 4626)
41 #pragma warning(disable : 4820)
42 #pragma warning(disable : 5267)
43 #pragma warning(disable : 5026)
44 #pragma warning(disable : 5027)
45 #pragma warning(disable : 5045)
46 #pragma warning(disable : 5246)
47#endif
48
49#if defined(__clang__) && defined(NDEBUG) && !defined(DCA_INLINE)
50 #define DCA_INLINE inline __attribute__((always_inline))
51#elif !defined(DCA_INLINE)
52 #define DCA_INLINE inline
53#endif
54
55#if !defined(DCA_CPU_INSTRUCTIONS)
56 #define DCA_CPU_INSTRUCTIONS 0
57#endif
58
59#if !defined(DCA_CHECK_FOR_INSTRUCTION)
60 #define DCA_CHECK_FOR_INSTRUCTION(x) (DCA_CPU_INSTRUCTIONS & x)
61#endif
62
63#if !defined(DCA_CHECK_FOR_AVX)
64 #define DCA_CHECK_FOR_AVX(x) (DCA_CPU_INSTRUCTIONS >= x)
65#endif
66
67#if !defined(DCA_NEON)
68 #define DCA_NEON (1 << 4)
69#endif
70#if !defined(DCA_AVX)
71 #define DCA_AVX (1 << 5)
72#endif
73#if !defined(DCA_AVX2)
74 #define DCA_AVX2 (1 << 6)
75#endif
76#if !defined(DCA_AVX512)
77 #define DCA_AVX512 (1 << 7)
78#endif
79
80#if defined _WIN32
81 #if !defined DiscordCoreAPI_EXPORTS_NOPE
82 #if defined DiscordCoreAPI_EXPORTS
83 #if !defined DiscordCoreAPI_Dll
84 #define DiscordCoreAPI_Dll __declspec(dllexport)
85 #endif
86 #else
87 #if !defined DiscordCoreAPI_Dll
88 #define DiscordCoreAPI_Dll __declspec(dllimport)
89 #endif
90 #endif
91 #else
92 #define DiscordCoreAPI_Dll
93 #endif
94 #if !defined WIN32_LEAN_AND_MEAN
95 #define WIN32_LEAN_AND_MEAN
96 #endif
97 #if !defined WINRT_LEAN_AND_MEAN
98 #define WINRT_LEAN_AND_MEAN
99 #endif
100 #if !defined(NOMINMAX)
101 #define NOMINMAX
102 #endif
103 #include <chrono>
104DCA_INLINE tm getTime(time_t time) {
105 tm timeNew{};
106 gmtime_s(&timeNew, &time);
107 return timeNew;
108}
109 #include <WinSock2.h>
110#else
111 #if !defined DiscordCoreAPI_Dll
112 #define DiscordCoreAPI_Dll
113 #endif
114 #include <arpa/inet.h>
115 #include <sys/time.h>
116 #include <pthread.h>
117 #include <cstdint>
118 #include <cstring>
119 #include <time.h>
120 #include <ctime>
121DCA_INLINE tm getTime(time_t time) {
122 return *gmtime(&time);
123}
124#endif
125
126#include <jsonifier/Index.hpp>
127
128#include <source_location>
129#include <shared_mutex>
130#include <immintrin.h>
131#include <functional>
132#include <semaphore>
133#include <concepts>
134#include <iostream>
135#include <sstream>
136#include <iomanip>
137#include <vector>
138#include <atomic>
139#include <random>
140#include <string>
141#include <thread>
142#include <mutex>
143#include <queue>
144#include <array>
145
146using namespace std::literals;
147
148/**
149 * \defgroup main_endpoints Main Endpoints
150/// @brief For all of the discord api's endpoints.
151 */
152
153/**
154 * \defgroup voice_connection Voice Connection
155/// @brief For all of the voice connection related stuff.
156 */
157
158/**
159 * \defgroup discord_events Discord Events
160/// @brief For all of the events that could be sent by the discord api.
161 */
162
163/**
164 * \defgroup utilities Utilities
165/// @brief For utility classes/functions.
166 */
167
168/**
169 * \defgroup foundation_entities Foundation Entities
170/// @brief For all of the building blocks of the main endpoints.
171 */
172
173/**
174 * \defgroup discord_events Discord Events
175/// @brief For all of events that could be sent by discord's websockets.
176 */
177
178/**
179 * \defgroup discord_core_internal DiscordCoreInternal
180/// @brief For all of the internal api stuff.
181 */
182
183/**
184 * @brief The main namespace for the forward-facing interfaces.
185 *
186 * \ingroup discord_core_api
187 */
188
189namespace discord_core_api {
190
191 DCA_INLINE thread_local jsonifier::jsonifier_core<false> parser{};
192
193 template<typename value_type> using stop_watch = jsonifier_internal::stop_watch<value_type>;
194 using sys_clock = std::chrono::system_clock;
195 using hrclock = std::chrono::high_resolution_clock;
196 using milliseconds = std::chrono::duration<int64_t, std::milli>;
197 using microseconds = std::chrono::duration<int64_t, std::micro>;
198 using nanoseconds = std::chrono::duration<int64_t, std::nano>;
199 using seconds = std::chrono::duration<int64_t, std::ratio<1, 1>>;
200
201 enum class print_message_type {
202 general = 0,
203 https = 1,
204 websocket = 2,
205 };
206
207 constexpr jsonifier::string_view shiftToBrightGreen() {
208 return "\033[1;40;92m";
209 }
210
211 constexpr jsonifier::string_view shiftToBrightBlue() {
212 return "\033[1;40;96m";
213 }
214
215 constexpr jsonifier::string_view shiftToBrightRed() {
216 return "\033[1;40;91m";
217 }
218
219 constexpr jsonifier::string_view reset() {
220 return "\033[0m";
221 }
222
223 /**
224 * \addtogroup utilities
225 * @{
226 */
227
228 /// @brief Class for printing different types of messages to output and error streams.
230 public:
231 DCA_INLINE message_printer() = default;
232
233 /// @brief Initialize the message_printer with configuration settings and output/error streams.
234 /// @tparam value_type the type containing configuration settings.
235 /// @param other an instance of value_type with configuration settings.
236 template<typename value_type> DCA_INLINE static void initialize(const value_type& other) {
237 doWePrintGeneralErrors.store(other.doWePrintGeneralErrorMessages(), std::memory_order_release);
238 doWePrintGeneralSuccesses.store(other.doWePrintGeneralSuccessMessages(), std::memory_order_release);
239 doWePrintHttpsErrors.store(other.doWePrintHttpsErrorMessages(), std::memory_order_release);
240 doWePrintHttpsSuccesses.store(other.doWePrintHttpsSuccessMessages(), std::memory_order_release);
241 doWePrintWebSocketErrors.store(other.doWePrintWebSocketErrorMessages(), std::memory_order_release);
242 doWePrintWebSocketSuccesses.store(other.doWePrintWebSocketSuccessMessages(), std::memory_order_release);
243 outputStream = other.getOutputStream();
244 errorStream = other.getErrorStream();
245 }
246
247 /// @brief Print an error message of the specified type.
248 /// @tparam messageType the type of message to print.
249 /// @param what the error message.
250 /// @param where the source location where the error occurred (default: current source location).
251 template<print_message_type messageType, typename string_type>
252 DCA_INLINE static void printError(const string_type& what, std::source_location where = std::source_location::current()) {
253 switch (messageType) {
254 case print_message_type::general: {
255 if (doWePrintGeneralErrors.load(std::memory_order_acquire)) {
256 std::unique_lock lock{ accessMutex };
257 *errorStream << shiftToBrightRed() << "General error, caught at: " << where.file_name() << ", " << where.line() << ":" << where.column()
258 << ", in: " << where.function_name() << ", it is: " << what << std::endl
259 << reset() << std::endl;
260 }
261 break;
262 }
263 case print_message_type::websocket: {
264 if (doWePrintWebSocketErrors.load(std::memory_order_acquire)) {
265 std::unique_lock lock{ accessMutex };
266 *errorStream << shiftToBrightRed() << "WebSocket error, caught at: " << where.file_name() << ", " << where.line() << ":" << where.column()
267 << ", in: " << where.function_name() << ", it is: " << what << std::endl
268 << reset() << std::endl;
269 }
270 break;
271 }
272 case print_message_type::https: {
273 if (doWePrintHttpsErrors.load(std::memory_order_acquire)) {
274 std::unique_lock lock{ accessMutex };
275 *errorStream << shiftToBrightRed() << "Https error, caught at: " << where.file_name() << ", " << where.line() << ":" << where.column()
276 << ", in: " << where.function_name() << ", it is: " << what << std::endl
277 << reset() << std::endl;
278 }
279 break;
280 }
281 }
282 }
283
284 /// @brief Print a success message of the specified type.
285 /// @tparam messageType the type of message to print.
286 /// @param what the success message.
287 /// @param where the source location where the success occurred (default: current source location).
288 template<print_message_type messageType, typename string_type>
289 DCA_INLINE static void printSuccess(const string_type& what, std::source_location where = std::source_location::current()) {
290 switch (messageType) {
291 case print_message_type::general: {
292 if (doWePrintGeneralSuccesses.load(std::memory_order_acquire)) {
293 std::unique_lock lock{ accessMutex };
294 *outputStream << shiftToBrightBlue() << "General success, caught at: " << where.file_name() << ", " << where.line() << ":" << where.column()
295 << ", in: " << where.function_name() << ", it is: " << what << std::endl
296 << reset() << std::endl;
297 }
298 break;
299 }
300 case print_message_type::websocket: {
301 if (doWePrintWebSocketSuccesses.load(std::memory_order_acquire)) {
302 std::unique_lock lock{ accessMutex };
303 *outputStream << shiftToBrightGreen() << "WebSocket success, caught at: " << where.file_name() << ", " << where.line() << ":" << where.column()
304 << ", in: " << where.function_name() << ", it is: " << what << std::endl
305 << reset() << std::endl;
306 }
307 break;
308 }
309 case print_message_type::https: {
310 if (doWePrintHttpsSuccesses.load(std::memory_order_acquire)) {
311 std::unique_lock lock{ accessMutex };
312 *outputStream << shiftToBrightGreen() << "Https success, caught at: " << where.file_name() << ", " << where.line() << ":" << where.column()
313 << ", in: " << where.function_name() << ", it is: " << what << std::endl
314 << reset() << std::endl;
315 }
316 break;
317 }
318 }
319 }
320
321 protected:
322 DCA_INLINE static std::atomic_bool doWePrintWebSocketSuccesses{};///< Flag to control printing of websocket success messages.
323 DCA_INLINE static std::atomic_bool doWePrintGeneralSuccesses{};///< Flag to control printing of general success messages.
324 DCA_INLINE static std::atomic_bool doWePrintWebSocketErrors{};///< Flag to control printing of websocket error messages.
325 DCA_INLINE static std::atomic_bool doWePrintHttpsSuccesses{};///< Flag to control printing of https success messages.
326 DCA_INLINE static std::atomic_bool doWePrintGeneralErrors{};///< Flag to control printing of general error messages.
327 DCA_INLINE static std::atomic_bool doWePrintHttpsErrors{};///< Flag to control printing of https error messages.
328 DCA_INLINE static std::ostream* outputStream{};///< Pointer to the output stream for message printing.
329 DCA_INLINE static std::ostream* errorStream{};///< Pointer to the error stream for message printing.
330 DCA_INLINE static std::mutex accessMutex{};///< Mutex for thread-safe access to shared resources.
331 };
332
333 /// @brief Time formatting methods.
334 enum class time_format : char {
335 long_date = 'D',///< "20 April 2021" - Long Date
336 long_date_time = 'F',///< "Tuesday, 20 April 2021 16:20" - Long Date/Time
337 long_time = 'T',///< "16:20:30" - Long Time
338 short_date = 'd',///< "20/04/2021" - Short Date
339 short_date_time = 'f',///< "20 April 2021 16:20" - Short Date/Time
340 short_time = 't',///< "16:20" - Short Time
341 };
342
343 class time_stamp;
344
345 /// @brief A base class for handling time stamps and conversions.
346 /// @tparam value_type the value type to be used with the time stamp.
347 template<typename value_type> class time_stamp_base {
348 public:
349 static constexpr uint64_t msPerSecond{ 1000ULL };
350 static constexpr uint64_t secondsPerMinute{ 60ULL };
351 static constexpr uint64_t minutesPerHour{ 60ULL };
352 static constexpr uint64_t msPerMinute{ msPerSecond * secondsPerMinute };
353 static constexpr uint64_t msPerHour{ msPerMinute * minutesPerHour };
354 static constexpr uint64_t secondsPerHour{ minutesPerHour * secondsPerMinute };
355 static constexpr uint64_t hoursPerDay{ 24ULL };
356 static constexpr uint64_t secondsPerDay{ secondsPerHour * hoursPerDay };
357 static constexpr uint64_t daysPerMonth{ 30ULL };
358 static constexpr uint64_t secondsPerMonth{ secondsPerDay * daysPerMonth };
359 static constexpr uint64_t daysPerYear{ 365ULL };
360 static constexpr uint64_t secondsPerYear{ secondsPerDay * daysPerYear };
361 /// @brief Checks if the time stamp is equal to a string representation.
362 /// @param other the string to compare with.
363 /// @return true if equal, false otherwise.
364 DCA_INLINE bool operator==(jsonifier::string_view other) const {
365 return static_cast<jsonifier::string>(*static_cast<const value_type*>(this)) == other;
366 }
367
368 /// @brief Converts given time values into a future iso8601 time stamp.
369 /// @param minutesToAdd number of minutes to add.
370 /// @param hoursToAdd number of hours to add.
371 /// @param daysToAdd number of days to add.
372 /// @param monthsToAdd number of months to add.
373 /// @param yearsToAdd number of years to add.
374 /// @param timeFormat format for the resulting time stamp.
375 /// @return iso8601 time stamp string.
376 DCA_INLINE static jsonifier::string convertToFutureISO8601TimeStamp(uint64_t minutesToAdd, uint64_t hoursToAdd, uint64_t daysToAdd, uint64_t monthsToAdd, uint64_t yearsToAdd,
377 time_format timeFormat) {
378 std::time_t result = std::time(nullptr);
379 uint64_t secondsToAdd = (yearsToAdd * secondsPerYear) + (monthsToAdd * secondsPerMonth) + (daysToAdd * secondsPerDay) + ((hoursToAdd + 8) * secondsPerHour) +
380 (minutesToAdd * secondsPerMinute);
381 result += secondsToAdd;
382 std::tm resultTwo{ getTime(result) };
383 jsonifier::string returnString{};
384 if (resultTwo.tm_isdst) {
385 if (resultTwo.tm_hour + 4ULL >= 24) {
386 resultTwo.tm_hour = resultTwo.tm_hour - 24;
387 ++resultTwo.tm_mday;
388 }
389 auto newValue =
390 getMsSinceEpoch(static_cast<uint64_t>(resultTwo.tm_year) + 1900ULL, static_cast<uint64_t>(resultTwo.tm_mon) + 1ULL, static_cast<uint64_t>(resultTwo.tm_mday),
391 static_cast<uint64_t>(resultTwo.tm_hour) + 4ULL, static_cast<uint64_t>(resultTwo.tm_min), static_cast<uint64_t>(resultTwo.tm_sec));
392 returnString = getISO8601TimeStamp(timeFormat, newValue);
393 } else {
394 if (resultTwo.tm_hour + 5ULL >= 24) {
395 resultTwo.tm_hour = resultTwo.tm_hour - 24;
396 ++resultTwo.tm_mday;
397 }
398 auto newValue =
399 getMsSinceEpoch(static_cast<uint64_t>(resultTwo.tm_year) + 1900ULL, static_cast<uint64_t>(resultTwo.tm_mon) + 1ULL, static_cast<uint64_t>(resultTwo.tm_mday),
400 static_cast<uint64_t>(resultTwo.tm_hour) + 5ULL, static_cast<uint64_t>(resultTwo.tm_min), static_cast<uint64_t>(resultTwo.tm_sec));
401 returnString = getISO8601TimeStamp(timeFormat, newValue);
402 }
403 return returnString;
404 }
405
406 /// @brief Converts the current time into an iso8601 time stamp.
407 /// @param timeFormat format for the resulting time stamp.
408 /// @return iso8601 time stamp string.
409 DCA_INLINE static jsonifier::string convertToCurrentISO8601TimeStamp(time_format timeFormat) {
410 std::time_t result = std::time(nullptr);
411 std::tm resultTwo{ getTime(result) };
412 jsonifier::string returnString{};
413 if (resultTwo.tm_isdst) {
414 if (resultTwo.tm_hour + 4ULL >= 24) {
415 resultTwo.tm_hour = resultTwo.tm_hour - 24;
416 ++resultTwo.tm_mday;
417 }
418 auto newValue =
419 getMsSinceEpoch(static_cast<uint64_t>(resultTwo.tm_year) + 1900ULL, static_cast<uint64_t>(resultTwo.tm_mon) + 1ULL, static_cast<uint64_t>(resultTwo.tm_mday),
420 static_cast<uint64_t>(resultTwo.tm_hour) + 4ULL, static_cast<uint64_t>(resultTwo.tm_min), static_cast<uint64_t>(resultTwo.tm_sec));
421 returnString = getISO8601TimeStamp(timeFormat, newValue);
422 } else {
423 if (resultTwo.tm_hour + 5ULL >= 24) {
424 resultTwo.tm_hour = resultTwo.tm_hour - 24;
425 ++resultTwo.tm_mday;
426 }
427 auto newValue =
428 getMsSinceEpoch(static_cast<uint64_t>(resultTwo.tm_year) + 1900ULL, static_cast<uint64_t>(resultTwo.tm_mon) + 1ULL, static_cast<uint64_t>(resultTwo.tm_mday),
429 static_cast<uint64_t>(resultTwo.tm_hour) + 5ULL, static_cast<uint64_t>(resultTwo.tm_min), static_cast<uint64_t>(resultTwo.tm_sec));
430 returnString = getISO8601TimeStamp(timeFormat, newValue);
431 }
432 return returnString;
433 }
434
435 /// @brief Checks if a certain time duration has elapsed.
436 /// @param days number of days for elapsed time.
437 /// @param hours number of hours for elapsed time.
438 /// @param minutes number of minutes for elapsed time.
439 /// @return true if the specified time has elapsed, otherwise false.
440 DCA_INLINE bool hasTimeElapsed(int64_t days, int64_t hours, int64_t minutes) const {
441 int64_t startTimeRaw{ static_cast<int64_t>(convertTimeStampToTimeUnits(static_cast<jsonifier::string>(*static_cast<const value_type*>(this)))) };
442 startTimeRaw = std::chrono::local_time<std::chrono::milliseconds>(std::chrono::milliseconds{ startTimeRaw }).time_since_epoch().count();
443 auto currentTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
444 auto targetElapsedTime =
445 ((static_cast<int64_t>(days) * secondsPerDay) + ((static_cast<int64_t>(hours)) * secondsPerHour) + (static_cast<int64_t>(minutes) * secondsPerMinute)) * 1000LL;
446 auto actualElapsedTime = currentTime - startTimeRaw;
447 if (actualElapsedTime <= 0) {
448 return false;
449 }
450 if (actualElapsedTime >= targetElapsedTime) {
451 return true;
452 } else {
453 return false;
454 }
455 }
456
457 /// @brief Converts milliseconds into a human-readable duration string.
458 /// @param durationInMs duration in milliseconds to convert.
459 /// @return human-readable duration string.
460 DCA_INLINE static jsonifier::string convertMsToDurationString(uint64_t durationInMs) {
461 jsonifier::string newString{};
462 uint64_t hoursLeft = static_cast<uint64_t>(trunc(durationInMs / msPerHour));
463 uint64_t minutesLeft = static_cast<uint64_t>(trunc((durationInMs % msPerHour) / msPerMinute));
464 uint64_t secondsLeft = static_cast<uint64_t>(trunc(((durationInMs % msPerHour) % msPerMinute) / msPerSecond));
465 if (hoursLeft >= 1) {
466 newString += jsonifier::toString(hoursLeft) + " hours, ";
467 newString += jsonifier::toString(minutesLeft) + " minutes, ";
468 newString += jsonifier::toString(secondsLeft) + " seconds.";
469 } else if (minutesLeft >= 1) {
470 newString += jsonifier::toString(minutesLeft) + " minutes, ";
471 newString += jsonifier::toString(secondsLeft) + " seconds.";
472 } else {
473 newString += jsonifier::toString(secondsLeft) + " seconds.";
474 }
475 return newString;
476 }
477
478 /// @brief Gets an iso8601 time stamp string based on the provided time format.
479 /// @param timeFormat format for the resulting time stamp.
480 /// @param inputTime input time value.
481 /// @return iso8601 time stamp string.
482 DCA_INLINE static jsonifier::string getISO8601TimeStamp(time_format timeFormat, uint64_t inputTime) {
483 uint64_t timeValue = static_cast<uint64_t>(inputTime) / 1000ULL;
484 time_t rawTime(static_cast<time_t>(timeValue));
485 std::tm resultTwo{ getTime(rawTime) };
486 jsonifier::string timeStamp{};
487 timeStamp.resize(48);
488 switch (timeFormat) {
490 uint64_t sizeResponse = strftime(timeStamp.data(), 48, "%d %B %G", &resultTwo);
491 timeStamp.resize(sizeResponse);
492 break;
493 }
495 uint64_t sizeResponse = strftime(timeStamp.data(), 48, "%FT%T", &resultTwo);
496 timeStamp.resize(sizeResponse);
497 break;
498 }
500 uint64_t sizeResponse = strftime(timeStamp.data(), 48, "%T", &resultTwo);
501 timeStamp.resize(sizeResponse);
502 break;
503 }
505 uint64_t sizeResponse = strftime(timeStamp.data(), 48, "%d/%m/%g", &resultTwo);
506 timeStamp.resize(sizeResponse);
507 break;
508 }
510 uint64_t sizeResponse = strftime(timeStamp.data(), 48, "%d %B %G %R", &resultTwo);
511 timeStamp.resize(sizeResponse);
512 break;
513 }
515 uint64_t sizeResponse = strftime(timeStamp.data(), 48, "%R", &resultTwo);
516 timeStamp.resize(sizeResponse);
517 break;
518 }
519 default: {
520 break;
521 }
522 }
523 return timeStamp;
524 }
525
526 /// @brief Gets the time since the unix epoch for the specified date and time.
527 /// @param year year.
528 /// @param month month.
529 /// @param day day.
530 /// @param hour hour.
531 /// @param minute minute.
532 /// @param second second.
533 /// @return time since unix epoch in milliseconds.
534 DCA_INLINE static uint64_t getMsSinceEpoch(uint64_t year, uint64_t month, uint64_t day, uint64_t hour, uint64_t minute, uint64_t second) {
535 static constexpr uint64_t secondsInJan{ 31ULL * secondsPerDay };
536 static constexpr uint64_t secondsInFeb{ 28ULL * secondsPerDay };
537 static constexpr uint64_t secondsInMar{ 31ULL * secondsPerDay };
538 static constexpr uint64_t secondsInApr{ 30ULL * secondsPerDay };
539 static constexpr uint64_t secondsInMay{ 31ULL * secondsPerDay };
540 static constexpr uint64_t secondsInJun{ 30ULL * secondsPerDay };
541 static constexpr uint64_t secondsInJul{ 31ULL * secondsPerDay };
542 static constexpr uint64_t secondsInAug{ 31ULL * secondsPerDay };
543 static constexpr uint64_t secondsInSep{ 30ULL * secondsPerDay };
544 static constexpr uint64_t secondsInOct{ 31ULL * secondsPerDay };
545 static constexpr uint64_t secondsInNov{ 30ULL * secondsPerDay };
546 static constexpr uint64_t secondsInDec{ 31ULL * secondsPerDay };
547 seconds value{};
548 for (uint64_t x = 1970ULL; x < year; ++x) {
549 value += seconds{ secondsInJan };
550 value += seconds{ secondsInFeb };
551 value += seconds{ secondsInMar };
552 value += seconds{ secondsInApr };
553 value += seconds{ secondsInMay };
554 value += seconds{ secondsInJun };
555 value += seconds{ secondsInJul };
556 value += seconds{ secondsInAug };
557 value += seconds{ secondsInSep };
558 value += seconds{ secondsInOct };
559 value += seconds{ secondsInNov };
560 value += seconds{ secondsInDec };
561 if (x % 4ULL == 0ULL) {
562 value += seconds{ secondsPerDay };
563 }
564 }
565 if (month > 0) {
566 value += seconds{ static_cast<uint64_t>((day - 1ULL) * secondsPerDay) };
567 value += seconds{ static_cast<uint64_t>(hour * secondsPerHour) };
568 value += seconds{ static_cast<uint64_t>(minute * secondsPerMinute) };
569 value += seconds{ second };
570 }
571 if (month > 1ULL) {
572 value += seconds{ secondsInJan };
573 }
574 if (month > 2ULL) {
575 value += seconds{ secondsInFeb };
576 }
577 if (month > 3ULL) {
578 value += seconds{ secondsInMar };
579 }
580 if (month > 4ULL) {
581 value += seconds{ secondsInApr };
582 }
583 if (month > 5ULL) {
584 value += seconds{ secondsInMay };
585 }
586 if (month > 6ULL) {
587 value += seconds{ secondsInJun };
588 }
589 if (month > 7ULL) {
590 value += seconds{ secondsInJul };
591 }
592 if (month > 8ULL) {
593 value += seconds{ secondsInAug };
594 }
595 if (month > 9ULL) {
596 value += seconds{ secondsInSep };
597 }
598 if (month > 10ULL) {
599 value += seconds{ secondsInOct };
600 }
601 if (month > 11ULL) {
602 value += seconds{ secondsInNov };
603 }
604 return static_cast<uint64_t>(std::chrono::duration_cast<milliseconds>(value).count());
605 }
606
607 protected:
608 /// @brief Converts a string time stamp into a uint64_t time value.
609 /// @param originalTimeStamp original time stamp string.
610 /// @return converted time value in milliseconds.
611 DCA_INLINE static uint64_t convertTimeStampToTimeUnits(jsonifier::string_view originalTimeStamp) {
612 if (originalTimeStamp != "" && originalTimeStamp.size() >= 19) {
613 auto newValue =
614 getMsSinceEpoch(jsonifier::strToUint64(originalTimeStamp.substr(0ULL, 4ULL).data()), jsonifier::strToUint64(originalTimeStamp.substr(5ULL, 6ULL).data()),
615 jsonifier::strToUint64(originalTimeStamp.substr(8ULL, 9ULL).data()), jsonifier::strToUint64(originalTimeStamp.substr(11ULL, 12ULL).data()),
616 jsonifier::strToUint64(originalTimeStamp.substr(14ULL, 15ULL).data()), jsonifier::strToUint64(originalTimeStamp.substr(17ULL, 18ULL).data()));
617 return newValue;
618 } else {
619 return static_cast<uint64_t>(std::chrono::duration_cast<milliseconds>(sys_clock::now().time_since_epoch()).count());
620 }
621 }
622
623 /// @brief Converts a string time stamp into a uint64_t time value.
624 /// @param stringTimeStamp string time stamp to convert.
625 /// @return converted time value in milliseconds.
626 DCA_INLINE uint64_t convertStringToUintTimeStamp(jsonifier::string_view stringTimeStamp) const {
627 return convertTimeStampToTimeUnits(stringTimeStamp);
628 }
629
630 /// @brief Converts a uint64_t time value into a string time stamp.
631 /// @param uintTimeStamp time value to convert.
632 /// @return string time stamp.
633 DCA_INLINE jsonifier::string convertUintToStringTimeStamp(uint64_t uintTimeStamp) const {
635 }
636 };
637
638 /// @brief A class that extends time_stamp_base to provide additional functionality.
639 class time_stamp : public time_stamp_base<time_stamp> {
640 public:
641 template<typename value_type> friend class time_stamp_base;
642
643 /// @brief Default constructor for time_stamp.
644 DCA_INLINE time_stamp() = default;
645
646 /// @brief Move assignment operator to move a string value into time_stamp.
647 /// @param valueNew the string value to move.
648 /// @return reference to the modified time_stamp instance.
649 DCA_INLINE time_stamp& operator=(jsonifier::string_view valueNew) {
651 return *this;
652 }
653
654 /// @brief Move constructor to create a time_stamp instance by moving a string value.
655 /// @param valueNew the string value to move.
656 DCA_INLINE time_stamp(jsonifier::string_view valueNew) {
657 *this = valueNew;
658 }
659
660 /// @brief Assignment operator to assign a uint64_t value to time_stamp.
661 /// @param valueNew the new uint64_t value to assign.
662 /// @return reference to the modified time_stamp instance.
663 DCA_INLINE time_stamp& operator=(uint64_t valueNew) {
664 value = valueNew;
665 return *this;
666 }
667
668 /// @brief Constructor to create a time_stamp instance from a uint64_t value.
669 /// @param valueNew the uint64_t value to create the instance from.
670 DCA_INLINE time_stamp(uint64_t valueNew) {
671 *this = valueNew;
672 }
673
674 /// @brief Conversion operator to convert time_stamp to int64_t.
675 /// @return the int64_t value represented by the time_stamp instance.
676 DCA_INLINE operator uint64_t() const {
677 return value;
678 }
679
680 /// @brief Conversion operator to convert time_stamp to jsonifier::string.
681 /// @return the jsonifier::string value represented by the time_stamp instance.
682 DCA_INLINE operator jsonifier::string() const {
684 }
685
686 protected:
687 uint64_t value{};///< The value stored in the time_stamp instance.
688 };
689
690 class snowflake;
691
692 /// @brief A class for converting snowflake id's into the data structures they represent.
693 /// @tparam value_type The type of value being acquired.
694 template<typename value_type = void> class to_entity {
695 DCA_INLINE static value_type toEntity(snowflake initialId, snowflake additionalId);
696
697 DCA_INLINE static value_type toEntity(snowflake initialId);
698 };
699
700 /// @brief A class representing a snowflake identifier with various operations.
701 class snowflake {
702 public:
703 /// @brief Default constructor for snowflake.
704 DCA_INLINE snowflake() = default;
705
706 /// @brief A class for converting snowflake id's into the data structures they represent.
707 /// @tparam value_type The type of value being acquired.
708 /// @return value_type If successful, the intended data structure.
709 template<typename value_type> DCA_INLINE value_type toEntity() {
710 return to_entity<value_type>{}.toEntity(*this);
711 }
712
713 /// @brief A class for converting snowflake id's into the data structures they represent.
714 /// @param additionalId For certain classes, a second Id for collecting the data structure.
715 /// @tparam value_type The type of value being acquired.
716 /// @return value_type If successful, the intended data structure.
717 template<typename value_type> DCA_INLINE value_type toEntity(snowflake additionalId) {
718 return to_entity<value_type>{}.toEntity(*this, additionalId);
719 }
720
721 /// @brief Assignment operator to assign a string value to snowflake.
722 /// @param other the string value to assign.
723 /// @return reference to the modified snowflake instance.
724 DCA_INLINE snowflake& operator=(const jsonifier::string& other) {
725 if (other.size() > 0) {
726 for (auto& value: other) {
727 if (!std::isdigit(static_cast<uint8_t>(value))) {
728 return *this;
729 }
730 }
731 id = jsonifier::strToUint64(other);
732 }
733 return *this;
734 }
735
736 /// @brief Constructor to create a snowflake instance from a string value.
737 /// @param other the string value to create the instance from.
738 DCA_INLINE snowflake(const jsonifier::string& other) {
739 *this = other;
740 }
741
742 /// @brief Assignment operator to assign a uint64_t value to snowflake.
743 /// @param other the uint64_t value to assign.
744 /// @return reference to the modified snowflake instance.
745 DCA_INLINE snowflake& operator=(uint64_t other) {
746 id = other;
747 return *this;
748 }
749
750 /// @brief Constructor to create a snowflake instance from a uint64_t value.
751 /// @param other the uint64_t value to create the instance from.
752 DCA_INLINE snowflake(uint64_t other) {
753 *this = other;
754 }
755
756 /// @brief Conversion operator to convert snowflake to jsonifier::string.
757 /// @return the jsonifier::string value represented by the snowflake instance.
758 DCA_INLINE explicit operator jsonifier::string() const {
759 return jsonifier::toString(id);
760 }
761
762 /// @brief Explicit conversion operator to convert snowflake to uint64_t.
763 /// @return the uint64_t value represented by the snowflake instance.
764 DCA_INLINE explicit operator const uint64_t&() const {
765 return id;
766 }
767
768 DCA_INLINE bool operator==(const snowflake& other) const {
769 return id == other.id;
770 }
771
772 DCA_INLINE bool operator==(jsonifier::string_view other) const {
773 return operator jsonifier::string() == other;
774 }
775
776 DCA_INLINE bool operator==(uint64_t other) const {
777 return id == other;
778 }
779
780 /// @brief Concatenation operator to concatenate snowflake and a string value.
781 /// @tparam value_type the type of the string value.
782 /// @param rhs the string value to concatenate.
783 /// @return the concatenated string.
784 template<jsonifier::concepts::string_t value_type> DCA_INLINE jsonifier::string operator+(jsonifier::string_view rhs) const {
785 jsonifier::string newString{ operator jsonifier::string() };
786 newString += rhs;
787 return newString;
788 }
789
790 /// @brief Friend function to concatenate snowflake and a string value.
791 /// @param lhs the snowflake instance.
792 /// @param other the string value to concatenate.
793 /// @return the concatenated string.
794 DCA_INLINE friend jsonifier::string operator+(const snowflake& lhs, jsonifier::string_view other) {
795 jsonifier::string lhsNew{ static_cast<jsonifier::string>(lhs) };
796 lhsNew += other;
797 return lhsNew;
798 }
799
800 /// @brief Friend function to concatenate two values.
801 /// @tparam value_type01 the type of the first value.
802 /// @tparam value_type02 the type of the second value.
803 /// @param lhs the first value.
804 /// @param rhs the second value.
805 /// @return the concatenated string.
806 template<jsonifier::concepts::string_t value_type01, typename value_type02> friend DCA_INLINE jsonifier::string operator+(const value_type01& lhs, const value_type02& rhs) {
807 jsonifier::string newString{ lhs };
808 newString += rhs.operator jsonifier::string();
809 return newString;
810 }
811
812 /// @brief Friend function to concatenate two values.
813 /// @tparam value_type01 the type of the first value.
814 /// @tparam value_type02 the type of the second value.
815 /// @param lhs the first value.
816 /// @param rhs the second value.
817 /// @return the concatenated string.
818 template<uint64_t size> friend DCA_INLINE jsonifier::string operator+(const char (&lhs)[size], const snowflake& rhs) {
819 jsonifier::string newString{ lhs };
820 newString += rhs.operator jsonifier::string();
821 return newString;
822 }
823
824 /// @brief Converts the snowflake id into a time and date stamp.
825 /// @return a jsonifier::string containing the timestamp.
826 DCA_INLINE jsonifier::string getCreatedAtTimeStamp() {
827 uint64_t timeStamp{ static_cast<uint64_t>((id >> 22) + 1420070400000) };
829 }
830
831 protected:
832 uint64_t id{};///< The snowflake id.
833 };
834
835 DCA_INLINE std::ostream& operator<<(std::ostream& os, snowflake sf) {
836 os << sf.operator jsonifier::string();
837 return os;
838 }
839
840 /// @brief An exception class derived from std::runtime_error for dca-related exceptions.
841 struct dca_exception : public std::runtime_error {
842 /// @brief Constructor to create a dca_exception with an error message and optional source location.
843 /// @param error the error message.
844 /// @param location the source location of the exception (default: current location).
845 DCA_INLINE dca_exception(jsonifier::string_view error, std::source_location location = std::source_location::current()) : std::runtime_error{ "No error." } {
846 auto newError = jsonifier::string{ "Thrown from: " };
847 auto newString = location.file_name();
848 if (newString) {
849 newError += newString;
850 }
851 newError += jsonifier::string{ " (" } + jsonifier::toString(location.line()) + jsonifier::string{ ":" };
852 newError += jsonifier::toString(location.column()) + jsonifier::string{ ")\n" };
853 newError += error;
854 if (!newError.empty()) {
855 *static_cast<std::runtime_error*>(this) = std::runtime_error{ std::string{ newError } };
856 }
857 };
858 };
859
860 /**@}*/
861
862 /**
863 * \addtogroup voice_connection
864 * @{
865 */
866
867 /// @brief For selecting the type of streamer that the given bot is, one must be one server and one of client per connection.
868 enum class stream_type { none = 0, client = 1, server = 2 };
869
870 /**@}*/
871}
Class for printing different types of messages to output and error streams.
Definition Base.hpp:229
static DCA_INLINE std::atomic_bool doWePrintGeneralErrors
Flag to control printing of general error messages.
Definition Base.hpp:326
static DCA_INLINE std::mutex accessMutex
Mutex for thread-safe access to shared resources.
Definition Base.hpp:330
static DCA_INLINE std::atomic_bool doWePrintHttpsSuccesses
Flag to control printing of https success messages.
Definition Base.hpp:325
static DCA_INLINE std::atomic_bool doWePrintWebSocketErrors
Flag to control printing of websocket error messages.
Definition Base.hpp:324
static DCA_INLINE void printSuccess(const string_type &what, std::source_location where=std::source_location::current())
Print a success message of the specified type.
Definition Base.hpp:289
static DCA_INLINE std::atomic_bool doWePrintGeneralSuccesses
Flag to control printing of general success messages.
Definition Base.hpp:323
static DCA_INLINE std::ostream * errorStream
Pointer to the error stream for message printing.
Definition Base.hpp:329
static DCA_INLINE void printError(const string_type &what, std::source_location where=std::source_location::current())
Print an error message of the specified type.
Definition Base.hpp:252
static DCA_INLINE std::atomic_bool doWePrintHttpsErrors
Flag to control printing of https error messages.
Definition Base.hpp:327
static DCA_INLINE std::atomic_bool doWePrintWebSocketSuccesses
Flag to control printing of websocket success messages.
Definition Base.hpp:322
static DCA_INLINE std::ostream * outputStream
Pointer to the output stream for message printing.
Definition Base.hpp:328
static DCA_INLINE void initialize(const value_type &other)
Initialize the message_printer with configuration settings and output/error streams.
Definition Base.hpp:236
A class representing a snowflake identifier with various operations.
Definition Base.hpp:701
DCA_INLINE snowflake(uint64_t other)
Constructor to create a snowflake instance from a uint64_t value.
Definition Base.hpp:752
DCA_INLINE friend jsonifier::string operator+(const snowflake &lhs, jsonifier::string_view other)
Friend function to concatenate snowflake and a string value.
Definition Base.hpp:794
DCA_INLINE jsonifier::string operator+(jsonifier::string_view rhs) const
Concatenation operator to concatenate snowflake and a string value.
Definition Base.hpp:784
DCA_INLINE snowflake(const jsonifier::string &other)
Constructor to create a snowflake instance from a string value.
Definition Base.hpp:738
friend DCA_INLINE jsonifier::string operator+(const value_type01 &lhs, const value_type02 &rhs)
Friend function to concatenate two values.
Definition Base.hpp:806
DCA_INLINE snowflake & operator=(const jsonifier::string &other)
Assignment operator to assign a string value to snowflake.
Definition Base.hpp:724
friend DCA_INLINE jsonifier::string operator+(const char(&lhs)[size], const snowflake &rhs)
Friend function to concatenate two values.
Definition Base.hpp:818
DCA_INLINE snowflake & operator=(uint64_t other)
Assignment operator to assign a uint64_t value to snowflake.
Definition Base.hpp:745
DCA_INLINE snowflake()=default
Default constructor for snowflake.
uint64_t id
The snowflake id.
Definition Base.hpp:832
DCA_INLINE jsonifier::string getCreatedAtTimeStamp()
Converts the snowflake id into a time and date stamp.
Definition Base.hpp:826
DCA_INLINE value_type toEntity()
A class for converting snowflake id's into the data structures they represent.
Definition Base.hpp:709
DCA_INLINE value_type toEntity(snowflake additionalId)
A class for converting snowflake id's into the data structures they represent.
Definition Base.hpp:717
A base class for handling time stamps and conversions.
Definition Base.hpp:347
static DCA_INLINE jsonifier::string convertMsToDurationString(uint64_t durationInMs)
Converts milliseconds into a human-readable duration string.
Definition Base.hpp:460
static DCA_INLINE jsonifier::string convertToCurrentISO8601TimeStamp(time_format timeFormat)
Converts the current time into an iso8601 time stamp.
Definition Base.hpp:409
DCA_INLINE bool operator==(jsonifier::string_view other) const
Checks if the time stamp is equal to a string representation.
Definition Base.hpp:364
static DCA_INLINE uint64_t getMsSinceEpoch(uint64_t year, uint64_t month, uint64_t day, uint64_t hour, uint64_t minute, uint64_t second)
Gets the time since the unix epoch for the specified date and time.
Definition Base.hpp:534
static DCA_INLINE jsonifier::string convertToFutureISO8601TimeStamp(uint64_t minutesToAdd, uint64_t hoursToAdd, uint64_t daysToAdd, uint64_t monthsToAdd, uint64_t yearsToAdd, time_format timeFormat)
Converts given time values into a future iso8601 time stamp.
Definition Base.hpp:376
DCA_INLINE bool hasTimeElapsed(int64_t days, int64_t hours, int64_t minutes) const
Checks if a certain time duration has elapsed.
Definition Base.hpp:440
DCA_INLINE jsonifier::string convertUintToStringTimeStamp(uint64_t uintTimeStamp) const
Converts a uint64_t time value into a string time stamp.
Definition Base.hpp:633
static DCA_INLINE jsonifier::string getISO8601TimeStamp(time_format timeFormat, uint64_t inputTime)
Gets an iso8601 time stamp string based on the provided time format.
Definition Base.hpp:482
static DCA_INLINE uint64_t convertTimeStampToTimeUnits(jsonifier::string_view originalTimeStamp)
Converts a string time stamp into a uint64_t time value.
Definition Base.hpp:611
DCA_INLINE uint64_t convertStringToUintTimeStamp(jsonifier::string_view stringTimeStamp) const
Converts a string time stamp into a uint64_t time value.
Definition Base.hpp:626
A class that extends time_stamp_base to provide additional functionality.
Definition Base.hpp:639
DCA_INLINE time_stamp(uint64_t valueNew)
Constructor to create a time_stamp instance from a uint64_t value.
Definition Base.hpp:670
DCA_INLINE time_stamp & operator=(jsonifier::string_view valueNew)
Move assignment operator to move a string value into time_stamp.
Definition Base.hpp:649
uint64_t value
The value stored in the time_stamp instance.
Definition Base.hpp:687
DCA_INLINE time_stamp()=default
Default constructor for time_stamp.
DCA_INLINE time_stamp(jsonifier::string_view valueNew)
Move constructor to create a time_stamp instance by moving a string value.
Definition Base.hpp:656
DCA_INLINE time_stamp & operator=(uint64_t valueNew)
Assignment operator to assign a uint64_t value to time_stamp.
Definition Base.hpp:663
A class for converting snowflake id's into the data structures they represent.
Definition Base.hpp:694
time_format
Time formatting methods.
Definition Base.hpp:334
@ short_date_time
"20 April 2021 16:20" - Short Date/Time
Definition Base.hpp:339
@ short_time
"16:20" - Short Time
Definition Base.hpp:340
@ short_date
"20/04/2021" - Short Date
Definition Base.hpp:338
@ long_time
"16:20:30" - Long Time
Definition Base.hpp:337
@ long_date
"20 April 2021" - Long Date
Definition Base.hpp:335
@ long_date_time
"Tuesday, 20 April 2021 16:20" - Long Date/Time
Definition Base.hpp:336
stream_type
For selecting the type of streamer that the given bot is, one must be one server and one of client pe...
Definition Base.hpp:868
The main namespace for the forward-facing interfaces.
An exception class derived from std::runtime_error for dca-related exceptions.
Definition Base.hpp:841
DCA_INLINE dca_exception(jsonifier::string_view error, std::source_location location=std::source_location::current())
Constructor to create a dca_exception with an error message and optional source location.
Definition Base.hpp:845