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