discord-bot/libs/DPP-10.0.29/include/dpp/utility.h

1055 lines
31 KiB
C++

/************************************************************************************
*
* D++, A Lightweight C++ library for Discord
*
* SPDX-License-Identifier: Apache-2.0
* Copyright 2021 Craig Edwards and D++ contributors
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
************************************************************************************/
#pragma once
#include <dpp/export.h>
#include <dpp/snowflake.h>
#include <dpp/misc-enum.h>
#include <string>
#include <vector>
#include <unordered_map>
#include <map>
#include <functional>
#include <cstddef>
#include <variant>
#include <memory>
#include <string_view>
/**
* @brief The main namespace for D++ functions, classes and types
*/
namespace dpp {
enum sticker_format : uint8_t;
/**
* @brief Macro that expands to static_asserts checking sizeof and alignof are equal between two types.
*/
#define DPP_CHECK_ABI_COMPAT(a, b) \
static_assert(sizeof(a) == sizeof(b), #a " and " #b " must be the same size for ABI compatibility"); \
static_assert(alignof(a) == alignof(b), #a " and " #b " must be the same alignment for ABI compatibility"); \
/**
* @brief Utility helper functions, generally for logging, running programs, time/date manipulation, etc
*/
namespace utility {
/**
* @brief Helper function to easily create discord's cdn endpoint urls.
* @warning **For internal use only!**
*
* @see https://discord.com/developers/docs/reference#image-formatting-cdn-endpoints
* @param allowed_formats A vector of supported formats for the endpoint from the discord docs
* @param path_without_extension The path for the endpoint (without the extension e.g. `.png`)
* @param format the wished format to return. Must be one of the formats passed in `allowed_formats`, otherwise it returns an empty string
* @param size the image size which will be appended as a querystring to the url.
* It must be any power of two between 16 and 4096, otherwise no querystring will be appended (discord then returns the image as their default size)
* @param prefer_animated Whether the user prefers gif format. If true, it'll return gif format whenever the image is available as animated.
* In this case, the `format`-parameter is only used for non-animated images.
* @param is_animated Whether the image is actually animated or not
* @return std::string endpoint url or empty string
*/
std::string DPP_EXPORT cdn_endpoint_url(const std::vector<image_type> &allowed_formats, const std::string &path_without_extension, const dpp::image_type format, uint16_t size, bool prefer_animated = false, bool is_animated = false);
/**
* @brief Helper function to easily create discord's cdn endpoint urls.
* @warning **For internal use only!**
*
* @see https://discord.com/developers/docs/reference#image-formatting-cdn-endpoints
* @param allowed_formats A vector of supported formats for the endpoint from the discord docs
* @param path_without_extension The path for the endpoint (without the extension e.g. `.png`)
* @param hash The hash (optional). If not empty, it will be prefixed with `a_` for animated images (`is_animated`=true)
* @param format the wished format to return. Must be one of the formats passed in `allowed_formats`, otherwise it returns an empty string
* @param size the image size which will be appended as a querystring to the url.
* It must be any power of two between 16 and 4096, otherwise no querystring will be appended (discord then returns the image as their default size)
* @param prefer_animated Whether the user prefers gif format. If true, it'll return gif format whenever the image is available as animated.
* In this case, the `format`-parameter is only used for non-animated images.
* @param is_animated Whether the image is actually animated or not
* @return std::string endpoint url or empty string
*/
std::string DPP_EXPORT cdn_endpoint_url_hash(const std::vector<image_type> &allowed_formats, const std::string &path_without_extension, const std::string &hash, const dpp::image_type format, uint16_t size, bool prefer_animated = false, bool is_animated = false);
/**
* @brief Helper function to easily create discord's cdn endpoint urls (specialised for stickers)
* @warning **For internal use only!**
*
* @see https://discord.com/developers/docs/reference#image-formatting-cdn-endpoints
* @param sticker_id The sticker ID. Returns empty string if 0
* @param format The format type
* @return std::string endpoint url or empty string
*/
std::string DPP_EXPORT cdn_endpoint_url_sticker(snowflake sticker_id, sticker_format format);
/**
* @brief Supported AVX instruction set type for audio mixing
*/
enum avx_type_t : uint8_t {
/**
* @brief No AVX Support
*/
avx_none,
/**
* @brief AVX support
*/
avx_1,
/**
* @brief AVX2 support
*/
avx_2,
/**
* @brief AVX512 support
*/
avx_512,
};
/**
* @brief Timestamp formats for dpp::utility::timestamp()
*
* @note These values are the actual character values specified by the Discord API
* and should not be changed unless the Discord API changes the specification!
* They have been sorted into numerical order of their ASCII value to keep C++ happy.
*/
enum time_format : uint8_t {
/**
* @brief "20 April 2021" - Long Date
*/
tf_long_date = 'D',
/**
* @brief "Tuesday, 20 April 2021 16:20" - Long Date/Time
*/
tf_long_datetime = 'F',
/**
* @brief "2 months ago" - Relative Time
*/
tf_relative_time = 'R',
/**
* @brief "16:20:30" - Long Time
*/
tf_long_time = 'T',
/**
* @brief "20/04/2021" - Short Date
*/
tf_short_date = 'd',
/**
* @brief "20 April 2021 16:20" - Short Date/Time
*/
tf_short_datetime = 'f',
/**
* @brief "16:20" - Short Time
*/
tf_short_time = 't',
};
/**
* @brief Guild navigation types for dpp::utility::guild_navigation()
*/
enum guild_navigation_type {
/**
* @brief _Customize_ tab with the server's dpp::onboarding_prompt
*/
gnt_customize,
/**
* @brief "16:20" _Browse Channels_ tab
*/
gnt_browse,
/**
* @brief Server Guide
*/
gnt_guide,
};
/**
* @brief The base URL for CDN content such as profile pictures and guild icons.
*/
inline const std::string cdn_host = "https://cdn.discordapp.com";
/**
* @brief The base URL for message/user/channel links.
*/
inline const std::string url_host = "https://discord.com";
/**
* @brief Callback for the results of a command executed via dpp::utility::exec
*/
typedef std::function<void(const std::string& output)> cmd_result_t;
/**
* @brief Run a commandline program asynchronously. The command line program
* is spawned in a separate std::thread, and when complete, its output from
* stdout is passed to the callback function in its string parameter. For example:
* ```cpp
* dpp::utility::exec("/bin/ls", {"-al"}, [](const std::string& output) {
* std::cout << "Output of 'ls -al': " << output << "\n";
* });
* ```
*
* @param cmd The command to run.
* @param parameters Command line parameters. Each will be escaped using `std::quoted`.
* @param callback The callback to call on completion.
*/
void DPP_EXPORT exec(const std::string& cmd, std::vector<std::string> parameters = {}, cmd_result_t callback = {});
/**
* @brief Return a mentionable timestamp (used in a message). These timestamps will display the given timestamp in the user's timezone and locale.
*
* @param ts Time stamp to convert
* @param tf Format of timestamp using dpp::utility::time_format
* @return std::string The formatted timestamp
*/
std::string DPP_EXPORT timestamp(time_t ts, time_format tf = tf_short_datetime);
/**
* @brief Create a mentionable guild navigation (used in a message).
*
* @param guild_id The guild ID
* @param gnt Guild navigation type using dpp::utility::guild_navigation_type
* @return std::string The formatted timestamp
*/
std::string DPP_EXPORT guild_navigation(const snowflake guild_id, guild_navigation_type gnt);
/**
* @brief Returns current date and time
*
* @return std::string Current date and time in "Y-m-d H:M:S" format
*/
std::string DPP_EXPORT current_date_time();
/**
* @brief Convert a dpp::loglevel enum value to a string
*
* @param in log level to convert
* @return std::string string form of log level
*/
std::string DPP_EXPORT loglevel(dpp::loglevel in);
/**
* @brief Store a 128 bit icon hash (profile picture, server icon etc)
* as a 128 bit binary value made of two uint64_t.
* Has a constructor to build one from a string, and a method to fetch
* the value back in string form.
*/
struct DPP_EXPORT iconhash {
/**
* @brief High 64 bits.
*/
uint64_t first;
/**
* @brief Low 64 bits.
*/
uint64_t second;
/**
* @brief Construct a new iconhash object
* @param _first Leftmost portion of the hash value
* @param _second Rightmost portion of the hash value
*/
iconhash(uint64_t _first = 0, uint64_t _second = 0) noexcept;
/**
* @brief Construct a new iconhash object
*
* @param hash String hash to construct from.
* Must contain a 32 character hex string.
*
* @throws std::length_error if the provided
* string is not exactly 32 characters long.
*/
iconhash(const std::string &hash);
/**
* @brief Assign from std::string
*
* @param assignment string to assign from.
*
* @throws std::length_error if the provided
* string is not exactly 32 characters long.
*/
iconhash& operator=(const std::string &assignment);
/**
* @brief Check if one iconhash is equal to another
*
* @param other other iconhash to compare
* @return True if the iconhash objects match
*/
bool operator==(const iconhash& other) const noexcept;
/**
* @brief Change value of iconhash object
*
* @param hash String hash to change to.
* Must contain a 32 character hex string.
*
* @throws std::length_error if the provided
* string is not exactly 32 characters long.
*/
void set(const std::string &hash);
/**
* @brief Convert iconhash back to 32 character
* string value.
*
* @return std::string Hash value
*/
std::string to_string() const;
};
/**
* @brief Image to be received or sent to API calls.
*
* This class is carefully crafted to be 16 bytes,
* this is why we use a ptr + 4 byte size instead of a vector.
* We want this class to be substitutable with iconhash in data structures.
*/
struct DPP_EXPORT image_data {
/**
* @brief Data in bytes of the image.
*/
std::unique_ptr<std::byte[]> data = nullptr;
/**
* @brief Size of the data in bytes.
*/
uint32_t size = 0;
/**
* @brief Type of the image.
*
* @see image_type
*/
image_type type = {};
/**
* @brief Construct an empty image.
*/
image_data() = default;
/**
* @brief Copy an image.
*
* @param rhs Image to copy
*/
image_data(const image_data& rhs);
/**
* @brief Move an image.
*
* @param rhs Image to copy
*/
image_data(image_data&&) noexcept = default;
/**
* @brief Construct from string buffer
*
* @param format Image format
* @param str Data in a string
* @see image_type
*/
image_data(image_type format, std::string_view bytes);
/**
* @brief Construct from byte buffer
*
* @param format Image format
* @param buf Byte buffer
* @param size_t Image size in bytes
* @see image_type
*/
image_data(image_type format, const std::byte* bytes, uint32_t byte_size);
/**
* @brief Copy an image data.
*
* @param rhs Image to copy
* @return self for chaining
*/
image_data& operator=(const image_data& rhs);
/**
* @brief Move an image data.
*
* @param rhs Image to move from
* @return self for chaining
*/
image_data& operator=(image_data&& rhs) noexcept = default;
/**
* @brief Set image data.
*
* @param format Format of the image
* @param data Data of the image
*/
void set(image_type format, std::string_view bytes);
/**
* @brief Set image data.
*
* @param format Format of the image
* @param data Data of the image
*/
void set(image_type format, const std::byte* bytes, uint32_t byte_size);
/**
* @brief Encode to base64.
*
* @return std::string New string with the image data encoded in base64
*/
std::string base64_encode() const;
/**
* @brief Get the file extension.
*
* Alias for \ref file_extension
* @return std::string File extension e.g. `.png`
*/
std::string get_file_extension() const;
/**
* @brief Get the mime type.
*
* Alias for \ref mime_type
* @return std::string File mime type e.g. "image/png"
*/
std::string get_mime_type() const;
/**
* @brief Check if this is an empty image.
*
* @return bool Whether the image is empty or not
*/
bool empty() const noexcept;
/**
* @brief Build a data URI scheme suitable for sending to Discord
*
* @see https://discord.com/developers/docs/reference#image-data
* @return The data URI scheme as a json or null if empty
*/
json to_nullable_json() const;
};
/**
* @brief Wrapper class around a variant for either iconhash or image,
* for API objects that have one or the other (generally iconhash when receiving,
* image when uploading an image)
*/
struct icon {
/**
* @brief Iconhash received or image data for upload.
*/
std::variant<std::monostate, iconhash, image_data> hash_or_data;
/**
* @brief Assign to iconhash.
*
* @param hash Iconhash
*/
icon& operator=(const iconhash& hash);
/**
* @brief Assign to iconhash.
*
* @param hash Iconhash
*/
icon& operator=(iconhash&& hash) noexcept;
/**
* @brief Assign to image.
*
* @param img Image
*/
icon& operator=(const image_data& img);
/**
* @brief Assign to image.
*
* @param img Image
*/
icon& operator=(image_data&& img) noexcept;
/**
* @brief Check whether this icon is stored as an iconhash
*
* @see iconhash
* @return bool Whether this icon is stored as an iconhash
*/
bool is_iconhash() const;
/**
* @brief Get as icon hash.
*
* @warn The behavior is undefined if `is_iconhash() == false`
* @return iconhash& This iconhash
*/
iconhash& as_iconhash() &;
/**
* @brief Get as icon hash.
*
* @warn The behavior is undefined if `is_iconhash() == false`
* @return iconhash& This iconhash
*/
const iconhash& as_iconhash() const&;
/**
* @brief Get as icon hash.
*
* @warn The behavior is undefined if `is_iconhash() == false`
* @return iconhash& This iconhash
*/
iconhash&& as_iconhash() &&;
/**
* @brief Check whether this icon is stored as an image
*
* @see image_data
* @return bool Whether this icon is stored as an image
*/
bool is_image_data() const;
/**
* @brief Get as image data.
*
* @warn The behavior is undefined if `is_image_data() == false`
* @return image_data& This image
*/
image_data& as_image_data() &;
/**
* @brief Get as image.
*
* @warn The behavior is undefined if `is_image_data() == false`
* @return image_data& This image
*/
const image_data& as_image_data() const&;
/**
* @brief Get as image.
*
* @warn The behavior is undefined if `is_image_data() == false`
* @return image_data& This image
*/
image_data&& as_image_data() &&;
};
/**
* @brief Return the current time with fractions of seconds.
* This is a unix epoch time with the fractional seconds part
* after the decimal place.
*
* @return double time with fractional seconds
*/
double DPP_EXPORT time_f();
/**
* @brief Returns true if D++ was built with voice support
*
* @return bool True if voice support is compiled in (libsodium/libopus)
*/
bool DPP_EXPORT has_voice();
/**
* @brief Returns an enum value indicating which AVX instruction
* set is used for mixing received voice data, if any
*
* @return avx_type_t AVX type
*/
avx_type_t DPP_EXPORT voice_avx();
/**
* @brief Returns true if D++ was built with coroutine support
*
* @return bool True if coroutines are supported
*/
bool DPP_EXPORT is_coro_enabled();
/**
* @brief Convert a byte count to display value
*
* @param c number of bytes
* @return std::string display value suffixed with M, G, T where necessary
*/
std::string DPP_EXPORT bytes(uint64_t c);
/**
* @brief A class used to represent an uptime in hours, minutes,
* seconds and days, with helper functions to convert from time_t
* and display as a string.
*/
struct DPP_EXPORT uptime {
/**
* @brief Number of days.
*/
uint16_t days;
/**
* @brief Number of hours.
*/
uint8_t hours;
/**
* @brief Number of minutes.
*/
uint8_t mins;
/**
* @brief Number of seconds.
*/
uint8_t secs;
/**
* @brief Construct a new uptime object
*/
uptime();
/**
* @brief Construct a new uptime object
*
* @param diff A time_t to initialise the object from
*/
uptime(time_t diff);
/**
* @brief Construct a new uptime object
*
* @param diff A time_t to initialise the object from
*/
uptime(double diff);
/**
* @brief Get uptime as string
*
* @return std::string Uptime as string
*/
std::string to_string() const;
/**
* @brief Get uptime as seconds
*
* @return uint64_t Uptime as seconds
*/
uint64_t to_secs() const;
/**
* @brief Get uptime as milliseconds
*
* @return uint64_t Uptime as milliseconds
*/
uint64_t to_msecs() const;
};
/**
* @brief Convert doubles to RGB for sending in embeds
*
* @param red red value, between 0 and 1 inclusive
* @param green green value, between 0 and 1 inclusive
* @param blue blue value, between 0 and 1 inclusive
* @return uint32_t returned integer colour value
*/
uint32_t DPP_EXPORT rgb(double red, double green, double blue);
/**
* @brief Convert ints to RGB for sending in embeds
*
* @param red red value, between 0 and 255 inclusive
* @param green green value, between 0 and 255 inclusive
* @param blue blue value, between 0 and 255 inclusive
* @return uint32_t returned integer colour value
*/
uint32_t DPP_EXPORT rgb(int red, int green, int blue);
/**
* @brief Convert doubles to CMYK for sending in embeds
*
* @param c cyan value, between 0 and 1 inclusive
* @param m magenta value, between 0 and 1 inclusive
* @param y yellow value, between 0 and 1 inclusive
* @param k key (black) value, between 0 and 1 inclusive
* @return uint32_t returned integer colour value
*/
uint32_t DPP_EXPORT cmyk(double c, double m, double y, double k);
/**
* @brief Convert ints to CMYK for sending in embeds
*
* @param c cyan value, between 0 and 255 inclusive
* @param m magenta value, between 0 and 255 inclusive
* @param y yellow value, between 0 and 255 inclusive
* @param k key (black) value, between 0 and 255 inclusive
* @return uint32_t returned integer colour value
*/
uint32_t DPP_EXPORT cmyk(int c, int m, int y, int k);
/**
* @brief Convert doubles to HSL for sending in embeds
*
* @param h hue value, between 0 and 1 inclusive
* @param s saturation value in percentage, between 0 and 1 inclusive
* @param l lightness value in percentage, between 0 and 1 inclusive
* @return uint32_t returned integer colour value
*/
uint32_t DPP_EXPORT hsl(double h, double s, double l);
/**
* @brief Convert ints to HSL for sending in embeds
*
* @param h hue value, between 0 and 360 inclusive
* @param s saturation value in percentage, between 0 and 100 inclusive
* @param l lightness value in percentage, between 0 and 100 inclusive
* @return uint32_t returned integer colour value
*/
uint32_t DPP_EXPORT hsl(int h, int s, int l);
/**
* @brief Output hex values of a section of memory for debugging
*
* @param data The start of the data to display
* @param length The length of data to display
*/
std::string DPP_EXPORT debug_dump(uint8_t* data, size_t length);
/**
* @brief Returns the length of a UTF-8 string in codepoints
*
* @param str string to count length of
* @return size_t length of string (0 for invalid utf8)
*/
size_t DPP_EXPORT utf8len(const std::string &str);
/**
* @brief Return substring of a UTF-8 encoded string in codepoints
*
* @param str string to return substring from
* @param start start codepoint offset
* @param length length in codepoints
* @return std::string Substring in UTF-8 or empty string if invalid UTF-8 passed in
*/
std::string DPP_EXPORT utf8substr(const std::string& str, std::string::size_type start, std::string::size_type length);
/**
* @brief Read a whole file into a std::string.
* @note This function can take a while if this is a large file, causing events to not reply and also taking up a lot of memory. Make sure you have enough memory, and use dpp::interaction_create_t::thinking in events where you call this function on big files.
* @warning Be aware this function can block! If you are regularly reading large files, consider caching them.
* @param filename The path to the file to read
* @return std::string The file contents
* @throw dpp::file_exception on failure to read the entire file
*/
std::string DPP_EXPORT read_file(const std::string& filename);
/**
* @brief Validate a string value
* In the event the length of the string is less than _min, then an exception of type dpp:length_exception
* will be thrown. If the string is longer than _max UTF8 codepoints it will be truncated to fit.
*
* @param value The value to validate
* @param _min Minimum length
* @param _max Maximum length
* @param exception_message Exception message to throw if value length < _min
* @return std::string Validated string, truncated if necessary.
* @throw dpp::length_exception if value UTF8 length < _min
*/
std::string DPP_EXPORT validate(const std::string& value, size_t _min, size_t _max, const std::string& exception_message);
/**
* @brief Get the url query parameter for the cdn endpoint. Internally used to build url getters.
*
* @param size size to generate url parameter for. Must be any power of two between 16 and 4096 (inclusive) or it'll return an empty string.
* @return std::string url query parameter e.g. `?size=128`, or an empty string
*/
std::string DPP_EXPORT avatar_size(uint32_t size);
/**
* @brief Split (tokenize) a string into a vector, using the given separators
*
* @param in Input string
* @param sep Separator characters
* @return std::vector<std::string> Tokenized strings
*/
std::vector<std::string> DPP_EXPORT tokenize(std::string const &in, const char* sep = "\r\n");
/**
* @brief Create a bot invite
*
* @param bot_id Bot ID
* @param permissions Permission bitmask of the bot to invite
* @param scopes Scopes to use
* @return Invite URL
*/
std::string DPP_EXPORT bot_invite_url(const snowflake bot_id, const uint64_t permissions = 0, const std::vector<std::string>& scopes = {"bot", "applications.commands"});
/**
* @brief Escapes Discord's markdown sequences in a string
*
* @param text Text to escape
* @param escape_code_blocks If set to false, then code blocks are not escaped.
* This means that you can still use a code block, and the text within will be left as-is.
* If set to true, code blocks will also be escaped so that ` symbol may be used as a normal
* character.
* @return std::string The text with the markdown special characters escaped with a backslash
*/
std::string DPP_EXPORT markdown_escape(const std::string& text, bool escape_code_blocks = false);
/**
* @brief Encodes a url parameter similar to [php urlencode()](https://www.php.net/manual/en/function.urlencode.php)
*
* @param value String to encode
* @return std::string URL encoded string
*/
std::string DPP_EXPORT url_encode(const std::string &value);
/**
* @brief Create a mentionable slashcommand (used in a message).
* @param command_id The ID of the slashcommand
* @param command_name The command name
* @param subcommand Optional: The subcommand name (for mentioning a subcommand)
* @return std::string The formatted mention
*/
std::string DPP_EXPORT slashcommand_mention(snowflake command_id, const std::string &command_name, const std::string &subcommand = "");
/**
* @brief Create a mentionable slashcommand (used in a message).
* @param command_id The ID of the slashcommand
* @param command_name The command name
* @param subcommand_group The subcommand group name
* @param subcommand The subcommand name
* @return std::string The formatted mention of the slashcommand with its subcommand
*/
std::string DPP_EXPORT slashcommand_mention(snowflake command_id, const std::string &command_name, const std::string &subcommand_group, const std::string &subcommand);
/**
* @brief Create a mentionable user.
* @param id The ID of the user.
* @return std::string The formatted mention of the user.
*/
std::string DPP_EXPORT user_mention(const snowflake& id);
/**
* @brief Create a mentionable channel.
* @param id The ID of the channel.
* @return std::string The formatted mention of the channel.
*/
std::string DPP_EXPORT channel_mention(const snowflake& id);
/**
* @brief Create a mentionable emoji
* @param name The name of the emoji.
* @param id The ID of the emoji.
* @param is_animated is emoji animated.
* @return std::string The formatted mention of the emoji.
*/
std::string DPP_EXPORT emoji_mention(std::string_view name, snowflake id, bool is_animated = false);
/**
* @brief Create a mentionable role.
* @param id The ID of the role.
* @return std::string The formatted mention of the role.
*/
std::string DPP_EXPORT role_mention(const snowflake& id);
/**
* @brief Create a URL for message.
* @param guild_id The ID of the guild where message is written.
* @param channel_id The ID of the channel where message is written.
* @param message_id The ID of the message.
* @return std::string The URL to message or empty string if any of ids is 0.
*/
std::string DPP_EXPORT message_url(const snowflake& guild_id, const snowflake& channel_id, const snowflake& message_id);
/**
* @brief Create a URL for message.
* @param guild_id The ID of the guild where channel is located.
* @param channel_id The ID of the channel.
* @return std::string The URL to message or empty string if any of ids is 0.
*/
std::string DPP_EXPORT channel_url(const snowflake& guild_id, const snowflake& channel_id);
/**
* @brief Create a URL for message.
* @param guild_id The ID of the guild where thread is located.
* @param thread_id The ID of the thread.
* @return std::string The URL to message or empty string if any of ids is 0.
*/
std::string DPP_EXPORT thread_url(const snowflake& guild_id, const snowflake& thread_id);
/**
* @brief Create a URL for message.
* @param user_id The ID of the guild where thread is located.
* @return std::string The URL to message or empty string if id is 0.
*/
std::string DPP_EXPORT user_url(const snowflake& user_id);
#ifdef _DOXYGEN_
/**
* @brief Get the mime type for an image type.
* @param type Image type
* @return std::string The mime type for this image type
*/
std::string DPP_EXPORT mime_type(image_type type);
/**
* @brief Get the mime type for a sticker format.
* @param format Sticker format
* @return std::string The mime type for this sticker format
*/
std::string DPP_EXPORT mime_type(sticker_format format);
/**
* @brief Get the file extension for an image type.
* @param type Image type
* @return std::string The file extension (e.g. ".png") for this image type
*/
std::string DPP_EXPORT file_extension(image_type type);
/**
* @brief Get the file extension for a sticker format.
* @param format Sticker format
* @return std::string The file extension (e.g. ".png") for this sticker format
*/
std::string DPP_EXPORT file_extension(sticker_format format);
#else
/**
* @brief Get the mime type for an image type.
* @param type Image type
* @return std::string The mime type for this image type
*/
template <typename T>
extern std::enable_if_t<std::is_same_v<T, image_type>, std::string> DPP_EXPORT mime_type(T type);
/**
* @brief Get the mime type for a sticker format.
* @param format Sticker format
* @return std::string The mime type for this sticker format
*/
template <typename T>
extern std::enable_if_t<std::is_same_v<T, sticker_format>, std::string> DPP_EXPORT mime_type(T format);
/**
* @brief Get the file extension for an image type.
* @param type Image type
* @return std::string The file extension (e.g. ".png") for this image type
*/
template <typename T>
extern std::enable_if_t<std::is_same_v<T, image_type>, std::string> DPP_EXPORT file_extension(T type);
/**
* @brief Get the file extension for a sticker format.
* @param format Sticker format
* @return std::string The file extension (e.g. ".png") for this sticker format
*/
template <typename T>
extern std::enable_if_t<std::is_same_v<T, sticker_format>, std::string> DPP_EXPORT file_extension(T format);
#endif
/**
* @brief Returns the library's version string
*
* @return std::string version
*/
std::string DPP_EXPORT version();
/**
* @brief Build a URL parameter string e.g. "?a=b&c=d&e=f" from a map of key/value pairs.
* Entries with empty key names or values are omitted.
*
* @param parameters parameters to create a url query string for
* @return std::string A correctly encoded url query string
*/
std::string DPP_EXPORT make_url_parameters(const std::map<std::string, std::string>& parameters);
/**
* @brief Build a URL parameter string e.g. "?a=b&c=d&e=f" from a map of key/value pairs.
* Entries with empty key names or zero values are omitted.
*
* @param parameters parameters to create a url query string for
* @return std::string A correctly encoded url query string
*/
std::string DPP_EXPORT make_url_parameters(const std::map<std::string, uint64_t>& parameters);
/**
* @brief Set the name of the current thread for debugging and statistical reporting
*
* @param name New name to set
*/
void DPP_EXPORT set_thread_name(const std::string& name);
#ifdef __cpp_concepts // if c++20
/**
* @brief Concept satisfied if a callable F can be called using the arguments Args, and that its return value is convertible to R.
*
* @tparam F Callable object
* @tparam R Return type to check for convertibility to
* @tparam Args... Arguments to use to resolve the overload
* @return Whether the expression `F(Args...)` is convertible to R
*/
template <typename F, typename R, typename... Args>
concept callable_returns = std::convertible_to<std::invoke_result_t<F, Args...>, R>;
/**
* @brief Type trait to check if a callable F can be called using the arguments Args, and that its return value is convertible to R.
*
* @deprecated In C++20 mode, prefer using the concept `callable_returns`.
* @tparam F Callable object
* @tparam R Return type to check for convertibility to
* @tparam Args... Arguments to use to resolve the overload
* @return Whether the expression `F(Args...)` is convertible to R
*/
template <typename F, typename R, typename... Args>
inline constexpr bool callable_returns_v = callable_returns<F, R, Args...>;
#else
/**
* @brief Type trait to check if a callable F can be called using the arguments Args, and that its return value is convertible to R.
*
* @tparam F Callable object
* @tparam R Return type to check for convertibility to
* @tparam Args... Arguments to use to resolve the overload
* @return Whether the expression `F(Args...)` is convertible to R
*/
template <typename F, typename R, typename... Args>
inline constexpr bool callable_returns_v = std::is_convertible_v<std::invoke_result_t<F, Args...>, R>;
#endif
/**
* @brief Utility struct that has the same size and alignment as another but does nothing. Useful for ABI compatibility.
*
* @tparam T Type to mimic
*/
template <typename T>
struct alignas(T) dummy {
/** @brief Array of bytes with a size mimicking T */
std::array<std::byte, sizeof(T)> data;
};
} // namespace utility
} // namespace dpp