From 10e352b672c026379002e632b72fb39f0b60ca6b Mon Sep 17 00:00:00 2001 From: Craig Edwards Date: Mon, 11 Dec 2023 22:50:05 +0000 Subject: [PATCH 01/89] [skip ci] version bump --- include/dpp/version.h | 6 +++--- makerelease.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/dpp/version.h b/include/dpp/version.h index a02707d165..e3131506b6 100644 --- a/include/dpp/version.h +++ b/include/dpp/version.h @@ -22,9 +22,9 @@ #pragma once #if !defined(DPP_VERSION_LONG) -#define DPP_VERSION_LONG 0x00100029 -#define DPP_VERSION_SHORT 100029 -#define DPP_VERSION_TEXT "D++ 10.0.29 (05-Nov-2023)" +#define DPP_VERSION_LONG 0x00100030 +#define DPP_VERSION_SHORT 100030 +#define DPP_VERSION_TEXT "D++ 10.0.30 (11-Dec-2023)" #define DPP_VERSION_MAJOR ((DPP_VERSION_LONG & 0x00ff0000) >> 16) #define DPP_VERSION_MINOR ((DPP_VERSION_LONG & 0x0000ff00) >> 8) diff --git a/makerelease.sh b/makerelease.sh index d114140f57..bcf7af5ca9 100755 --- a/makerelease.sh +++ b/makerelease.sh @@ -19,7 +19,7 @@ mv "./libdpp - RPM Package ARMv6/libdpp-$NEWVER-Linux.rpm" "./assets/libdpp-$NEW # deb mv "./libdpp - Debian Package amd64/libdpp-$NEWVER-Linux.deb" "./assets/libdpp-$NEWVER-linux-x64.deb" mv "./libdpp - Debian Package Linux x86/libdpp-$NEWVER-Linux.deb" "./assets/libdpp-$NEWVER-linux-i386.deb" -mv "./libdpp - Debian Package amd64/libdpp-$NEWVER-Linux.deb" "./assets/libdpp-$NEWVER-linux-rpi-arm64.deb" +mv "./libdpp - Debian Package arm64/libdpp-$NEWVER-Linux.deb" "./assets/libdpp-$NEWVER-linux-rpi-arm64.deb" mv "./libdpp - Debian Package arm7hf/libdpp-$NEWVER-Linux.deb" "./assets/libdpp-$NEWVER-linux-rpi-arm7hf.deb" mv "./libdpp - Debian Package ARMv6/libdpp-$NEWVER-Linux.deb" "./assets/libdpp-$NEWVER-linux-rpi-arm6.deb" From 4ab7b5222c78cfcc294411299efbcd6e03289439 Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Tue, 12 Dec 2023 12:18:00 +0000 Subject: [PATCH 02/89] docs: added the homebrew version to readme (#1041) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b43c633d6e..62cb25d904 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/brainboxdotcc/DPP/badge)](https://securityscorecards.dev/viewer/?uri=github.com/brainboxdotcc/DPP) [![AUR version](https://img.shields.io/aur/version/dpp)](https://aur.archlinux.org/packages/dpp) ![vcpkg version](https://img.shields.io/vcpkg/v/dpp) +[![Homebrew version](https://img.shields.io/homebrew/v/libdpp)](https://formulae.brew.sh/formula/libdpp#default) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) From 8ac81687f3a42d9cca51bd84d5e030ca0961386b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 15:52:51 +0000 Subject: [PATCH 03/89] build(deps): bump ubuntu from `f5c3e53` to `f2034e7` (#1042) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fe4f331bbb..fcee08471c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:focal@sha256:f5c3e53367f142fab0b49908550bdcdc4fb619d2f61ec1dfa60d26e0d59ac9e7 +FROM ubuntu:focal@sha256:f2034e7195f61334e6caff6ecf2e965f92d11e888309065da85ff50c617732b8 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --no-install-recommends -y libssl-dev zlib1g-dev libsodium-dev libopus-dev cmake pkg-config g++ gcc git make && apt-get clean && rm -rf /var/lib/apt/lists/* From ccc7133079feab92a9e69875fe1f8f4340ab2663 Mon Sep 17 00:00:00 2001 From: rept1d <32854273+rept1d@users.noreply.github.com> Date: Tue, 19 Dec 2023 12:36:37 +0300 Subject: [PATCH 04/89] fix: use of uninitialized value in command_option copy ctor (#1044) --- src/dpp/slashcommand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dpp/slashcommand.cpp b/src/dpp/slashcommand.cpp index 5b4b8cb9b0..77dd4bfebe 100644 --- a/src/dpp/slashcommand.cpp +++ b/src/dpp/slashcommand.cpp @@ -331,7 +331,7 @@ command_option_choice &command_option_choice::fill_from_json_impl(nlohmann::json } command_option::command_option(command_option_type t, const std::string &n, const std::string &d, bool r) : - type(t), name(n), description(d), required(r), autocomplete(false) + type(t), name(n), description(d), required(r), focused(false), autocomplete(false) { if (std::any_of(n.begin(), n.end(), [](unsigned char c){ return std::isupper(c); })) { throw dpp::logic_exception(err_command_has_caps, "Command options can not contain capital letters in the name of the option."); From 912f8b3f59d192b4e675cb9446898ee9c6229c04 Mon Sep 17 00:00:00 2001 From: rept1d <32854273+rept1d@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:14:23 +0300 Subject: [PATCH 05/89] fix: avoid memory leaks in event_map (#1043) --- src/dpp/discordevents.cpp | 142 ++++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 68 deletions(-) diff --git a/src/dpp/discordevents.cpp b/src/dpp/discordevents.cpp index 18396ed225..013f2344ee 100644 --- a/src/dpp/discordevents.cpp +++ b/src/dpp/discordevents.cpp @@ -320,85 +320,91 @@ void set_ts_not_null(const json* j, const char* keyname, time_t &v) } } -const std::map eventmap = { - { "__LOG__", new dpp::events::logger() }, - { "GUILD_CREATE", new dpp::events::guild_create() }, - { "GUILD_UPDATE", new dpp::events::guild_update() }, - { "GUILD_DELETE", new dpp::events::guild_delete() }, - { "GUILD_MEMBER_UPDATE", new dpp::events::guild_member_update() }, - { "RESUMED", new dpp::events::resumed() }, - { "READY", new dpp::events::ready() }, - { "CHANNEL_CREATE", new dpp::events::channel_create() }, - { "CHANNEL_UPDATE", new dpp::events::channel_update() }, - { "CHANNEL_DELETE", new dpp::events::channel_delete() }, - { "PRESENCE_UPDATE", new dpp::events::presence_update() }, - { "TYPING_START", new dpp::events::typing_start() }, - { "MESSAGE_CREATE", new dpp::events::message_create() }, - { "MESSAGE_UPDATE", new dpp::events::message_update() }, - { "MESSAGE_DELETE", new dpp::events::message_delete() }, - { "MESSAGE_DELETE_BULK", new dpp::events::message_delete_bulk() }, - { "MESSAGE_REACTION_ADD", new dpp::events::message_reaction_add() }, - { "MESSAGE_REACTION_REMOVE", new dpp::events::message_reaction_remove() }, - { "MESSAGE_REACTION_REMOVE_ALL", new dpp::events::message_reaction_remove_all() }, - { "MESSAGE_REACTION_REMOVE_EMOJI", new dpp::events::message_reaction_remove_emoji() }, - { "CHANNEL_PINS_UPDATE", new dpp::events::channel_pins_update() }, - { "GUILD_BAN_ADD", new dpp::events::guild_ban_add() }, - { "GUILD_BAN_REMOVE", new dpp::events::guild_ban_remove() }, - { "GUILD_EMOJIS_UPDATE", new dpp::events::guild_emojis_update() }, - { "GUILD_INTEGRATIONS_UPDATE", new dpp::events::guild_integrations_update() }, - { "INTEGRATION_CREATE", new dpp::events::integration_create() }, - { "INTEGRATION_UPDATE", new dpp::events::integration_update() }, - { "INTEGRATION_DELETE", new dpp::events::integration_delete() }, - { "GUILD_MEMBER_ADD", new dpp::events::guild_member_add() }, - { "GUILD_MEMBER_REMOVE", new dpp::events::guild_member_remove() }, - { "GUILD_MEMBERS_CHUNK", new dpp::events::guild_members_chunk() }, - { "GUILD_ROLE_CREATE", new dpp::events::guild_role_create() }, - { "GUILD_ROLE_UPDATE", new dpp::events::guild_role_update() }, - { "GUILD_ROLE_DELETE", new dpp::events::guild_role_delete() }, - { "VOICE_STATE_UPDATE", new dpp::events::voice_state_update() }, - { "VOICE_SERVER_UPDATE", new dpp::events::voice_server_update() }, - { "WEBHOOKS_UPDATE", new dpp::events::webhooks_update() }, - { "INVITE_CREATE", new dpp::events::invite_create() }, - { "INVITE_DELETE", new dpp::events::invite_delete() }, - { "INTERACTION_CREATE", new dpp::events::interaction_create() }, - { "USER_UPDATE", new dpp::events::user_update() }, - { "GUILD_JOIN_REQUEST_DELETE", new dpp::events::guild_join_request_delete() }, +template +static dpp::events::event* make_static_event() noexcept { + static EventType event; + return &event; +} + +static const std::map event_map = { + { "__LOG__", make_static_event() }, + { "GUILD_CREATE", make_static_event() }, + { "GUILD_UPDATE", make_static_event() }, + { "GUILD_DELETE", make_static_event() }, + { "GUILD_MEMBER_UPDATE", make_static_event() }, + { "RESUMED", make_static_event() }, + { "READY", make_static_event() }, + { "CHANNEL_CREATE", make_static_event() }, + { "CHANNEL_UPDATE", make_static_event() }, + { "CHANNEL_DELETE", make_static_event() }, + { "PRESENCE_UPDATE", make_static_event() }, + { "TYPING_START", make_static_event() }, + { "MESSAGE_CREATE", make_static_event() }, + { "MESSAGE_UPDATE", make_static_event() }, + { "MESSAGE_DELETE", make_static_event() }, + { "MESSAGE_DELETE_BULK", make_static_event() }, + { "MESSAGE_REACTION_ADD", make_static_event() }, + { "MESSAGE_REACTION_REMOVE", make_static_event() }, + { "MESSAGE_REACTION_REMOVE_ALL", make_static_event() }, + { "MESSAGE_REACTION_REMOVE_EMOJI", make_static_event() }, + { "CHANNEL_PINS_UPDATE", make_static_event() }, + { "GUILD_BAN_ADD", make_static_event() }, + { "GUILD_BAN_REMOVE", make_static_event() }, + { "GUILD_EMOJIS_UPDATE", make_static_event() }, + { "GUILD_INTEGRATIONS_UPDATE", make_static_event() }, + { "INTEGRATION_CREATE", make_static_event() }, + { "INTEGRATION_UPDATE", make_static_event() }, + { "INTEGRATION_DELETE", make_static_event() }, + { "GUILD_MEMBER_ADD", make_static_event() }, + { "GUILD_MEMBER_REMOVE", make_static_event() }, + { "GUILD_MEMBERS_CHUNK", make_static_event() }, + { "GUILD_ROLE_CREATE", make_static_event() }, + { "GUILD_ROLE_UPDATE", make_static_event() }, + { "GUILD_ROLE_DELETE", make_static_event() }, + { "VOICE_STATE_UPDATE", make_static_event() }, + { "VOICE_SERVER_UPDATE", make_static_event() }, + { "WEBHOOKS_UPDATE", make_static_event() }, + { "INVITE_CREATE", make_static_event() }, + { "INVITE_DELETE", make_static_event() }, + { "INTERACTION_CREATE", make_static_event() }, + { "USER_UPDATE", make_static_event() }, + { "GUILD_JOIN_REQUEST_DELETE", make_static_event() }, { "GUILD_JOIN_REQUEST_UPDATE", nullptr }, - { "STAGE_INSTANCE_CREATE", new dpp::events::stage_instance_create() }, - { "STAGE_INSTANCE_UPDATE", new dpp::events::stage_instance_update() }, - { "STAGE_INSTANCE_DELETE", new dpp::events::stage_instance_delete() }, - { "THREAD_CREATE", new dpp::events::thread_create() }, - { "THREAD_UPDATE", new dpp::events::thread_update() }, - { "THREAD_DELETE", new dpp::events::thread_delete() }, - { "THREAD_LIST_SYNC", new dpp::events::thread_list_sync() }, - { "THREAD_MEMBER_UPDATE", new dpp::events::thread_member_update() }, - { "THREAD_MEMBERS_UPDATE", new dpp::events::thread_members_update() }, - { "GUILD_STICKERS_UPDATE", new dpp::events::guild_stickers_update() }, + { "STAGE_INSTANCE_CREATE", make_static_event() }, + { "STAGE_INSTANCE_UPDATE", make_static_event() }, + { "STAGE_INSTANCE_DELETE", make_static_event() }, + { "THREAD_CREATE", make_static_event() }, + { "THREAD_UPDATE", make_static_event() }, + { "THREAD_DELETE", make_static_event() }, + { "THREAD_LIST_SYNC", make_static_event() }, + { "THREAD_MEMBER_UPDATE", make_static_event() }, + { "THREAD_MEMBERS_UPDATE", make_static_event() }, + { "GUILD_STICKERS_UPDATE", make_static_event() }, { "GUILD_APPLICATION_COMMAND_COUNTS_UPDATE", nullptr }, { "APPLICATION_COMMAND_PERMISSIONS_UPDATE", nullptr }, { "EMBEDDED_ACTIVITY_UPDATE", nullptr }, { "GUILD_APPLICATION_COMMAND_INDEX_UPDATE", nullptr }, { "CHANNEL_TOPIC_UPDATE", nullptr }, { "VOICE_CHANNEL_STATUS_UPDATE", nullptr }, - { "GUILD_SCHEDULED_EVENT_CREATE", new dpp::events::guild_scheduled_event_create() }, - { "GUILD_SCHEDULED_EVENT_UPDATE", new dpp::events::guild_scheduled_event_update() }, - { "GUILD_SCHEDULED_EVENT_DELETE", new dpp::events::guild_scheduled_event_delete() }, - { "GUILD_SCHEDULED_EVENT_USER_ADD", new dpp::events::guild_scheduled_event_user_add() }, - { "GUILD_SCHEDULED_EVENT_USER_REMOVE", new dpp::events::guild_scheduled_event_user_remove() }, - { "AUTO_MODERATION_RULE_CREATE", new dpp::events::automod_rule_create() }, - { "AUTO_MODERATION_RULE_UPDATE", new dpp::events::automod_rule_update() }, - { "AUTO_MODERATION_RULE_DELETE", new dpp::events::automod_rule_delete() }, - { "AUTO_MODERATION_ACTION_EXECUTION", new dpp::events::automod_rule_execute() }, - { "GUILD_AUDIT_LOG_ENTRY_CREATE", new dpp::events::guild_audit_log_entry_create() }, - { "ENTITLEMENT_CREATE", new dpp::events::entitlement_create() }, - { "ENTITLEMENT_UPDATE", new dpp::events::entitlement_update() }, - { "ENTITLEMENT_DELETE", new dpp::events::entitlement_delete() }, + { "GUILD_SCHEDULED_EVENT_CREATE", make_static_event() }, + { "GUILD_SCHEDULED_EVENT_UPDATE", make_static_event() }, + { "GUILD_SCHEDULED_EVENT_DELETE", make_static_event() }, + { "GUILD_SCHEDULED_EVENT_USER_ADD", make_static_event() }, + { "GUILD_SCHEDULED_EVENT_USER_REMOVE", make_static_event() }, + { "AUTO_MODERATION_RULE_CREATE", make_static_event() }, + { "AUTO_MODERATION_RULE_UPDATE", make_static_event() }, + { "AUTO_MODERATION_RULE_DELETE", make_static_event() }, + { "AUTO_MODERATION_ACTION_EXECUTION", make_static_event() }, + { "GUILD_AUDIT_LOG_ENTRY_CREATE", make_static_event() }, + { "ENTITLEMENT_CREATE", make_static_event() }, + { "ENTITLEMENT_UPDATE", make_static_event() }, + { "ENTITLEMENT_DELETE", make_static_event() }, }; void discord_client::handle_event(const std::string &event, json &j, const std::string &raw) { - auto ev_iter = eventmap.find(event); - if (ev_iter != eventmap.end()) { + auto ev_iter = event_map.find(event); + if (ev_iter != event_map.end()) { /* A handler with nullptr is silently ignored. We don't plan to make a handler for it * so this usually some user-only thing that's crept into the API and shown to bots * that we dont care about. From 8144480f1f261435374df23d2294eb00f2353002 Mon Sep 17 00:00:00 2001 From: rept1d <32854273+rept1d@users.noreply.github.com> Date: Wed, 20 Dec 2023 03:50:00 +0300 Subject: [PATCH 06/89] refactor: fix and improve utf8 utilities (#1046) --- include/dpp/utility.h | 30 ++++++++--- src/dpp/commandhandler.cpp | 2 +- src/dpp/utility.cpp | 108 ++++++++++++++++--------------------- 3 files changed, 69 insertions(+), 71 deletions(-) diff --git a/include/dpp/utility.h b/include/dpp/utility.h index 55ec9e83b5..47b85f925d 100644 --- a/include/dpp/utility.h +++ b/include/dpp/utility.h @@ -738,22 +738,36 @@ uint32_t DPP_EXPORT hsl(int h, int s, int l); std::string DPP_EXPORT debug_dump(uint8_t* data, size_t length); /** - * @brief Returns the length of a UTF-8 string in codepoints - * + * @brief Returns the length of a UTF-8 string in codepoints. + * @note Result is unspecified for strings that are not valid UTF-8. + * * @param str string to count length of - * @return size_t length of string (0 for invalid utf8) + * @return size_t Length of string */ -size_t DPP_EXPORT utf8len(const std::string &str); +size_t DPP_EXPORT utf8len(std::string_view str); /** - * @brief Return substring of a UTF-8 encoded string in codepoints - * + * @brief Return subview of a UTF-8 encoded string in codepoints. + * @note You must ensure that the resulting view is not used after the lifetime of the viewed string has ended. + * @note Result is unspecified for strings that are not valid UTF-8. + * + * @param str string to return substring from + * @param start start codepoint offset + * @param length length in codepoints + * @return std::string_view The requested subview + */ +std::string_view DPP_EXPORT utf8subview(std::string_view str, size_t start, size_t length); + +/** + * @brief Return substring of a UTF-8 encoded string in codepoints. + * @note Result is unspecified for strings that are not valid UTF-8. + * * @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 + * @return std::string The requested substring */ -std::string DPP_EXPORT utf8substr(const std::string& str, std::string::size_type start, std::string::size_type length); +std::string DPP_EXPORT utf8substr(std::string_view str, size_t start, size_t length); /** * @brief Read a whole file into a std::string. diff --git a/src/dpp/commandhandler.cpp b/src/dpp/commandhandler.cpp index 9e15168f53..e337b0eee9 100644 --- a/src/dpp/commandhandler.cpp +++ b/src/dpp/commandhandler.cpp @@ -168,7 +168,7 @@ bool commandhandler::string_has_prefix(std::string &str) { for (auto& p : prefixes) { size_t prefix_length = utility::utf8len(p); - if (utility::utf8substr(str, 0, prefix_length) == p) { + if (utility::utf8subview(str, 0, prefix_length) == p) { str.erase(str.begin(), str.begin() + prefix_length); return true; } diff --git a/src/dpp/utility.cpp b/src/dpp/utility.cpp index 07638d1201..ff0dcde276 100644 --- a/src/dpp/utility.cpp +++ b/src/dpp/utility.cpp @@ -482,83 +482,67 @@ void exec(const std::string& cmd, std::vector parameters, cmd_resul t.detach(); } -size_t utf8len(const std::string &str) -{ - size_t i = 0, iBefore = 0, count = 0; - const char* s = str.c_str(); - if (*s == 0) { - return 0; - } +size_t utf8len(std::string_view str) { + const size_t raw_len = str.length(); + size_t pos = 0; + size_t code_points = 0; - while (s[i] > 0) { -ascii: - i++; - } + while (pos != raw_len) { + const unsigned char cur = str[pos]; - count += i - iBefore; + size_t code_point_len = 1; + code_point_len += static_cast(cur >= 0b11000000); + code_point_len += static_cast(cur >= 0b11100000); + code_point_len += static_cast(cur >= 0b11110000); - while (s[i]) { - if (s[i] > 0) { - iBefore = i; - goto ascii; - } else { - switch (0xF0 & s[i]) { - case 0xE0: - i += 3; - break; - case 0xF0: - i += 4; - break; - default: - i += 2; - break; - } + if (raw_len - pos < code_point_len) { + return 0; // invalid utf8, avoid going past the end } + pos += code_point_len; - count++; + code_points += 1; } - return count; + return code_points; } -std::string utf8substr(const std::string& str, std::string::size_type start, std::string::size_type leng) -{ - if (leng == 0) { - return ""; - } - if (start == 0 && leng >= utf8len(str)) { - return str; - } - std::string::size_type i, ix, q, min = std::string::npos, max = std::string::npos; - for (q = 0, i = 0, ix = str.length(); i < ix; i++, q++) { - if (q == start) { - min = i; +std::string_view utf8subview(std::string_view str, size_t start, size_t length) { + const size_t raw_len = str.length(); + size_t pos = 0; + size_t code_points = 0; + + size_t subview_start = raw_len; + size_t subview_len = std::string_view::npos; + + while (pos != raw_len) { + if (code_points == start) { + subview_start = pos; } - if (q <= start + leng || leng == std::string::npos) { - max = i; + if (code_points == start + length) { + subview_len = pos - subview_start; + break; // no point in traversing the remainder of the string } - unsigned char c = (unsigned char)str[i]; - if (c < 0x80) { - i += 0; - } else if ((c & 0xE0) == 0xC0) { - i += 1; - } else if ((c & 0xF0) == 0xE0) { - i += 2; - } else if ((c & 0xF8) == 0xF0) { - i += 3; - } else { - return ""; //invalid utf8 + const unsigned char cur = str[pos]; + + size_t code_point_len = 1; + code_point_len += static_cast(cur >= 0b11000000); + code_point_len += static_cast(cur >= 0b11100000); + code_point_len += static_cast(cur >= 0b11110000); + + if (raw_len - pos < code_point_len) { + return ""; // invalid utf8, avoid going past the end } + pos += code_point_len; + + code_points += 1; } - if (q <= start + leng || leng == std::string::npos) { - max = i; - } - if (min == std::string::npos || max == std::string::npos) { - return ""; - } - return str.substr(min, max); + return str.substr(subview_start, subview_len); +} + +std::string utf8substr(std::string_view str, size_t start, size_t length) { + return std::string(utf8subview(str, start, length)); } std::string read_file(const std::string& filename) From e5991da0fec68ba1d907728acc8a37c275f217aa Mon Sep 17 00:00:00 2001 From: rept1d <32854273+rept1d@users.noreply.github.com> Date: Wed, 20 Dec 2023 10:41:32 +0300 Subject: [PATCH 07/89] fix: properly free ssl session and ssl context (#1049) --- src/dpp/sslclient.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index 3d6577fa03..845ab4adcb 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -99,10 +99,20 @@ struct keepalive_cache_t { dpp::socket sfd; }; +/** + * @brief Custom deleter for SSL_CTX + */ +class openssl_context_deleter { +public: + void operator()(SSL_CTX* context) const noexcept { + SSL_CTX_free(context); + } +}; + /** * @brief OpenSSL context */ -thread_local SSL_CTX* openssl_context = nullptr; +thread_local std::unique_ptr openssl_context; /** * @brief Keepalive sessions, per-thread @@ -273,13 +283,7 @@ ssl_client::ssl_client(const std::string &_hostname, const std::string &_port, b if (plaintext) { ssl = nullptr; } else { - try { - ssl = new openssl_connection(); - } - catch (std::bad_alloc&) { - delete ssl; - throw; - } + ssl = new openssl_connection(); } } try { @@ -321,21 +325,21 @@ void ssl_client::connect() const SSL_METHOD *method = TLS_client_method(); /* Create new client-method instance */ /* Create SSL context */ - openssl_context = SSL_CTX_new(method); - if (openssl_context == nullptr) { + openssl_context.reset(SSL_CTX_new(method)); + if (!openssl_context) { throw dpp::connection_exception(err_ssl_context, "Failed to create SSL client context!"); } /* Do not allow SSL 3.0, TLS 1.0 or 1.1 * https://www.packetlabs.net/posts/tls-1-1-no-longer-secure/ */ - if (!SSL_CTX_set_min_proto_version(openssl_context, TLS1_2_VERSION)) { + if (!SSL_CTX_set_min_proto_version(openssl_context.get(), TLS1_2_VERSION)) { throw dpp::connection_exception(err_ssl_version, "Failed to set minimum SSL version!"); } } /* Create SSL session */ - ssl->ssl = SSL_new(openssl_context); + ssl->ssl = SSL_new(openssl_context.get()); if (ssl->ssl == nullptr) { throw dpp::connection_exception(err_ssl_new, "SSL_new failed!"); } @@ -646,6 +650,9 @@ void ssl_client::cleanup() { this->close(); if (!keepalive) { + if (ssl != nullptr) { + SSL_free(ssl->ssl); + } delete ssl; } } From 24c88c31addae079ffb1f60b23ce3932e6102d4e Mon Sep 17 00:00:00 2001 From: rept1d <32854273+rept1d@users.noreply.github.com> Date: Wed, 20 Dec 2023 14:02:25 +0300 Subject: [PATCH 08/89] fix: remove unnecessary SSL_free (#1050) --- src/dpp/sslclient.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index 845ab4adcb..428bdebe32 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -650,9 +650,6 @@ void ssl_client::cleanup() { this->close(); if (!keepalive) { - if (ssl != nullptr) { - SSL_free(ssl->ssl); - } delete ssl; } } From 8a9986d2905e49b6b39fa955daf3069e3b876a0f Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Wed, 27 Dec 2023 10:13:10 +0000 Subject: [PATCH 09/89] CI: unit-test and non unit-test jobs are now merged into one (#1051) --- .github/workflows/ci.yml | 75 ++++++++++++---------------------------- 1 file changed, 23 insertions(+), 52 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3898391d1a..87199b0128 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,20 +27,33 @@ permissions: contents: read jobs: - linux-with-unit-test: + linux: permissions: contents: write concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.cfg.arch }}-(${{ matrix.cfg.cpp-version }}) cancel-in-progress: true name: Linux ${{matrix.cfg.arch}} (${{matrix.cfg.cpp-version}}) runs-on: ${{matrix.cfg.os}} strategy: fail-fast: false # Don't fail everything if one fails. We want to test each OS/Compiler individually matrix: + # GitHub hosted runners on Azure + # arm7hf is a self-hosted docker-based runner at Brainbox.cc. Raspberry Pi 4, 8gb 4-core with NEON cfg: - - { arch: 'amd64', os: ubuntu-20.04, cpp-version: g++-8 } - + - { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: clang-10, cpp-version: clang++-10, cmake-flags: '', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-11, cpp-version: clang++-11, cmake-flags: '', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-12, cpp-version: clang++-12, cmake-flags: '', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-13, cpp-version: clang++-13, cmake-flags: '', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-14, cpp-version: clang++-14, cmake-flags: '', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-15, cpp-version: clang++-15, cmake-flags: '-DDPP_CORO=ON', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-12, cpp-version: g++-12, cmake-flags: '-DDPP_CORO=ON', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-11, cpp-version: g++-11, cmake-flags: '-DDPP_CORO=ON', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-10, cpp-version: g++-10, cmake-flags: '', cpack: 'yes', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: g++-9, cpp-version: g++-9, cmake-flags: '', cpack: 'no', ctest: 'no' } + - { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: g++-8, cpp-version: g++-8, cmake-flags: '', cpack: 'no', ctest: 'yes' } + - { arch: 'arm7hf', concurrency: 4, os: [self-hosted, linux, ARM], package: g++-12, cpp-version: g++-12, cmake-flags: '', cpack: 'yes', ctest: 'no' } + - { arch: 'arm64', concurrency: 4, os: [self-hosted, linux, ARM64], package: g++-12, cpp-version: g++-12, cmake-flags: '', cpack: 'yes', ctest: 'no' } steps: - name: Harden Runner uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 @@ -51,17 +64,18 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install apt packages - run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y ${{ matrix.cfg.cpp-version }} libsodium-dev libopus-dev zlib1g-dev rpm + run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y ${{ matrix.cfg.package }} pkg-config libsodium-dev libopus-dev zlib1g-dev rpm - name: Generate CMake - run: mkdir build && cd build && cmake -DDPP_NO_VCPKG=ON -DAVX_TYPE=AVX0 -DCMAKE_BUILD_TYPE=Release .. + run: mkdir build && cd build && cmake -DDPP_NO_VCPKG=ON -DAVX_TYPE=AVX0 -DCMAKE_BUILD_TYPE=Release ${{matrix.cfg.cmake-flags}} .. env: CXX: ${{matrix.cfg.cpp-version}} - name: Build Project - run: cd build && make -j2 + run: cd build && make -j${{ matrix.cfg.concurrency }} - name: Run unit tests + if: ${{ matrix.cfg.ctest == 'yes' }} run: cd build && ctest -VV env: DPP_UNIT_TEST_TOKEN: ${{secrets.DPP_UNIT_TEST_TOKEN}} @@ -71,49 +85,6 @@ jobs: TEST_USER_ID: ${{secrets.TEST_USER_ID}} TEST_EVENT_ID: ${{secrets.TEST_EVENT_ID}} - linux-no-unit-tests: - permissions: - contents: write - name: Linux ${{matrix.cfg.arch}} (${{matrix.cfg.cpp-version}}) - runs-on: ${{matrix.cfg.os}} - strategy: - fail-fast: false # Don't fail everything if one fails. We want to test each OS/Compiler individually - matrix: - # GitHub hosted runners on Azure - # arm7hf is a self-hosted docker-based runner at Brainbox.cc. Raspberry Pi 4, 8gb 4-core with NEON - cfg: - - { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: clang-10, cpp-version: clang++-10, cmake-flags: '', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-11, cpp-version: clang++-11, cmake-flags: '', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-12, cpp-version: clang++-12, cmake-flags: '', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-13, cpp-version: clang++-13, cmake-flags: '', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-14, cpp-version: clang++-14, cmake-flags: '', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: clang-15, cpp-version: clang++-15, cmake-flags: '-DDPP_CORO=ON', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-12, cpp-version: g++-12, cmake-flags: '-DDPP_CORO=ON', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-11, cpp-version: g++-11, cmake-flags: '-DDPP_CORO=ON', cpack: 'no' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-22.04, package: g++-10, cpp-version: g++-10, cmake-flags: '', cpack: 'yes' } - - { arch: 'amd64', concurrency: 2, os: ubuntu-20.04, package: g++-9, cpp-version: g++-9, cmake-flags: '', cpack: 'no' } - - { arch: 'arm7hf', concurrency: 4, os: [self-hosted, linux, ARM], package: g++-12, cpp-version: g++-12, cmake-flags: '', cpack: 'yes' } - - { arch: 'arm64', concurrency: 4, os: [self-hosted, linux, ARM64], package: g++-12, cpp-version: g++-12, cmake-flags: '', cpack: 'yes' } - steps: - - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 - with: - egress-policy: audit - - - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Install apt packages - run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y ${{ matrix.cfg.package }} pkg-config libsodium-dev libopus-dev zlib1g-dev rpm - - - name: Generate CMake - run: mkdir build && cd build && cmake -DDPP_NO_VCPKG=ON -DAVX_TYPE=AVX0 -DCMAKE_BUILD_TYPE=Release ${{matrix.cfg.cmake-flags}} .. - env: - CXX: ${{matrix.cfg.cpp-version}} - - - name: Build Project - run: cd build && make -j${{ matrix.cfg.concurrency }} - - name: Package distributable if: ${{ matrix.cfg.cpack == 'yes' }} run: cd build && cpack --verbose @@ -142,8 +113,8 @@ jobs: matrix: # arm64 is a self-hosted runner on a Mac M2 Mini, ran inside a virtual machine by Archie Jaskowicz. cfg: - - { arch: 'x64', concurrency: 3, os: macos-latest, cpp-version: clang++-14, cmake-flags: '', cpack: 'no' } - - { arch: 'arm64', concurrency: 2, os: [self-hosted, ARM64, macOS], cpp-version: clang++-15, cmake-flags: '', cpack: 'no' } + - { arch: 'x64', concurrency: 3, os: macos-latest, cpp-version: clang++-14, cmake-flags: ''} + - { arch: 'arm64', concurrency: 2, os: [self-hosted, ARM64, macOS], cpp-version: clang++-15, cmake-flags: ''} steps: - name: Harden Runner uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 From 00febe452e59376f0eb981f6ab3b71e7f53e48e8 Mon Sep 17 00:00:00 2001 From: Piotr Chorzelewski <45640997+harrrson@users.noreply.github.com> Date: Fri, 29 Dec 2023 23:31:01 +0100 Subject: [PATCH 10/89] fix: cmyk calculations - blue value calculations (#1053) --- src/dpp/utility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dpp/utility.cpp b/src/dpp/utility.cpp index ff0dcde276..321bad46d4 100644 --- a/src/dpp/utility.cpp +++ b/src/dpp/utility.cpp @@ -408,7 +408,7 @@ uint32_t rgb(int red, int green, int blue) { uint32_t cmyk(double c, double m, double y, double k) { int r = (int)(255 * (1 - c) * (1 - k)); int g = (int)(255 * (1 - m) * (1 - k)); - int b = (int)(255 * (1 - y) * (1 - m)); + int b = (int)(255 * (1 - y) * (1 - k)); return rgb(r, g, b); } From d694b036a3797f4f7d1b7c09172f0c043519be06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:19:22 +0000 Subject: [PATCH 11/89] build(deps): bump actions/stale from 8.0.0 to 9.0.0 (#1054) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d14cf9cb4a..dc0b36c411 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -18,7 +18,7 @@ jobs: with: egress-policy: audit - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 with: stale-issue-message: 'This issue has had no activity and is being marked as stale. If you still wish to continue with this issue please comment to reopen it.' stale-pr-message: 'This pull request has had no activity and is being marked as stale. If you still wish to continue with this pull request please comment to reopen it.' From 9789fee0e4750d61ab59013136d4ed8504e6ecc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:19:39 +0000 Subject: [PATCH 12/89] build(deps): bump actions/upload-artifact from 3.1.3 to 4.0.0 (#1055) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/scorecard.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87199b0128..e70f31207a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,14 +91,14 @@ jobs: - name: Upload Binary (DEB) if: ${{ matrix.cfg.cpack == 'yes' }} - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: "libdpp - Debian Package ${{matrix.cfg.arch}}" path: '${{github.workspace}}/build/*.deb' - name: Upload Binary (RPM) if: ${{ matrix.cfg.cpack == 'yes' }} - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: "libdpp - RPM Package ${{matrix.cfg.arch}}" path: '${{github.workspace}}/build/*.rpm' @@ -209,7 +209,7 @@ jobs: - name: Upload Binary if: ${{ matrix.cfg.upload }} - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: "libdpp - Windows ${{matrix.cfg.name}}-${{matrix.cfg.config}}-vs${{matrix.cfg.vs}}" path: '${{github.workspace}}/main/build/*.zip' @@ -251,13 +251,13 @@ jobs: run: cd build && sudo cpack --verbose || cat /home/runner/work/DPP/DPP/build/_CPack_Packages/Linux/DEB/PreinstallOutput.log - name: Upload Binaries (DEB) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: "libdpp - Debian Package ${{matrix.cfg.name}}" path: "${{github.workspace}}/build/*.deb" - name: Upload Binaries (RPM) - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: "libdpp - RPM Package ${{matrix.cfg.name}}" path: "${{github.workspace}}/build/*.rpm" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 1087bb0419..356fded12f 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -64,7 +64,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: SARIF file path: results.sarif From 197175c1e501c40fd03eb8e5e0010a9f4791e430 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:19:51 +0000 Subject: [PATCH 13/89] build(deps): bump github/codeql-action from 2.22.8 to 3.22.12 (#1056) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d70dce6dda..91b0a78a4b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -50,7 +50,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8 + uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -65,6 +65,6 @@ jobs: make -j2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8 + uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 356fded12f..491626b5a5 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -72,6 +72,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8 + uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 with: sarif_file: results.sarif From 32a995c78b1d13b8b7d9df73c1412423d943b909 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:20:14 +0000 Subject: [PATCH 14/89] build(deps): bump actions/labeler from 4.3.0 to 5.0.0 (#1057) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 444ccf3c61..4cc35411d4 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -17,6 +17,6 @@ jobs: with: egress-policy: audit - - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0 + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 3eafd7d9f016b1099d4c79a5ad451cdf210b9043 Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Wed, 3 Jan 2024 17:22:44 -0500 Subject: [PATCH 15/89] docs: improve windows VS tutorials (#1058) --- .cspell.json | 4 +++- docpages/install/install-windows-vs-zip.md | 5 ++++- docpages/make_a_bot/windows_vs.md | 11 ++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.cspell.json b/.cspell.json index 6c41761e10..5404e2ae81 100644 --- a/.cspell.json +++ b/.cspell.json @@ -99,6 +99,7 @@ "stringified", "disdppgloss", "awaiter", + "awaiters", "resumer", "checkered", "ramen", @@ -136,7 +137,8 @@ "NOMINMAX", "sku", "skus", - "Codecademy" + "Codecademy", + "tparam" ], "flagWords": [ "hte" diff --git a/docpages/install/install-windows-vs-zip.md b/docpages/install/install-windows-vs-zip.md index e55254bca6..19d7fc3917 100644 --- a/docpages/install/install-windows-vs-zip.md +++ b/docpages/install/install-windows-vs-zip.md @@ -2,7 +2,7 @@ To add D++ to a Visual Studio project, using **Visual Studio 2019** or **Visual Studio 2022**, follow the steps below. The steps below assume an empty project, if you are adding to an existing project simply skip steps 1 through 4, and step 13. -\note It is possible to skip this entire tutorial, and obtain a [pre-made Visual Studio template containing the latest D++ build (for 32 and 64 bit, release and debug profiles) by clicking here](https://github.com/brainboxdotcc/windows-bot-template/). +\note It is possible to skip this entire tutorial, and obtain a \ref build-a-discord-bot-windows-visual-studio "pre-made Visual Studio template containing the latest D++ build (for 32 and 64 bit, release and debug profiles) by clicking here". 1. Make sure you have Visual Studio 2019 or 2022. Community, Professional or Enterprise work fine. These instructions are not for Visual Studio Code. You can [download the correct version here](https://visualstudio.microsoft.com/downloads/). Note that older versions of Visual Studio will not work as they do not support enough of the C++17 standard. @@ -50,8 +50,11 @@ To add D++ to a Visual Studio project, using **Visual Studio 2019** or **Visual ## Troubleshooting +\note A much easier way of getting a bot running is available \ref build-a-discord-bot-windows-visual-studio "here"! We recommend using that one if this process seems too complex or you run into too many issues. + - If you get an error that a DLL is missing (e.g. `dpp.dll` or `opus.dll`) when starting your bot, then simply copy all DLLs from the **bin** directory of where you extracted the D++ zip file to, into the same directory where your bot's executable is. You only need to do this once. There should be several of these DLL files: `dpp.dll`, `zlib.dll`, `openssl.dll` and `libcrypto.dll` (or similarly named SSL related files), `libsodium.dll` and `opus.dll`. - Please note that if you change the architecture (step 13) you must reconfigure all of steps 7 through 12 again as these configurations are specific to each architecture. This is to allow for different sets of precompiled libs, e.g. for `x86`, `x64`, etc. +- If you get an error that says "Debug/Release mismatch", **you are using the wrong configuration of the D++ dll**. Your bot's executable and the dpp.dll file should both be built in either Release or Debug, you get this error if they are different. We recommend using \ref build-a-discord-bot-windows-visual-studio "the bot template", it has all those things already set up. - You should run your bot from a command prompt. If you do not, and it exits, you will not be able to see any output as the window will immediately close. - If you need to update the `opus.dll` or `zlib.dll` (or any other prebuilt dll) these can be obtained by requesting them to be installed via `vcpkg` then copying the dlls, libraries and headers from the vcpkg `install` folder. - Stuck? You can find us on the [official discord server](https://discord.gg/dpp) - ask away! We don't bite! diff --git a/docpages/make_a_bot/windows_vs.md b/docpages/make_a_bot/windows_vs.md index 6726ab7cec..9755efde9b 100644 --- a/docpages/make_a_bot/windows_vs.md +++ b/docpages/make_a_bot/windows_vs.md @@ -22,10 +22,19 @@ If you prefer a video tutorial, you can watch the video below! Otherwise, scroll \image html vsproj_2.png 5. Click "Local Windows debugger" to compile and run your bot! \image html vsproj_3.png -6. Observe the build output. There may be warnings, but so long as the build output ends with "1 succeeded" then the process has worked. You may now run your bot! +6. Observe the build output, so long as the build output ends with "1 succeeded" then the process has worked. You may now run your bot! \image html vsproj_14.png ## Troubleshooting +- If you get an error that looks like this: \code{.unparsed} 1>MyBot.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: class dpp::async +__cdecl dpp::interaction_create_t::co_reply(class std::basic_string,class std::allocator > const &)const +" (__imp_?co_reply@interaction_create_t@dpp@@QEBA?AV?$async@Uconfirmation_callback_t@dpp@@@2@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) +referenced in function "public: class dpp::task __cdecl `int __cdecl main(void)'::`2'::$_ResumeCoro$1::operator()(struct dpp::slashcommand_t const &)const " +(??R$_ResumeCoro$1@?1??main@@YAHXZ@QEBA?AV?$task@X@dpp@@AEBUslashcommand_t@3@@Z) +1>...\windows-bot-template-main\x64\Debug\MyBot.exe : fatal error LNK1120: 1 unresolved externals +1>Done building project "MyBot.vcxproj" -- FAILED. +\endcode Make sure your don't have another version of the library installed through vcpkg. The template uses a slightly different version of D++ that has coroutines, while the vcpkg version does not, and the latter overwrites it! Uninstalling the library through vcpkg should fix this issue. - If you get an error that a DLL is missing (e.g. `dpp.dll` or `opus.dll`) when starting your bot, then simply copy all DLLs from the **bin** directory of where you cloned the D++ repository to, into the same directory where your bot's executable is. You only need to do this once. There should be several of these DLL files: `dpp.dll`, `zlib.dll`, `openssl.dll` and `libcrypto.dll` (or similarly named SSL related files), `libsodium.dll` and `opus.dll`. Note the template project does this for you, so you should never encounter this issue. +- If you get an error that says "Debug/Release mismatch", **you are using the wrong configuration of the D++ dll**. Your bot's executable and the dpp.dll file should both be built in the same configuration (Release or Debug), you get this error if they are different. **This also means you altered the template in a significant way,** we recommend you undo your modifications or reinstall the template. - Stuck? You can find us on the [official Discord server](https://discord.gg/dpp) - ask away! We don't bite! From 9d498f36ee214ffe5362ab4f9d52a28cd63475cc Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Sat, 6 Jan 2024 13:21:11 -0500 Subject: [PATCH 16/89] fix: send stickers in message if present --- include/dpp/message.h | 2 +- src/dpp/message.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/dpp/message.h b/include/dpp/message.h index f2b1d1b7e6..e8cbae17b9 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -1848,7 +1848,7 @@ struct DPP_EXPORT message : public managed, json_interface { snowflake webhook_id; /** - * @brief Stickers. + * @brief Partial stickers. Only id, name and format_type are filled */ std::vector stickers; diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index d4523b5ff7..5e74fcf083 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -942,6 +942,12 @@ json message::to_json(bool with_id, bool is_interaction_response) const { } } + if (stickers.size()) { + auto [it, _] = j.emplace("sticker_ids", json::array()); + for (const sticker &s : stickers) { + it->push_back(std::to_string(s.id)); + } + } j["components"] = json::array(); for (auto & component : components) { From aa697142577b378980ff11b86b4a576381903399 Mon Sep 17 00:00:00 2001 From: Amber Ehrlich Date: Sat, 6 Jan 2024 13:36:40 -0500 Subject: [PATCH 17/89] feat: dpp::message::add_sticker --- include/dpp/message.h | 18 ++++++++++++++++++ src/dpp/message.cpp | 22 ++++++++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/include/dpp/message.h b/include/dpp/message.h index e8cbae17b9..4a593ecf7a 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -2181,6 +2181,24 @@ struct DPP_EXPORT message : public managed, json_interface { */ message& add_embed(const embed& e); + /** + * @brief Add a sticker to this message + * + * As of writing this, a message can only contain up to 3 stickers + * @param s sticker to add + * @return message& reference to self + */ + message& add_sticker(const sticker& s); + + /** + * @brief Add a sticker to this message + * + * As of writing this, a message can only contain up to 3 stickers + * @param id id of the sticker to add + * @return message& reference to self + */ + message& add_sticker(const snowflake& id); + /** * @brief Set the flags * diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index 5e74fcf083..9b304cf094 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -535,26 +535,32 @@ message::message(snowflake _channel_id, const std::string &_content, message_typ type = t; } -message& message::add_component(const component& c) -{ +message& message::add_component(const component& c) { components.emplace_back(c); return *this; } -message& message::add_embed(const embed& e) -{ +message& message::add_embed(const embed& e) { embeds.emplace_back(e); return *this; } -message& message::set_flags(uint16_t f) -{ +message& message::add_sticker(const sticker& s) { + stickers.emplace_back(s); + return *this; +} + +message& message::add_sticker(const snowflake& id) { + stickers.emplace_back().id = id; + return *this; +} + +message& message::set_flags(uint16_t f) { flags = f; return *this; } -message& message::set_type(message_type t) -{ +message& message::set_type(message_type t) { type = t; return *this; } From 468a1971cb01d20df7b60986fe3cf3378e16cbb7 Mon Sep 17 00:00:00 2001 From: folospior Date: Sat, 6 Jan 2024 21:14:29 +0100 Subject: [PATCH 18/89] docs: Update Xcode page. (#1061) --- docpages/make_a_bot/xcode.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docpages/make_a_bot/xcode.md b/docpages/make_a_bot/xcode.md index 7247e38b8d..519d2a07d5 100644 --- a/docpages/make_a_bot/xcode.md +++ b/docpages/make_a_bot/xcode.md @@ -4,8 +4,6 @@ To create a bot with Xcode, follow the steps below to create a *working skeleton project you can build upon*. -\note Since the brew package for D++ only supports C++17, you can't use coro with this project. If you wish to use coro, you need to \ref buildosx "build from source". If you do build from source, look to replace the include and library paths in this project to `/usr/local/include` and `/usr/local/lib`. - 1. Make sure you have Xcode downloaded, along with the developer command tools (for AppleClang). 2. Clone the [template project](https://github.com/Jaskowicz1/mac-bot-template/). **Make sure you download the entire project and not just the .cpp file.** 3. Open Xcode, hit "Open Existing Project" or "File"->"Open", navigate to the template folder and open the .xcodeproj file. You can also double click the file in Finder. From 3237a74b46fd8aa7b528f1dffc0af532399dbd7c Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Fri, 12 Jan 2024 14:52:58 +0000 Subject: [PATCH 19/89] feat: Added the ability to set voice channel statuses (#1064) --- include/dpp/cluster.h | 11 +++++++++++ include/dpp/cluster_coro_calls.h | 12 ++++++++++++ include/dpp/cluster_sync_calls.h | 15 +++++++++++++++ src/dpp/cluster/channel.cpp | 5 +++++ src/dpp/cluster_coro_calls.cpp | 4 ++++ src/dpp/cluster_sync_calls.cpp | 4 ++++ 6 files changed, 51 insertions(+) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index a3a632e95e..eb275d96bf 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -3703,6 +3703,17 @@ class DPP_EXPORT cluster { */ void skus_get(command_completion_event_t callback = utility::log_error()); + /** + * @brief Set the status of a voice channel. + * + * @see https://github.com/discord/discord-api-docs/pull/6400 (please replace soon). + * @param channel_id The channel to update. + * @param status The new status for the channel. + * @param callback Function to call when the API call completes. + * On success the callback will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void channel_set_voice_status(snowflake channel_id, const std::string& status, command_completion_event_t callback = utility::log_error()); + #include #ifdef DPP_CORO #include diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index 22cdcef0c4..21431c9dfa 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -576,6 +576,18 @@ */ [[nodiscard]] async co_channels_get(snowflake guild_id); +/** + * @brief Set the status of a voice channel. + * + * @see dpp::cluster::channel_set_voice_status + * @see https://github.com/discord/discord-api-docs/pull/6400 (please replace soon). + * @param channel_id The channel to update. + * @param status The new status for the channel. + * @return confirmation returned object on completion + * \memberof dpp::cluster + */ +[[nodiscard]] async co_channel_set_voice_status(snowflake channel_id, const std::string& status); + /** * @brief Create a dm channel * @see dpp::cluster::create_dm_channel diff --git a/include/dpp/cluster_sync_calls.h b/include/dpp/cluster_sync_calls.h index 26e81f111a..140b9ba5a1 100644 --- a/include/dpp/cluster_sync_calls.h +++ b/include/dpp/cluster_sync_calls.h @@ -714,6 +714,21 @@ confirmation channel_typing_sync(snowflake cid); */ channel_map channels_get_sync(snowflake guild_id); +/** + * @brief Set the status of a voice channel. + * + * @see dpp::cluster::channel_set_voice_status + * @see https://github.com/discord/discord-api-docs/pull/6400 (please replace soon). + * @param channel_id The channel to update. + * @param status The new status for the channel. + * @return confirmation returned object on completion + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +confirmation channel_set_voice_status_sync(snowflake channel_id, const std::string& status); + /** * @brief Create a dm channel * @see dpp::cluster::create_dm_channel diff --git a/src/dpp/cluster/channel.cpp b/src/dpp/cluster/channel.cpp index 5b51448faf..388547f034 100644 --- a/src/dpp/cluster/channel.cpp +++ b/src/dpp/cluster/channel.cpp @@ -98,4 +98,9 @@ void cluster::channels_get(snowflake guild_id, command_completion_event_t callba rest_request_list(this, API_PATH "/guilds", std::to_string(guild_id), "channels", m_get, "", callback); } +void cluster::channel_set_voice_status(snowflake channel_id, const std::string& status, command_completion_event_t callback) { + json j({ {"status", status} }); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "voice-status", m_put, j.dump(), callback); +} + } // namespace dpp diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp index d03183cdeb..28f0eca82a 100644 --- a/src/dpp/cluster_coro_calls.cpp +++ b/src/dpp/cluster_coro_calls.cpp @@ -219,6 +219,10 @@ async cluster::co_channels_get(snowflake guild_id) { return async{ this, static_cast(&cluster::channels_get), guild_id }; } +async cluster::co_channel_set_voice_status(snowflake channel_id, const std::string& status) { + return async{ this, static_cast(&cluster::channel_set_voice_status), channel_id, status }; +} + async cluster::co_create_dm_channel(snowflake user_id) { return async{ this, static_cast(&cluster::create_dm_channel), user_id }; } diff --git a/src/dpp/cluster_sync_calls.cpp b/src/dpp/cluster_sync_calls.cpp index 66e057c1ee..876c0d0327 100644 --- a/src/dpp/cluster_sync_calls.cpp +++ b/src/dpp/cluster_sync_calls.cpp @@ -217,6 +217,10 @@ channel_map cluster::channels_get_sync(snowflake guild_id) { return dpp::sync(this, static_cast(&cluster::channels_get), guild_id); } +confirmation cluster::channel_set_voice_status_sync(snowflake channel_id, const std::string& status) { + return dpp::sync(this, static_cast(&cluster::channel_set_voice_status), channel_id, status); +} + channel cluster::create_dm_channel_sync(snowflake user_id) { return dpp::sync(this, static_cast(&cluster::create_dm_channel), user_id); } From aaffc5ca2b859ff93697482a5579196bf8773198 Mon Sep 17 00:00:00 2001 From: Arshia Aghaei Date: Thu, 25 Jan 2024 15:16:12 +0330 Subject: [PATCH 20/89] Added dpp::cluster::guild_member_timeout_remove and its sync/coro versions (#1067) --- include/dpp/cluster.h | 13 +++++++++++++ include/dpp/cluster_coro_calls.h | 14 ++++++++++++++ include/dpp/cluster_sync_calls.h | 17 +++++++++++++++++ src/dpp/cluster/guild_member.cpp | 6 ++++++ src/dpp/cluster_coro_calls.cpp | 4 ++++ src/dpp/cluster_sync_calls.cpp | 4 ++++ 6 files changed, 58 insertions(+) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index eb275d96bf..45b79dd0ea 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -2389,6 +2389,19 @@ class DPP_EXPORT cluster { */ void guild_member_timeout(snowflake guild_id, snowflake user_id, time_t communication_disabled_until, command_completion_event_t callback = utility::log_error()); + /** + * @brief Remove the timeout of a guild member. + * A shortcut for guild_member_timeout(guild_id, user_id, 0, callback) + * Fires a `Guild Member Update` Gateway event. + * @see https://discord.com/developers/docs/resources/guild#modify-guild-member + * @note This method supports audit log reasons set by the cluster::set_audit_reason() method. + * @param guild_id Guild ID to remove the member timeout from + * @param user_id User ID to remove the timeout for + * @param callback Function to call when the API call completes. + * On success the callback will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void guild_member_timeout_remove(snowflake guild_id, snowflake user_id, command_completion_event_t callback = utility::log_error()); + /** * @brief Add guild ban * diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index 21431c9dfa..018af88503 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -1236,6 +1236,20 @@ */ [[nodiscard]] async co_guild_member_timeout(snowflake guild_id, snowflake user_id, time_t communication_disabled_until); +/** + * @brief Remove the timeout of a guild member. + * A shortcut for guild_member_timeout(guild_id, user_id, 0, callback) + * Fires a `Guild Member Update` Gateway event. + * @see dpp::cluster::guild_member_timeout_remove + * @see https://discord.com/developers/docs/resources/guild#modify-guild-member + * @note This method supports audit log reasons set by the cluster::set_audit_reason() method. + * @param guild_id Guild ID to remove the member timeout from + * @param user_id User ID to remove the timeout for + * @return confirmation returned object on completion + * \memberof dpp::cluster + */ +[[nodiscard]] async co_guild_member_timeout_remove(snowflake guild_id, snowflake user_id); + /** * @brief Remove role from guild member * diff --git a/include/dpp/cluster_sync_calls.h b/include/dpp/cluster_sync_calls.h index 140b9ba5a1..6764719a83 100644 --- a/include/dpp/cluster_sync_calls.h +++ b/include/dpp/cluster_sync_calls.h @@ -1512,6 +1512,23 @@ confirmation guild_member_kick_sync(snowflake guild_id, snowflake user_id); */ confirmation guild_member_timeout_sync(snowflake guild_id, snowflake user_id, time_t communication_disabled_until); +/** + * @brief Remove the timeout of a guild member. + * A shortcut for guild_member_timeout(guild_id, user_id, 0, callback) + * Fires a `Guild Member Update` Gateway event. + * @see dpp::cluster::guild_member_timeout_remove + * @see https://discord.com/developers/docs/resources/guild#modify-guild-member + * @note This method supports audit log reasons set by the cluster::set_audit_reason() method. + * @param guild_id Guild ID to remove the member timeout from + * @param user_id User ID to remove the timeout for + * @return confirmation returned object on completion + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +confirmation guild_member_timeout_remove_sync(snowflake guild_id, snowflake user_id); + /** * @brief Remove role from guild member * diff --git a/src/dpp/cluster/guild_member.cpp b/src/dpp/cluster/guild_member.cpp index e851e9c7ad..5921d5a2b1 100644 --- a/src/dpp/cluster/guild_member.cpp +++ b/src/dpp/cluster/guild_member.cpp @@ -96,6 +96,12 @@ void cluster::guild_member_timeout(snowflake guild_id, snowflake user_id, time_t rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(), callback); } +void cluster::guild_member_timeout_remove(snowflake guild_id, snowflake user_id, command_completion_event_t callback) { + json j; + j["communication_disabled_until"] = json::value_t::null; + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(), callback); +} + void cluster::guild_member_delete_role(snowflake guild_id, snowflake user_id, snowflake role_id, command_completion_event_t callback) { rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id) + "/roles/" + std::to_string(role_id), m_delete, "", callback); diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp index 28f0eca82a..5f8ae7b971 100644 --- a/src/dpp/cluster_coro_calls.cpp +++ b/src/dpp/cluster_coro_calls.cpp @@ -411,6 +411,10 @@ async cluster::co_guild_member_timeout(snowflake guild_ return async{ this, static_cast(&cluster::guild_member_timeout), guild_id, user_id, communication_disabled_until }; } +async cluster::co_guild_member_timeout_remove(snowflake guild_id, snowflake user_id) { + return async{ this, static_cast(&cluster::guild_member_timeout_remove), guild_id, user_id }; +} + async cluster::co_guild_member_delete_role(snowflake guild_id, snowflake user_id, snowflake role_id) { return async{ this, static_cast(&cluster::guild_member_delete_role), guild_id, user_id, role_id }; } diff --git a/src/dpp/cluster_sync_calls.cpp b/src/dpp/cluster_sync_calls.cpp index 876c0d0327..a19ec593fc 100644 --- a/src/dpp/cluster_sync_calls.cpp +++ b/src/dpp/cluster_sync_calls.cpp @@ -409,6 +409,10 @@ confirmation cluster::guild_member_timeout_sync(snowflake guild_id, snowflake us return dpp::sync(this, static_cast(&cluster::guild_member_timeout), guild_id, user_id, communication_disabled_until); } +confirmation cluster::guild_member_timeout_remove_sync(snowflake guild_id, snowflake user_id) { + return dpp::sync(this, static_cast(&cluster::guild_member_timeout_remove), guild_id, user_id); +} + confirmation cluster::guild_member_delete_role_sync(snowflake guild_id, snowflake user_id, snowflake role_id) { return dpp::sync(this, static_cast(&cluster::guild_member_delete_role), guild_id, user_id, role_id); } From 71263e84de880a4c3bcbf67abaf9dec8f2559517 Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Fri, 26 Jan 2024 15:29:01 +0000 Subject: [PATCH 21/89] ci: labeler no longer fails (#1068) --- .github/labeler.yml | 75 +++++++++++++++++++++-------------- .github/workflows/labeler.yml | 2 +- 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 62a6ca852e..b3941c42c3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,35 +1,52 @@ documentation: -- '**Doxyfile' -- '**docpages/**' -- '**/*.h' -- '**/documentation.yml' -- '**.cspell.json' -- '**README.md' -- '**SECURITY.md' -- '**CONTRIBUTING.md' -- '**CODE_OF_CONDUCT.md' +- changed-files: + - any-glob-to-any-file: + - '**Doxyfile' + - '**docpages/**' + - '**/*.h' + - '**/documentation.yml' + - '**.cspell.json' + - '**README.md' + - '**SECURITY.md' + - '**CONTRIBUTING.md' + - '**CODE_OF_CONDUCT.md' + build: -- '**buildtools/**' -- '**cmake/**' -- '**library-vcpkg/**' -- '**library/**' -- '**win32/**' -- '**CMakeLists.txt' -- '**CMakeSettings.json' -- '**settings.json' -- '**dpp.pc.in' +- changed-files: + - any-glob-to-any-file: + - '**buildtools/**' + - '**cmake/**' + - '**library-vcpkg/**' + - '**library/**' + - '**win32/**' + - '**CMakeLists.txt' + - '**CMakeSettings.json' + - '**settings.json' + - '**dpp.pc.in' + packaging: -- '**vcpkg/**' -- '**makerelease.sh' -- '**sign.sh' -- '**Dockerfile' +- changed-files: + - any-glob-to-any-file: + - '**vcpkg/**' + - '**makerelease.sh' + - '**sign.sh' + - '**Dockerfile' + submodules: -- '**.gitmodules' -- '**doxygen-awesome-css/**' # Ideally, nobody should be touching this, but it's here just in-case. +- changed-files: + - any-glob-to-any-file: + - '**.gitmodules' + - '**doxygen-awesome-css/**' # Ideally, nobody should be touching this, but it's here just in-case. + github_actions: -- '**.github/labeler.yml' -- '**.github/dependabot.yml' -- '**.github/workflows/**' +- changed-files: + - any-glob-to-any-file: + - '**.github/labeler.yml' + - '**.github/dependabot.yml' + - '**.github/workflows/**' + code: -- '**src/**' -- '**include/**' +- changed-files: + - any-glob-to-any-file: + - '**src/**' + - '**include/**' diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 4cc35411d4..7add5f9e35 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -7,7 +7,7 @@ permissions: contents: read jobs: - triage: + labeler: permissions: pull-requests: write # Labeler needs to be able to add labels to PRs. runs-on: ubuntu-latest From 12df0ab196865fe5b68d0f2ce38574751f50168e Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Mon, 29 Jan 2024 16:37:27 +0000 Subject: [PATCH 22/89] feat: added newly_created bool to threads (#1069) --- include/dpp/thread.h | 6 ++++++ src/dpp/thread.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/include/dpp/thread.h b/include/dpp/thread.h index 2dee940be0..893ef04a28 100644 --- a/include/dpp/thread.h +++ b/include/dpp/thread.h @@ -165,6 +165,12 @@ class DPP_EXPORT thread : public channel, public json_interface { */ uint8_t member_count = 0; + /** + * @brief Was this thread newly created? + * @note This will only show in dpp::cluster::on_thread_create if the thread was just made. + */ + bool newly_created{false}; + /** * @brief Returns true if the thread is within an announcement channel * diff --git a/src/dpp/thread.cpp b/src/dpp/thread.cpp index 9c95954c23..8cfe5d618a 100644 --- a/src/dpp/thread.cpp +++ b/src/dpp/thread.cpp @@ -44,6 +44,8 @@ thread& thread::fill_from_json_impl(json* j) { set_int32_not_null(j, "total_message_sent", this->total_messages_sent); set_int8_not_null(j, "message_count", this->message_count); set_int8_not_null(j, "member_count", this->member_count); + set_bool_not_null(j, "newly_created", this->newly_created); + auto json_metadata = (*j)["thread_metadata"]; metadata.archived = bool_not_null(&json_metadata, "archived"); metadata.archive_timestamp = ts_not_null(&json_metadata, "archive_timestamp"); From 81d4875b4334efdd63241eafac2e94309e89f711 Mon Sep 17 00:00:00 2001 From: Piotr Chorzelewski <45640997+harrrson@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:38:08 +0100 Subject: [PATCH 23/89] feat: Added expire and issued timestamps in attachment (#1065) --- include/dpp/message.h | 14 ++++++++++++++ src/dpp/message.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/dpp/message.h b/include/dpp/message.h index 4a593ecf7a..1c274b3ae8 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -1172,6 +1172,20 @@ struct DPP_EXPORT attachment { * @return true if remixed */ bool is_remix() const; + + /** + * @brief Returns expiration timestamp for attachment's URL + * + * @return timestamp of URL expiration + */ + time_t get_expire_time() const; + + /** + * @brief Returns creation timestamp for attachment's URL + * + * @return timestamp of URL creation + */ + time_t get_issued_time() const; }; /** diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index 9b304cf094..b7da4fc5af 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -882,6 +882,38 @@ bool attachment::is_remix() const { return flags & a_is_remix; } +time_t attachment::get_expire_time() const { + size_t attr_position = url.find('?'); + /* If no attributes were sent in url, we do not need to parse more */ + if(url.npos == attr_position){ + return 0; + } + std::string attributes = url.substr(attr_position + 1); + std::vector attr_list = utility::tokenize(attributes, "&"); + auto ex_attr = std::find_if(attr_list.begin(), attr_list.end(), [](const std::string& s){return s.substr(0, 3) == "ex=";}); + if(attr_list.end() == ex_attr){ + return 0; + } + /* Erase 'ex=' prefix before parsing */ + return std::stol(ex_attr->substr(3), nullptr, 16); +} + +time_t attachment::get_issued_time() const { + size_t attr_position = url.find('?'); + /* No attributes were sent in url, so we do not need to parse more */ + if(url.npos == attr_position){ + return 0; + } + std::string attributes = url.substr(attr_position + 1); + std::vector attr_list = utility::tokenize(attributes, "&"); + auto is_attr = std::find_if(attr_list.begin(), attr_list.end(), [](const std::string& s){return s.substr(0, 3) == "is=";}); + if(attr_list.end() == is_attr){ + return 0; + } + /* Erase 'is=' prefix before parsing */ + return std::stol(is_attr->substr(3), nullptr, 16); +} + json message::to_json(bool with_id, bool is_interaction_response) const { /* This is the basics. once it works, expand on it. */ json j({ From e40b954e2755b892faa3fe0ef12919e0065ec25a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:15:41 +0000 Subject: [PATCH 24/89] build(deps): bump ubuntu from `f2034e7` to `bb1c416` (#1076) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fcee08471c..d70d882be2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:focal@sha256:f2034e7195f61334e6caff6ecf2e965f92d11e888309065da85ff50c617732b8 +FROM ubuntu:focal@sha256:bb1c41682308d7040f74d103022816d41c50d7b0c89e9d706a74b4e548636e54 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --no-install-recommends -y libssl-dev zlib1g-dev libsodium-dev libopus-dev cmake pkg-config g++ gcc git make && apt-get clean && rm -rf /var/lib/apt/lists/* From 74bb72755ff4ec0ddcaa4cd54a972dae605b4f2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:16:24 +0000 Subject: [PATCH 25/89] build(deps): bump github/codeql-action from 3.22.12 to 3.23.2 (#1075) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 91b0a78a4b..1a476d0758 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -50,7 +50,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -65,6 +65,6 @@ jobs: make -j2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 491626b5a5..4ed2606803 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -72,6 +72,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12 + uses: github/codeql-action/upload-sarif@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 with: sarif_file: results.sarif From 0782618a0ba674d22954b4385f9e75acd2a0e2d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:17:11 +0000 Subject: [PATCH 26/89] build(deps): bump actions/upload-artifact from 4.0.0 to 4.3.0 (#1074) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/scorecard.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e70f31207a..783d0ab6fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,14 +91,14 @@ jobs: - name: Upload Binary (DEB) if: ${{ matrix.cfg.cpack == 'yes' }} - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: "libdpp - Debian Package ${{matrix.cfg.arch}}" path: '${{github.workspace}}/build/*.deb' - name: Upload Binary (RPM) if: ${{ matrix.cfg.cpack == 'yes' }} - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: "libdpp - RPM Package ${{matrix.cfg.arch}}" path: '${{github.workspace}}/build/*.rpm' @@ -209,7 +209,7 @@ jobs: - name: Upload Binary if: ${{ matrix.cfg.upload }} - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: "libdpp - Windows ${{matrix.cfg.name}}-${{matrix.cfg.config}}-vs${{matrix.cfg.vs}}" path: '${{github.workspace}}/main/build/*.zip' @@ -251,13 +251,13 @@ jobs: run: cd build && sudo cpack --verbose || cat /home/runner/work/DPP/DPP/build/_CPack_Packages/Linux/DEB/PreinstallOutput.log - name: Upload Binaries (DEB) - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: "libdpp - Debian Package ${{matrix.cfg.name}}" path: "${{github.workspace}}/build/*.deb" - name: Upload Binaries (RPM) - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: "libdpp - RPM Package ${{matrix.cfg.name}}" path: "${{github.workspace}}/build/*.rpm" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 4ed2606803..7e863e7f66 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -64,7 +64,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: SARIF file path: results.sarif From 65a071a44542e80f23a2b59910059b89bd3094d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:17:30 +0000 Subject: [PATCH 27/89] build(deps): bump actions/dependency-review-action from 3.1.4 to 4.0.0 (#1073) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 10eb780233..3fa8b859bb 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -24,4 +24,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: 'Dependency Review' - uses: actions/dependency-review-action@01bc87099ba56df1e897b6874784491ea6309bc4 # v3.1.4 + uses: actions/dependency-review-action@4901385134134e04cec5fbe5ddfe3b2c5bd5d976 # v4.0.0 From efd947cb4721756c7459d3d48429ef830c18a3c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:17:49 +0000 Subject: [PATCH 28/89] build(deps): bump GitGuardian/ggshield-action from 1.22.0 to 1.24.0 (#1072) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 23dfe6d00c..a274a5f11b 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -23,7 +23,7 @@ jobs: with: fetch-depth: 0 # fetch all history so multiple commits can be scanned - name: GitGuardian scan - uses: GitGuardian/ggshield-action@9074c0893e8ee86ccd6418177a0eb3e5aa02262a # master + uses: GitGuardian/ggshield-action@8d9acaf1808c26018eb69e0fe8adee8161417101 # master env: GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} From dfb80047d1bd24532b17a83ac1ff0e5f6fea3180 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Feb 2024 05:18:09 +0000 Subject: [PATCH 29/89] build(deps): bump shivammathur/setup-php from 2.28.0 to 2.29.0 (#1071) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/construct-vcpkg-info.yml | 2 +- .github/workflows/documentation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/construct-vcpkg-info.yml b/.github/workflows/construct-vcpkg-info.yml index 847580c838..9c6291c4e4 100644 --- a/.github/workflows/construct-vcpkg-info.yml +++ b/.github/workflows/construct-vcpkg-info.yml @@ -20,7 +20,7 @@ jobs: egress-policy: audit - name: Setup PHP - uses: shivammathur/setup-php@e6f75134d35752277f093989e72e140eaa222f35 # v2 + uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # v2 with: php-version: '8.1' diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index fa11037649..269fee9327 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -30,7 +30,7 @@ jobs: egress-policy: audit - name: Setup PHP - uses: shivammathur/setup-php@e6f75134d35752277f093989e72e140eaa222f35 # v2 + uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # v2 with: php-version: '8.0' From 843bdc358b81032cc3d2f69e976fd33f652b5af4 Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Sun, 4 Feb 2024 04:29:53 -0500 Subject: [PATCH 30/89] fix: it's going to be OK (#1078) --- src/dpp/httpsclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dpp/httpsclient.cpp b/src/dpp/httpsclient.cpp index 31ef37e49c..d6e4bc7302 100644 --- a/src/dpp/httpsclient.cpp +++ b/src/dpp/httpsclient.cpp @@ -175,7 +175,7 @@ bool https_client::handle_buffer(std::string &buffer) h.erase(h.begin()); /* HTTP/1.1 200 OK */ std::vector req_status = utility::tokenize(status_line, " "); - if (req_status.size() >= 3 && (req_status[0] == "HTTP/1.1" || req_status[0] == "HTTP/1.0") && atoi(req_status[1].c_str())) { + if (req_status.size() >= 2 && (req_status[0] == "HTTP/1.1" || req_status[0] == "HTTP/1.0") && atoi(req_status[1].c_str())) { for(auto &hd : h) { std::string::size_type sep = hd.find(": "); if (sep != std::string::npos) { From d3e6d1e2b17d8cdba600195f0c3443845524d70b Mon Sep 17 00:00:00 2001 From: Axyte Date: Thu, 8 Feb 2024 17:58:40 +0530 Subject: [PATCH 31/89] [fix] default callback parameters (#1079) --- include/dpp/cluster.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index 45b79dd0ea..7f18f6e9aa 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -1427,7 +1427,7 @@ class DPP_EXPORT cluster { * @param callback Function to call when the API call completes. * On success the callback will contain a dpp::confirmation object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). */ - void interaction_followup_create(const std::string &token, const message &m, command_completion_event_t callback); + void interaction_followup_create(const std::string &token, const message &m, command_completion_event_t callback = utility::log_error()); /** * @brief Edit original followup message to a slash command @@ -2498,7 +2498,7 @@ class DPP_EXPORT cluster { * @param callback Function to call when the API call completes. * On success the callback will contain a dpp::dtemplate object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). */ - void guild_template_create(snowflake guild_id, const std::string &name, const std::string &description, command_completion_event_t callback); + void guild_template_create(snowflake guild_id, const std::string &name, const std::string &description, command_completion_event_t callback = utility::log_error()); /** * @brief Syncs the template to the guild's current state. From ac50140aaa6b6783c2a876aef93cabbf0ff3dc72 Mon Sep 17 00:00:00 2001 From: folospior Date: Thu, 15 Feb 2024 07:20:32 +0100 Subject: [PATCH 32/89] [feat] alter set_allowed_mentions (#1081) --- include/dpp/message.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/dpp/message.h b/include/dpp/message.h index 1c274b3ae8..d6def6a0d0 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -2074,15 +2074,15 @@ struct DPP_EXPORT message : public managed, json_interface { /** * @brief Set the allowed mentions object for pings on the message * - * @param _parse_users whether or not to parse users in the message content or embeds - * @param _parse_roles whether or not to parse roles in the message content or embeds - * @param _parse_everyone whether or not to parse everyone/here in the message content or embeds - * @param _replied_user if set to true and this is a reply, then ping the user we reply to - * @param users list of user ids to allow pings for - * @param roles list of role ids to allow pings for + * @param _parse_users whether or not to parse users in the message content or embeds, default false + * @param _parse_roles whether or not to parse roles in the message content or embeds, default false + * @param _parse_everyone whether or not to parse everyone/here in the message content or embeds, default false + * @param _replied_user if set to true and this is a reply, then ping the user we reply to, default false + * @param users list of user ids to allow pings for, default an empty vector + * @param roles list of role ids to allow pings for, default an empty vector * @return message& reference to self */ - message& set_allowed_mentions(bool _parse_users, bool _parse_roles, bool _parse_everyone, bool _replied_user, const std::vector &users, const std::vector &roles); + message& set_allowed_mentions(bool _parse_users = false, bool _parse_roles = false, bool _parse_everyone = false, bool _replied_user = false, const std::vector &users = {}, const std::vector &roles = {}); using json_interface::fill_from_json; using json_interface::to_json; From 053e6ca7a21b9f678de1b984d87d3661e6bb6d1c Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Thu, 15 Feb 2024 01:20:55 -0500 Subject: [PATCH 33/89] fix: fix bug in human readable errors (#1077) --- src/dpp/cluster/confirmation.cpp | 48 +++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/dpp/cluster/confirmation.cpp b/src/dpp/cluster/confirmation.cpp index 41cc6915a1..83f8d712bb 100644 --- a/src/dpp/cluster/confirmation.cpp +++ b/src/dpp/cluster/confirmation.cpp @@ -72,6 +72,36 @@ bool confirmation_callback_t::is_error() const { } } +namespace { + +std::vector find_errors_in_array(const std::string& obj, size_t index, const std::string& current_field, json::iterator begin, json::iterator end) { + std::vector ret; + + for (auto it = begin; it != end; ++it) { + if (auto errors = it->find("_errors"); errors != it->end()) { + for (auto errordetails = errors->begin(); errordetails != errors->end(); ++errordetails) { + error_detail detail; + detail.code = (*errordetails)["code"].get(); + detail.reason = (*errordetails)["message"].get(); + detail.field = current_field + it.key(); + detail.object = obj; + detail.index = index; + ret.emplace_back(detail); + } + } else { // subobject has errors + auto sub_errors = find_errors_in_array(obj, index, current_field + it.key() + ".", it->begin(), it->end()); + + if (!sub_errors.empty()) { + ret.reserve(ret.capacity() + sub_errors.size()); + std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(ret)); + } + } + } + return ret; +} + +} + error_info confirmation_callback_t::get_error() const { if (is_error()) { json j = json::parse(this->http_info.body); @@ -145,19 +175,11 @@ error_info confirmation_callback_t::get_error() const { /* An object that has a subobject with errors */ for (auto index = obj->begin(); index != obj->end(); ++index) { int array_index = std::atoll(index.key().c_str()); - for (auto index2 = index->begin(); index2 != index->end(); ++index2) { - if (index2->find("_errors") != index2->end()) { - /* A single object where one or more fields generated an error */ - for (auto errordetails = (*index2)["_errors"].begin(); errordetails != (*index2)["_errors"].end(); ++errordetails) { - error_detail detail; - detail.code = (*errordetails)["code"].get(); - detail.reason = (*errordetails)["message"].get(); - detail.object = obj.key(); - detail.field = index2.key(); - detail.index = array_index; - e.errors.emplace_back(detail); - } - } + auto sub_errors = find_errors_in_array(obj.key(), array_index, {}, index->begin(), index->end()); + + if (!sub_errors.empty()) { + e.errors.reserve(e.errors.capacity() + sub_errors.size()); + std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors)); } } } From 4334c9420b3d919a557253439415137a4f2ebb6a Mon Sep 17 00:00:00 2001 From: cmdeck2 <32135661+CMDisme@users.noreply.github.com> Date: Fri, 16 Feb 2024 11:26:39 -0500 Subject: [PATCH 34/89] Fixed getting archived threads Used get_active_threads as a template to properly implement threads_get_public_archived and threads_get_private_archived --- src/dpp/cluster/thread.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/dpp/cluster/thread.cpp b/src/dpp/cluster/thread.cpp index 8e8ab147e3..45b500e961 100644 --- a/src/dpp/cluster/thread.cpp +++ b/src/dpp/cluster/thread.cpp @@ -70,7 +70,20 @@ void cluster::threads_get_private_archived(snowflake channel_id, time_t before_t {"before", before_timestamp}, {"limit", limit}, }); - rest_request_list(this, API_PATH "/channels", std::to_string(channel_id), "/threads/archived/private" + parameters, m_get, "", callback); + this->post_rest(API_PATH "/channels", std::to_string(channel_id), "/threads/archived/private" + parameters, m_get, "", [this, callback](json &j, const http_request_completion_t& http) { + std::unordered_map list; + confirmation_callback_t e(this, confirmation(), http); + if (!e.is_error()) { + if (j.contains("threads")) { + for (auto &curr_item: j["threads"]) { + list[snowflake_not_null(&curr_item, "id")].fill_from_json(&curr_item); + } + } + } + if (callback) { + callback(confirmation_callback_t(this, list, http)); + } + }); } void cluster::threads_get_public_archived(snowflake channel_id, time_t before_timestamp, uint16_t limit, command_completion_event_t callback) { @@ -78,7 +91,20 @@ void cluster::threads_get_public_archived(snowflake channel_id, time_t before_ti {"before", before_timestamp}, {"limit", limit}, }); - rest_request_list(this, API_PATH "/channels", std::to_string(channel_id), "/threads/archived/public" + parameters, m_get, "", callback); + this->post_rest(API_PATH "/channels", std::to_string(channel_id), "/threads/archived/public" + parameters, m_get, "", [this, callback](json &j, const http_request_completion_t& http) { + std::unordered_map list; + confirmation_callback_t e(this, confirmation(), http); + if (!e.is_error()) { + if (j.contains("threads")) { + for (auto &curr_item: j["threads"]) { + list[snowflake_not_null(&curr_item, "id")].fill_from_json(&curr_item); + } + } + } + if (callback) { + callback(confirmation_callback_t(this, list, http)); + } + }); } void cluster::thread_member_get(const snowflake thread_id, const snowflake user_id, command_completion_event_t callback) { From 4b017b67fcfdd65f769c0995dbc8b94e79fa401b Mon Sep 17 00:00:00 2001 From: SelfishPig <62257049+SelfishPig@users.noreply.github.com> Date: Sat, 17 Feb 2024 11:46:48 -0600 Subject: [PATCH 35/89] Added change_voice_channel to discordclient (#1083) --- include/dpp/discordclient.h | 14 ++++++++++++++ src/dpp/discordclient.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/dpp/discordclient.h b/include/dpp/discordclient.h index ff2f7736f7..7d915035a0 100644 --- a/include/dpp/discordclient.h +++ b/include/dpp/discordclient.h @@ -504,6 +504,20 @@ class DPP_EXPORT discord_client : public websocket_client */ discord_client& connect_voice(snowflake guild_id, snowflake channel_id, bool self_mute = false, bool self_deaf = false); + /** + * @brief Change voice channel + * + * @param guild_id Guild where the voice channel is + * @param channel_id Channel ID of the voice channel + * @param self_mute True if the bot should mute itself + * @param self_deaf True if the bot should deafen itself + * @return reference to self + * @note This is NOT a synchronous blocking call! The bot isn't instantly ready to send or listen for audio, + * as we have to wait for the connection to the voice server to be established! + * e.g. wait for dpp::cluster::on_voice_ready event, and then send the audio within that event. + */ + discord_client& change_voice_channel(snowflake guild_id, snowflake channel_id, bool self_mute = false, bool self_deaf = false); + /** * @brief Disconnect from the connected voice channel on a guild * diff --git a/src/dpp/discordclient.cpp b/src/dpp/discordclient.cpp index 0f925f6313..63c322875e 100644 --- a/src/dpp/discordclient.cpp +++ b/src/dpp/discordclient.cpp @@ -634,6 +634,36 @@ discord_client& discord_client::connect_voice(snowflake guild_id, snowflake chan return *this; } +discord_client& discord_client::change_voice_channel(snowflake guild_id, snowflake channel_id, bool self_mute, bool self_deaf) { +#ifdef HAVE_VOICE + std::unique_lock lock(voice_mutex); + if (connecting_voice_channels.find(guild_id) != connecting_voice_channels.end()) { + if (connecting_voice_channels[guild_id]->channel_id != channel_id) { + connecting_voice_channels[guild_id] = std::make_unique(this, channel_id); + /* Once sent, this expects two events (in any order) on the websocket: + * VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE + */ + log(ll_debug, "Sending op 4 to change VC channel, guild " + std::to_string(guild_id) + " channel " + std::to_string(channel_id)); + queue_message(jsonobj_to_string(json({ + { "op", 4 }, + { "d", { + { "guild_id", std::to_string(guild_id) }, + { "channel_id", std::to_string(channel_id) }, + { "self_mute", self_mute }, + { "self_deaf", self_deaf }, + } + } + })), false); + } else { + log(ll_debug, "Requested the bot switch to voice channel " + std::to_string(channel_id) + " on guild " + std::to_string(guild_id) + ", but it seems we are already in this VC"); + } + } else { + log(ll_debug, "Requested the bot switch to voice channel " + std::to_string(channel_id) + " on guild " + std::to_string(guild_id) + ", but we aren't connected to a VC"); + } +#endif + return *this; +} + std::string discord_client::jsonobj_to_string(const nlohmann::json& json) { if (protocol == ws_json) { return json.dump(); From fdfe48bce8f28879504a130d9ffea97c84c70d42 Mon Sep 17 00:00:00 2001 From: SelfishPig <62257049+SelfishPig@users.noreply.github.com> Date: Mon, 19 Feb 2024 04:27:53 -0600 Subject: [PATCH 36/89] Merge change_voice_channel into connect_voice (#1085) --- include/dpp/discordclient.h | 14 -------- src/dpp/discordclient.cpp | 64 +++++++++++-------------------------- 2 files changed, 18 insertions(+), 60 deletions(-) diff --git a/include/dpp/discordclient.h b/include/dpp/discordclient.h index 7d915035a0..ff2f7736f7 100644 --- a/include/dpp/discordclient.h +++ b/include/dpp/discordclient.h @@ -504,20 +504,6 @@ class DPP_EXPORT discord_client : public websocket_client */ discord_client& connect_voice(snowflake guild_id, snowflake channel_id, bool self_mute = false, bool self_deaf = false); - /** - * @brief Change voice channel - * - * @param guild_id Guild where the voice channel is - * @param channel_id Channel ID of the voice channel - * @param self_mute True if the bot should mute itself - * @param self_deaf True if the bot should deafen itself - * @return reference to self - * @note This is NOT a synchronous blocking call! The bot isn't instantly ready to send or listen for audio, - * as we have to wait for the connection to the voice server to be established! - * e.g. wait for dpp::cluster::on_voice_ready event, and then send the audio within that event. - */ - discord_client& change_voice_channel(snowflake guild_id, snowflake channel_id, bool self_mute = false, bool self_deaf = false); - /** * @brief Disconnect from the connected voice channel on a guild * diff --git a/src/dpp/discordclient.cpp b/src/dpp/discordclient.cpp index 63c322875e..c1ba3a2a9c 100644 --- a/src/dpp/discordclient.cpp +++ b/src/dpp/discordclient.cpp @@ -609,57 +609,29 @@ uint64_t discord_client::get_channel_count() { } discord_client& discord_client::connect_voice(snowflake guild_id, snowflake channel_id, bool self_mute, bool self_deaf) { -#ifdef HAVE_VOICE - std::unique_lock lock(voice_mutex); - if (connecting_voice_channels.find(guild_id) == connecting_voice_channels.end()) { - connecting_voice_channels[guild_id] = std::make_unique(this, channel_id); - /* Once sent, this expects two events (in any order) on the websocket: - * VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE - */ - log(ll_debug, "Sending op 4 to join VC, guild " + std::to_string(guild_id) + " channel " + std::to_string(channel_id)); - queue_message(jsonobj_to_string(json({ - { "op", 4 }, - { "d", { - { "guild_id", std::to_string(guild_id) }, - { "channel_id", std::to_string(channel_id) }, - { "self_mute", self_mute }, - { "self_deaf", self_deaf }, - } - } - })), false); - } else { - log(ll_debug, "Requested the bot connect to voice channel " + std::to_string(channel_id) + " on guild " + std::to_string(guild_id) + ", but it seems we are already on this VC"); - } -#endif - return *this; -} - -discord_client& discord_client::change_voice_channel(snowflake guild_id, snowflake channel_id, bool self_mute, bool self_deaf) { #ifdef HAVE_VOICE std::unique_lock lock(voice_mutex); if (connecting_voice_channels.find(guild_id) != connecting_voice_channels.end()) { - if (connecting_voice_channels[guild_id]->channel_id != channel_id) { - connecting_voice_channels[guild_id] = std::make_unique(this, channel_id); - /* Once sent, this expects two events (in any order) on the websocket: - * VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE - */ - log(ll_debug, "Sending op 4 to change VC channel, guild " + std::to_string(guild_id) + " channel " + std::to_string(channel_id)); - queue_message(jsonobj_to_string(json({ - { "op", 4 }, - { "d", { - { "guild_id", std::to_string(guild_id) }, - { "channel_id", std::to_string(channel_id) }, - { "self_mute", self_mute }, - { "self_deaf", self_deaf }, - } - } - })), false); - } else { - log(ll_debug, "Requested the bot switch to voice channel " + std::to_string(channel_id) + " on guild " + std::to_string(guild_id) + ", but it seems we are already in this VC"); + if (connecting_voice_channels[guild_id]->channel_id == channel_id) { + log(ll_debug, "Requested the bot connect to voice channel " + std::to_string(channel_id) + " on guild " + std::to_string(guild_id) + ", but it seems we are already on this VC"); + return *this; } - } else { - log(ll_debug, "Requested the bot switch to voice channel " + std::to_string(channel_id) + " on guild " + std::to_string(guild_id) + ", but we aren't connected to a VC"); } + connecting_voice_channels[guild_id] = std::make_unique(this, channel_id); + /* Once sent, this expects two events (in any order) on the websocket: + * VOICE_SERVER_UPDATE and VOICE_STATUS_UPDATE + */ + log(ll_debug, "Sending op 4 to join VC, guild " + std::to_string(guild_id) + " channel " + std::to_string(channel_id)); + queue_message(jsonobj_to_string(json({ + { "op", 4 }, + { "d", { + { "guild_id", std::to_string(guild_id) }, + { "channel_id", std::to_string(channel_id) }, + { "self_mute", self_mute }, + { "self_deaf", self_deaf }, + } + } + })), false); #endif return *this; } From 23a9932c473a2f2e382afd2c0bf2b8eda32aa1cb Mon Sep 17 00:00:00 2001 From: "Craig Edwards (Brain)" Date: Mon, 19 Feb 2024 10:28:39 +0000 Subject: [PATCH 37/89] FIX: Potential uninitialised value returned if empty string passed to from_string() (#1087) --- .cspell.json | 5 +- .vscode/settings.json | 4 +- include/dpp/stringops.h | 3 + include/dpp/unicode_emoji.h | 292 +++++++++++++++++++++++++++++++++--- 4 files changed, 283 insertions(+), 21 deletions(-) diff --git a/.cspell.json b/.cspell.json index 5404e2ae81..8c27cde7bf 100644 --- a/.cspell.json +++ b/.cspell.json @@ -138,7 +138,10 @@ "sku", "skus", "Codecademy", - "tparam" + "tparam", + "khanda", + "oclock", + "moai" ], "flagWords": [ "hte" diff --git a/.vscode/settings.json b/.vscode/settings.json index 90c8db6d31..16f12674a0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -81,6 +81,8 @@ "semaphore": "cpp", "stop_token": "cpp", "charconv": "cpp", - "any": "cpp" + "any": "cpp", + "ranges": "cpp", + "span": "cpp" } } \ No newline at end of file diff --git a/include/dpp/stringops.h b/include/dpp/stringops.h index 279d84c6c9..9383fa4d06 100644 --- a/include/dpp/stringops.h +++ b/include/dpp/stringops.h @@ -139,6 +139,9 @@ template T from_string(const std::string &s, std::ios_base & (*f)(s */ template T from_string(const std::string &s) { + if (s.empty()) { + return static_cast(0); + } T t; std::istringstream iss(s); iss >> t; diff --git a/include/dpp/unicode_emoji.h b/include/dpp/unicode_emoji.h index 2a0e556706..ea832b9537 100644 --- a/include/dpp/unicode_emoji.h +++ b/include/dpp/unicode_emoji.h @@ -17,6 +17,7 @@ namespace unicode_emoji { inline constexpr const char _100[] = "💯"; inline constexpr const char _1234[] = "🔢"; inline constexpr const char soccer[] = "⚽"; + inline constexpr const char soccer_ball[] = "⚽"; inline constexpr const char basketball[] = "🏀"; inline constexpr const char football[] = "🏈"; inline constexpr const char baseball[] = "⚾"; @@ -31,6 +32,7 @@ namespace unicode_emoji { inline constexpr const char table_tennis[] = "🏓"; inline constexpr const char badminton[] = "🏸"; inline constexpr const char hockey[] = "🏒"; + inline constexpr const char ice_hockey[] = "🏒"; inline constexpr const char field_hockey[] = "🏑"; inline constexpr const char lacrosse[] = "🥍"; inline constexpr const char cricket_game[] = "🏏"; @@ -39,23 +41,27 @@ namespace unicode_emoji { inline constexpr const char goal[] = "🥅"; inline constexpr const char goal_net[] = "🥅"; inline constexpr const char golf[] = "⛳"; + inline constexpr const char flag_in_hole[] = "⛳"; inline constexpr const char kite[] = "🪁"; inline constexpr const char playground_slide[] = "🛝"; inline constexpr const char bow_and_arrow[] = "🏹"; inline constexpr const char archery[] = "🏹"; inline constexpr const char fishing_pole_and_fish[] = "🎣"; + inline constexpr const char fishing_pole[] = "🎣"; inline constexpr const char diving_mask[] = "🤿"; inline constexpr const char boxing_glove[] = "🥊"; inline constexpr const char boxing_gloves[] = "🥊"; inline constexpr const char martial_arts_uniform[] = "🥋"; inline constexpr const char karate_uniform[] = "🥋"; inline constexpr const char running_shirt_with_sash[] = "🎽"; + inline constexpr const char running_shirt[] = "🎽"; inline constexpr const char skateboard[] = "🛹"; inline constexpr const char roller_skate[] = "🛼"; inline constexpr const char sled[] = "🛷"; inline constexpr const char ice_skate[] = "⛸️"; inline constexpr const char curling_stone[] = "🥌"; inline constexpr const char ski[] = "🎿"; + inline constexpr const char skis[] = "🎿"; inline constexpr const char skier[] = "⛷️"; inline constexpr const char snowboarder[] = "🏂"; inline constexpr const char snowboarder_tone1[] = "🏂🏻"; @@ -595,10 +601,13 @@ namespace unicode_emoji { inline constexpr const char ballet_shoes[] = "🩰"; inline constexpr const char art[] = "🎨"; inline constexpr const char clapper[] = "🎬"; + inline constexpr const char clapper_board[] = "🎬"; inline constexpr const char microphone[] = "🎤"; inline constexpr const char headphones[] = "🎧"; + inline constexpr const char headphone[] = "🎧"; inline constexpr const char musical_score[] = "🎼"; inline constexpr const char musical_keyboard[] = "🎹"; + inline constexpr const char maracas[] = "🪇"; inline constexpr const char drum[] = "🥁"; inline constexpr const char drum_with_drumsticks[] = "🥁"; inline constexpr const char long_drum[] = "🪘"; @@ -608,21 +617,25 @@ namespace unicode_emoji { inline constexpr const char guitar[] = "🎸"; inline constexpr const char banjo[] = "🪕"; inline constexpr const char violin[] = "🎻"; + inline constexpr const char flute[] = "🪈"; inline constexpr const char game_die[] = "🎲"; inline constexpr const char chess_pawn[] = "♟️"; inline constexpr const char dart[] = "🎯"; + inline constexpr const char direct_hit[] = "🎯"; inline constexpr const char bowling[] = "🎳"; inline constexpr const char video_game[] = "🎮"; inline constexpr const char slot_machine[] = "🎰"; inline constexpr const char jigsaw[] = "🧩"; + inline constexpr const char puzzle_piece[] = "🧩"; inline constexpr const char flag_white[] = "🏳️"; inline constexpr const char flag_black[] = "🏴"; + inline constexpr const char pirate_flag[] = "🏴‍☠️"; inline constexpr const char checkered_flag[] = "🏁"; inline constexpr const char triangular_flag_on_post[] = "🚩"; inline constexpr const char rainbow_flag[] = "🏳️‍🌈"; inline constexpr const char gay_pride_flag[] = "🏳️‍🌈"; inline constexpr const char transgender_flag[] = "🏳️‍⚧️"; - inline constexpr const char pirate_flag[] = "🏴‍☠️"; + inline constexpr const char united_nations[] = "🇺🇳"; inline constexpr const char flag_af[] = "🇦🇫"; inline constexpr const char flag_ax[] = "🇦🇽"; inline constexpr const char flag_al[] = "🇦🇱"; @@ -884,17 +897,17 @@ namespace unicode_emoji { inline constexpr const char flag_sj[] = "🇸🇯"; inline constexpr const char flag_ta[] = "🇹🇦"; inline constexpr const char flag_um[] = "🇺🇲"; - inline constexpr const char united_nations[] = "🇺🇳"; inline constexpr const char green_apple[] = "🍏"; inline constexpr const char apple[] = "🍎"; + inline constexpr const char red_apple[] = "🍎"; inline constexpr const char pear[] = "🍐"; inline constexpr const char tangerine[] = "🍊"; inline constexpr const char lemon[] = "🍋"; inline constexpr const char banana[] = "🍌"; inline constexpr const char watermelon[] = "🍉"; inline constexpr const char grapes[] = "🍇"; - inline constexpr const char blueberries[] = "🫐"; inline constexpr const char strawberry[] = "🍓"; + inline constexpr const char blueberries[] = "🫐"; inline constexpr const char melon[] = "🍈"; inline constexpr const char cherries[] = "🍒"; inline constexpr const char peach[] = "🍑"; @@ -903,27 +916,30 @@ namespace unicode_emoji { inline constexpr const char coconut[] = "🥥"; inline constexpr const char kiwi[] = "🥝"; inline constexpr const char kiwifruit[] = "🥝"; + inline constexpr const char kiwi_fruit[] = "🥝"; inline constexpr const char tomato[] = "🍅"; inline constexpr const char eggplant[] = "🍆"; inline constexpr const char avocado[] = "🥑"; - inline constexpr const char olive[] = "🫒"; + inline constexpr const char pea_pod[] = "🫛"; inline constexpr const char broccoli[] = "🥦"; inline constexpr const char leafy_green[] = "🥬"; - inline constexpr const char bell_pepper[] = "🫑"; inline constexpr const char cucumber[] = "🥒"; inline constexpr const char hot_pepper[] = "🌶️"; + inline constexpr const char bell_pepper[] = "🫑"; inline constexpr const char corn[] = "🌽"; + inline constexpr const char ear_of_corn[] = "🌽"; inline constexpr const char carrot[] = "🥕"; + inline constexpr const char olive[] = "🫒"; inline constexpr const char garlic[] = "🧄"; inline constexpr const char onion[] = "🧅"; inline constexpr const char potato[] = "🥔"; inline constexpr const char sweet_potato[] = "🍠"; + inline constexpr const char ginger_root[] = "🫚"; inline constexpr const char croissant[] = "🥐"; inline constexpr const char bagel[] = "🥯"; inline constexpr const char bread[] = "🍞"; inline constexpr const char french_bread[] = "🥖"; inline constexpr const char baguette_bread[] = "🥖"; - inline constexpr const char flatbread[] = "🫓"; inline constexpr const char pretzel[] = "🥨"; inline constexpr const char cheese[] = "🧀"; inline constexpr const char cheese_wedge[] = "🧀"; @@ -941,7 +957,9 @@ namespace unicode_emoji { inline constexpr const char hot_dog[] = "🌭"; inline constexpr const char hamburger[] = "🍔"; inline constexpr const char fries[] = "🍟"; + inline constexpr const char french_fries[] = "🍟"; inline constexpr const char pizza[] = "🍕"; + inline constexpr const char flatbread[] = "🫓"; inline constexpr const char sandwich[] = "🥪"; inline constexpr const char stuffed_flatbread[] = "🥙"; inline constexpr const char stuffed_pita[] = "🥙"; @@ -958,15 +976,20 @@ namespace unicode_emoji { inline constexpr const char jar[] = "🫙"; inline constexpr const char spaghetti[] = "🍝"; inline constexpr const char ramen[] = "🍜"; + inline constexpr const char steaming_bowl[] = "🍜"; inline constexpr const char stew[] = "🍲"; + inline constexpr const char pot_of_food[] = "🍲"; inline constexpr const char curry[] = "🍛"; + inline constexpr const char curry_rice[] = "🍛"; inline constexpr const char sushi[] = "🍣"; inline constexpr const char bento[] = "🍱"; + inline constexpr const char bento_box[] = "🍱"; inline constexpr const char dumpling[] = "🥟"; inline constexpr const char oyster[] = "🦪"; inline constexpr const char fried_shrimp[] = "🍤"; inline constexpr const char rice_ball[] = "🍙"; inline constexpr const char rice[] = "🍚"; + inline constexpr const char cooked_rice[] = "🍚"; inline constexpr const char rice_cracker[] = "🍘"; inline constexpr const char fish_cake[] = "🍥"; inline constexpr const char fortune_cookie[] = "🥠"; @@ -979,7 +1002,9 @@ namespace unicode_emoji { inline constexpr const char pie[] = "🥧"; inline constexpr const char cupcake[] = "🧁"; inline constexpr const char cake[] = "🍰"; + inline constexpr const char shortcake[] = "🍰"; inline constexpr const char birthday[] = "🎂"; + inline constexpr const char birthday_cake[] = "🎂"; inline constexpr const char custard[] = "🍮"; inline constexpr const char pudding[] = "🍮"; inline constexpr const char flan[] = "🍮"; @@ -1000,6 +1025,7 @@ namespace unicode_emoji { inline constexpr const char baby_bottle[] = "🍼"; inline constexpr const char teapot[] = "🫖"; inline constexpr const char coffee[] = "☕"; + inline constexpr const char hot_beverage[] = "☕"; inline constexpr const char tea[] = "🍵"; inline constexpr const char mate[] = "🧉"; inline constexpr const char beverage_box[] = "🧃"; @@ -1007,6 +1033,7 @@ namespace unicode_emoji { inline constexpr const char bubble_tea[] = "🧋"; inline constexpr const char sake[] = "🍶"; inline constexpr const char beer[] = "🍺"; + inline constexpr const char beer_mug[] = "🍺"; inline constexpr const char beers[] = "🍻"; inline constexpr const char champagne_glass[] = "🥂"; inline constexpr const char clinking_glass[] = "🥂"; @@ -1027,21 +1054,29 @@ namespace unicode_emoji { inline constexpr const char chopsticks[] = "🥢"; inline constexpr const char salt[] = "🧂"; inline constexpr const char dog[] = "🐶"; + inline constexpr const char dog_face[] = "🐶"; inline constexpr const char cat[] = "🐱"; + inline constexpr const char cat_face[] = "🐱"; inline constexpr const char mouse[] = "🐭"; + inline constexpr const char mouse_face[] = "🐭"; inline constexpr const char hamster[] = "🐹"; inline constexpr const char rabbit[] = "🐰"; + inline constexpr const char rabbit_face[] = "🐰"; inline constexpr const char fox[] = "🦊"; inline constexpr const char fox_face[] = "🦊"; inline constexpr const char bear[] = "🐻"; inline constexpr const char panda_face[] = "🐼"; + inline constexpr const char panda[] = "🐼"; inline constexpr const char polar_bear[] = "🐻‍❄️"; inline constexpr const char koala[] = "🐨"; inline constexpr const char tiger[] = "🐯"; + inline constexpr const char tiger_face[] = "🐯"; inline constexpr const char lion_face[] = "🦁"; inline constexpr const char lion[] = "🦁"; inline constexpr const char cow[] = "🐮"; + inline constexpr const char cow_face[] = "🐮"; inline constexpr const char pig[] = "🐷"; + inline constexpr const char pig_face[] = "🐷"; inline constexpr const char pig_nose[] = "🐽"; inline constexpr const char frog[] = "🐸"; inline constexpr const char monkey_face[] = "🐵"; @@ -1055,26 +1090,31 @@ namespace unicode_emoji { inline constexpr const char baby_chick[] = "🐤"; inline constexpr const char hatching_chick[] = "🐣"; inline constexpr const char hatched_chick[] = "🐥"; + inline constexpr const char goose[] = "🪿"; inline constexpr const char duck[] = "🦆"; + inline constexpr const char black_bird[] = "🐦‍⬛"; inline constexpr const char eagle[] = "🦅"; inline constexpr const char owl[] = "🦉"; inline constexpr const char bat[] = "🦇"; inline constexpr const char wolf[] = "🐺"; inline constexpr const char boar[] = "🐗"; inline constexpr const char horse[] = "🐴"; + inline constexpr const char horse_face[] = "🐴"; inline constexpr const char unicorn[] = "🦄"; inline constexpr const char unicorn_face[] = "🦄"; + inline constexpr const char moose[] = "🫎"; inline constexpr const char bee[] = "🐝"; + inline constexpr const char honeybee[] = "🐝"; + inline constexpr const char worm[] = "🪱"; inline constexpr const char bug[] = "🐛"; inline constexpr const char butterfly[] = "🦋"; inline constexpr const char snail[] = "🐌"; - inline constexpr const char worm[] = "🪱"; inline constexpr const char lady_beetle[] = "🐞"; inline constexpr const char ant[] = "🐜"; inline constexpr const char fly[] = "🪰"; - inline constexpr const char mosquito[] = "🦟"; - inline constexpr const char cockroach[] = "🪳"; inline constexpr const char beetle[] = "🪲"; + inline constexpr const char cockroach[] = "🪳"; + inline constexpr const char mosquito[] = "🦟"; inline constexpr const char cricket[] = "🦗"; inline constexpr const char spider[] = "🕷️"; inline constexpr const char spider_web[] = "🕸️"; @@ -1086,26 +1126,26 @@ namespace unicode_emoji { inline constexpr const char sauropod[] = "🦕"; inline constexpr const char octopus[] = "🐙"; inline constexpr const char squid[] = "🦑"; + inline constexpr const char jellyfish[] = "🪼"; inline constexpr const char shrimp[] = "🦐"; inline constexpr const char lobster[] = "🦞"; inline constexpr const char crab[] = "🦀"; inline constexpr const char blowfish[] = "🐡"; inline constexpr const char tropical_fish[] = "🐠"; inline constexpr const char fish[] = "🐟"; - inline constexpr const char seal[] = "🦭"; inline constexpr const char dolphin[] = "🐬"; inline constexpr const char whale[] = "🐳"; inline constexpr const char whale2[] = "🐋"; inline constexpr const char shark[] = "🦈"; + inline constexpr const char seal[] = "🦭"; inline constexpr const char crocodile[] = "🐊"; inline constexpr const char tiger2[] = "🐅"; inline constexpr const char leopard[] = "🐆"; inline constexpr const char zebra[] = "🦓"; inline constexpr const char gorilla[] = "🦍"; inline constexpr const char orangutan[] = "🦧"; - inline constexpr const char elephant[] = "🐘"; inline constexpr const char mammoth[] = "🦣"; - inline constexpr const char bison[] = "🦬"; + inline constexpr const char elephant[] = "🐘"; inline constexpr const char hippopotamus[] = "🦛"; inline constexpr const char rhino[] = "🦏"; inline constexpr const char rhinoceros[] = "🦏"; @@ -1113,13 +1153,16 @@ namespace unicode_emoji { inline constexpr const char camel[] = "🐫"; inline constexpr const char giraffe[] = "🦒"; inline constexpr const char kangaroo[] = "🦘"; + inline constexpr const char bison[] = "🦬"; inline constexpr const char water_buffalo[] = "🐃"; inline constexpr const char ox[] = "🐂"; inline constexpr const char cow2[] = "🐄"; + inline constexpr const char donkey[] = "🫏"; inline constexpr const char racehorse[] = "🐎"; inline constexpr const char pig2[] = "🐖"; inline constexpr const char ram[] = "🐏"; inline constexpr const char sheep[] = "🐑"; + inline constexpr const char ewe[] = "🐑"; inline constexpr const char llama[] = "🦙"; inline constexpr const char goat[] = "🐐"; inline constexpr const char deer[] = "🦌"; @@ -1130,6 +1173,7 @@ namespace unicode_emoji { inline constexpr const char cat2[] = "🐈"; inline constexpr const char black_cat[] = "🐈‍⬛"; inline constexpr const char feather[] = "🪶"; + inline constexpr const char wing[] = "🪽"; inline constexpr const char rooster[] = "🐓"; inline constexpr const char turkey[] = "🦃"; inline constexpr const char dodo[] = "🦤"; @@ -1159,29 +1203,32 @@ namespace unicode_emoji { inline constexpr const char evergreen_tree[] = "🌲"; inline constexpr const char deciduous_tree[] = "🌳"; inline constexpr const char palm_tree[] = "🌴"; + inline constexpr const char wood[] = "🪵"; inline constexpr const char seedling[] = "🌱"; inline constexpr const char herb[] = "🌿"; inline constexpr const char shamrock[] = "☘️"; inline constexpr const char four_leaf_clover[] = "🍀"; inline constexpr const char bamboo[] = "🎍"; + inline constexpr const char potted_plant[] = "🪴"; inline constexpr const char tanabata_tree[] = "🎋"; inline constexpr const char leaves[] = "🍃"; inline constexpr const char fallen_leaf[] = "🍂"; inline constexpr const char maple_leaf[] = "🍁"; - inline constexpr const char empty_nest[] = "🪹"; inline constexpr const char nest_with_eggs[] = "🪺"; + inline constexpr const char empty_nest[] = "🪹"; inline constexpr const char mushroom[] = "🍄"; inline constexpr const char shell[] = "🐚"; + inline constexpr const char spiral_shell[] = "🐚"; inline constexpr const char coral[] = "🪸"; inline constexpr const char rock[] = "🪨"; - inline constexpr const char wood[] = "🪵"; inline constexpr const char ear_of_rice[] = "🌾"; - inline constexpr const char potted_plant[] = "🪴"; + inline constexpr const char sheaf_of_rice[] = "🌾"; inline constexpr const char bouquet[] = "💐"; inline constexpr const char tulip[] = "🌷"; inline constexpr const char rose[] = "🌹"; inline constexpr const char wilted_rose[] = "🥀"; inline constexpr const char wilted_flower[] = "🥀"; + inline constexpr const char hyacinth[] = "🪻"; inline constexpr const char lotus[] = "🪷"; inline constexpr const char hibiscus[] = "🌺"; inline constexpr const char cherry_blossom[] = "🌸"; @@ -1192,6 +1239,7 @@ namespace unicode_emoji { inline constexpr const char first_quarter_moon_with_face[] = "🌛"; inline constexpr const char last_quarter_moon_with_face[] = "🌜"; inline constexpr const char new_moon_with_face[] = "🌚"; + inline constexpr const char new_moon_face[] = "🌚"; inline constexpr const char full_moon[] = "🌕"; inline constexpr const char waning_gibbous_moon[] = "🌖"; inline constexpr const char last_quarter_moon[] = "🌗"; @@ -1208,16 +1256,21 @@ namespace unicode_emoji { inline constexpr const char dizzy[] = "💫"; inline constexpr const char star[] = "⭐"; inline constexpr const char star2[] = "🌟"; + inline constexpr const char glowing_star[] = "🌟"; inline constexpr const char sparkles[] = "✨"; inline constexpr const char zap[] = "⚡"; + inline constexpr const char high_voltage[] = "⚡"; inline constexpr const char comet[] = "☄️"; inline constexpr const char boom[] = "💥"; + inline constexpr const char collision[] = "💥"; inline constexpr const char fire[] = "🔥"; inline constexpr const char flame[] = "🔥"; inline constexpr const char cloud_tornado[] = "🌪️"; inline constexpr const char cloud_with_tornado[] = "🌪️"; + inline constexpr const char tornado[] = "🌪️"; inline constexpr const char rainbow[] = "🌈"; inline constexpr const char sunny[] = "☀️"; + inline constexpr const char sun[] = "☀️"; inline constexpr const char white_sun_small_cloud[] = "🌤️"; inline constexpr const char white_sun_with_small_cloud[] = "🌤️"; inline constexpr const char partly_sunny[] = "⛅"; @@ -1238,13 +1291,16 @@ namespace unicode_emoji { inline constexpr const char snowman2[] = "☃️"; inline constexpr const char snowman[] = "⛄"; inline constexpr const char wind_blowing_face[] = "🌬️"; + inline constexpr const char wind_face[] = "🌬️"; inline constexpr const char dash[] = "💨"; + inline constexpr const char dashing_away[] = "💨"; inline constexpr const char droplet[] = "💧"; inline constexpr const char sweat_drops[] = "💦"; inline constexpr const char bubbles[] = "🫧"; inline constexpr const char umbrella[] = "☔"; inline constexpr const char umbrella2[] = "☂️"; inline constexpr const char ocean[] = "🌊"; + inline constexpr const char water_wave[] = "🌊"; inline constexpr const char fog[] = "🌫️"; inline constexpr const char watch[] = "⌚"; inline constexpr const char mobile_phone[] = "📱"; @@ -1260,11 +1316,15 @@ namespace unicode_emoji { inline constexpr const char trackball[] = "🖲️"; inline constexpr const char joystick[] = "🕹️"; inline constexpr const char compression[] = "🗜️"; + inline constexpr const char clamp[] = "🗜️"; inline constexpr const char minidisc[] = "💽"; + inline constexpr const char computer_disk[] = "💽"; inline constexpr const char floppy_disk[] = "💾"; inline constexpr const char cd[] = "💿"; + inline constexpr const char optical_disk[] = "💿"; inline constexpr const char dvd[] = "📀"; inline constexpr const char vhs[] = "📼"; + inline constexpr const char videocassette[] = "📼"; inline constexpr const char camera[] = "📷"; inline constexpr const char camera_with_flash[] = "📸"; inline constexpr const char video_camera[] = "📹"; @@ -1276,7 +1336,9 @@ namespace unicode_emoji { inline constexpr const char telephone[] = "☎️"; inline constexpr const char pager[] = "📟"; inline constexpr const char fax[] = "📠"; + inline constexpr const char fax_machine[] = "📠"; inline constexpr const char tv[] = "📺"; + inline constexpr const char television[] = "📺"; inline constexpr const char radio[] = "📻"; inline constexpr const char microphone2[] = "🎙️"; inline constexpr const char studio_microphone[] = "🎙️"; @@ -1296,6 +1358,7 @@ namespace unicode_emoji { inline constexpr const char low_battery[] = "🪫"; inline constexpr const char electric_plug[] = "🔌"; inline constexpr const char bulb[] = "💡"; + inline constexpr const char light_bulb[] = "💡"; inline constexpr const char flashlight[] = "🔦"; inline constexpr const char candle[] = "🕯️"; inline constexpr const char diya_lamp[] = "🪔"; @@ -1305,14 +1368,19 @@ namespace unicode_emoji { inline constexpr const char money_with_wings[] = "💸"; inline constexpr const char dollar[] = "💵"; inline constexpr const char yen[] = "💴"; + inline constexpr const char yen_banknote[] = "💴"; inline constexpr const char euro[] = "💶"; + inline constexpr const char euro_banknote[] = "💶"; inline constexpr const char pound[] = "💷"; inline constexpr const char coin[] = "🪙"; inline constexpr const char moneybag[] = "💰"; + inline constexpr const char money_bag[] = "💰"; inline constexpr const char credit_card[] = "💳"; inline constexpr const char identification_card[] = "🪪"; inline constexpr const char gem[] = "💎"; + inline constexpr const char gem_stone[] = "💎"; inline constexpr const char scales[] = "⚖️"; + inline constexpr const char balance_scale[] = "⚖️"; inline constexpr const char ladder[] = "🪜"; inline constexpr const char toolbox[] = "🧰"; inline constexpr const char screwdriver[] = "🪛"; @@ -1328,18 +1396,22 @@ namespace unicode_emoji { inline constexpr const char gear[] = "⚙️"; inline constexpr const char mouse_trap[] = "🪤"; inline constexpr const char bricks[] = "🧱"; + inline constexpr const char brick[] = "🧱"; inline constexpr const char chains[] = "⛓️"; inline constexpr const char magnet[] = "🧲"; inline constexpr const char gun[] = "🔫"; + inline constexpr const char pistol[] = "🔫"; inline constexpr const char bomb[] = "💣"; inline constexpr const char firecracker[] = "🧨"; inline constexpr const char axe[] = "🪓"; inline constexpr const char knife[] = "🔪"; + inline constexpr const char kitchen_knife[] = "🔪"; inline constexpr const char dagger[] = "🗡️"; inline constexpr const char dagger_knife[] = "🗡️"; inline constexpr const char crossed_swords[] = "⚔️"; inline constexpr const char shield[] = "🛡️"; inline constexpr const char smoking[] = "🚬"; + inline constexpr const char cigarette[] = "🚬"; inline constexpr const char coffin[] = "⚰️"; inline constexpr const char headstone[] = "🪦"; inline constexpr const char urn[] = "⚱️"; @@ -1350,6 +1422,7 @@ namespace unicode_emoji { inline constexpr const char nazar_amulet[] = "🧿"; inline constexpr const char hamsa[] = "🪬"; inline constexpr const char barber[] = "💈"; + inline constexpr const char barber_pole[] = "💈"; inline constexpr const char alembic[] = "⚗️"; inline constexpr const char telescope[] = "🔭"; inline constexpr const char microscope[] = "🔬"; @@ -1382,9 +1455,11 @@ namespace unicode_emoji { inline constexpr const char soap[] = "🧼"; inline constexpr const char toothbrush[] = "🪥"; inline constexpr const char razor[] = "🪒"; + inline constexpr const char hair_pick[] = "🪮"; inline constexpr const char sponge[] = "🧽"; inline constexpr const char bucket[] = "🪣"; inline constexpr const char squeeze_bottle[] = "🧴"; + inline constexpr const char lotion_bottle[] = "🧴"; inline constexpr const char bellhop[] = "🛎️"; inline constexpr const char bellhop_bell[] = "🛎️"; inline constexpr const char key[] = "🔑"; @@ -1396,6 +1471,7 @@ namespace unicode_emoji { inline constexpr const char couch_and_lamp[] = "🛋️"; inline constexpr const char bed[] = "🛏️"; inline constexpr const char sleeping_accommodation[] = "🛌"; + inline constexpr const char person_in_bed[] = "🛌"; inline constexpr const char person_in_bed_tone1[] = "🛌🏻"; inline constexpr const char person_in_bed_light_skin_tone[] = "🛌🏻"; inline constexpr const char person_in_bed_tone2[] = "🛌🏼"; @@ -1416,14 +1492,18 @@ namespace unicode_emoji { inline constexpr const char shopping_cart[] = "🛒"; inline constexpr const char shopping_trolley[] = "🛒"; inline constexpr const char gift[] = "🎁"; + inline constexpr const char wrapped_gift[] = "🎁"; inline constexpr const char balloon[] = "🎈"; inline constexpr const char flags[] = "🎏"; + inline constexpr const char carp_streamer[] = "🎏"; inline constexpr const char ribbon[] = "🎀"; inline constexpr const char magic_wand[] = "🪄"; inline constexpr const char pinata[] = "🪅"; inline constexpr const char confetti_ball[] = "🎊"; inline constexpr const char tada[] = "🎉"; + inline constexpr const char party_popper[] = "🎉"; inline constexpr const char dolls[] = "🎎"; + inline constexpr const char folding_hand_fan[] = "🪭"; inline constexpr const char izakaya_lantern[] = "🏮"; inline constexpr const char wind_chime[] = "🎐"; inline constexpr const char mirror_ball[] = "🪩"; @@ -1483,6 +1563,7 @@ namespace unicode_emoji { inline constexpr const char orange_book[] = "📙"; inline constexpr const char books[] = "📚"; inline constexpr const char book[] = "📖"; + inline constexpr const char open_book[] = "📖"; inline constexpr const char bookmark[] = "🔖"; inline constexpr const char safety_pin[] = "🧷"; inline constexpr const char link[] = "🔗"; @@ -1497,8 +1578,10 @@ namespace unicode_emoji { inline constexpr const char scissors[] = "✂️"; inline constexpr const char pen_ballpoint[] = "🖊️"; inline constexpr const char lower_left_ballpoint_pen[] = "🖊️"; + inline constexpr const char pen[] = "🖊️"; inline constexpr const char pen_fountain[] = "🖋️"; inline constexpr const char lower_left_fountain_pen[] = "🖋️"; + inline constexpr const char fountain_pen[] = "🖋️"; inline constexpr const char black_nib[] = "✒️"; inline constexpr const char paintbrush[] = "🖌️"; inline constexpr const char lower_left_paintbrush[] = "🖌️"; @@ -1512,8 +1595,11 @@ namespace unicode_emoji { inline constexpr const char lock_with_ink_pen[] = "🔏"; inline constexpr const char closed_lock_with_key[] = "🔐"; inline constexpr const char lock[] = "🔒"; + inline constexpr const char locked[] = "🔒"; inline constexpr const char unlock[] = "🔓"; + inline constexpr const char unlocked[] = "🔓"; inline constexpr const char grinning[] = "😀"; + inline constexpr const char grinning_face[] = "😀"; inline constexpr const char smiley[] = "😃"; inline constexpr const char smile[] = "😄"; inline constexpr const char grin[] = "😁"; @@ -1526,6 +1612,7 @@ namespace unicode_emoji { inline constexpr const char rolling_on_the_floor_laughing[] = "🤣"; inline constexpr const char smiling_face_with_tear[] = "🥲"; inline constexpr const char relaxed[] = "☺️"; + inline constexpr const char smiling_face[] = "☺️"; inline constexpr const char blush[] = "😊"; inline constexpr const char innocent[] = "😇"; inline constexpr const char slight_smile[] = "🙂"; @@ -1533,11 +1620,14 @@ namespace unicode_emoji { inline constexpr const char upside_down[] = "🙃"; inline constexpr const char upside_down_face[] = "🙃"; inline constexpr const char wink[] = "😉"; + inline constexpr const char winking_face[] = "😉"; inline constexpr const char relieved[] = "😌"; + inline constexpr const char relieved_face[] = "😌"; inline constexpr const char heart_eyes[] = "😍"; inline constexpr const char smiling_face_with_3_hearts[] = "🥰"; inline constexpr const char kissing_heart[] = "😘"; inline constexpr const char kissing[] = "😗"; + inline constexpr const char kissing_face[] = "😗"; inline constexpr const char kissing_smiling_eyes[] = "😙"; inline constexpr const char kissing_closed_eyes[] = "😚"; inline constexpr const char yum[] = "😋"; @@ -1554,33 +1644,45 @@ namespace unicode_emoji { inline constexpr const char star_struck[] = "🤩"; inline constexpr const char partying_face[] = "🥳"; inline constexpr const char smirk[] = "😏"; + inline constexpr const char smirking_face[] = "😏"; inline constexpr const char unamused[] = "😒"; + inline constexpr const char unamused_face[] = "😒"; inline constexpr const char disappointed[] = "😞"; inline constexpr const char pensive[] = "😔"; + inline constexpr const char pensive_face[] = "😔"; inline constexpr const char worried[] = "😟"; + inline constexpr const char worried_face[] = "😟"; inline constexpr const char confused[] = "😕"; + inline constexpr const char confused_face[] = "😕"; inline constexpr const char slight_frown[] = "🙁"; inline constexpr const char slightly_frowning_face[] = "🙁"; inline constexpr const char frowning2[] = "☹️"; inline constexpr const char white_frowning_face[] = "☹️"; + inline constexpr const char frowning_face[] = "☹️"; inline constexpr const char persevere[] = "😣"; inline constexpr const char confounded[] = "😖"; inline constexpr const char tired_face[] = "😫"; inline constexpr const char weary[] = "😩"; + inline constexpr const char weary_face[] = "😩"; inline constexpr const char pleading_face[] = "🥺"; inline constexpr const char cry[] = "😢"; + inline constexpr const char crying_face[] = "😢"; inline constexpr const char sob[] = "😭"; inline constexpr const char triumph[] = "😤"; inline constexpr const char angry[] = "😠"; + inline constexpr const char angry_face[] = "😠"; inline constexpr const char rage[] = "😡"; + inline constexpr const char pouting_face[] = "😡"; inline constexpr const char face_with_symbols_over_mouth[] = "🤬"; inline constexpr const char exploding_head[] = "🤯"; inline constexpr const char flushed[] = "😳"; + inline constexpr const char flushed_face[] = "😳"; inline constexpr const char hot_face[] = "🥵"; inline constexpr const char cold_face[] = "🥶"; inline constexpr const char face_in_clouds[] = "😶‍🌫️"; inline constexpr const char scream[] = "😱"; inline constexpr const char fearful[] = "😨"; + inline constexpr const char fearful_face[] = "😨"; inline constexpr const char cold_sweat[] = "😰"; inline constexpr const char disappointed_relieved[] = "😥"; inline constexpr const char sweat[] = "😓"; @@ -1601,19 +1703,23 @@ namespace unicode_emoji { inline constexpr const char neutral_face[] = "😐"; inline constexpr const char face_with_diagonal_mouth[] = "🫤"; inline constexpr const char expressionless[] = "😑"; + inline constexpr const char shaking_face[] = "🫨"; inline constexpr const char grimacing[] = "😬"; inline constexpr const char rolling_eyes[] = "🙄"; inline constexpr const char face_with_rolling_eyes[] = "🙄"; inline constexpr const char hushed[] = "😯"; + inline constexpr const char hushed_face[] = "😯"; inline constexpr const char frowning[] = "😦"; inline constexpr const char anguished[] = "😧"; inline constexpr const char open_mouth[] = "😮"; inline constexpr const char astonished[] = "😲"; inline constexpr const char yawning_face[] = "🥱"; inline constexpr const char sleeping[] = "😴"; + inline constexpr const char sleeping_face[] = "😴"; inline constexpr const char drooling_face[] = "🤤"; inline constexpr const char drool[] = "🤤"; inline constexpr const char sleepy[] = "😪"; + inline constexpr const char sleepy_face[] = "😪"; inline constexpr const char face_exhaling[] = "😮‍💨"; inline constexpr const char dizzy_face[] = "😵"; inline constexpr const char face_with_spiral_eyes[] = "😵‍💫"; @@ -1637,13 +1743,16 @@ namespace unicode_emoji { inline constexpr const char smiling_imp[] = "😈"; inline constexpr const char imp[] = "👿"; inline constexpr const char japanese_ogre[] = "👹"; + inline constexpr const char ogre[] = "👹"; inline constexpr const char japanese_goblin[] = "👺"; + inline constexpr const char goblin[] = "👺"; inline constexpr const char clown[] = "🤡"; inline constexpr const char clown_face[] = "🤡"; inline constexpr const char poop[] = "💩"; inline constexpr const char shit[] = "💩"; inline constexpr const char hankey[] = "💩"; inline constexpr const char poo[] = "💩"; + inline constexpr const char pile_of_poo[] = "💩"; inline constexpr const char ghost[] = "👻"; inline constexpr const char skull[] = "💀"; inline constexpr const char skeleton[] = "💀"; @@ -1651,17 +1760,21 @@ namespace unicode_emoji { inline constexpr const char skull_and_crossbones[] = "☠️"; inline constexpr const char alien[] = "👽"; inline constexpr const char space_invader[] = "👾"; + inline constexpr const char alien_monster[] = "👾"; inline constexpr const char robot[] = "🤖"; inline constexpr const char robot_face[] = "🤖"; inline constexpr const char jack_o_lantern[] = "🎃"; inline constexpr const char smiley_cat[] = "😺"; + inline constexpr const char grinning_cat[] = "😺"; inline constexpr const char smile_cat[] = "😸"; inline constexpr const char joy_cat[] = "😹"; inline constexpr const char heart_eyes_cat[] = "😻"; inline constexpr const char smirk_cat[] = "😼"; inline constexpr const char kissing_cat[] = "😽"; inline constexpr const char scream_cat[] = "🙀"; + inline constexpr const char weary_cat[] = "🙀"; inline constexpr const char crying_cat_face[] = "😿"; + inline constexpr const char crying_cat[] = "😿"; inline constexpr const char pouting_cat[] = "😾"; inline constexpr const char heart_hands[] = "🫶"; inline constexpr const char heart_hands_tone1[] = "🫶🏻"; @@ -1692,6 +1805,7 @@ namespace unicode_emoji { inline constexpr const char open_hands_tone4[] = "👐🏾"; inline constexpr const char open_hands_tone5[] = "👐🏿"; inline constexpr const char raised_hands[] = "🙌"; + inline constexpr const char raising_hands[] = "🙌"; inline constexpr const char raised_hands_tone1[] = "🙌🏻"; inline constexpr const char raised_hands_tone2[] = "🙌🏼"; inline constexpr const char raised_hands_tone3[] = "🙌🏽"; @@ -1705,6 +1819,7 @@ namespace unicode_emoji { inline constexpr const char clap_tone5[] = "👏🏿"; inline constexpr const char handshake[] = "🤝"; inline constexpr const char shaking_hands[] = "🤝"; + inline constexpr const char handshake_tone1[] = "🤝🏻"; inline constexpr const char handshake_light_skin_tone[] = "🤝🏻"; inline constexpr const char handshake_tone1_tone2[] = "🫱🏻‍🫲🏼"; inline constexpr const char handshake_light_skin_tone_medium_light_skin_tone[] = "🫱🏻‍🫲🏼"; @@ -1716,6 +1831,7 @@ namespace unicode_emoji { inline constexpr const char handshake_light_skin_tone_dark_skin_tone[] = "🫱🏻‍🫲🏿"; inline constexpr const char handshake_tone2_tone1[] = "🫱🏼‍🫲🏻"; inline constexpr const char handshake_medium_light_skin_tone_light_skin_tone[] = "🫱🏼‍🫲🏻"; + inline constexpr const char handshake_tone2[] = "🤝🏼"; inline constexpr const char handshake_medium_light_skin_tone[] = "🤝🏼"; inline constexpr const char handshake_tone2_tone3[] = "🫱🏼‍🫲🏽"; inline constexpr const char handshake_medium_light_skin_tone_medium_skin_tone[] = "🫱🏼‍🫲🏽"; @@ -1727,6 +1843,7 @@ namespace unicode_emoji { inline constexpr const char handshake_medium_skin_tone_light_skin_tone[] = "🫱🏽‍🫲🏻"; inline constexpr const char handshake_tone3_tone2[] = "🫱🏽‍🫲🏼"; inline constexpr const char handshake_medium_skin_tone_medium_light_skin_tone[] = "🫱🏽‍🫲🏼"; + inline constexpr const char handshake_tone3[] = "🤝🏽"; inline constexpr const char handshake_medium_skin_tone[] = "🤝🏽"; inline constexpr const char handshake_tone3_tone4[] = "🫱🏽‍🫲🏾"; inline constexpr const char handshake_medium_skin_tone_medium_dark_skin_tone[] = "🫱🏽‍🫲🏾"; @@ -1738,6 +1855,7 @@ namespace unicode_emoji { inline constexpr const char handshake_medium_dark_skin_tone_medium_light_skin_tone[] = "🫱🏾‍🫲🏼"; inline constexpr const char handshake_tone4_tone3[] = "🫱🏾‍🫲🏽"; inline constexpr const char handshake_medium_dark_skin_tone_medium_skin_tone[] = "🫱🏾‍🫲🏽"; + inline constexpr const char handshake_tone4[] = "🤝🏾"; inline constexpr const char handshake_medium_dark_skin_tone[] = "🤝🏾"; inline constexpr const char handshake_tone4_tone5[] = "🫱🏾‍🫲🏿"; inline constexpr const char handshake_medium_dark_skin_tone_dark_skin_tone[] = "🫱🏾‍🫲🏿"; @@ -1749,10 +1867,12 @@ namespace unicode_emoji { inline constexpr const char handshake_dark_skin_tone_medium_skin_tone[] = "🫱🏿‍🫲🏽"; inline constexpr const char handshake_tone5_tone4[] = "🫱🏿‍🫲🏾"; inline constexpr const char handshake_dark_skin_tone_medium_dark_skin_tone[] = "🫱🏿‍🫲🏾"; + inline constexpr const char handshake_tone5[] = "🤝🏿"; inline constexpr const char handshake_dark_skin_tone[] = "🤝🏿"; inline constexpr const char thumbsup[] = "👍"; inline constexpr const char plus1[] = "👍"; inline constexpr const char thumbup[] = "👍"; + inline constexpr const char thumbs_up[] = "👍"; inline constexpr const char thumbsup_tone1[] = "👍🏻"; inline constexpr const char plus1_tone1[] = "👍🏻"; inline constexpr const char thumbup_tone1[] = "👍🏻"; @@ -1771,6 +1891,7 @@ namespace unicode_emoji { inline constexpr const char thumbsdown[] = "👎"; inline constexpr const char minus1[] = "👎"; inline constexpr const char thumbdown[] = "👎"; + inline constexpr const char thumbs_down[] = "👎"; inline constexpr const char thumbsdown_tone1[] = "👎🏻"; inline constexpr const char _1_tone1[] = "👎🏻"; inline constexpr const char thumbdown_tone1[] = "👎🏻"; @@ -1787,12 +1908,14 @@ namespace unicode_emoji { inline constexpr const char _1_tone5[] = "👎🏿"; inline constexpr const char thumbdown_tone5[] = "👎🏿"; inline constexpr const char punch[] = "👊"; + inline constexpr const char oncoming_fist[] = "👊"; inline constexpr const char punch_tone1[] = "👊🏻"; inline constexpr const char punch_tone2[] = "👊🏼"; inline constexpr const char punch_tone3[] = "👊🏽"; inline constexpr const char punch_tone4[] = "👊🏾"; inline constexpr const char punch_tone5[] = "👊🏿"; inline constexpr const char fist[] = "✊"; + inline constexpr const char raised_fist[] = "✊"; inline constexpr const char fist_tone1[] = "✊🏻"; inline constexpr const char fist_tone2[] = "✊🏼"; inline constexpr const char fist_tone3[] = "✊🏽"; @@ -1822,6 +1945,28 @@ namespace unicode_emoji { inline constexpr const char right_fist_tone4[] = "🤜🏾"; inline constexpr const char right_facing_fist_tone5[] = "🤜🏿"; inline constexpr const char right_fist_tone5[] = "🤜🏿"; + inline constexpr const char leftwards_pushing_hand[] = "🫷"; + inline constexpr const char leftwards_pushing_hand_tone1[] = "🫷🏻"; + inline constexpr const char leftwards_pushing_hand_light_skin_tone[] = "🫷🏻"; + inline constexpr const char leftwards_pushing_hand_tone2[] = "🫷🏼"; + inline constexpr const char leftwards_pushing_hand_medium_light_skin_tone[] = "🫷🏼"; + inline constexpr const char leftwards_pushing_hand_tone3[] = "🫷🏽"; + inline constexpr const char leftwards_pushing_hand_medium_skin_tone[] = "🫷🏽"; + inline constexpr const char leftwards_pushing_hand_tone4[] = "🫷🏾"; + inline constexpr const char leftwards_pushing_hand_medium_dark_skin_tone[] = "🫷🏾"; + inline constexpr const char leftwards_pushing_hand_tone5[] = "🫷🏿"; + inline constexpr const char leftwards_pushing_hand_dark_skin_tone[] = "🫷🏿"; + inline constexpr const char rightwards_pushing_hand[] = "🫸"; + inline constexpr const char rightwards_pushing_hand_tone1[] = "🫸🏻"; + inline constexpr const char rightwards_pushing_hand_light_skin_tone[] = "🫸🏻"; + inline constexpr const char rightwards_pushing_hand_tone2[] = "🫸🏼"; + inline constexpr const char rightwards_pushing_hand_medium_light_skin_tone[] = "🫸🏼"; + inline constexpr const char rightwards_pushing_hand_tone3[] = "🫸🏽"; + inline constexpr const char rightwards_pushing_hand_medium_skin_tone[] = "🫸🏽"; + inline constexpr const char rightwards_pushing_hand_tone4[] = "🫸🏾"; + inline constexpr const char rightwards_pushing_hand_medium_dark_skin_tone[] = "🫸🏾"; + inline constexpr const char rightwards_pushing_hand_tone5[] = "🫸🏿"; + inline constexpr const char rightwards_pushing_hand_dark_skin_tone[] = "🫸🏿"; inline constexpr const char fingers_crossed[] = "🤞"; inline constexpr const char hand_with_index_and_middle_finger_crossed[] = "🤞"; inline constexpr const char fingers_crossed_tone1[] = "🤞🏻"; @@ -1835,6 +1980,7 @@ namespace unicode_emoji { inline constexpr const char fingers_crossed_tone5[] = "🤞🏿"; inline constexpr const char hand_with_index_and_middle_fingers_crossed_tone5[] = "🤞🏿"; inline constexpr const char v[] = "✌️"; + inline constexpr const char victory_hand[] = "✌️"; inline constexpr const char v_tone1[] = "✌🏻"; inline constexpr const char v_tone2[] = "✌🏼"; inline constexpr const char v_tone3[] = "✌🏽"; @@ -1986,6 +2132,7 @@ namespace unicode_emoji { inline constexpr const char raised_hand_with_fingers_splayed_tone5[] = "🖐🏿"; inline constexpr const char vulcan[] = "🖖"; inline constexpr const char raised_hand_with_part_between_middle_and_ring_fingers[] = "🖖"; + inline constexpr const char vulcan_salute[] = "🖖"; inline constexpr const char vulcan_tone1[] = "🖖🏻"; inline constexpr const char raised_hand_with_part_between_middle_and_ring_fingers_tone1[] = "🖖🏻"; inline constexpr const char vulcan_tone2[] = "🖖🏼"; @@ -1997,6 +2144,7 @@ namespace unicode_emoji { inline constexpr const char vulcan_tone5[] = "🖖🏿"; inline constexpr const char raised_hand_with_part_between_middle_and_ring_fingers_tone5[] = "🖖🏿"; inline constexpr const char wave[] = "👋"; + inline constexpr const char waving_hand[] = "👋"; inline constexpr const char wave_tone1[] = "👋🏻"; inline constexpr const char wave_tone2[] = "👋🏼"; inline constexpr const char wave_tone3[] = "👋🏽"; @@ -2037,6 +2185,7 @@ namespace unicode_emoji { inline constexpr const char rightwards_hand_tone5[] = "🫱🏿"; inline constexpr const char rightwards_hand_dark_skin_tone[] = "🫱🏿"; inline constexpr const char muscle[] = "💪"; + inline constexpr const char flexed_biceps[] = "💪"; inline constexpr const char muscle_tone1[] = "💪🏻"; inline constexpr const char muscle_tone2[] = "💪🏼"; inline constexpr const char muscle_tone3[] = "💪🏽"; @@ -2062,6 +2211,7 @@ namespace unicode_emoji { inline constexpr const char writing_hand_tone4[] = "✍🏾"; inline constexpr const char writing_hand_tone5[] = "✍🏿"; inline constexpr const char pray[] = "🙏"; + inline constexpr const char folded_hands[] = "🙏"; inline constexpr const char pray_tone1[] = "🙏🏻"; inline constexpr const char pray_tone2[] = "🙏🏼"; inline constexpr const char pray_tone3[] = "🙏🏽"; @@ -2103,7 +2253,9 @@ namespace unicode_emoji { inline constexpr const char mechanical_leg[] = "🦿"; inline constexpr const char lipstick[] = "💄"; inline constexpr const char kiss[] = "💋"; + inline constexpr const char kiss_mark[] = "💋"; inline constexpr const char lips[] = "👄"; + inline constexpr const char mouth[] = "👄"; inline constexpr const char biting_lip[] = "🫦"; inline constexpr const char tooth[] = "🦷"; inline constexpr const char tongue[] = "👅"; @@ -2171,6 +2323,7 @@ namespace unicode_emoji { inline constexpr const char boy_tone4[] = "👦🏾"; inline constexpr const char boy_tone5[] = "👦🏿"; inline constexpr const char adult[] = "🧑"; + inline constexpr const char person[] = "🧑"; inline constexpr const char adult_tone1[] = "🧑🏻"; inline constexpr const char adult_light_skin_tone[] = "🧑🏻"; inline constexpr const char adult_tone2[] = "🧑🏼"; @@ -2249,6 +2402,7 @@ namespace unicode_emoji { inline constexpr const char woman_red_haired_tone5[] = "👩🏿‍🦰"; inline constexpr const char woman_red_haired_dark_skin_tone[] = "👩🏿‍🦰"; inline constexpr const char man_red_haired[] = "👨‍🦰"; + inline constexpr const char man_red_hair[] = "👨‍🦰"; inline constexpr const char man_red_haired_tone1[] = "👨🏻‍🦰"; inline constexpr const char man_red_haired_light_skin_tone[] = "👨🏻‍🦰"; inline constexpr const char man_red_haired_tone2[] = "👨🏼‍🦰"; @@ -2360,6 +2514,7 @@ namespace unicode_emoji { inline constexpr const char man_bald_tone5[] = "👨🏿‍🦲"; inline constexpr const char man_bald_dark_skin_tone[] = "👨🏿‍🦲"; inline constexpr const char bearded_person[] = "🧔"; + inline constexpr const char person_beard[] = "🧔"; inline constexpr const char bearded_person_tone1[] = "🧔🏻"; inline constexpr const char bearded_person_light_skin_tone[] = "🧔🏻"; inline constexpr const char bearded_person_tone2[] = "🧔🏼"; @@ -2393,6 +2548,7 @@ namespace unicode_emoji { inline constexpr const char man_tone5_beard[] = "🧔🏿‍♂️"; inline constexpr const char man_dark_skin_tone_beard[] = "🧔🏿‍♂️"; inline constexpr const char older_adult[] = "🧓"; + inline constexpr const char older_person[] = "🧓"; inline constexpr const char older_adult_tone1[] = "🧓🏻"; inline constexpr const char older_adult_light_skin_tone[] = "🧓🏻"; inline constexpr const char older_adult_tone2[] = "🧓🏼"; @@ -2405,6 +2561,7 @@ namespace unicode_emoji { inline constexpr const char older_adult_dark_skin_tone[] = "🧓🏿"; inline constexpr const char older_woman[] = "👵"; inline constexpr const char grandma[] = "👵"; + inline constexpr const char old_woman[] = "👵"; inline constexpr const char older_woman_tone1[] = "👵🏻"; inline constexpr const char grandma_tone1[] = "👵🏻"; inline constexpr const char older_woman_tone2[] = "👵🏼"; @@ -2416,6 +2573,7 @@ namespace unicode_emoji { inline constexpr const char older_woman_tone5[] = "👵🏿"; inline constexpr const char grandma_tone5[] = "👵🏿"; inline constexpr const char older_man[] = "👴"; + inline constexpr const char old_man[] = "👴"; inline constexpr const char older_man_tone1[] = "👴🏻"; inline constexpr const char older_man_tone2[] = "👴🏼"; inline constexpr const char older_man_tone3[] = "👴🏽"; @@ -3328,6 +3486,7 @@ namespace unicode_emoji { inline constexpr const char mrs_claus_tone5[] = "🤶🏿"; inline constexpr const char mother_christmas_tone5[] = "🤶🏿"; inline constexpr const char santa[] = "🎅"; + inline constexpr const char santa_claus[] = "🎅"; inline constexpr const char santa_tone1[] = "🎅🏻"; inline constexpr const char santa_tone2[] = "🎅🏼"; inline constexpr const char santa_tone3[] = "🎅🏽"; @@ -3506,6 +3665,7 @@ namespace unicode_emoji { inline constexpr const char man_fairy_tone5[] = "🧚🏿‍♂️"; inline constexpr const char man_fairy_dark_skin_tone[] = "🧚🏿‍♂️"; inline constexpr const char angel[] = "👼"; + inline constexpr const char baby_angel[] = "👼"; inline constexpr const char angel_tone1[] = "👼🏻"; inline constexpr const char angel_tone2[] = "👼🏼"; inline constexpr const char angel_tone3[] = "👼🏽"; @@ -4024,6 +4184,7 @@ namespace unicode_emoji { inline constexpr const char man_in_steamy_room_tone5[] = "🧖🏿‍♂️"; inline constexpr const char man_in_steamy_room_dark_skin_tone[] = "🧖🏿‍♂️"; inline constexpr const char nail_care[] = "💅"; + inline constexpr const char nail_polish[] = "💅"; inline constexpr const char nail_care_tone1[] = "💅🏻"; inline constexpr const char nail_care_tone2[] = "💅🏼"; inline constexpr const char nail_care_tone3[] = "💅🏽"; @@ -4036,6 +4197,7 @@ namespace unicode_emoji { inline constexpr const char selfie_tone4[] = "🤳🏾"; inline constexpr const char selfie_tone5[] = "🤳🏿"; inline constexpr const char dancer[] = "💃"; + inline constexpr const char woman_dancing[] = "💃"; inline constexpr const char dancer_tone1[] = "💃🏻"; inline constexpr const char dancer_tone2[] = "💃🏼"; inline constexpr const char dancer_tone3[] = "💃🏽"; @@ -4873,6 +5035,7 @@ namespace unicode_emoji { inline constexpr const char kiss_woman_woman_dark_skin_tone[] = "👩🏿‍❤️‍💋‍👩🏿"; inline constexpr const char kiss_mm[] = "👨‍❤️‍💋‍👨"; inline constexpr const char couplekiss_mm[] = "👨‍❤️‍💋‍👨"; + inline constexpr const char kiss_man_man[] = "👨‍❤️‍💋‍👨"; inline constexpr const char kiss_man_man_tone1[] = "👨🏻‍❤️‍💋‍👨🏻"; inline constexpr const char kiss_man_man_light_skin_tone[] = "👨🏻‍❤️‍💋‍👨🏻"; inline constexpr const char kiss_man_man_tone1_tone2[] = "👨🏻‍❤️‍💋‍👨🏼"; @@ -4958,6 +5121,7 @@ namespace unicode_emoji { inline constexpr const char safety_vest[] = "🦺"; inline constexpr const char womans_clothes[] = "👚"; inline constexpr const char shirt[] = "👕"; + inline constexpr const char t_shirt[] = "👕"; inline constexpr const char jeans[] = "👖"; inline constexpr const char briefs[] = "🩲"; inline constexpr const char shorts[] = "🩳"; @@ -4969,16 +5133,21 @@ namespace unicode_emoji { inline constexpr const char sari[] = "🥻"; inline constexpr const char thong_sandal[] = "🩴"; inline constexpr const char womans_flat_shoe[] = "🥿"; + inline constexpr const char flat_shoe[] = "🥿"; inline constexpr const char high_heel[] = "👠"; inline constexpr const char sandal[] = "👡"; + inline constexpr const char womans_sandal[] = "👡"; inline constexpr const char boot[] = "👢"; + inline constexpr const char womans_boot[] = "👢"; inline constexpr const char mans_shoe[] = "👞"; inline constexpr const char athletic_shoe[] = "👟"; + inline constexpr const char running_shoe[] = "👟"; inline constexpr const char hiking_boot[] = "🥾"; inline constexpr const char socks[] = "🧦"; inline constexpr const char gloves[] = "🧤"; inline constexpr const char scarf[] = "🧣"; inline constexpr const char tophat[] = "🎩"; + inline constexpr const char top_hat[] = "🎩"; inline constexpr const char billed_cap[] = "🧢"; inline constexpr const char womans_hat[] = "👒"; inline constexpr const char mortar_board[] = "🎓"; @@ -4988,31 +5157,40 @@ namespace unicode_emoji { inline constexpr const char crown[] = "👑"; inline constexpr const char ring[] = "💍"; inline constexpr const char pouch[] = "👝"; + inline constexpr const char clutch_bag[] = "👝"; inline constexpr const char purse[] = "👛"; inline constexpr const char handbag[] = "👜"; inline constexpr const char briefcase[] = "💼"; inline constexpr const char school_satchel[] = "🎒"; + inline constexpr const char backpack[] = "🎒"; inline constexpr const char luggage[] = "🧳"; inline constexpr const char eyeglasses[] = "👓"; + inline constexpr const char glasses[] = "👓"; inline constexpr const char dark_sunglasses[] = "🕶️"; inline constexpr const char goggles[] = "🥽"; inline constexpr const char closed_umbrella[] = "🌂"; + inline constexpr const char pink_heart[] = "🩷"; inline constexpr const char heart[] = "❤️"; + inline constexpr const char red_heart[] = "❤️"; inline constexpr const char orange_heart[] = "🧡"; inline constexpr const char yellow_heart[] = "💛"; inline constexpr const char green_heart[] = "💚"; + inline constexpr const char light_blue_heart[] = "🩵"; inline constexpr const char blue_heart[] = "💙"; inline constexpr const char purple_heart[] = "💜"; inline constexpr const char black_heart[] = "🖤"; - inline constexpr const char brown_heart[] = "🤎"; + inline constexpr const char grey_heart[] = "🩶"; inline constexpr const char white_heart[] = "🤍"; + inline constexpr const char brown_heart[] = "🤎"; inline constexpr const char broken_heart[] = "💔"; inline constexpr const char heart_exclamation[] = "❣️"; inline constexpr const char heavy_heart_exclamation_mark_ornament[] = "❣️"; inline constexpr const char two_hearts[] = "💕"; inline constexpr const char revolving_hearts[] = "💞"; inline constexpr const char heartbeat[] = "💓"; + inline constexpr const char beating_heart[] = "💓"; inline constexpr const char heartpulse[] = "💗"; + inline constexpr const char growing_heart[] = "💗"; inline constexpr const char sparkling_heart[] = "💖"; inline constexpr const char cupid[] = "💘"; inline constexpr const char gift_heart[] = "💝"; @@ -5026,6 +5204,7 @@ namespace unicode_emoji { inline constexpr const char star_and_crescent[] = "☪️"; inline constexpr const char om_symbol[] = "🕉️"; inline constexpr const char wheel_of_dharma[] = "☸️"; + inline constexpr const char khanda[] = "🪯"; inline constexpr const char star_of_david[] = "✡️"; inline constexpr const char six_pointed_star[] = "🔯"; inline constexpr const char menorah[] = "🕎"; @@ -5042,6 +5221,7 @@ namespace unicode_emoji { inline constexpr const char virgo[] = "♍"; inline constexpr const char libra[] = "♎"; inline constexpr const char scorpius[] = "♏"; + inline constexpr const char scorpio[] = "♏"; inline constexpr const char sagittarius[] = "♐"; inline constexpr const char capricorn[] = "♑"; inline constexpr const char aquarius[] = "♒"; @@ -5078,16 +5258,20 @@ namespace unicode_emoji { inline constexpr const char o2[] = "🅾️"; inline constexpr const char sos[] = "🆘"; inline constexpr const char x[] = "❌"; + inline constexpr const char cross_mark[] = "❌"; inline constexpr const char o[] = "⭕"; inline constexpr const char octagonal_sign[] = "🛑"; inline constexpr const char stop_sign[] = "🛑"; inline constexpr const char no_entry[] = "⛔"; inline constexpr const char name_badge[] = "📛"; inline constexpr const char no_entry_sign[] = "🚫"; + inline constexpr const char prohibited[] = "🚫"; inline constexpr const char anger[] = "💢"; inline constexpr const char hotsprings[] = "♨️"; + inline constexpr const char hot_springs[] = "♨️"; inline constexpr const char no_pedestrians[] = "🚷"; inline constexpr const char do_not_litter[] = "🚯"; + inline constexpr const char no_littering[] = "🚯"; inline constexpr const char no_bicycles[] = "🚳"; inline constexpr const char non_potable_water[] = "🚱"; inline constexpr const char underage[] = "🔞"; @@ -5096,6 +5280,7 @@ namespace unicode_emoji { inline constexpr const char exclamation[] = "❗"; inline constexpr const char grey_exclamation[] = "❕"; inline constexpr const char question[] = "❓"; + inline constexpr const char question_mark[] = "❓"; inline constexpr const char grey_question[] = "❔"; inline constexpr const char bangbang[] = "‼️"; inline constexpr const char interrobang[] = "⁉️"; @@ -5117,29 +5302,37 @@ namespace unicode_emoji { inline constexpr const char globe_with_meridians[] = "🌐"; inline constexpr const char diamond_shape_with_a_dot_inside[] = "💠"; inline constexpr const char m[] = "Ⓜ️"; + inline constexpr const char circled_m[] = "Ⓜ️"; inline constexpr const char cyclone[] = "🌀"; inline constexpr const char zzz[] = "💤"; inline constexpr const char atm[] = "🏧"; inline constexpr const char wc[] = "🚾"; + inline constexpr const char water_closet[] = "🚾"; inline constexpr const char wheelchair[] = "♿"; inline constexpr const char parking[] = "🅿️"; + inline constexpr const char elevator[] = "🛗"; inline constexpr const char u7a7a[] = "🈳"; inline constexpr const char sa[] = "🈂️"; inline constexpr const char passport_control[] = "🛂"; inline constexpr const char customs[] = "🛃"; inline constexpr const char baggage_claim[] = "🛄"; inline constexpr const char left_luggage[] = "🛅"; - inline constexpr const char elevator[] = "🛗"; + inline constexpr const char wireless[] = "🛜"; inline constexpr const char mens[] = "🚹"; + inline constexpr const char mens_room[] = "🚹"; inline constexpr const char womens[] = "🚺"; + inline constexpr const char womens_room[] = "🚺"; inline constexpr const char baby_symbol[] = "🚼"; inline constexpr const char restroom[] = "🚻"; inline constexpr const char put_litter_in_its_place[] = "🚮"; inline constexpr const char cinema[] = "🎦"; inline constexpr const char signal_strength[] = "📶"; + inline constexpr const char antenna_bars[] = "📶"; inline constexpr const char koko[] = "🈁"; inline constexpr const char symbols[] = "🔣"; + inline constexpr const char input_symbols[] = "🔣"; inline constexpr const char information_source[] = "ℹ️"; + inline constexpr const char information[] = "ℹ️"; inline constexpr const char abc[] = "🔤"; inline constexpr const char abcd[] = "🔡"; inline constexpr const char capital_abcd[] = "🔠"; @@ -5160,6 +5353,7 @@ namespace unicode_emoji { inline constexpr const char eight[] = "8️⃣"; inline constexpr const char nine[] = "9️⃣"; inline constexpr const char keycap_ten[] = "🔟"; + inline constexpr const char input_numbers[] = "🔢"; inline constexpr const char hash[] = "#️⃣"; inline constexpr const char asterisk[] = "*️⃣"; inline constexpr const char keycap_asterisk[] = "*️⃣"; @@ -5183,14 +5377,20 @@ namespace unicode_emoji { inline constexpr const char arrow_up_small[] = "🔼"; inline constexpr const char arrow_down_small[] = "🔽"; inline constexpr const char arrow_right[] = "➡️"; + inline constexpr const char right_arrow[] = "➡️"; inline constexpr const char arrow_left[] = "⬅️"; + inline constexpr const char left_arrow[] = "⬅️"; inline constexpr const char arrow_up[] = "⬆️"; + inline constexpr const char up_arrow[] = "⬆️"; inline constexpr const char arrow_down[] = "⬇️"; + inline constexpr const char down_arrow[] = "⬇️"; inline constexpr const char arrow_upper_right[] = "↗️"; inline constexpr const char arrow_lower_right[] = "↘️"; inline constexpr const char arrow_lower_left[] = "↙️"; inline constexpr const char arrow_upper_left[] = "↖️"; + inline constexpr const char up_left_arrow[] = "↖️"; inline constexpr const char arrow_up_down[] = "↕️"; + inline constexpr const char up_down_arrow[] = "↕️"; inline constexpr const char left_right_arrow[] = "↔️"; inline constexpr const char arrow_right_hook[] = "↪️"; inline constexpr const char leftwards_arrow_with_hook[] = "↩️"; @@ -5203,6 +5403,7 @@ namespace unicode_emoji { inline constexpr const char arrows_clockwise[] = "🔃"; inline constexpr const char musical_note[] = "🎵"; inline constexpr const char notes[] = "🎶"; + inline constexpr const char musical_notes[] = "🎶"; inline constexpr const char heavy_plus_sign[] = "➕"; inline constexpr const char heavy_minus_sign[] = "➖"; inline constexpr const char heavy_division_sign[] = "➗"; @@ -5212,17 +5413,24 @@ namespace unicode_emoji { inline constexpr const char heavy_dollar_sign[] = "💲"; inline constexpr const char currency_exchange[] = "💱"; inline constexpr const char tm[] = "™️"; + inline constexpr const char trade_mark[] = "™️"; inline constexpr const char copyright[] = "©️"; inline constexpr const char registered[] = "®️"; inline constexpr const char wavy_dash[] = "〰️"; inline constexpr const char curly_loop[] = "➰"; inline constexpr const char loop[] = "➿"; inline constexpr const char end[] = "🔚"; + inline constexpr const char end_arrow[] = "🔚"; inline constexpr const char back[] = "🔙"; + inline constexpr const char back_arrow[] = "🔙"; inline constexpr const char on[] = "🔛"; + inline constexpr const char on_arrow[] = "🔛"; inline constexpr const char top[] = "🔝"; + inline constexpr const char top_arrow[] = "🔝"; inline constexpr const char soon[] = "🔜"; + inline constexpr const char soon_arrow[] = "🔜"; inline constexpr const char heavy_check_mark[] = "✔️"; + inline constexpr const char check_mark[] = "✔️"; inline constexpr const char ballot_box_with_check[] = "☑️"; inline constexpr const char radio_button[] = "🔘"; inline constexpr const char white_circle[] = "⚪"; @@ -5259,11 +5467,13 @@ namespace unicode_emoji { inline constexpr const char yellow_square[] = "🟨"; inline constexpr const char speaker[] = "🔈"; inline constexpr const char mute[] = "🔇"; + inline constexpr const char muted_speaker[] = "🔇"; inline constexpr const char sound[] = "🔉"; inline constexpr const char loud_sound[] = "🔊"; inline constexpr const char bell[] = "🔔"; inline constexpr const char no_bell[] = "🔕"; inline constexpr const char mega[] = "📣"; + inline constexpr const char megaphone[] = "📣"; inline constexpr const char loudspeaker[] = "📢"; inline constexpr const char speech_left[] = "🗨️"; inline constexpr const char left_speech_bubble[] = "🗨️"; @@ -5273,36 +5483,65 @@ namespace unicode_emoji { inline constexpr const char anger_right[] = "🗯️"; inline constexpr const char right_anger_bubble[] = "🗯️"; inline constexpr const char spades[] = "♠️"; + inline constexpr const char spade_suit[] = "♠️"; inline constexpr const char clubs[] = "♣️"; + inline constexpr const char club_suit[] = "♣️"; inline constexpr const char hearts[] = "♥️"; + inline constexpr const char heart_suit[] = "♥️"; inline constexpr const char diamonds[] = "♦️"; + inline constexpr const char diamond_suit[] = "♦️"; inline constexpr const char black_joker[] = "🃏"; + inline constexpr const char joker[] = "🃏"; inline constexpr const char flower_playing_cards[] = "🎴"; inline constexpr const char mahjong[] = "🀄"; inline constexpr const char clock1[] = "🕐"; + inline constexpr const char one_oclock[] = "🕐"; inline constexpr const char clock2[] = "🕑"; + inline constexpr const char two_oclock[] = "🕑"; inline constexpr const char clock3[] = "🕒"; + inline constexpr const char three_oclock[] = "🕒"; inline constexpr const char clock4[] = "🕓"; + inline constexpr const char four_oclock[] = "🕓"; inline constexpr const char clock5[] = "🕔"; + inline constexpr const char five_oclock[] = "🕔"; inline constexpr const char clock6[] = "🕕"; + inline constexpr const char six_oclock[] = "🕕"; inline constexpr const char clock7[] = "🕖"; + inline constexpr const char seven_oclock[] = "🕖"; inline constexpr const char clock8[] = "🕗"; + inline constexpr const char eight_oclock[] = "🕗"; inline constexpr const char clock9[] = "🕘"; + inline constexpr const char nine_oclock[] = "🕘"; inline constexpr const char clock10[] = "🕙"; + inline constexpr const char ten_oclock[] = "🕙"; inline constexpr const char clock11[] = "🕚"; + inline constexpr const char eleven_oclock[] = "🕚"; inline constexpr const char clock12[] = "🕛"; + inline constexpr const char twelve_oclock[] = "🕛"; inline constexpr const char clock130[] = "🕜"; + inline constexpr const char one_thirty[] = "🕜"; inline constexpr const char clock230[] = "🕝"; + inline constexpr const char two_thirty[] = "🕝"; inline constexpr const char clock330[] = "🕞"; + inline constexpr const char three_thirty[] = "🕞"; inline constexpr const char clock430[] = "🕟"; + inline constexpr const char four_thirty[] = "🕟"; inline constexpr const char clock530[] = "🕠"; + inline constexpr const char five_thirty[] = "🕠"; inline constexpr const char clock630[] = "🕡"; + inline constexpr const char six_thirty[] = "🕡"; inline constexpr const char clock730[] = "🕢"; + inline constexpr const char seven_thirty[] = "🕢"; inline constexpr const char clock830[] = "🕣"; + inline constexpr const char eight_thirty[] = "🕣"; inline constexpr const char clock930[] = "🕤"; + inline constexpr const char nine_thirty[] = "🕤"; inline constexpr const char clock1030[] = "🕥"; + inline constexpr const char ten_thirty[] = "🕥"; inline constexpr const char clock1130[] = "🕦"; + inline constexpr const char eleven_thirty[] = "🕦"; inline constexpr const char clock1230[] = "🕧"; + inline constexpr const char twelve_thirty[] = "🕧"; inline constexpr const char female_sign[] = "♀️"; inline constexpr const char male_sign[] = "♂️"; inline constexpr const char transgender_symbol[] = "⚧"; @@ -5334,9 +5573,11 @@ namespace unicode_emoji { inline constexpr const char regional_indicator_b[] = "🇧"; inline constexpr const char regional_indicator_a[] = "🇦"; inline constexpr const char red_car[] = "🚗"; + inline constexpr const char automobile[] = "🚗"; inline constexpr const char taxi[] = "🚕"; inline constexpr const char blue_car[] = "🚙"; inline constexpr const char pickup_truck[] = "🛻"; + inline constexpr const char minibus[] = "🚐"; inline constexpr const char bus[] = "🚌"; inline constexpr const char trolleybus[] = "🚎"; inline constexpr const char race_car[] = "🏎️"; @@ -5344,16 +5585,17 @@ namespace unicode_emoji { inline constexpr const char police_car[] = "🚓"; inline constexpr const char ambulance[] = "🚑"; inline constexpr const char fire_engine[] = "🚒"; - inline constexpr const char minibus[] = "🚐"; inline constexpr const char truck[] = "🚚"; inline constexpr const char articulated_lorry[] = "🚛"; inline constexpr const char tractor[] = "🚜"; inline constexpr const char probing_cane[] = "🦯"; - inline constexpr const char crutch[] = "🩼"; inline constexpr const char manual_wheelchair[] = "🦽"; inline constexpr const char motorized_wheelchair[] = "🦼"; + inline constexpr const char crutch[] = "🩼"; inline constexpr const char scooter[] = "🛴"; + inline constexpr const char kick_scooter[] = "🛴"; inline constexpr const char bike[] = "🚲"; + inline constexpr const char bicycle[] = "🚲"; inline constexpr const char motor_scooter[] = "🛵"; inline constexpr const char motorbike[] = "🛵"; inline constexpr const char motorcycle[] = "🏍️"; @@ -5370,12 +5612,15 @@ namespace unicode_emoji { inline constexpr const char suspension_railway[] = "🚟"; inline constexpr const char railway_car[] = "🚃"; inline constexpr const char train[] = "🚋"; + inline constexpr const char tram_car[] = "🚋"; inline constexpr const char mountain_railway[] = "🚞"; inline constexpr const char monorail[] = "🚝"; inline constexpr const char bullettrain_side[] = "🚄"; inline constexpr const char bullettrain_front[] = "🚅"; + inline constexpr const char bullet_train[] = "🚅"; inline constexpr const char light_rail[] = "🚈"; inline constexpr const char steam_locomotive[] = "🚂"; + inline constexpr const char locomotive[] = "🚂"; inline constexpr const char train2[] = "🚆"; inline constexpr const char metro[] = "🚇"; inline constexpr const char tram[] = "🚊"; @@ -5395,6 +5640,7 @@ namespace unicode_emoji { inline constexpr const char sailboat[] = "⛵"; inline constexpr const char speedboat[] = "🚤"; inline constexpr const char motorboat[] = "🛥️"; + inline constexpr const char motor_boat[] = "🛥️"; inline constexpr const char cruise_ship[] = "🛳️"; inline constexpr const char passenger_ship[] = "🛳️"; inline constexpr const char ferry[] = "⛴️"; @@ -5403,16 +5649,20 @@ namespace unicode_emoji { inline constexpr const char anchor[] = "⚓"; inline constexpr const char hook[] = "🪝"; inline constexpr const char fuelpump[] = "⛽"; + inline constexpr const char fuel_pump[] = "⛽"; inline constexpr const char construction[] = "🚧"; inline constexpr const char vertical_traffic_light[] = "🚦"; inline constexpr const char traffic_light[] = "🚥"; inline constexpr const char busstop[] = "🚏"; + inline constexpr const char bus_stop[] = "🚏"; inline constexpr const char map[] = "🗺️"; inline constexpr const char world_map[] = "🗺️"; inline constexpr const char moyai[] = "🗿"; + inline constexpr const char moai[] = "🗿"; inline constexpr const char statue_of_liberty[] = "🗽"; inline constexpr const char tokyo_tower[] = "🗼"; inline constexpr const char european_castle[] = "🏰"; + inline constexpr const char castle[] = "🏰"; inline constexpr const char japanese_castle[] = "🏯"; inline constexpr const char stadium[] = "🏟️"; inline constexpr const char ferris_wheel[] = "🎡"; @@ -5437,6 +5687,7 @@ namespace unicode_emoji { inline constexpr const char house_with_garden[] = "🏡"; inline constexpr const char homes[] = "🏘️"; inline constexpr const char house_buildings[] = "🏘️"; + inline constexpr const char houses[] = "🏘️"; inline constexpr const char house_abandoned[] = "🏚️"; inline constexpr const char derelict_house_building[] = "🏚️"; inline constexpr const char hut[] = "🛖"; @@ -5465,16 +5716,19 @@ namespace unicode_emoji { inline constexpr const char railroad_track[] = "🛤️"; inline constexpr const char motorway[] = "🛣️"; inline constexpr const char japan[] = "🗾"; + inline constexpr const char map_of_japan[] = "🗾"; inline constexpr const char rice_scene[] = "🎑"; inline constexpr const char park[] = "🏞️"; inline constexpr const char national_park[] = "🏞️"; inline constexpr const char sunrise[] = "🌅"; inline constexpr const char sunrise_over_mountains[] = "🌄"; inline constexpr const char stars[] = "🌠"; + inline constexpr const char shooting_star[] = "🌠"; inline constexpr const char sparkler[] = "🎇"; inline constexpr const char fireworks[] = "🎆"; inline constexpr const char city_sunset[] = "🌇"; inline constexpr const char city_sunrise[] = "🌇"; + inline constexpr const char sunset[] = "🌇"; inline constexpr const char city_dusk[] = "🌆"; inline constexpr const char cityscape[] = "🏙️"; inline constexpr const char night_with_stars[] = "🌃"; From 9ccd5db6171862f85c481974a6b3acd6d3ae6741 Mon Sep 17 00:00:00 2001 From: "Craig Edwards (Brain)" Date: Mon, 19 Feb 2024 10:30:37 +0000 Subject: [PATCH 38/89] FIX: dont attempt to reschedule timers that are deleted (FIXES: #1048) (#1088) --- src/dpp/cluster/timer.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dpp/cluster/timer.cpp b/src/dpp/cluster/timer.cpp index 94099c7a9e..e6d7df1814 100644 --- a/src/dpp/cluster/timer.cpp +++ b/src/dpp/cluster/timer.cpp @@ -97,10 +97,21 @@ void cluster::tick_timers() { } } for (auto & t : scheduled) { + timer handle = t->handle; /* Call handler */ t->on_tick(t->handle); - /* Reschedule for next tick */ - timer_reschedule(t); + /* Reschedule if it wasn't deleted. + * Note: We wrap the .contains() check in a lambda as it needs locking + * for thread safety, but timer_rescheudle also locks the container, so this + * is the cleanest way to do it. + */ + bool not_deleted = ([handle, this]() -> bool { + std::lock_guard l(timer_guard); + return timer_list.find(handle) != timer_list.end(); + }()); + if (not_deleted) { + timer_reschedule(t); + } } } From 9c549f56feff00b13fc83193ce4aea6dc009058a Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Mon, 19 Feb 2024 14:13:25 +0000 Subject: [PATCH 39/89] fix: ts_not_null now works for all timezones (#1089) --- src/dpp/discordevents.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/dpp/discordevents.cpp b/src/dpp/discordevents.cpp index 013f2344ee..72c9596b77 100644 --- a/src/dpp/discordevents.cpp +++ b/src/dpp/discordevents.cpp @@ -286,10 +286,18 @@ time_t ts_not_null(const json* j, const char* keyname) } crossplatform_strptime(timedate.substr(0, 19).c_str(), "%Y-%m-%dT%T", ×tamp); timestamp.tm_isdst = 0; - retval = mktime(×tamp); + #ifndef _WIN32 + retval = timegm(×tamp); + #else + retval = _mkgmtime(×tamp); + #endif } else { crossplatform_strptime(timedate.substr(0, 19).c_str(), "%Y-%m-%d %T", ×tamp); - retval = mktime(×tamp); + #ifndef _WIN32 + retval = timegm(×tamp); + #else + retval = _mkgmtime(×tamp); + #endif } } return retval; @@ -311,10 +319,18 @@ void set_ts_not_null(const json* j, const char* keyname, time_t &v) } crossplatform_strptime(timedate.substr(0, 19).c_str(), "%Y-%m-%dT%T", ×tamp); timestamp.tm_isdst = 0; - retval = mktime(×tamp); + #ifndef _WIN32 + retval = timegm(×tamp); + #else + retval = _mkgmtime(×tamp); + #endif } else { crossplatform_strptime(timedate.substr(0, 19).c_str(), "%Y-%m-%d %T", ×tamp); - retval = mktime(×tamp); + #ifndef _WIN32 + retval = timegm(×tamp); + #else + retval = _mkgmtime(×tamp); + #endif } v = retval; } From bbba73fc15786c466d5dc04616be6442d3078a85 Mon Sep 17 00:00:00 2001 From: Craig Edwards Date: Fri, 23 Feb 2024 14:06:41 +0000 Subject: [PATCH 40/89] fix: Add version parameter to co_request --- buildtools/classes/Generator/CoroGenerator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buildtools/classes/Generator/CoroGenerator.php b/buildtools/classes/Generator/CoroGenerator.php index 70cb5126a8..8f8c68d142 100644 --- a/buildtools/classes/Generator/CoroGenerator.php +++ b/buildtools/classes/Generator/CoroGenerator.php @@ -116,7 +116,7 @@ public function getCommentArray(): array */ public function saveHeader(string $content): void { - $content .= "[[nodiscard]] async co_request(const std::string &url, http_method method, const std::string &postdata = \"\", const std::string &mimetype = \"text/plain\", const std::multimap &headers = {});\n\n"; + $content .= "[[nodiscard]] async co_request(const std::string &url, http_method method, const std::string &postdata = \"\", const std::string &mimetype = \"text/plain\", const std::multimap &headers = {}, const std::string &protocol = "1.1");\n\n"; file_put_contents('include/dpp/cluster_coro_calls.h', $content); } @@ -125,7 +125,7 @@ public function saveHeader(string $content): void */ public function saveCpp(string $cppcontent): void { - $cppcontent .= "dpp::async dpp::cluster::co_request(const std::string &url, http_method method, const std::string &postdata, const std::string &mimetype, const std::multimap &headers) {\n\treturn async{ [&, this] (C &&cc) { return this->request(url, method, std::forward(cc), postdata, mimetype, headers); }};\n} + $cppcontent .= "dpp::async dpp::cluster::co_request(const std::string &url, http_method method, const std::string &postdata, const std::string &mimetype, const std::multimap &headers, const std::string &protocol) {\n\treturn async{ [&, this] (C &&cc) { return this->request(url, method, std::forward(cc), postdata, mimetype, headers, protocol); }};\n} #endif "; From 46044c8f80134633f7b396b4d5814f83d54a96d3 Mon Sep 17 00:00:00 2001 From: Craig Edwards Date: Fri, 23 Feb 2024 14:17:38 +0000 Subject: [PATCH 41/89] fix: add version parameter as optional parameter to co_request, has been part of request for some time --- buildtools/classes/Generator/CoroGenerator.php | 2 +- buildtools/make_struct.php | 2 ++ include/dpp/cluster_coro_calls.h | 2 +- src/dpp/cluster_coro_calls.cpp | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/buildtools/classes/Generator/CoroGenerator.php b/buildtools/classes/Generator/CoroGenerator.php index 8f8c68d142..1a68809a70 100644 --- a/buildtools/classes/Generator/CoroGenerator.php +++ b/buildtools/classes/Generator/CoroGenerator.php @@ -116,7 +116,7 @@ public function getCommentArray(): array */ public function saveHeader(string $content): void { - $content .= "[[nodiscard]] async co_request(const std::string &url, http_method method, const std::string &postdata = \"\", const std::string &mimetype = \"text/plain\", const std::multimap &headers = {}, const std::string &protocol = "1.1");\n\n"; + $content .= "[[nodiscard]] async co_request(const std::string &url, http_method method, const std::string &postdata = \"\", const std::string &mimetype = \"text/plain\", const std::multimap &headers = {}, const std::string &protocol = \"1.1\");\n\n"; file_put_contents('include/dpp/cluster_coro_calls.h', $content); } diff --git a/buildtools/make_struct.php b/buildtools/make_struct.php index 3f43a1e105..32a052b202 100644 --- a/buildtools/make_struct.php +++ b/buildtools/make_struct.php @@ -40,6 +40,8 @@ 'channel_typing' => 'confirmation', 'message_get_reactions' => 'emoji_map', 'thread_create_in_forum' => 'thread', + 'threads_get_private_archived' => 'thread_map', + 'threads_get_public_archived' => 'thread_map', 'threads_get_active' => 'active_threads', 'user_get_cached' => 'user_identified', 'application_role_connection_get' => 'application_role_connection', diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index 018af88503..b0a2b1b46b 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -2494,5 +2494,5 @@ /* End of auto-generated definitions */ -[[nodiscard]] async co_request(const std::string &url, http_method method, const std::string &postdata = "", const std::string &mimetype = "text/plain", const std::multimap &headers = {}); +[[nodiscard]] async co_request(const std::string &url, http_method method, const std::string &postdata = "", const std::string &mimetype = "text/plain", const std::multimap &headers = {}, const std::string &protocol = "1.1"); diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp index 5f8ae7b971..4b3d2287fa 100644 --- a/src/dpp/cluster_coro_calls.cpp +++ b/src/dpp/cluster_coro_calls.cpp @@ -827,8 +827,8 @@ async cluster::co_get_webhook_with_token(snowflake webh }; /* End of auto-generated definitions */ -dpp::async dpp::cluster::co_request(const std::string &url, http_method method, const std::string &postdata, const std::string &mimetype, const std::multimap &headers) { - return async{ [&, this] (C &&cc) { return this->request(url, method, std::forward(cc), postdata, mimetype, headers); }}; +dpp::async dpp::cluster::co_request(const std::string &url, http_method method, const std::string &postdata, const std::string &mimetype, const std::multimap &headers, const std::string &protocol) { + return async{ [&, this] (C &&cc) { return this->request(url, method, std::forward(cc), postdata, mimetype, headers, protocol); }}; } #endif From a543e49acdc1de20bbe6d3adb335560dacb5bb71 Mon Sep 17 00:00:00 2001 From: Orlando <109116795+osirais@users.noreply.github.com> Date: Sat, 2 Mar 2024 03:13:28 -0600 Subject: [PATCH 42/89] feat: add embed-only message ctor (#1100) --- include/dpp/message.h | 9 ++++++++- src/dpp/message.cpp | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/dpp/message.h b/include/dpp/message.h index d6def6a0d0..2d11b527e2 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -2023,13 +2023,20 @@ struct DPP_EXPORT message : public managed, json_interface { */ message(snowflake channel_id, const std::string &content, message_type type = mt_default); + /** + * @brief Construct a new message object with content + * + * @param _embed An embed to send + */ + message(const embed& _embed); + /** * @brief Construct a new message object with a channel and content * * @param channel_id The channel to send the message to * @param _embed An embed to send */ - message(snowflake channel_id, const embed & _embed); + message(snowflake channel_id, const embed& _embed); /** * @brief Construct a new message object with content diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index b7da4fc5af..850a6c67ed 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -622,11 +622,14 @@ message::message(const std::string &_content, message_type t) : message() { type = t; } -message::message(snowflake _channel_id, const embed& _embed) : message() { - channel_id = _channel_id; +message::message(const embed& _embed) : message() { embeds.emplace_back(_embed); } +message::message(snowflake _channel_id, const embed& _embed) : message(_embed) { + channel_id = _channel_id; +} + embed::embed(json* j) : embed() { title = string_not_null(j, "title"); type = string_not_null(j, "type"); From 5e293d7531b3d0f46c180d5dcfeff38fd5398e71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 09:17:46 +0000 Subject: [PATCH 43/89] build(deps): bump microsoft/setup-msbuild from 1.3.1 to 2.0.0 (#1094) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 783d0ab6fc..03d14f9f90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -176,7 +176,7 @@ jobs: path: main - name: Add MSBuild to PATH - uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 + uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0 - name: Install chocolatey packages ${{ matrix.cfg.arch}} uses: seanmiddleditch/gha-setup-ninja@8b297075da4cd2a5f1fd21fe011b499edf06e9d2 # master From 8304e311fe4462cd9806f5a52454c3af7f76f07c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 09:17:55 +0000 Subject: [PATCH 44/89] build(deps): bump actions/upload-artifact from 4.3.0 to 4.3.1 (#1095) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 10 +++++----- .github/workflows/scorecard.yml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03d14f9f90..13272987d1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,14 +91,14 @@ jobs: - name: Upload Binary (DEB) if: ${{ matrix.cfg.cpack == 'yes' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: "libdpp - Debian Package ${{matrix.cfg.arch}}" path: '${{github.workspace}}/build/*.deb' - name: Upload Binary (RPM) if: ${{ matrix.cfg.cpack == 'yes' }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: "libdpp - RPM Package ${{matrix.cfg.arch}}" path: '${{github.workspace}}/build/*.rpm' @@ -209,7 +209,7 @@ jobs: - name: Upload Binary if: ${{ matrix.cfg.upload }} - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: "libdpp - Windows ${{matrix.cfg.name}}-${{matrix.cfg.config}}-vs${{matrix.cfg.vs}}" path: '${{github.workspace}}/main/build/*.zip' @@ -251,13 +251,13 @@ jobs: run: cd build && sudo cpack --verbose || cat /home/runner/work/DPP/DPP/build/_CPack_Packages/Linux/DEB/PreinstallOutput.log - name: Upload Binaries (DEB) - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: "libdpp - Debian Package ${{matrix.cfg.name}}" path: "${{github.workspace}}/build/*.deb" - name: Upload Binaries (RPM) - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: "libdpp - RPM Package ${{matrix.cfg.name}}" path: "${{github.workspace}}/build/*.rpm" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 7e863e7f66..abdf316701 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -64,7 +64,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: SARIF file path: results.sarif From 1f9123ceed7f418cabe9a9f84f646231130d85b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 09:18:03 +0000 Subject: [PATCH 45/89] build(deps): bump docker/setup-buildx-action from 3.0.0 to 3.1.0 (#1096) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index c476da7b33..230583070a 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -31,7 +31,7 @@ jobs: uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + uses: docker/setup-buildx-action@0d103c3126aa41d772a8362f6aa67afac040f80c # v3.1.0 - name: Login to DockerHub uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 From e44660b4608f6bf8c365519b6840c3a814b30d71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 09:18:11 +0000 Subject: [PATCH 46/89] build(deps): bump step-security/harden-runner from 2.6.1 to 2.7.0 (#1097) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/codeql.yml | 2 +- .github/workflows/construct-vcpkg-info.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/documentation-check.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/gitguardian.yml | 2 +- .github/workflows/labeler.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/sitemap.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/target-master.yml | 2 +- .github/workflows/test-docs-examples.yml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13272987d1..82632fc3b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - { arch: 'arm64', concurrency: 4, os: [self-hosted, linux, ARM64], package: g++-12, cpp-version: g++-12, cmake-flags: '', cpack: 'yes', ctest: 'no' } steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit @@ -117,7 +117,7 @@ jobs: - { arch: 'arm64', concurrency: 2, os: [self-hosted, ARM64, macOS], cpp-version: clang++-15, cmake-flags: ''} steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit @@ -166,7 +166,7 @@ jobs: runs-on: ${{matrix.cfg.os}} steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit @@ -231,7 +231,7 @@ jobs: runs-on: ${{matrix.cfg.os}} steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1a476d0758..411b336fd4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/construct-vcpkg-info.yml b/.github/workflows/construct-vcpkg-info.yml index 9c6291c4e4..38441d42b8 100644 --- a/.github/workflows/construct-vcpkg-info.yml +++ b/.github/workflows/construct-vcpkg-info.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 3fa8b859bb..fc3a42dfaa 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 230583070a..7351aafd2f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -22,7 +22,7 @@ jobs: cancel-in-progress: false steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/documentation-check.yml b/.github/workflows/documentation-check.yml index 7b63b8e81e..838f04fc3a 100644 --- a/.github/workflows/documentation-check.yml +++ b/.github/workflows/documentation-check.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 269fee9327..75d3def61c 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index a274a5f11b..4b992676ac 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -14,7 +14,7 @@ jobs: cancel-in-progress: true steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 7add5f9e35..0027d6a3f2 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index abdf316701..c205955dc1 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/sitemap.yml b/.github/workflows/sitemap.yml index cfb51f435e..b5ee2028e0 100644 --- a/.github/workflows/sitemap.yml +++ b/.github/workflows/sitemap.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index dc0b36c411..d11167f341 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/target-master.yml b/.github/workflows/target-master.yml index 02bfbbe5be..f92c20a53a 100644 --- a/.github/workflows/target-master.yml +++ b/.github/workflows/target-master.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit diff --git a/.github/workflows/test-docs-examples.yml b/.github/workflows/test-docs-examples.yml index 816573316a..4631ae1b64 100644 --- a/.github/workflows/test-docs-examples.yml +++ b/.github/workflows/test-docs-examples.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 with: egress-policy: audit From d08dcca3703283370bb18f13a2f6910121f879a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 09:18:21 +0000 Subject: [PATCH 47/89] build(deps): bump actions/dependency-review-action from 4.0.0 to 4.1.3 (#1093) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index fc3a42dfaa..d057728b39 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -24,4 +24,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: 'Dependency Review' - uses: actions/dependency-review-action@4901385134134e04cec5fbe5ddfe3b2c5bd5d976 # v4.0.0 + uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3 From aaec558419f6c82a899884c51ae8b222f360b0eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 09:18:28 +0000 Subject: [PATCH 48/89] build(deps): bump doxygen-awesome-css from `df88fe4` to `c01e51e` (#1098) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- doxygen-awesome-css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen-awesome-css b/doxygen-awesome-css index df88fe4fdd..c01e51e461 160000 --- a/doxygen-awesome-css +++ b/doxygen-awesome-css @@ -1 +1 @@ -Subproject commit df88fe4fdd97714fadfd3ef17de0b4401f804052 +Subproject commit c01e51e461a5f0d45422aa21cdf4e50181d04a19 From b39692bba42ce5577103ebb3736244d51a722eee Mon Sep 17 00:00:00 2001 From: Rafael Date: Sat, 2 Mar 2024 17:46:09 +0100 Subject: [PATCH 49/89] fix: correct wrong linking order to fix static build (#1102) --- library/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 3879d10e2f..ba47b77cf7 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -258,7 +258,7 @@ foreach (fullmodname ${subdirlist}) endif() else() - target_link_libraries(${modname} PUBLIC ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${ZLIB_LIBRARIES}) + target_link_libraries(${modname} PUBLIC ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARIES}) if (MINGW) target_link_libraries(${modname} PUBLIC wsock32 ws2_32 crypt32) endif () From 3d3028d0aad157fe178880d2eaa3e870124e76e6 Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Sun, 3 Mar 2024 20:51:51 +0000 Subject: [PATCH 50/89] docs: added a thinking page (#1092) --- docpages/example_code/thinking.cpp | 36 +++++++++++++++++++ .../interactions_and_components.md | 1 + .../interactions_and_components/thinking.md | 9 +++++ 3 files changed, 46 insertions(+) create mode 100644 docpages/example_code/thinking.cpp create mode 100644 docpages/example_programs/interactions_and_components/thinking.md diff --git a/docpages/example_code/thinking.cpp b/docpages/example_code/thinking.cpp new file mode 100644 index 0000000000..dce146e619 --- /dev/null +++ b/docpages/example_code/thinking.cpp @@ -0,0 +1,36 @@ +#include + +int main() { + dpp::cluster bot("token"); + + bot.on_log(dpp::utility::cout_logger()); + + /* The event is fired when someone issues your commands */ + bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) { + /* Check which command they ran */ + if (event.command.get_command_name() == "thinking") { + /* + * true for Ephemeral. + * You can set this to false if you want everyone to see the thinking response. + */ + event.thinking(true, [event](const dpp::confirmation_callback_t& callback) { + event.edit_original_response(dpp::message("thonk")); + }); + + } + }); + + bot.on_ready([&bot](const dpp::ready_t& event) { + if (dpp::run_once()) { + /* Create a new global command on ready event */ + dpp::slashcommand newcommand("thinking", "Thinking example...", bot.me.id); + + /* Register the command */ + bot.global_command_create(newcommand); + } + }); + + bot.start(dpp::st_wait); + + return 0; +} diff --git a/docpages/example_programs/interactions_and_components.md b/docpages/example_programs/interactions_and_components.md index 0112f192bb..44f2ce7e7b 100644 --- a/docpages/example_programs/interactions_and_components.md +++ b/docpages/example_programs/interactions_and_components.md @@ -8,3 +8,4 @@ Interactions are a unified way provided by Discord to handle \ref slashcommands * \subpage components-menu * \subpage modal-dialog-interactions * \subpage context-menu +* \subpage thinking diff --git a/docpages/example_programs/interactions_and_components/thinking.md b/docpages/example_programs/interactions_and_components/thinking.md new file mode 100644 index 0000000000..87bb2a09aa --- /dev/null +++ b/docpages/example_programs/interactions_and_components/thinking.md @@ -0,0 +1,9 @@ +\page thinking Thinking + +A common mistake people do is use `event.thinking` with `event.reply`, however, they always run into the `Interaction has already been acknowledged.` error! The reason for this is because `event.thinking` is a response to the interaction, meaning you have acknowledged it! You should use dpp::interaction_create_t::edit_original_response instead. + +Below is an example, showing how you should properly use the thinking method. + +\include{cpp} thinking.cpp + +This will make the bot think briefly, then change the response to "thonk"! From 63c00d8aca04a2e6fd4d3c0d79d87c39390533f8 Mon Sep 17 00:00:00 2001 From: Mohammed Keyvanzadeh Date: Sun, 3 Mar 2024 16:11:02 +0330 Subject: [PATCH 51/89] fix: get size of object instead of pointer The `this` keyword is evaluated to a pointer to an object of a given type so `sizeof(this)` returns the size of the pointer instead of the object so use `sizeof(*this)` instead. --- include/dpp/cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/dpp/cache.h b/include/dpp/cache.h index c43242b444..cdfa3788f8 100644 --- a/include/dpp/cache.h +++ b/include/dpp/cache.h @@ -250,7 +250,7 @@ template class cache { */ size_t bytes() { std::shared_lock l(cache_mutex); - return sizeof(this) + (cache_map->bucket_count() * sizeof(size_t)); + return sizeof(*this) + (cache_map->bucket_count() * sizeof(size_t)); } }; From 3f34d9d28d9421d2f1966f77c06b59aca1c01271 Mon Sep 17 00:00:00 2001 From: Mohammed Keyvanzadeh Date: Mon, 4 Mar 2024 17:53:21 +0330 Subject: [PATCH 52/89] fix: out-of-bounds read of MIME types (#1104) --- src/dpp/httpsclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dpp/httpsclient.cpp b/src/dpp/httpsclient.cpp index d6e4bc7302..b18675cd65 100644 --- a/src/dpp/httpsclient.cpp +++ b/src/dpp/httpsclient.cpp @@ -103,7 +103,7 @@ multipart_content https_client::build_multipart(const std::string &json, const s /* Multiple files */ for (size_t i = 0; i < filenames.size(); ++i) { content += part_start + "name=\"files[" + std::to_string(i) + "]\"; filename=\"" + filenames[i] + "\""; - content += "\r\nContent-Type: " + (mimetypes.size() < i || mimetypes[i].empty() ? default_mime_type : mimetypes[i]) + two_cr; + content += "\r\nContent-Type: " + (mimetypes.size() <= i || mimetypes[i].empty() ? default_mime_type : mimetypes[i]) + two_cr; content += contents[i]; content += "\r\n"; } From 19944809cf9d5eeb2d6cfeda828b914779af0f4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Mar 2024 06:57:38 +0000 Subject: [PATCH 53/89] build(deps): bump ubuntu from `bb1c416` to `80ef4a4` (#1105) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d70d882be2..e353f81393 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:focal@sha256:bb1c41682308d7040f74d103022816d41c50d7b0c89e9d706a74b4e548636e54 +FROM ubuntu:focal@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9c35d ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --no-install-recommends -y libssl-dev zlib1g-dev libsodium-dev libopus-dev cmake pkg-config g++ gcc git make && apt-get clean && rm -rf /var/lib/apt/lists/* From 4f8391411f9171c42980600a7293f2dd4f9da761 Mon Sep 17 00:00:00 2001 From: Kai Tamkun <13513421+heimskr@users.noreply.github.com> Date: Sat, 23 Mar 2024 09:54:54 -0700 Subject: [PATCH 54/89] Ability to suppress embeds (#1107) --- include/dpp/cluster.h | 9 +++++++++ include/dpp/message.h | 8 ++++++++ src/dpp/cluster/message.cpp | 10 ++++++++++ src/dpp/message.cpp | 13 +++++++++++-- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index 7f18f6e9aa..54e446a5ca 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -1769,6 +1769,15 @@ class DPP_EXPORT cluster { */ void message_edit(const struct message &m, command_completion_event_t callback = utility::log_error()); + /** + * @brief Edit the flags of a message on a channel. The callback function is called when the message has been edited + * + * @param m Message to edit the flags of + * @param callback Function to call when the API call completes. + * On success the callback will contain a dpp::message object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void message_edit_flags(const struct message &m, command_completion_event_t callback = utility::log_error()); + /** * @brief Add a reaction to a message. The reaction string must be either an `emojiname:id` or a unicode character. * diff --git a/include/dpp/message.h b/include/dpp/message.h index 2d11b527e2..6455540e62 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -2130,6 +2130,14 @@ struct DPP_EXPORT message : public managed, json_interface { */ bool suppress_embeds() const; + /** + * @brief Set whether embeds should be suppressed + * + * @param suppress whether embeds should be suppressed + * @return message& reference to self + */ + message& suppress_embeds(bool suppress); + /** * @brief True if source message was deleted * diff --git a/src/dpp/cluster/message.cpp b/src/dpp/cluster/message.cpp index 231670b31c..06fc23faba 100644 --- a/src/dpp/cluster/message.cpp +++ b/src/dpp/cluster/message.cpp @@ -119,6 +119,16 @@ void cluster::message_edit(const message &m, command_completion_event_t callback }, m.file_data); } +void cluster::message_edit_flags(const message &m, command_completion_event_t callback) { + this->post_rest_multipart(API_PATH "/channels", std::to_string(m.channel_id), "messages/" + std::to_string(m.id), m_patch, nlohmann::json{ + {"flags", m.flags}, + }.dump(), [this, callback](json &j, const http_request_completion_t& http) { + if (callback) { + callback(confirmation_callback_t(this, message(this).fill_from_json(&j), http)); + } + }, m.file_data); +} + void cluster::message_get(snowflake message_id, snowflake channel_id, command_completion_event_t callback) { rest_request(this, API_PATH "/channels", std::to_string(channel_id), "messages/" + std::to_string(message_id), m_get, "", callback); diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index 850a6c67ed..31e53ea3fb 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -357,7 +357,7 @@ void to_json(json& j, const component& cp) { o["type"] = "channel"; } else if (v.type == dpp::cdt_user) { o["type"] = "user"; - } + } j["default_values"].push_back(o); } } @@ -844,7 +844,7 @@ reaction::reaction(json* j) { } } -attachment::attachment(struct message* o) +attachment::attachment(struct message* o) : id(0) , size(0) , width(0) @@ -1071,6 +1071,15 @@ bool message::suppress_embeds() const { return flags & m_suppress_embeds; } +message& message::suppress_embeds(bool suppress) { + if (suppress) { + flags |= m_suppress_embeds; + } else { + flags &= ~m_suppress_embeds; + } + return *this; +} + bool message::is_source_message_deleted() const { return flags & m_source_message_deleted; } From 44bfb17f982ef71315a9eb47dc769468f68497e5 Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Thu, 28 Mar 2024 19:45:31 +0000 Subject: [PATCH 55/89] docs: fixed missing/incorrect params for many functions (#1110) --- include/dpp/cluster.h | 2 +- include/dpp/cluster_coro_calls.h | 11 ++++++++++- include/dpp/cluster_sync_calls.h | 14 +++++++++++++- include/dpp/coro/coroutine.h | 2 +- include/dpp/discordevents.h | 4 ++-- include/dpp/discordvoiceclient.h | 2 +- include/dpp/emoji.h | 3 ++- include/dpp/event_router.h | 2 +- include/dpp/guild.h | 2 +- include/dpp/httpsclient.h | 2 +- include/dpp/prune.h | 2 +- include/dpp/role.h | 3 ++- include/dpp/scheduled_event.h | 3 ++- include/dpp/sku.h | 8 +++++++- include/dpp/sslclient.h | 1 + include/dpp/utility.h | 27 ++++++++++++++------------- src/dpp/cluster_coro_calls.cpp | 4 ++++ src/dpp/cluster_sync_calls.cpp | 4 ++++ 18 files changed, 68 insertions(+), 28 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index 54e446a5ca..d7b7e27469 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -2804,7 +2804,7 @@ class DPP_EXPORT cluster { * @brief Get the guild's onboarding configuration * * @see https://discord.com/developers/docs/resources/guild#get-guild-onboarding - * @param o The onboarding object + * @param guild_id The guild to pull the onboarding configuration from. * @param callback Function to call when the API call completes. * On success the callback will contain a dpp::onboarding object in confirmation_callback_t::value filled to match the vanity url. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). */ diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index b0a2b1b46b..f5a41fa1ea 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -1063,7 +1063,7 @@ * * @see dpp::cluster::guild_get_onboarding * @see https://discord.com/developers/docs/resources/guild#get-guild-onboarding - * @param o The onboarding object + * @param guild_id The guild to pull the onboarding configuration from. * @return onboarding returned object on completion * \memberof dpp::cluster */ @@ -1528,6 +1528,15 @@ */ [[nodiscard]] async co_message_edit(const struct message &m); +/** + * @brief Edit the flags of a message on a channel. The callback function is called when the message has been edited + * + * @param m Message to edit the flags of + * @return message returned object on completion + * \memberof dpp::cluster + */ +[[nodiscard]] async co_message_edit_flags(const struct message &m); + /** * @brief Get a message * diff --git a/include/dpp/cluster_sync_calls.h b/include/dpp/cluster_sync_calls.h index 6764719a83..505c80029d 100644 --- a/include/dpp/cluster_sync_calls.h +++ b/include/dpp/cluster_sync_calls.h @@ -1303,7 +1303,7 @@ confirmation guild_sync_integration_sync(snowflake guild_id, snowflake integrati * * @see dpp::cluster::guild_get_onboarding * @see https://discord.com/developers/docs/resources/guild#get-guild-onboarding - * @param o The onboarding object + * @param guild_id The guild to pull the onboarding configuration from. * @return onboarding returned object on completion * \memberof dpp::cluster * @throw dpp::rest_exception upon failure to execute REST function @@ -1870,6 +1870,18 @@ confirmation message_delete_reaction_emoji_sync(snowflake message_id, snowflake */ message message_edit_sync(const struct message &m); +/** + * @brief Edit the flags of a message on a channel. The callback function is called when the message has been edited + * + * @param m Message to edit the flags of + * @return message returned object on completion + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +message message_edit_flags_sync(const struct message &m); + /** * @brief Get a message * diff --git a/include/dpp/coro/coroutine.h b/include/dpp/coro/coroutine.h index a03d670b41..869882c2c8 100644 --- a/include/dpp/coro/coroutine.h +++ b/include/dpp/coro/coroutine.h @@ -58,7 +58,7 @@ using handle_t = std_coroutine::coroutine_handle>; /** * @brief Base class of dpp::coroutine. * - * @warn This class should not be used directly by a user, use dpp::coroutine instead. + * @warning This class should not be used directly by a user, use dpp::coroutine instead. * @note This class contains all the functions used internally by co_await. It is intentionally opaque and a private base of dpp::coroutine so a user cannot call await_suspend and await_resume directly. */ template diff --git a/include/dpp/discordevents.h b/include/dpp/discordevents.h index c29d686bfc..184294818b 100644 --- a/include/dpp/discordevents.h +++ b/include/dpp/discordevents.h @@ -55,7 +55,7 @@ void DPP_EXPORT set_snowflake_array_not_null(const nlohmann::json* j, const char /** * @brief Applies a function to each element of a json array. - * @param j nlohmann::json instance to retrieve value from + * @param parent nlohmann::json instance to retrieve value from * @param key key name to check for the values * @param fn function to apply to each element */ @@ -65,7 +65,7 @@ void DPP_EXPORT for_each_json(nlohmann::json* parent, std::string_view key, cons * @brief Sets an array of objects from a json field value, if defined, else does nothing * @tparam T The class of which the array consists of. Must be derived from dpp::json_interface * @param j nlohmann::json instance to retrieve value from - * @param keyname key name to check for the values + * @param key key name to check for the values * @param v Value to change */ template void set_object_array_not_null(nlohmann::json* j, std::string_view key, std::vector& v) { diff --git a/include/dpp/discordvoiceclient.h b/include/dpp/discordvoiceclient.h index e71f221e1b..07e4364483 100644 --- a/include/dpp/discordvoiceclient.h +++ b/include/dpp/discordvoiceclient.h @@ -862,7 +862,7 @@ class DPP_EXPORT discord_voice_client : public websocket_client /** * @brief Change the iteration interval time. * - * @param time The time (in milliseconds) between each interval when parsing audio. + * @param interval The time (in milliseconds) between each interval when parsing audio. * * @return Reference to self. */ diff --git a/include/dpp/emoji.h b/include/dpp/emoji.h index 7e0549bd2a..6249b4c9eb 100644 --- a/include/dpp/emoji.h +++ b/include/dpp/emoji.h @@ -208,7 +208,8 @@ class DPP_EXPORT emoji : public managed, public json_interface { /** * @brief Load an image into the object * - * @param image_blob Image binary data + * @param data Image binary data + * @param size Size of the image. * @param type Type of image. It can be one of `i_gif`, `i_jpg` or `i_png`. * @return emoji& Reference to self * @throw dpp::length_exception Image content exceeds discord maximum of 256 kilobytes diff --git a/include/dpp/event_router.h b/include/dpp/event_router.h index 33793144f1..1657fbd592 100644 --- a/include/dpp/event_router.h +++ b/include/dpp/event_router.h @@ -690,7 +690,7 @@ template class event_router_t { * @brief Attach a callable to the event, adding a listener. * The callable should be of the form `void(const T&)` * where T is the event type for this event router. - * + *f * @warning You cannot call this within an event handler. * * @param fun Callable to attach to event diff --git a/include/dpp/guild.h b/include/dpp/guild.h index cbb394ce15..db631c33d1 100644 --- a/include/dpp/guild.h +++ b/include/dpp/guild.h @@ -1990,7 +1990,7 @@ struct DPP_EXPORT onboarding : public json_interface { /** * @brief Set guild_id of this onboarding object * - * @param guild_id Guild ID to set + * @param id Guild ID to set * @return Reference to self, so these method calls may be chained */ onboarding& set_guild_id(const snowflake id); diff --git a/include/dpp/httpsclient.h b/include/dpp/httpsclient.h index f043d533f7..7884baab39 100644 --- a/include/dpp/httpsclient.h +++ b/include/dpp/httpsclient.h @@ -249,7 +249,7 @@ class DPP_EXPORT https_client : public ssl_client { * @param extra_headers Additional request headers, e.g. user-agent, authorization, etc * @param plaintext_connection Set to true to make the connection plaintext (turns off SSL) * @param request_timeout How many seconds before the connection is considered failed if not finished - * @param http_protocol Request HTTP protocol + * @param protocol Request HTTP protocol (default: 1.1) */ https_client(const std::string &hostname, uint16_t port = 443, const std::string &urlpath = "/", const std::string &verb = "GET", const std::string &req_body = "", const http_headers& extra_headers = {}, bool plaintext_connection = false, uint16_t request_timeout = 5, const std::string &protocol = "1.1"); diff --git a/include/dpp/prune.h b/include/dpp/prune.h index 9952b841f2..36e6275f6d 100644 --- a/include/dpp/prune.h +++ b/include/dpp/prune.h @@ -71,7 +71,7 @@ struct DPP_EXPORT prune : public json_interface { /** * @brief Build JSON from this object. * - * @param with_prune_count True if the prune count boolean is to be set in the built JSON + * @param with_id True if the prune count boolean is to be set in the built JSON * @return The JSON of the prune object */ json to_json(bool with_id = false) const; // Intentional shadow of json_interface, mostly present for documentation diff --git a/include/dpp/role.h b/include/dpp/role.h index 44ca4a597e..a3da13f367 100644 --- a/include/dpp/role.h +++ b/include/dpp/role.h @@ -307,7 +307,8 @@ class DPP_EXPORT role : public managed, public json_interface { /** * @brief Load a role icon. * - * @param image_blob Image binary data + * @param data Image binary data + * @param size Size of the image. * @param type Type of image. It can be one of `i_gif`, `i_jpg` or `i_png`. * @return emoji& Reference to self */ diff --git a/include/dpp/scheduled_event.h b/include/dpp/scheduled_event.h index b0617719e1..52d5c559ac 100644 --- a/include/dpp/scheduled_event.h +++ b/include/dpp/scheduled_event.h @@ -317,7 +317,8 @@ struct DPP_EXPORT scheduled_event : public managed, public json_interface { /** * @brief Construct a new SKU object with all data required. * - * @param id SKU id. + * @param id ID of the SKU. + * @param type Type of SKU (sku_type). + * @param application_id ID of the parent application. + * @param name Customer-facing name of your premium offering. + * @param slug System-generated URL slug based on the SKU's name. + * @param flags Flags bitmap from dpp::sku_flags. + * */ sku(const snowflake id, const sku_type type, const snowflake application_id, const std::string name, const std::string slug, const uint16_t flags); diff --git a/include/dpp/sslclient.h b/include/dpp/sslclient.h index b1e674efc4..f43e3a575d 100644 --- a/include/dpp/sslclient.h +++ b/include/dpp/sslclient.h @@ -58,6 +58,7 @@ bool close_socket(dpp::socket sfd); * @brief Set a socket to blocking or non-blocking IO * * @param sockfd socket to act upon + * @param non_blocking should socket be non-blocking? * @return false on error, true on success */ bool set_nonblocking(dpp::socket sockfd, bool non_blocking); diff --git a/include/dpp/utility.h b/include/dpp/utility.h index 47b85f925d..f78d3b5b9e 100644 --- a/include/dpp/utility.h +++ b/include/dpp/utility.h @@ -365,13 +365,13 @@ struct DPP_EXPORT image_data { * * @param rhs Image to copy */ - image_data(image_data&&) noexcept = default; + image_data(image_data&& rhs) noexcept = default; /** * @brief Construct from string buffer * * @param format Image format - * @param str Data in a string + * @param bytes Data in a string * @see image_type */ image_data(image_type format, std::string_view bytes); @@ -380,8 +380,8 @@ struct DPP_EXPORT image_data { * @brief Construct from byte buffer * * @param format Image format - * @param buf Byte buffer - * @param size_t Image size in bytes + * @param bytes Data of the image + * @param byte_size Image size in bytes * @see image_type */ image_data(image_type format, const std::byte* bytes, uint32_t byte_size); @@ -405,8 +405,8 @@ struct DPP_EXPORT image_data { /** * @brief Set image data. * - * @param format Format of the image - * @param data Data of the image + * @param format Image format + * @param bytes Data of the image */ void set(image_type format, std::string_view bytes); @@ -414,7 +414,8 @@ struct DPP_EXPORT image_data { * @brief Set image data. * * @param format Format of the image - * @param data Data of the image + * @param bytes Data of the image + * @param byte_size Image size in bytes */ void set(image_type format, const std::byte* bytes, uint32_t byte_size); @@ -507,7 +508,7 @@ struct icon { /** * @brief Get as icon hash. * - * @warn The behavior is undefined if `is_iconhash() == false` + * @warning The behavior is undefined if `is_iconhash() == false` * @return iconhash& This iconhash */ iconhash& as_iconhash() &; @@ -515,7 +516,7 @@ struct icon { /** * @brief Get as icon hash. * - * @warn The behavior is undefined if `is_iconhash() == false` + * @warning The behavior is undefined if `is_iconhash() == false` * @return iconhash& This iconhash */ const iconhash& as_iconhash() const&; @@ -523,7 +524,7 @@ struct icon { /** * @brief Get as icon hash. * - * @warn The behavior is undefined if `is_iconhash() == false` + * @warning The behavior is undefined if `is_iconhash() == false` * @return iconhash& This iconhash */ iconhash&& as_iconhash() &&; @@ -539,7 +540,7 @@ struct icon { /** * @brief Get as image data. * - * @warn The behavior is undefined if `is_image_data() == false` + * @warning The behavior is undefined if `is_image_data() == false` * @return image_data& This image */ image_data& as_image_data() &; @@ -547,7 +548,7 @@ struct icon { /** * @brief Get as image. * - * @warn The behavior is undefined if `is_image_data() == false` + * @warning The behavior is undefined if `is_image_data() == false` * @return image_data& This image */ const image_data& as_image_data() const&; @@ -555,7 +556,7 @@ struct icon { /** * @brief Get as image. * - * @warn The behavior is undefined if `is_image_data() == false` + * @warning The behavior is undefined if `is_image_data() == false` * @return image_data& This image */ image_data&& as_image_data() &&; diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp index 4b3d2287fa..dbf3da3757 100644 --- a/src/dpp/cluster_coro_calls.cpp +++ b/src/dpp/cluster_coro_calls.cpp @@ -503,6 +503,10 @@ async cluster::co_message_edit(const message &m) { return async{ this, static_cast(&cluster::message_edit), m }; } +async cluster::co_message_edit_flags(const message &m) { + return async{ this, static_cast(&cluster::message_edit_flags), m }; +} + async cluster::co_message_get(snowflake message_id, snowflake channel_id) { return async{ this, static_cast(&cluster::message_get), message_id, channel_id }; } diff --git a/src/dpp/cluster_sync_calls.cpp b/src/dpp/cluster_sync_calls.cpp index a19ec593fc..3dc14c2201 100644 --- a/src/dpp/cluster_sync_calls.cpp +++ b/src/dpp/cluster_sync_calls.cpp @@ -501,6 +501,10 @@ message cluster::message_edit_sync(const message &m) { return dpp::sync(this, static_cast(&cluster::message_edit), m); } +message cluster::message_edit_flags_sync(const message &m) { + return dpp::sync(this, static_cast(&cluster::message_edit_flags), m); +} + message cluster::message_get_sync(snowflake message_id, snowflake channel_id) { return dpp::sync(this, static_cast(&cluster::message_get), message_id, channel_id); } From 38142b82151433e3da1916a0166194b93a16f97b Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Fri, 29 Mar 2024 21:21:18 +0000 Subject: [PATCH 56/89] docs: rewrote the CLion VCPKG page to use VS toolchain (#1111) --- docpages/03_installing.md | 1 - docpages/04_building_a_bot.md | 1 + docpages/images/clionvstoolchain.png | Bin 0 -> 78629 bytes docpages/images/clionvstoolchain2.png | Bin 0 -> 16101 bytes docpages/install/install-vcpkg.md | 6 +-- .../install/install-windows-clion-vcpkg.md | 38 ---------------- docpages/make_a_bot/clion_windows.md | 42 ++++++++++++++++++ 7 files changed, 46 insertions(+), 42 deletions(-) create mode 100644 docpages/images/clionvstoolchain.png create mode 100644 docpages/images/clionvstoolchain2.png delete mode 100644 docpages/install/install-windows-clion-vcpkg.md create mode 100644 docpages/make_a_bot/clion_windows.md diff --git a/docpages/03_installing.md b/docpages/03_installing.md index 210d17afeb..dc3e42d9d4 100644 --- a/docpages/03_installing.md +++ b/docpages/03_installing.md @@ -7,7 +7,6 @@ There are many ways to install D++, either from a package manager, or from sourc * \subpage install-vcpkg * \subpage install-arch-aur * \subpage install-windows-vs-zip -* \subpage install-windows-clion-vcpkg * \subpage install-xmake * \subpage install-brew * \subpage install-from-source diff --git a/docpages/04_building_a_bot.md b/docpages/04_building_a_bot.md index ba55d6e50a..41cfe43247 100644 --- a/docpages/04_building_a_bot.md +++ b/docpages/04_building_a_bot.md @@ -7,6 +7,7 @@ Click on a link below for a guide specifically for your system: * \subpage creating-a-bot-application * \subpage build-a-discord-bot-windows-visual-studio * \subpage build-a-discord-bot-windows-wsl +* \subpage install-windows-clion-vcpkg * \subpage build-a-discord-bot-linux-clion * \subpage buildcmake * \subpage buildmeson diff --git a/docpages/images/clionvstoolchain.png b/docpages/images/clionvstoolchain.png new file mode 100644 index 0000000000000000000000000000000000000000..bd55db95ba2f675aadce308bb8792879d9382266 GIT binary patch literal 78629 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 I5yPPW1DPQ}YXATM literal 0 HcmV?d00001 diff --git a/docpages/install/install-vcpkg.md b/docpages/install/install-vcpkg.md index 80717d578e..d672253c19 100644 --- a/docpages/install/install-vcpkg.md +++ b/docpages/install/install-vcpkg.md @@ -14,12 +14,12 @@ To install D++ on a system with VCPKG: ```cmd c:\vcpkg>vcpkg list dpp -dpp:x64-windows 10.0.24 D++ Extremely Lightweight C++ Discord Library. +dpp:x64-windows 10.0.29 D++ Extremely Lightweight C++ Discord Library. ``` -- You may now use the library within a `CMake` based project by adding instructions such as these to your `CMakeLists.txt`: +- You may now use the library within a `CMake` based project by adding the following instructions to your `CMakeLists.txt`: ```cmake find_package(dpp CONFIG REQUIRED) -target_link_libraries(your_target_name PRIVATE dpp::dpp) +target_link_libraries(${PROJECT_NAME} PRIVATE dpp::dpp) ``` diff --git a/docpages/install/install-windows-clion-vcpkg.md b/docpages/install/install-windows-clion-vcpkg.md deleted file mode 100644 index 1a1ea9a94f..0000000000 --- a/docpages/install/install-windows-clion-vcpkg.md +++ /dev/null @@ -1,38 +0,0 @@ -\page install-windows-clion-vcpkg Installing D++ for CLion via VCPKG (Windows) - -\warning This page is for **Windows only**. If you want to use CLion on Linux, look to use \ref build-a-discord-bot-linux-clion "this page". Like always with windows, we highly recommends you use the [pre-made Visual Studio template](https://github.com/brainboxdotcc/windows-bot-template/) - -To add D++ to a CLion project, you need obtain the library through VCPKG and then configure your CLion project and `CMakeLists.txt`. - -1. Build [VCPKG](https://vcpkg.io/) on your system (skip if you already have it). -2. Run `vcpkg install dpp:x64-windows`. -3. VCPKG will install the library along with the dependencies for you. -4. Now check if dpp has been installed using `vcpkg list dpp`. -```cmd -C:/vcpkg>vcpkg list dpp -dpp:x64-windows 10.0.23 D++ Extremely Lightweight C++ Discord Library. -``` - -5. To use vcpkg in CLion, add the following line to your CMake options in the settings (Located under Settings > Build, Execution, Deployment > CMake) -```cmd --DCMAKE_TOOLCHAIN_FILE=path_to_vcpkg_root_folder/scripts/buildsystems/vcpkg.cmake -``` - For example, if your root folder is `C:/vcpkg/` then the CMake option will be: -```cmd --DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -``` - -6. Now proceed to add the following lines to your `CMakeLists.txt`: -```cmake -find_package(dpp CONFIG REQUIRED) -target_link_libraries(main PRIVATE dpp::dpp) -target_include_directories(main PRIVATE path_to_vcpkg_root_folder/installed/architecture-os/include) -``` - For example, if your VCPKG root is `C:/vcpkg/`, then your `CMakeLists.txt` should look like this: -```cmake -find_package(dpp CONFIG REQUIRED) -target_link_libraries(main PRIVATE dpp::dpp) -target_include_directories(main PRIVATE C:/vcpkg/installed/x64-windows/include) -``` - -7. Congratulations! Now try to build a test program to see if the installation succeeded. If you get stuck somewhere, feel free to ask us on the D++ [discord server](https://discord.gg/dpp). \ No newline at end of file diff --git a/docpages/make_a_bot/clion_windows.md b/docpages/make_a_bot/clion_windows.md new file mode 100644 index 0000000000..051f3dfb8e --- /dev/null +++ b/docpages/make_a_bot/clion_windows.md @@ -0,0 +1,42 @@ +\page install-windows-clion-vcpkg Building a Discord Bot using CLion & VCPKG (Windows) + +\warning This page is for **Windows only**. If you want to use CLion on Linux, look to use \ref build-a-discord-bot-linux-clion "this page". Like always with windows, we highly recommends you use the [pre-made Visual Studio template](https://github.com/brainboxdotcc/windows-bot-template/). This tutorial also assumes you have installed D++ via VCPKG already. If you haven't, look at \ref install-vcpkg "this page". + +### Changing Toolchains + +\note If you have already configured your toolchain to use anything **but** MinGW64, then you can skip to the next section. Otherwise, it is **critical** that you follow along with this section. It should also be noted that you **need** Visual Studio for this. + +Head on over to `File > Settings` (Ctrl+Alt+S), then navigate to `Build, Execution, Deployment > Toolchains`. + +If there is a Visual Studio toolchain there, drag it to the top of the list. This will make the Visual Studio toolchain the default toolchain. + +\image html clionvstoolchain.png + +If you don't have the Visual Studio toolchain, you can hit the plus symbol above the list of toolchains and add a toolchain. This is also how you can add WSL as a toolchain! + +\image html clionvstoolchain2.png + +From there, you need to drag it to the top (if it didn't already add at the top) to ensure it's the default toolchain. + +### Using VCPKG with CLion + +To use vcpkg in CLion, add the following line to your CMake options in the settings (Located under `Settings > Build, Execution, Deployment > CMake`) +```cmd +-DCMAKE_TOOLCHAIN_FILE=path_to_vcpkg_root_folder/scripts/buildsystems/vcpkg.cmake +``` +For example, if your root folder is `C:/vcpkg/` then the CMake option will be: +```cmd +-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake +``` + +### Making a test application. + +Open your `main.cpp` file and then copy and paste the following \ref firstbot "example program" in. Then, set your bot token (see \ref creating-a-bot-application). Here's how your `main.cpp` file should look: + +\include{cpp} firstbot.cpp + +If everything went well, you should now have a functioning bot! If not, feel free to ask us on the D++ [discord server](https://discord.gg/dpp). + +### Troubleshooting + +If you see a message like `Detecting C compiler ABI info - failed` or something along the lines of `"cl.exe" is not able to compile a simple test program`, then try to reinstall `Windows Build Tools` along with the `Windows SDK` from the Visual Studio Installer. From 68e7477e07342c70aa2d6079f8c1f38a8b406849 Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Sat, 30 Mar 2024 04:51:13 -0400 Subject: [PATCH 57/89] fix memory leak on libstdc++ (#1112) --- include/dpp/queues.h | 61 ++++++++++-- src/dpp/cluster.cpp | 9 +- src/dpp/queues.cpp | 218 ++++++++++++++++++++++++++----------------- 3 files changed, 188 insertions(+), 100 deletions(-) diff --git a/include/dpp/queues.h b/include/dpp/queues.h index b3e9b8ec97..3097d5bcb6 100644 --- a/include/dpp/queues.h +++ b/include/dpp/queues.h @@ -434,9 +434,9 @@ class DPP_EXPORT in_thread { std::map buckets; /** - * @brief Queue of requests to be made. + * @brief Queue of requests to be made. Sorted by http_request::endpoint. */ - std::map> requests_in; + std::vector> requests_in; /** * @brief Inbound queue thread loop. @@ -465,7 +465,7 @@ class DPP_EXPORT in_thread { * @param req http_request to post. The pointer will be freed when it has * been executed. */ - void post_request(http_request* req); + void post_request(std::unique_ptr req); }; /** @@ -516,10 +516,25 @@ class DPP_EXPORT request_queue { */ std::condition_variable out_ready; + /** + * @brief A completed request. Contains both the request and the response + */ + struct completed_request { + /** + * @brief Request sent + */ + std::unique_ptr request; + + /** + * @brief Response to the request + */ + std::unique_ptr response; + }; + /** * @brief Completed requests queue */ - std::queue> responses_out; + std::queue responses_out; /** * @brief A vector of inbound request threads forming a pool. @@ -533,9 +548,38 @@ class DPP_EXPORT request_queue { std::vector requests_in; /** - * @brief Completed requests to delete + * @brief A request queued for deletion in the queue. + */ + struct queued_deleting_request { + /** + * @brief Time to delete the request + */ + time_t time_to_delete; + + /** + * @brief The request to delete + */ + completed_request request; + + /** + * @brief Comparator for sorting purposes + * @param other Other queued request to compare the deletion time with + * @return bool Whether this request comes before another in strict ordering + */ + bool operator<(const queued_deleting_request& other) const noexcept; + + /** + * @brief Comparator for sorting purposes + * @param time Time to compare with + * @return bool Whether this request's deletion time is lower than the time given, for strict ordering + */ + bool operator<(time_t time) const noexcept; + }; + + /** + * @brief Completed requests to delete. Sorted by deletion time */ - std::multimap> responses_to_delete; + std::vector responses_to_delete; /** * @brief Set to true if the threads should terminate @@ -597,14 +641,13 @@ class DPP_EXPORT request_queue { ~request_queue(); /** - * @brief Put a http_request into the request queue. You should ALWAYS "new" an object - * to pass to here -- don't submit an object that's on the stack! + * @brief Put a http_request into the request queue. * @note Will use a simple hash function to determine which of the 'in queues' to place * this request onto. * @param req request to add * @return reference to self */ - request_queue& post_request(http_request *req); + request_queue& post_request(std::unique_ptr req); /** * @brief Returns true if the bot is currently globally rate limited diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index e8a13a9bab..611c091da4 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -322,8 +322,7 @@ json error_response(const std::string& message, http_request_completion_t& rv) } void cluster::post_rest(const std::string &endpoint, const std::string &major_parameters, const std::string ¶meters, http_method method, const std::string &postdata, json_encode_t callback, const std::string &filename, const std::string &filecontent, const std::string &filemimetype, const std::string &protocol) { - /* NOTE: This is not a memory leak! The request_queue will free the http_request once it reaches the end of its lifecycle */ - rest->post_request(new http_request(endpoint + (!major_parameters.empty() ? "/" : "") + major_parameters, parameters, [endpoint, callback](http_request_completion_t rv) { + rest->post_request(std::make_unique(endpoint + (!major_parameters.empty() ? "/" : "") + major_parameters, parameters, [endpoint, callback](http_request_completion_t rv) { json j; if (rv.error == h_success && !rv.body.empty()) { try { @@ -350,8 +349,7 @@ void cluster::post_rest_multipart(const std::string &endpoint, const std::string file_mimetypes.push_back(data.mimetype); } - /* NOTE: This is not a memory leak! The request_queue will free the http_request once it reaches the end of its lifecycle */ - rest->post_request(new http_request(endpoint + (!major_parameters.empty() ? "/" : "") + major_parameters, parameters, [endpoint, callback](http_request_completion_t rv) { + rest->post_request(std::make_unique(endpoint + (!major_parameters.empty() ? "/" : "") + major_parameters, parameters, [endpoint, callback](http_request_completion_t rv) { json j; if (rv.error == h_success && !rv.body.empty()) { try { @@ -369,8 +367,7 @@ void cluster::post_rest_multipart(const std::string &endpoint, const std::string void cluster::request(const std::string &url, http_method method, http_completion_event callback, const std::string &postdata, const std::string &mimetype, const std::multimap &headers, const std::string &protocol) { - /* NOTE: This is not a memory leak! The request_queue will free the http_request once it reaches the end of its lifecycle */ - raw_rest->post_request(new http_request(url, callback, method, postdata, mimetype, headers, protocol)); + raw_rest->post_request(std::make_unique(url, callback, method, postdata, mimetype, headers, protocol)); } gateway::gateway() : shards(0), session_start_total(0), session_start_remaining(0), session_start_reset_after(0), session_start_max_concurrency(0) { diff --git a/src/dpp/queues.cpp b/src/dpp/queues.cpp index 0d28de6b88..3625fadd2b 100644 --- a/src/dpp/queues.cpp +++ b/src/dpp/queues.cpp @@ -236,9 +236,46 @@ request_queue::~request_queue() out_ready.notify_one(); out_thread->join(); delete out_thread; - for (auto& ri : requests_in) { - delete ri; - } +} + +namespace +{ + +/** + * @brief Comparator for sorting a request container + */ +struct compare_request { + /** + * @brief Less_than comparator for sorting + * @param lhs Left-hand side + * @param rhs Right-hand side + * @return Whether lhs comes before rhs in strict ordering + */ + bool operator()(const std::unique_ptr& lhs, const std::unique_ptr& rhs) const noexcept { + return std::less{}(lhs->endpoint, rhs->endpoint); + }; + + /** + * @brief Less_than comparator for sorting + * @param lhs Left-hand side + * @param rhs Right-hand side + * @return Whether lhs comes before rhs in strict ordering + */ + bool operator()(const std::unique_ptr& lhs, std::string_view rhs) const noexcept { + return std::less{}(lhs->endpoint, rhs); + }; + + /** + * @brief Less_than comparator for sorting + * @param lhs Left-hand side + * @param rhs Right-hand side + * @return Whether lhs comes before rhs in strict ordering + */ + bool operator()(std::string_view lhs, const std::unique_ptr& rhs) const noexcept { + return std::less{}(lhs, rhs->endpoint); + }; +}; + } void in_thread::in_loop(uint32_t index) @@ -246,93 +283,92 @@ void in_thread::in_loop(uint32_t index) utility::set_thread_name(std::string("http_req/") + std::to_string(index)); while (!terminating) { std::mutex mtx; - std::unique_lock lock{ mtx }; + std::unique_lock lock{ mtx }; in_ready.wait_for(lock, std::chrono::seconds(1)); /* New request to be sent! */ if (!requests->globally_ratelimited) { - std::map> requests_in_copy; + std::vector requests_view; { - /* Make a safe copy within a mutex */ + /* Gather all the requests first within a mutex */ std::shared_lock lock(in_mutex); if (requests_in.empty()) { /* Nothing to copy, wait again */ continue; } - requests_in_copy = requests_in; + requests_view.reserve(requests_in.size()); + std::transform(requests_in.begin(), requests_in.end(), std::back_inserter(requests_view), [](const std::unique_ptr &r) { + return r.get(); + }); } - for (auto & bucket : requests_in_copy) { - for (auto req : bucket.second) { - - http_request_completion_t rv; - auto currbucket = buckets.find(bucket.first); - - if (currbucket != buckets.end()) { - /* There's a bucket for this request. Check its status. If the bucket says to wait, - * skip all requests in this bucket till its ok. - */ - if (currbucket->second.remaining < 1) { - uint64_t wait = (currbucket->second.retry_after ? currbucket->second.retry_after : currbucket->second.reset_after); - if ((uint64_t)time(nullptr) > currbucket->second.timestamp + wait) { - /* Time has passed, we can process this bucket again. send its request. */ - rv = req->run(creator); - } else { - if (!req->waiting) { - req->waiting = true; - } - /* Time not up yet, wait more */ - break; - } + for (auto& request_view : requests_view) { + const std::string &key = request_view->endpoint; + http_request_completion_t rv; + auto currbucket = buckets.find(key); + + if (currbucket != buckets.end()) { + /* There's a bucket for this request. Check its status. If the bucket says to wait, + * skip all requests in this bucket till its ok. + */ + if (currbucket->second.remaining < 1) { + uint64_t wait = (currbucket->second.retry_after ? currbucket->second.retry_after : currbucket->second.reset_after); + if ((uint64_t)time(nullptr) > currbucket->second.timestamp + wait) { + /* Time has passed, we can process this bucket again. send its request. */ + rv = request_view->run(creator); } else { - /* There's limit remaining, we can just run the request */ - rv = req->run(creator); + if (!request_view->waiting) { + request_view->waiting = true; + } + /* Time not up yet, wait more */ + break; } } else { - /* No bucket for this endpoint yet. Just send it, and make one from its reply */ - rv = req->run(creator); + /* There's limit remaining, we can just run the request */ + rv = request_view->run(creator); } - - bucket_t newbucket; - newbucket.limit = rv.ratelimit_limit; - newbucket.remaining = rv.ratelimit_remaining; - newbucket.reset_after = rv.ratelimit_reset_after; - newbucket.retry_after = rv.ratelimit_retry_after; - newbucket.timestamp = time(nullptr); - requests->globally_ratelimited = rv.ratelimit_global; - if (requests->globally_ratelimited) { - requests->globally_limited_for = (newbucket.retry_after ? newbucket.retry_after : newbucket.reset_after); - } - buckets[req->endpoint] = newbucket; - - /* Make a new entry in the completion list and notify */ - http_request_completion_t* hrc = new http_request_completion_t(); - *hrc = rv; - { - std::unique_lock lock(requests->out_mutex); - requests->responses_out.push(std::make_pair(hrc, req)); - } - requests->out_ready.notify_one(); + } else { + /* No bucket for this endpoint yet. Just send it, and make one from its reply */ + rv = request_view->run(creator); } - } - { - std::unique_lock lock(in_mutex); - bool again = false; - do { - again = false; - for (auto & bucket : requests_in) { - for (auto req = bucket.second.begin(); req != bucket.second.end(); ++req) { - if ((*req)->is_completed()) { - requests_in[bucket.first].erase(req); - again = true; - goto out; /* Only clean way out of a nested loop */ - } + bucket_t newbucket; + newbucket.limit = rv.ratelimit_limit; + newbucket.remaining = rv.ratelimit_remaining; + newbucket.reset_after = rv.ratelimit_reset_after; + newbucket.retry_after = rv.ratelimit_retry_after; + newbucket.timestamp = time(nullptr); + requests->globally_ratelimited = rv.ratelimit_global; + if (requests->globally_ratelimited) { + requests->globally_limited_for = (newbucket.retry_after ? newbucket.retry_after : newbucket.reset_after); + } + buckets[request_view->endpoint] = newbucket; + + /* Remove the request from the incoming requests to transfer it to completed requests */ + std::unique_ptr request; + { + /* Find the owned pointer in requests_in */ + std::scoped_lock lock1{in_mutex}; + + auto [begin, end] = std::equal_range(requests_in.begin(), requests_in.end(), key, compare_request{}); + for (auto it = begin; it != end; ++it) { + if (it->get() == request_view) { + /* Grab and remove */ + request = std::move(*it); + requests_in.erase(it); + break; } } - out:; - } while (again); + } + /* Make a new entry in the completion list and notify */ + auto hrc = std::make_unique(); + *hrc = rv; + { + std::scoped_lock lock1(requests->out_mutex); + requests->responses_out.push({std::move(request), std::move(hrc)}); + } + requests->out_ready.notify_one(); } } else { @@ -346,47 +382,59 @@ void in_thread::in_loop(uint32_t index) } } +bool request_queue::queued_deleting_request::operator<(const queued_deleting_request& other) const noexcept { + return time_to_delete < other.time_to_delete; +} + +bool request_queue::queued_deleting_request::operator<(time_t time) const noexcept { + return time_to_delete < time; +} + + void request_queue::out_loop() { utility::set_thread_name("req_callback"); while (!terminating) { std::mutex mtx; - std::unique_lock lock{ mtx }; + std::unique_lock lock{ mtx }; out_ready.wait_for(lock, std::chrono::seconds(1)); time_t now = time(nullptr); /* A request has been completed! */ - std::pair queue_head = {}; + completed_request queue_head = {}; { - std::unique_lock lock(out_mutex); + std::scoped_lock lock1(out_mutex); if (responses_out.size()) { - queue_head = responses_out.front(); + queue_head = std::move(responses_out.front()); responses_out.pop(); } } - if (queue_head.first && queue_head.second) { - queue_head.second->complete(*queue_head.first); + if (queue_head.request && queue_head.response) { + queue_head.request->complete(*queue_head.response); /* Queue deletions for 60 seconds from now */ - responses_to_delete.insert(std::make_pair(now + 60, queue_head)); + auto when = now + 60; + auto where = std::lower_bound(responses_to_delete.begin(), responses_to_delete.end(), when); + responses_to_delete.insert(where, {when, std::move(queue_head)}); } /* Check for deletable items every second regardless of select status */ - while (responses_to_delete.size() && now >= responses_to_delete.begin()->first) { - delete responses_to_delete.begin()->second.first; - delete responses_to_delete.begin()->second.second; - responses_to_delete.erase(responses_to_delete.begin()); + auto end = std::lower_bound(responses_to_delete.begin(), responses_to_delete.end(), now); + if (end != responses_to_delete.begin()) { + responses_to_delete.erase(responses_to_delete.begin(), end); } } } /* Post a http_request into the queue */ -void in_thread::post_request(http_request* req) +void in_thread::post_request(std::unique_ptr req) { { - std::unique_lock lock(in_mutex); - requests_in[req->endpoint].push_back(req); + std::scoped_lock lock(in_mutex); + + auto where = std::lower_bound(requests_in.begin(), requests_in.end(), req->endpoint, compare_request{}); + requests_in.emplace(where, std::move(req)); } in_ready.notify_one(); } @@ -410,9 +458,9 @@ inline uint32_t hash(const char *s) } /* Post a http_request into a request queue */ -request_queue& request_queue::post_request(http_request* req) +request_queue& request_queue::post_request(std::unique_ptr req) { - requests_in[hash(req->endpoint.c_str()) % in_thread_pool_size]->post_request(req); + requests_in[hash(req->endpoint.c_str()) % in_thread_pool_size]->post_request(std::move(req)); return *this; } From 908588c7a87a58aadf4a6519df7c725ce539bcd4 Mon Sep 17 00:00:00 2001 From: Arshia Aghaei Date: Sat, 30 Mar 2024 13:01:16 +0330 Subject: [PATCH 58/89] feat: Added is_guild_owner for dpp::guild_member (#1109) Co-authored-by: Craig Edwards (Brain) --- include/dpp/guild.h | 8 ++++++++ src/dpp/guild.cpp | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/include/dpp/guild.h b/include/dpp/guild.h index db631c33d1..28c9bf720a 100644 --- a/include/dpp/guild.h +++ b/include/dpp/guild.h @@ -520,6 +520,14 @@ class DPP_EXPORT guild_member : public json_interface { */ bool has_rejoined() const; + /** + * @brief Is this user also the guild member? + * @return true if the user is the guild owner. + * @return false if the user is not the guild owner or the guild is not in the cache. + * @note If the guild cache is disabled, this function will always return false. + */ + bool is_guild_owner() const; + /** * @brief Returns true if the user has completed onboarding * diff --git a/src/dpp/guild.cpp b/src/dpp/guild.cpp index a1162321ea..236e05869d 100644 --- a/src/dpp/guild.cpp +++ b/src/dpp/guild.cpp @@ -347,6 +347,11 @@ bool guild_member::has_rejoined() const { return flags & dpp::gm_did_rejoin; } +bool guild_member::is_guild_owner() const { + auto* _guild = find_guild(guild_id); + return _guild != nullptr && _guild->owner_id == this->user_id; +} + bool guild_member::has_completed_onboarding() const { return flags & dpp::gm_completed_onboarding; } From a7582516ee59e998be04bb605515f504dddfb5fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:44:15 +0100 Subject: [PATCH 59/89] build(deps): bump GitGuardian/ggshield-action from 1.24.0 to 1.26.0 (#1114) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 4b992676ac..3560f29496 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -23,7 +23,7 @@ jobs: with: fetch-depth: 0 # fetch all history so multiple commits can be scanned - name: GitGuardian scan - uses: GitGuardian/ggshield-action@8d9acaf1808c26018eb69e0fe8adee8161417101 # master + uses: GitGuardian/ggshield-action@3af6bd67c964cffe01a0f8f5c0dd04b8cda99e6b # master env: GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} From a1aa9835bb648707b4f11d81b6ced4727394dfee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:44:38 +0100 Subject: [PATCH 60/89] build(deps): bump github/codeql-action from 3.23.2 to 3.24.9 (#1115) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 411b336fd4..ee368cf9bf 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -50,7 +50,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/init@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -65,6 +65,6 @@ jobs: make -j2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/analyze@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index c205955dc1..08e920a1a6 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -72,6 +72,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 # v3.23.2 + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: sarif_file: results.sarif From 4513458a6dd9dd6b201f4ccd127e6b615d6157ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:45:07 +0100 Subject: [PATCH 61/89] build(deps): bump docker/setup-buildx-action from 3.1.0 to 3.2.0 (#1116) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 7351aafd2f..626524cf12 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -31,7 +31,7 @@ jobs: uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@0d103c3126aa41d772a8362f6aa67afac040f80c # v3.1.0 + uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 - name: Login to DockerHub uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 From f6ad6064b61d42d309c790af9f250c6eb2cff736 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:45:32 +0100 Subject: [PATCH 62/89] build(deps): bump docker/login-action from 3.0.0 to 3.1.0 (#1117) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 626524cf12..0625bc0929 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -34,13 +34,13 @@ jobs: uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0 - name: Login to DockerHub - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to GitHub Container Registry - uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 with: registry: ghcr.io username: ${{ github.repository_owner }} From f2b843bc661ae5cfc0db2fe7ed09835147da2ada Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:46:01 +0100 Subject: [PATCH 63/89] build(deps): bump actions/checkout from 4.1.1 to 4.1.2 (#1118) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/codeql.yml | 2 +- .github/workflows/construct-vcpkg-info.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/documentation-check.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/gitguardian.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/test-docs-examples.yml | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82632fc3b0..1aa3e3a05e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: egress-policy: audit - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Install apt packages run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y ${{ matrix.cfg.package }} pkg-config libsodium-dev libopus-dev zlib1g-dev rpm @@ -122,7 +122,7 @@ jobs: egress-policy: audit - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Install homebrew packages run: brew install cmake make libsodium opus openssl pkg-config @@ -171,7 +171,7 @@ jobs: egress-policy: audit - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: path: main @@ -236,7 +236,7 @@ jobs: egress-policy: audit - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Install Packages run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt update && sudo apt-get install -y cmake rpm diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ee368cf9bf..54a2e2f121 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -46,7 +46,7 @@ jobs: egress-policy: audit - name: Checkout repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/construct-vcpkg-info.yml b/.github/workflows/construct-vcpkg-info.yml index 38441d42b8..18a92e24bd 100644 --- a/.github/workflows/construct-vcpkg-info.yml +++ b/.github/workflows/construct-vcpkg-info.yml @@ -25,7 +25,7 @@ jobs: php-version: '8.1' - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: submodules: recursive diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index d057728b39..671cb47878 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -22,6 +22,6 @@ jobs: egress-policy: audit - name: 'Checkout Repository' - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: 'Dependency Review' uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3 diff --git a/.github/workflows/documentation-check.yml b/.github/workflows/documentation-check.yml index 838f04fc3a..fee18fd920 100644 --- a/.github/workflows/documentation-check.yml +++ b/.github/workflows/documentation-check.yml @@ -27,7 +27,7 @@ jobs: egress-policy: audit - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Check docs spelling run: npx -y cspell lint --language-id=cpp --no-progress --no-summary --show-context --show-suggestions --relative --color docpages/*.md include/dpp/*.h diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 75d3def61c..68658a10af 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -35,7 +35,7 @@ jobs: php-version: '8.0' - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: submodules: recursive diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 3560f29496..8e519a7186 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -19,7 +19,7 @@ jobs: egress-policy: audit - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: fetch-depth: 0 # fetch all history so multiple commits can be scanned - name: GitGuardian scan diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 08e920a1a6..6394c3a570 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -37,7 +37,7 @@ jobs: egress-policy: audit - name: "Checkout code" - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: persist-credentials: false diff --git a/.github/workflows/test-docs-examples.yml b/.github/workflows/test-docs-examples.yml index 4631ae1b64..7a9bff2112 100644 --- a/.github/workflows/test-docs-examples.yml +++ b/.github/workflows/test-docs-examples.yml @@ -30,7 +30,7 @@ jobs: egress-policy: audit - name: Checkout D++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: submodules: recursive From 89b43ba1445f99114f1c583529d01ad210918c35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 12:46:50 +0100 Subject: [PATCH 64/89] build(deps): bump doxygen-awesome-css from `c01e51e` to `5b27b3a` (#1119) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- doxygen-awesome-css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen-awesome-css b/doxygen-awesome-css index c01e51e461..5b27b3a747 160000 --- a/doxygen-awesome-css +++ b/doxygen-awesome-css @@ -1 +1 @@ -Subproject commit c01e51e461a5f0d45422aa21cdf4e50181d04a19 +Subproject commit 5b27b3a747ca1e559fa54149762cca0bad6036fb From 3ac877c91033b4b0585446459c4a6c3a2b1ae591 Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Thu, 4 Apr 2024 11:39:08 +0100 Subject: [PATCH 65/89] fix: empty presences will now warn (#1121) --- src/dpp/cluster.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index 611c091da4..6966e70bb0 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -388,6 +388,11 @@ gateway::gateway(nlohmann::json* j) { } void cluster::set_presence(const dpp::presence &p) { + if(p.activities.empty()) { + log(ll_warning, "An empty presence was passed to set_presence."); + return; + } + json pres = p.to_json(); for (auto& s : shards) { if (s.second->is_connected()) { From f87c0f77f2a6f61f826d888987f469f33a9c4777 Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Fri, 5 Apr 2024 10:38:28 +0100 Subject: [PATCH 66/89] docs: added a timers page, added a note in setting_status for timers (#1120) --- docpages/example_code/timers_example1.cpp | 21 ++++++ docpages/example_code/timers_example2.cpp | 23 ++++++ docpages/example_code/timers_example3.cpp | 69 ++++++++++++++++++ docpages/example_programs/misc.md | 1 + .../example_programs/misc/setting_status.md | 2 + .../example_programs/misc/using_timers.md | 27 +++++++ docpages/images/timers_example1.png | Bin 0 -> 18700 bytes docpages/images/timers_example3.png | Bin 0 -> 48559 bytes 8 files changed, 143 insertions(+) create mode 100644 docpages/example_code/timers_example1.cpp create mode 100644 docpages/example_code/timers_example2.cpp create mode 100644 docpages/example_code/timers_example3.cpp create mode 100644 docpages/example_programs/misc/using_timers.md create mode 100644 docpages/images/timers_example1.png create mode 100644 docpages/images/timers_example3.png diff --git a/docpages/example_code/timers_example1.cpp b/docpages/example_code/timers_example1.cpp new file mode 100644 index 0000000000..b3777f11cc --- /dev/null +++ b/docpages/example_code/timers_example1.cpp @@ -0,0 +1,21 @@ +#include + +int main() { + /* Create the bot */ + dpp::cluster bot("token"); + + bot.on_log(dpp::utility::cout_logger()); + + bot.on_ready([&bot](const dpp::ready_t& event) { + /* Create a timer when the bot starts. */ + bot.start_timer([&bot](const dpp::timer& timer){ + /* Create a timer when the bot starts. */ + bot.request("https://dpp.dev/DPP-Logo.png", dpp::m_get, [&bot](const dpp::http_request_completion_t& callback) { + /* Create a message to our desired channel, with the D++ logo. */ + bot.message_create(dpp::message(1140010849432522843, "").add_file("image.png", callback.body)); + }); + }, 10); /* Do it every 10 seconds. Timers also start with this delay. */ + }); + + bot.start(dpp::st_wait); +} diff --git a/docpages/example_code/timers_example2.cpp b/docpages/example_code/timers_example2.cpp new file mode 100644 index 0000000000..07b02ed267 --- /dev/null +++ b/docpages/example_code/timers_example2.cpp @@ -0,0 +1,23 @@ +#include + +int main() { + /* Create the bot */ + dpp::cluster bot("token"); + + bot.on_log(dpp::utility::cout_logger()); + + bot.on_ready([&bot](const dpp::ready_t& event) { + /* Create a timer when the bot starts. */ + bot.start_timer([&bot](const dpp::timer& timer) { + /* Create a timer when the bot starts. */ + bot.request("https://dpp.dev/DPP-Logo.png", dpp::m_get, [&bot, timer](const dpp::http_request_completion_t& callback) { + /* Create a message to our desired channel, with the D++ logo. */ + bot.message_create(dpp::message(1140010849432522843, "").add_file("image.png", callback.body)); + /* Stop the timer by passing the timer handle in. */ + bot.stop_timer(timer); + }); + }, 10); /* Do it every 10 seconds. Timers also start with this delay. */ + }); + + bot.start(dpp::st_wait); +} diff --git a/docpages/example_code/timers_example3.cpp b/docpages/example_code/timers_example3.cpp new file mode 100644 index 0000000000..dd8f98abdb --- /dev/null +++ b/docpages/example_code/timers_example3.cpp @@ -0,0 +1,69 @@ +#include + +std::map user_timers{}; + +int main() { + /* Create the bot */ + dpp::cluster bot("token"); + + bot.on_log(dpp::utility::cout_logger()); + + /* The event is fired when someone issues your commands */ + bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) { + /* Check which command they ran */ + if (event.command.get_command_name() == "start_timer") { + /* Does user_timers contain the user id? */ + if (user_timers.find(event.command.usr.id) != user_timers.end()) { + event.reply("You've already got an in-progress timer!"); + return; + } + + /* Create a copy of the channel_id to copy in to the timer lambda. */ + dpp::snowflake channel_id = event.command.channel_id; + + /* Start the timer and save it to a local variable. */ + dpp::timer timer = bot.start_timer([&bot, channel_id](const dpp::timer& timer) { + bot.message_create(dpp::message(channel_id, "This is a timed message! Use /stop_timer to stop this!")); + }, 10); + + /* + * Add the timer to user_timers. + * As dpp::timer is just size_t (essentially the timer's ID), it's perfectly safe to copy it in. + */ + user_timers.emplace(event.command.usr.id, timer); + + event.reply("Started a timer every 10 seconds!"); + } + + if(event.command.get_command_name() == "stop_timer") { + /* Is user_timers empty? */ + if (user_timers.empty()) { + event.reply("There are no timers currently in-progress!"); + return; + } else if (user_timers.find(event.command.usr.id) == user_timers.end()) { /* Does user_timers not contain the user id? */ + event.reply("You've don't currently have a timer in-progress!"); + return; + } + + /* Stop the timer. */ + bot.stop_timer(user_timers[event.command.usr.id]); + /* Remove the timer from user_timers. */ + user_timers.erase(event.command.usr.id); + + event.reply("Stopped your timer!"); + } + }); + + bot.on_ready([&bot](const dpp::ready_t& event) { + if (dpp::run_once()) { + /* Create a new global command on ready event. */ + dpp::slashcommand start_timer("start_timer", "Start a 10 second timer!", bot.me.id); + dpp::slashcommand stop_timer("stop_timer", "Stop your 10 second timer!", bot.me.id); + + /* Register the commands. */ + bot.global_bulk_command_create({ start_timer, stop_timer }); + } + }); + + bot.start(dpp::st_wait); +} diff --git a/docpages/example_programs/misc.md b/docpages/example_programs/misc.md index 9e1151fd46..f8a1cc3578 100644 --- a/docpages/example_programs/misc.md +++ b/docpages/example_programs/misc.md @@ -12,3 +12,4 @@ This section lists examples that do not fit neatly into any of the categories ab * \subpage checking-member-permissions * \subpage setting_status * \subpage using-emojis +* \subpage using_timers diff --git a/docpages/example_programs/misc/setting_status.md b/docpages/example_programs/misc/setting_status.md index 088d7a1dfc..16796887b5 100644 --- a/docpages/example_programs/misc/setting_status.md +++ b/docpages/example_programs/misc/setting_status.md @@ -17,6 +17,8 @@ You can also play around with dpp::at_game, changing it to something like dpp::a Now, let's cover setting the bot status to say `Playing with x guilds!` every two minutes. +\note This example uses timers to update the status every 2 minutes. If you aren't familiar with D++'s own timers, please read \ref using_timers "this page on timers" before you continue. + \include{cpp} setting_status2.cpp If you followed that well, your bot should now say this on members list! diff --git a/docpages/example_programs/misc/using_timers.md b/docpages/example_programs/misc/using_timers.md new file mode 100644 index 0000000000..f561347a97 --- /dev/null +++ b/docpages/example_programs/misc/using_timers.md @@ -0,0 +1,27 @@ +\page using_timers Using Timers + +Timers are a great way to run something every x seconds, from setting the bot's status, to maybe even doing a http request! Luckily, D++ makes this incredibly easy by providing an easy-to-use timer system! This tutorial will show you a couple examples on how to use timers! + +First, we'll cover sending the D++ logo every 10 seconds! + +\include{cpp} timers_example1.cpp + +If all went well, you should get the D++ logo sent every 10 seconds to your desired channel! + +\image html timers_example1.png + +Now, let's make the same timer a one-shot timer, meaning it will only run once! + +\include{cpp} timers_example2.cpp + +Great! Now we've learnt the basics of timers and how to stop them! + +To finish off, let's make a timer that you can start and stop with commands. This example will store the timer in a map where the user is the owner of the timer! + +\include{cpp} timers_example3.cpp + +If that went well, it should work something like below! + +\image html timers_example3.png + +Great, now you've learnt how to store timers to manage at a later point! \ No newline at end of file diff --git a/docpages/images/timers_example1.png b/docpages/images/timers_example1.png new file mode 100644 index 0000000000000000000000000000000000000000..644303ceab2aeb8fab0e032533729c36cf0e2c3a GIT binary patch literal 18700 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 II;Vst0RQHpv;Y7A literal 0 HcmV?d00001 diff --git a/docpages/images/timers_example3.png b/docpages/images/timers_example3.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7089dce37a7b02a7fd6a019204a4bea82e530f GIT binary patch literal 48559 zcma&NWmFx(5~z#I#@#L0MuWS%ySo$I3GT3Qx8M@o-4b-;5D4z>!QFYBbMF27*8MSS zx_eetOSOJo6Q!agjRGJ9KtMpC$jV5lK|nw;KtMneBfx#8!13M|e7+#v)TG5AYX1-) ze@0-eMHNLMAQ}>oUQJ;?tG?soB%=N51X zj3H#zg8&U|JM$37r+mqHcjX~Q{fzQZ8&rQLeFj}@+jai)6&18Q=iJc$-{5e?wpsZ9 zWYh-+0sj*(i-^JbkEk<`5(*x}f3-O05Hf51ABCL%&k8^0_n9peCcYu#^FTmC2461t z6b~81=*18my16ELa3RsglVte)ubeh0%vzm6s+2`84|^4te|?G;3_^dsLe1&cARwM0 zX@CD-zBb2_^o=#E@@oG+m&fl?|5)jNWmMcYD@pm`wke3u&IU&xPOOde)pWr3qOf`n z!p)GxLJm(Nfi!LzO%Nt70hg--iXIQA`{~5a@A~hs8p8kTMyv`01J?t5JMdF3-4sMr zr&SKoE0MUbK>l?zWSc2>r!o#fO>$0;!+c;QlAkDqfO-y_Rz3hV&5y%-JjsY@oy|I^{#hm{k>{_!a2AfP?K`WaGZ@Z(Vop|uW+Q6N9083e4&dHzGG8Y4NE z)J>LO)wqilGhO?tx{LRv!yPpw20$%tUHI*`xSnpEYB64YcNHEME5Gy>CB@)06*ROn zb1Pg_GzA>}Pv6jsh)Gj2+gSpRlykuL0XnKt*Sow;UL$2B(2hV+f0I~n@cMQ9VEv(e zAP)32w6#QQH2TH|u-H0PrFQm%Uk+so-y$(!dgTD;!>Bg8>Ism}6%}E2$CjfF4ikCr zhp2mNo`@Cyb9a?;DtWli*lo(h>1VfoH$8$$#+J+rir0e)HF;xdKB~Rwq7LOy+88WW#Uk!jY;H^xZTT*mL z(ZaA8F^YTMWd!+^B#zfzvbtsHa|nAvnNm&BdrL?aHKg_~5&V7l!m=Sppm|BaeVXlv z+U=ZXhEM&vfhkd0lQKy|WYr0|umSQO!Qi;!05;S*1=s^`Ao+p`D%wsDS=_S-yV2fO z$It@36kc3~fqYZaR6~z&ZA2K0x^WhcmDw~Bw;w@xWTtlcP2xq&vl*rlS+>6ZHTDjK zzU4TT5Pt1e81kAi?UcRVUD~yBz8EZJ$}|1YhsQegfROibc$kdz_rrzp$6@%~q0umR zk+@T=*CnJv%$(@t-mebKW#c!Z{GWThMj?(z1RqqSu}EPF(Mtd5T}&?muj=*`j`;>q z-YLoYLucX1gQydpmV2-=!~>%-s6U1(nKqYyw}@#@Z379|Py#j`K&33|jJwertiTI0 zr0g*gwkp`XjD!LH7os`aP*vi$0-X$ERlLIj-xb<=x_Oo`WiicZbOdIN_g21k9LqlL z8>A7YTgIrW;sChpD!8m)SU|Lx(74wptJ9$6Dt>x#GYR4NN2^n+q$K9t7Gxq-I>Hy8 zYV2CdvFNHJ7q4O-R}D7zgS-05x98}m>Acmi@3mKFOwWth7X614+CU;6*wS9n9hrpA zy)UmbAJE~;M%LMB%7#n=H{Dp{(ni*}Wp&X~w9);_nnq#K-NhBxh|?tNj1hy|&N)P% z!y8fHHAS{Q)6SIR$JTyDa2ZjHNxE(3SeaDPg;S)`AqPcWhRN2EL+Ha@ zuchf3{Mt@$(p3e&RnlzSGZqE{h&iFXIALn-}1!j8as!h!qrVe7~24Bu!w|m3>?gfhNThFW9nLZNV*v7;_$$A#)L+Bsgc?wFT0Sb zt*A)XuM*dP-I9^EiNcqF+Sq=%fCYPRs#mBRX$X+8UJOchic2L8Ohc2|U&;@n9GW<6 z7CY7e-UZm@F0Sq0Xu`u7zi|hw6$ZYwxyc9`Gs7KYyfD1p=aB+8dq^(c{)toNyNKpL z{=g>zf;xar4$%6xUMQw1M`!MZL!M-utt~9D$YM5N_x5zW{+k^POkyp3=pT3@H%_ zn!c0UcHMp1z9dk-~OhYW5|i4nvH^)Ey1Ko$%66F)YFo zeXjCGIeOLKI7p{${kL{^8Q$;i7dGyTi~5DWY>gDNo2zQ-q7rfD5Te{Et*^NpOxXCn zKcTi)R_HSo4`qf$i;!*fV?rzCj7p^~NBe_N&2{FSZ;v(%?e~^b6EiaKTJ4v=gs%xH z4n|i;3jLyz+xr3M3mwn_5c`Vxm6QtRx}wiI?uneq;`AZ7$`ivmI1D-po`C3w3j$Ue zm4Vr7MU1^2I{m3na~)677k>9ip{#x|Y&h-EfRsfhFj+mNUm`p>EG+LF$rb*2xffXbN|9L+MF4TD~?@7}?~Ms)z%PbrB*#KxqI3ybF7Pl8Ed zOt^Nx&B|OTb(g4yNs#GH91HdO`ov*F!CrZtu&c9Tlf%r>e~=smPevM+73#Db>Yt$^ zy=WJ$Ou0@R5#~ZMeIXoghTIzqqUpVOJ@j($rMEo+#^7}D`2WQ0riAY+Yj$Yp*Migx zix0Ka?dIX@EkDJf=4yN&Zc~HyN6lg=lN8+!*pFRWYLr?$T^ASlHANCsdYKC3z(1Lh zFM_!Gm7^5rO%auD-_TH3dp|SYG`I~I@w`ipS;WzfNz+m7X1;|j@ z*tA056KU)ROI6?xpRm4z6Xt`IH0|Yr3U{U{AvLvhS^y8%3|N8`%YiXLp_;{|jQ^fa z0H73Y>Q>mly+*)OG8wH_BKB|&d9*NzX4^uv=X%Ih<06eRC&rY@h2&r0pmTHI<#m@& zRR7`(*DWI}?PyB($7p1@Ay!?6H;1Nmv1A|4<@nmz=$&B<*^$hb@N_Li z+;9JAYv->pokuPwcE68|l-KD5$I2TnB%c8r7)Sf+an-lt_c3>KB%&_x6E1psus>eg;(ezzG@i}&;Xc&^po-h&wzu-roxHhbP z?iX{zXDc9RG<@9A!sPY=F@qs9Gj>4632~zh$ub_jqMR^LjEZ#ls8+)Wt5rW0c3M`! z99%&p;nZytUQ&_=BwR5;XMqurRioFerC*}|=ZZ!D&S1>tpH7eV#O%=I8BE^-?id3& z(?~S?Cf~mFCA3!W!Z-&$8SD|XqY72pKDN}?b*BefW;`oOlDo)OLMrm5=4lAq;C}-q zAt1#;77Q>rl5$QTch|a=dP1pW4LLXp8>u61{ zV@r_vvCQKD%ABK`k>Dtr3;Srn&NmyJMBl$Q-=+c-#i;Qm&B+G#yE1l8j`CyTT)R|4 zjpp6(Yh!((ywyL@GOQTI;{t_`cXAWHRf&@jiZ4lED?H!b6;oZ)-rJ=HqJrG4cio*_ zxXD_<81-sX73Jj+Qsy{sp679+jm(CU4h~FmW5~cxt?2bpcoWrfRRh%+y$+((jrU8W zbNC?n!Xl0ZI|O2N&AgP*ueLjn8$+d!yPC7!-t^5k9h{2v#GV`RBq?J5drrJR}lD zLCdv~QeCyT*^0wF{g?yxPC9VQ6&9D{VbMGx{iokDi4e)TFx7-t`cLije*S?A-cJ}@ zg;U63Wu=aXXs{`|P~?nGum|%8zEI{Fw-Wvn>VdgSBzSy6w%r<6C>N!;7ifc-;^sF3 zm)U#D8p{SCj6KKAoY0fgtJTF+9Cf_lzy!W^ehbs9Lcu;$g#rCdvQl|6B=SU)gI5O0 zd+@%_v{8J!$aZGxpz?0NF&!G35E^;_e@wsJ;7rEfBM0*m$KUK~n1wHw&n1*&<8Hif zAH};qDs=N8sG607eJ=td#ciawi_``tXY~zWEz+u74#Y?Swdrcs`iMl>JLE9pIbGb@ zrfdX-i~kzTr5T1=?6b^0oe;KBLqZ5@Y|AArx+WSi&~0B~g>9Q<(MP`Htq?g{t*vNG zhpFN#FtQXn|3x5RceFfqvHNywq2OL$L4Ygen8tHQiM$X^$!@BZU~vMk3*-yi*ni+42a1cKEwRCUV4 zHyaeWrT@is`=3>5tK>zETRI{n5Sk0u4O>#Zt`Z>FI8gF%{q8%J(|O0CGW#`kfmddq zX)G#QREKl2)?8l5VmQt`Anebu7CjXsRVV!OFP!ER4se3zZ>wa^O0tRN5Z6z0%b{)O zbNif=nEi7{r&M}|GY0x|>~0}X)C~Dpp6hiw1Lj`xg`XC-)vn)~ z1E#%fWCc{9Cmbz8g5K*x2^Jem#y#AfVptdyL*ks5XztL@6qk%$_Cl83S$0moC)N=f_e!wMlBzXMEXAV|+tGisJd^;-W z@6A=V&2JL0JU4hEFVwr|6@>=PDqw93Xo(x+aD{hFXu0YJq6aB z5T(mQT^{%sXopn>d6%*KxfPvR+-gUgU8*0%k;BJB>Xz4mm*k0+nO?}K`SRev1q%iu zB@DNW_&R&+4U{89^|cf}M9TXvR}y&V`di3pdMnyjFE_45cbl6W2}8OfA!^%>ECZ4C zO~Gr+u4Y`hbE-Oz%$%A#Lyr4z!^QR@0+k+xGxPVRo?q;5iyI#hd^>?(?QPtx3pvsw z$Fp^p8|c_@;pKPJmY#s5?+_D4kjcuQGg;Y=Mpf`qC0VOqTXnUB{jUqEOmbdtHfT%D z`J;mi(8>zoTvnw-gIUS1)YLRpaj5pruEJl9m?4ui2Wf8!Z!r_h%*>a!w_$3_a$lDj z39{Ju6HIJhmt8FuWSTUEhf6SEF=5!alKbzeOp6J+ZC#>R*!gfW==1Ba<4l%EVtS>t zG9m50Uk}IXBxFR7ClV-X<43j9*_WVTk<5D}8vbNKs-ieL+AzV)WJFHyF1G)`hA$k2 z0d$ptvUw`MocHyc^v6aaTA8~>%uGq?;WHA0=0$eg)$?QxOsN2*=|1r)s_E&kBttfz+p zmXZU%V%mGN>92DT%e8)il|(u_lw$E1KV z)f(B74Q$TSA~`~CaJBT@?VX+5C-ZjBE))$#&XB9klj>^&;Yev@oNNU=Cy<#f!AI|B z@Nsc=x!7DgeVzplh+Jp8f$m6awT6iXpA_=&;FI|wm48Aq4-Y!qSQ^!8dV|J6ejV9I* ze(-Z^4v%Td&(P6=n=lAdc*zkqKqgWS%pi7xblBGi!>k74i2&1;c$FZr7_JLi^A&aG z4w+WUCv;AOrTZ;sevrtkk_h=U5q90(-)dKX!>|ap`{Rd|CT1&sR8M`sKNfsNY9+xJ6h4#mj_>YlCOFcc@3m z0ubZ&#SUjnS!+h46Y{FT%EynBzPPE!1}wX@fUD$l(eI3MiN&wZD0$`q?`okODa7o! z?Yl{aQdgv&r%YckQZ#+vepRTLy0?ga1r2ntx1X5}uB##C4$b%g)9B5y974)wY#$LYXxz%hvC3%#vN)pR zk$nz`p^h4}!9jyiif*WbTYAZQI~)W1mZMq@in##^!OGfm?hP?!;}GEQwdNh04AT`@ ziYJ)Ck}yB8-)PdT5Dk5scYQZMTB}=lGErIakyHh%4m|eZ{NEo?d`^&f?Ai1h>@zno z-?~<%jn5I_go0@Ed>~9`=sqj&zs8lF#z)Druox}7k#=;fj`TejX^$R-nXp>N8w|_I zragK{5@OLsk@HMzzZt;5D|hRIdL1U3xNjfM>D{&W_-3!A7b_jM;~lhfLkDvBS4WX5 z`{zu|@J_TRRG_lw_o5^8x-V+~M$fEq%DTLKb2cfw*+!UI`FHc4^8~T?EsK#bw|WNy z)L@jxs3)%e);9)nAGkfp4NqN%c9_+?9xmmC7mg7czQ?9ib>jR1Pm7Ea|UrT&2YSO$mTaF*V*m8Re7*yE@u=EFn2noJ^x`1$!~QWYr$$Q`dz zJ~yuZh!iH;)d8iNQxJVXSoptEn0E#ZmIbcf62dRD&Ro0E3q zg$k6+mTFk-_K;mjMY*p~Wa>mgqgJm++mDXgB%<{hCJYrSUzt{K(#`Wu0Y47}gm2BB zqTe|8C>)v967-upgaKbCjv4*fu*qG>2wy|i7 zNNKfu9Gnr=n%5E4UF#+O<(9-R+`yr`GLZPOMJo-#A%tS!i1kO!Bn~CF#0hP^ri!?1 zT#y2>g)7KjftYh=t{~tg&#>G;8tJJyU$wZV%(eJ7hbdxfel;)8r%Ew`pYzr&K&nU# zaeG2Yj-SMb+F~F8Zg4JNE|2&~{CuDpoeelaNlTvEMghimjdnvtj4E=H47OxfTY8f@ zeGQXXF?^%2Q0Li9DsS>hasGj(n<%~_Q$AAq5xj#0b4#V7(~(DEiH?pkn3F-SF1vAZ z^#kF_!UwJ+6+XR{ke+M|RGlxVuuZl8ai;2OZA}$_auyO#f>8%ewLG z!vx*i^Hcgq=^6z}jWC>Ie!`11y!;{47B7PNIZ<3*ys?uv{?H~jsvr~ZqYuOW_kThb zx=<_!dAdilGuj)R0Ch6*kD-*MzA3(kKf2Kh^OHR_0EaLe+#4 zqzWk(Q*Gs^#{_?R8Y1Y|D#5R2yl$$Z5FlCEX6PAGbj*I}GK;@#h}t|+JieHWRqr~ZW%RSE` zg8rQpL!Q-B9MKu{2mc(HZn`#o|86OAK@e|Rs9*zUJ`wt07Iw|iJz3kb3Ep0la_rEl z_@ww1wwN^v_n{4{rYKo=>);6UH%y%bZ1oE-HteQA%BRkjrH8q10VBilExt#Kn?lrL zXU3Eb7-C{YS+y_s4KH?~R$mkaWMmTIY{T9imj0*>6cQnM3vd>si!I%^)+2|h9?_|?rjTV-u> z4cwBDXIs85A6Pv@SjvB|z*DRq&M9Mm{fSH8ZZq!x3FpVKipEKMt@{jf8w6fwcsU>N z94(b85GB0iXC++4hf)+i>@?6Gn#nYYnx)6OtPggFq#<%U5T6HLFM6pEH(W{gY#8;< z`|a_@TV*kC+m=8D_q`qM0cKiXv4}ptqerZo0eiPO4$@ybA+EdALG-xBB#=&30jA>h%#%E8LvcoNnB3;Pvbb127j^JoALb$I@(7I$ zk^Ehdhf!L!^J=dr`vm|;VaiyzMqFJ4_eH>?XP;n!|dVAF1bZLC|{_SPRg z;-B)*Of)j*RgL?+K{E|$I+h(O%Ren+*}#%G*8ECV7(5lgDOnb zmg{Yjj#V$&Etkq9J&i-GgA(4dBKe`Zyokg3y z6pL@D1PVo4Gd4N)TtJMV`o4FT`LbOZSONGUGe)9Go}TQr8ww%RcJGXvYdpj?ERuROs>sfbB7v|tUZqwu#sC+%E%R=;Hv7ntleryq8`<8U+ z-XDr68}pxpkg=hMzfE%C>{WSVw$Zb!x#85%VgCLkDDYNb}EySeej^CBgNGc^rvv;}@ z^ii54foS-3bU99;v--}O=nL-d-m)3c=T2PsUXprymbL(ww=4^QA|*7_YTtXVKu2;6 za@i;ka!P>cRTFi@DK9pwt}^eTBPk`y4Y?AVS^_0K&i*|z%8Dm3CdPr6HeCWuZFpnp zqaMa|^W^ZyF=H|ORaNyeS^1sG$_n`~l^Lg-Vogrr2{@0-k9yg$-r6Q`yWCSI8z}Pb z>7OaX-9~f&_4x0w{`H6O*7t<3;IHR_Fm4y`hyj?wI88K4L(uA0TcgLq15-3>q07bR zLtuPav$?gA}ys?RfvP_^#ch_pM$M#HJTg34lw1BZ2Kqv>x2Tb3n`bT`p2 z6>|`I^16yR%b0PI&JjnT76H?O5J9rQ4}7u35kuV7?7nfq2#n( zD#5b@X_cC=a)bol+=cqsLldvOm}J)KqCH@IkSITURDzf!#PhAD2!A!1d#T@Ea}m;- zPwW5~{(wR?Cpjxz^bEP)1K(0O*8Au%lMs;eabo_0trYWA5&k23ezvJ%-;bsF=h}qk z&LuTySHpdoR>*7`qMe>I(YWc0%{=Yn>5o8@;bf1;op7|PyUMBhmy3L}k4_Sv?kBq( zWxnW{;trPFZYawn zq}b~qqvw|p{ciI}ndkzDQ-=m&F@uUY+&Q?V{XKC|p_QMP%>;GN-ZO%U%!&(>B$#PC zE`iF>BKT~nE7=@=q>$&Rn1+a>Y}Cs9XS$S-^iEk5p+3O+)qO-07op-p)MQrlr?$la zsRL$RSYV1PfyhInqw`-x1T)Yp19?Js=h%B^+!@ArRsZGe(E^X$qs z#c_Zr016^D66cz`mab&K0{yn&gz`LBTN|;jKA?9m zKXcBYl~Ek-+3e-^z%-2_8_IkI8tk!X5hZ09lMni3U&erbaaSP4#1h6qCLTvDClt^n z4*%U24FGh9oJo|f3m1>b{NCP9giq<|rabD-OMHqCv)_XPekorxXO1}gw^%-WINfE> zO4><#f-y22*NPO}+(wa8^3__p!n8`AMuc>Uq_MsWLK{;>$ebc38(tE@e=EES{aO#P zuEmd^xLmN0&n@VjJ5_3|SO~T?^aZ$fgZ+RoA`V4ya}(km|H|s~C&ZwPio3Jt0$q*W zpPc9txTm_O3@l^w*5&XolnJgnPqo5i2p*_VJ(spA*nA6wdjiXh`2PxW8!h7g1{8+& z5z&(EKg}6nFPDzS%J_iZ&RUmU2;{Ob(#W&^E_cNWe8bS#C}10PU(zluxg0N7dX5XN z_9fqYlZIv%O_kCjBQ3B#N78+wi;f|{Mh>=zDOp{kn(%p$vMHT-+*GugS6e3(abih( z+S=|N+|?M`rsARV7c$jAy+!t5to0>N$tHJm$l<;%V0q2lx+;mSq^t3sfrSs_v)wW; zNm(6e>3>kw&t=HYY)^(2A0950@1p zm|3$xnfkS}qbP)~2KQU4^aqau@o`M@?&t{f_t2`UgXcnYh4P!|fj8m&aEdXpoUuBQ zNlxBZ5Ncm9sjINX@?by{ z{|`P#fjQ^FjE`qB1It;{iqW!IHNo+gZ48`8GGGWa(g6LvlsXSenY1=VlnnlK7SkWL|~ zpli8-9lZF0yia$vkOrQb;UldLr_cQt?k`%AQ1rzjm~>Pj7NY(^CpXx*h=Mn&^hA~N zf)&I%9S_dXN{$g{ji}c`R6vr!F;4noA!zaoQ4eWVWQsEHA1q1a+UHPk!AHWbFjB}dB3?l#k|3es^QIYuuoeVf?NkH+QS?!gI7_C4 zyyyXEd8nZZ7#z(@M%{>xT>1h+A&3+im(8g;4;KOPsL+YR{Ytn+JQEU=PK|gSQ|B3%M-Fy@vyivK2^N8v0$} zI<4UKF~5ulzWBD!mtS402S(_fLk403)k&2^=9&>l`0}FmCO;&XTL?2N?FtgdKW{3x z4r9m$=Z3At&*jNAvw#%TjWXJAKz_9*0D$ajP^&R z5XkU*PLK*8{wXcV_2q3tsdK!#yw4Ub3Wrg{`xpqBkP26POErEW#wi(1{zn3pP46Rs zyYztCEfhFh1NFHYWHDnfu!;6oe!NgB@a{hz=5K~UIbM3G?@p~6N#-{|%T7Qz30)B@ zmF0?iTjJQpO0|y|ZXFZ_Wyr-j1_(uF@!>vH`z3c9xmJ7o(aoUci#SAK;8vkmp6IQNpkcU%0Ms|)W|^1l4Vz@*3oZxhU%Rg3j@M=24GzS z02KcYL@QDt=RJ1PkJy?Zh!6>bQ3=9J$T4Ek0rV>|mI}U?|#V zOczw#qvO<~LAf)Jp$J|Sjy5KmTzjI7D*YaIRNNj+V(Tu%JI{;u<6CHt*z@rX`iLsc z5_o^uvDUU+CQ`@2gQXbt(z7HcRp45~vK;ec1sswXM69YVyNSKXOvWn z2QE^_=wp10Fm|^gxntH)So)vsi#| zC>r$vTY~X30~GLoFEz^Kj|e|AVO~k>r3v+KYv6P7_2_6LG7!*6tTHILcMr|Z`hz1k zw~(bOTQtbnmTXL9gAKW{{!2o9ZDvL-(~fDUFD#lNoNjLUs8h?}{`BMokWC&5D*0n7 z%kW?C@ft zBA1I&^($4SqrrokkZ4ZIe-))Z%qi(lxnBwk+=!yEYZgFCurK9E*=9w>@ygIH|7oY2 z(Bl6r6RM`ZMfG&#cpYNIOo#wLkla4pS7RnC!CQz*#g=jojXty1Xf7Zi4T*7Yo=Qi> zrXsit4UrU3^=gZl%3P}gB)tEwLZ4PN-JpA7!lo57E9%M{h0hiJ9~byfxDGFw5sA|> zrrAv9qFF(q-d>O{G1y=}+~7Yc&GR4dR<#ze_cK_b95Jj&yNKz zAv$D2lUeCyPD`Wkk9}#_82Go2PBN2wt+QsISwp{$F036&c;Bhfe@(vqy7g)GA`4F{ zS6=tG5L4HR(7|=s5-ZBqfM&$6AMcXHOHE{eDrA5zNl5`NTT4)1gZS0(B*RtP&+k`( z7ayMvaL6o3?Wt~%t%U5q9OTNkQA=iUoIQd;J={_Fkd11TC)c+u#(!fNLjF&F_5bN* zm7Z7`Ob^5}NQiD_1C%OA#r?5rb~u%`vFHjd&g{!urs?A5s{QLbfZS{{Mx1%~OcQnu zXiLs|tp)NASJFx*D-C@nbQnx-woc{U=q;06o_;lLbtHAm@Nbdh|7$;xbcTJKu#gW& z>0}OKS`0%o7hd^RNKv#Mu+s-;sHy}w{u^pGjcv}TN<`CxlfK4k37f6myK0-B_D$jo zcwikz`=3H$nua(KKDI>*ff>-=Ii^}t-8U2XE6g<;1+QmZWV^(zT}tdos|^ zah=(?g2`}>IO0E8shlnpMHeQhuXfnO~+m1@B?>5Q>2Bhl2N|B^PCuJGP(FKs+lc7 zjHaT{0!yx|TU2}iTZ8$!-04W`%j1=6lbI!?mOmjH2ZP<`Wm)JKa+XKQDa~$ zbfS)q%rorl&Q!bnSH==T&X4H#WC93%w&4}k#MX^drn@g6Qc`lbQSl7!0f-q&hr4Q~ zbjXVe=o(z@PdL9Yj;7Wt?LJt<5=lCHG?ik zhQ1ia?=M*P8)*^#!*wDUgyCIfilWWF%=bCKWC3W5D2A&U^}oOu0oV-cwpw!2zkCA1 z>scnMQl> zL%ECAidgsi&|UODA{q~z0}R|NC!_fp+i9mGwRdeV$HL5hVQYt5?#4atdSSf_&B6xe z;e-v-#Ea^f;CI6Ro8}k57JRvvRB}X3?tX>>C8LrHKA|g}3dch8_w?sEyjb6`Y{ZW)EIn;47rin-%wo<4dw738uBAsGZF4CLZ&^kRaX2M8WQ~ zRkdL!wp~IN1{)Jblpxhb7?%osO{d*QhkpdK2vVFJUk9`e=i7_+)+n#rQ~4N^6j2Mr z*Eb4MAy^-L>NcN{gQ{~3GSVr7vy z9WAJ=Y*@G;U6z&%Si#gqmI8g8BB(J8Ec@QDMEY3dN)d$ug2D~QL|q89=YJ(Py+@

;l3p3VEq6Xho`E(j* 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 Date: Wed, 17 Apr 2024 00:28:04 +0200 Subject: [PATCH 67/89] =?UTF-8?q?capturing=20"bot"=20is=20not=20needed.=20?= =?UTF-8?q?Removing=20it=20resolves=20an=20unused=20variabl=E2=80=A6=20(#1?= =?UTF-8?q?132)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/unittest/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index fb599462a1..f1a64d2c0e 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -977,7 +977,7 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b return; } g.remove_icon(); - bot.guild_edit(g, [&bot](const dpp::confirmation_callback_t &result) { + bot.guild_edit(g, [](const dpp::confirmation_callback_t &result) { if (result.is_error()) { set_status(GUILD_EDIT, ts_failed, "guild_edit 2 errored:\n" + result.get_error().human_readable); return; From 56b6b07456408377d897c159f865d8d40a8a7761 Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Wed, 1 May 2024 03:30:39 -0400 Subject: [PATCH 68/89] fix: fix human_readable for good (#1135) --- include/dpp/restresults.h | 2 +- src/dpp/cluster/confirmation.cpp | 127 ++++++++++--------------------- src/unittest/test.cpp | 17 +++++ 3 files changed, 57 insertions(+), 89 deletions(-) diff --git a/include/dpp/restresults.h b/include/dpp/restresults.h index ec52ca1b71..3dd0ebb69c 100644 --- a/include/dpp/restresults.h +++ b/include/dpp/restresults.h @@ -220,7 +220,7 @@ struct DPP_EXPORT error_detail { /** * @brief Object field index */ - int index = 0; + DPP_DEPRECATED("index is unused and will be removed in a future version") int index = 0; }; /** diff --git a/src/dpp/cluster/confirmation.cpp b/src/dpp/cluster/confirmation.cpp index 83f8d712bb..0589705752 100644 --- a/src/dpp/cluster/confirmation.cpp +++ b/src/dpp/cluster/confirmation.cpp @@ -74,22 +74,39 @@ bool confirmation_callback_t::is_error() const { namespace { -std::vector find_errors_in_array(const std::string& obj, size_t index, const std::string& current_field, json::iterator begin, json::iterator end) { +std::vector find_errors_in_object(const std::string& obj, const std::string& current_field, const json &j) { std::vector ret; - for (auto it = begin; it != end; ++it) { - if (auto errors = it->find("_errors"); errors != it->end()) { - for (auto errordetails = errors->begin(); errordetails != errors->end(); ++errordetails) { - error_detail detail; - detail.code = (*errordetails)["code"].get(); - detail.reason = (*errordetails)["message"].get(); - detail.field = current_field + it.key(); - detail.object = obj; - detail.index = index; - ret.emplace_back(detail); + if (auto errors = j.find("_errors"); errors != j.end()) { + for (const json& errordetails : *errors) { + error_detail detail; + detail.code = errordetails["code"].get(); + detail.reason = errordetails["message"].get(); + detail.field = current_field; + detail.object = obj; + ret.emplace_back(detail); + } + } else { + for (auto it = j.begin(); it != j.end(); ++it) { + std::vector sub_errors; + std::string field; + + if (obj.empty()) { + field = current_field; + } else if (isdigit(*current_field.c_str())) { + /* An element of an array, e.g. an element of a slash command vector for global_bulk_slash_command_create */ + field = obj; + field += '['; + field += current_field; + field += ']'; + } else { + /* A field of an object, e.g. message.content too long */ + field = obj; + field += '.'; + field += current_field; } - } else { // subobject has errors - auto sub_errors = find_errors_in_array(obj, index, current_field + it.key() + ".", it->begin(), it->end()); + + sub_errors = find_errors_in_object(field, it.key(), *it); if (!sub_errors.empty()) { ret.reserve(ret.capacity() + sub_errors.size()); @@ -111,77 +128,14 @@ error_info confirmation_callback_t::get_error() const { set_string_not_null(&j, "message", e.message); json& errors = j["errors"]; for (auto obj = errors.begin(); obj != errors.end(); ++obj) { + std::vector sub_errors; + std::string field = isdigit(*obj.key().c_str()) ? "[" + obj.key() + "]" : obj.key(); - /* Arrays in the error report are numerically indexed with a number in a string. Ugh. */ - if (isdigit(*(obj.key().c_str()))) { - /* An array of error messages */ - int array_index = std::atoll(obj.key().c_str()); - for (auto index = obj->begin(); index != obj->end(); ++index) { - if (index->find("_errors") != index->end()) { - /* A single object where one or more fields generated an error */ - for (auto errordetails = (*index)["_errors"].begin(); errordetails != (*index)["_errors"].end(); ++errordetails) { - error_detail detail; - detail.code = (*errordetails)["code"].get(); - detail.reason = (*errordetails)["message"].get(); - detail.object.clear(); - detail.field = obj.key(); - detail.index = array_index; - e.errors.emplace_back(detail); - } - } else { - /* An object where one or more fields within it generated an error, e.g. slash command */ - for (auto fields = index->begin(); fields != index->end(); ++fields) { - if (fields->find("_errors") != fields->end()) { - for (auto errordetails = (*fields)["_errors"].begin(); errordetails != (*fields)["_errors"].end(); ++errordetails) { - error_detail detail; - detail.code = (*errordetails)["code"].get(); - detail.reason = (*errordetails)["message"].get(); - detail.field = fields.key(); - detail.object = obj.key(); - detail.index = array_index; - e.errors.emplace_back(detail); - } - } else { - /* An array of objects where one or more generated an error, e.g. slash command bulk registration */ - for (auto fields2 = fields->begin(); fields2 != fields->end(); ++fields2) { - for (auto errordetails = (*fields2)["_errors"].begin(); errordetails != (*fields2)["_errors"].end(); ++errordetails) { - error_detail detail; - detail.code = (*errordetails)["code"].get(); - detail.reason = (*errordetails)["message"].get(); - detail.field = index.key() + "[" + fields.key() + "]." + fields2.key(); - detail.object = obj.key(); - detail.index = array_index; - e.errors.emplace_back(detail); - } - } - } - } - } - } - - } else if (obj->find("_errors") != obj->end()) { - /* An object of error messages (rare) */ - e.errors.reserve((*obj)["_errors"].size()); - for (auto errordetails = (*obj)["_errors"].begin(); errordetails != (*obj)["_errors"].end(); ++errordetails) { - error_detail detail; - detail.code = (*errordetails)["code"].get(); - detail.reason = (*errordetails)["message"].get(); - detail.object.clear(); - detail.field = obj.key(); - detail.index = 0; - e.errors.emplace_back(detail); - } - } else { - /* An object that has a subobject with errors */ - for (auto index = obj->begin(); index != obj->end(); ++index) { - int array_index = std::atoll(index.key().c_str()); - auto sub_errors = find_errors_in_array(obj.key(), array_index, {}, index->begin(), index->end()); - - if (!sub_errors.empty()) { - e.errors.reserve(e.errors.capacity() + sub_errors.size()); - std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors)); - } - } + sub_errors = find_errors_in_object({}, field, *obj); + + if (!sub_errors.empty()) { + e.errors.reserve(e.errors.capacity() + sub_errors.size()); + std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors)); } } @@ -191,12 +145,9 @@ error_info confirmation_callback_t::get_error() const { if (error.object.empty()) { /* A singular field with an error in an unnamed object */ e.human_readable += prefix + "- " + error.field + ": " + error.reason + " (" + error.code + ")"; - } else if (isdigit(*(error.object.c_str()))) { - /* An unnamed array of objects where one or more generated an error, e.g. slash command bulk registration */ - e.human_readable += prefix + "- [" + error.object + "]." + error.field + ": " + error.reason + " (" + error.code + ")"; } else { - /* A named array of objects whre a field in the object has an error */ - e.human_readable += prefix + "- " + error.object + "[" + std::to_string(error.index) + "]." + error.field + ": " + error.reason + " (" + error.code + ")"; + /* An object field that caused an error */ + e.human_readable += prefix + "- " + error.object + '.' + error.field + ": " + error.reason + " (" + error.code + ")"; } } diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index f1a64d2c0e..1b76713535 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -188,6 +188,23 @@ Markdown lol ||spoiler|| ~~strikethrough~~ `small *code* block`\n"; }"; error_message_success = (error_message_success && error_test.get_error().human_readable == "50035: Invalid Form Body - [1].options[1].description: Must be between 1 and 100 in length. (BASE_TYPE_BAD_LENGTH)"); + error_test.http_info.body = "{\ + \"message\": \"Invalid Form Body\",\ + \"code\": 50035,\ + \"errors\": {\ + \"data\": {\ + \"poll\": {\ + \"_errors\": [\ + {\ + \"code\": \"POLL_TYPE_QUESTION_ALLOWS_TEXT_ONLY\",\ + \"message\": \"This poll type cannot include attachments, emoji or stickers with the question\"}\ + ]\ + }\ + }\ + }\ + }"; + error_message_success = (error_message_success && error_test.get_error().human_readable == "50035: Invalid Form Body - data.poll: This poll type cannot include attachments, emoji or stickers with the question (POLL_TYPE_QUESTION_ALLOWS_TEXT_ONLY)"); + set_test(ERRORS, error_message_success); set_test(MD_ESC_1, false); From fe2e6110439aa27fcf08851f49c3b83d4431b486 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:02:29 +0100 Subject: [PATCH 69/89] build(deps): bump github/codeql-action from 3.24.9 to 3.25.3 (#1137) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- .github/workflows/scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 54a2e2f121..82684a0691 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -50,7 +50,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -65,6 +65,6 @@ jobs: make -j2 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 6394c3a570..77b426090d 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -72,6 +72,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 with: sarif_file: results.sarif From b63c7d5e61e6f8ae232dea6add4077a93b4a4720 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:02:42 +0100 Subject: [PATCH 70/89] build(deps): bump actions/dependency-review-action from 4.1.3 to 4.3.2 (#1138) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 671cb47878..e9ecaf4427 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -24,4 +24,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3 + uses: actions/dependency-review-action@0c155c5e8556a497adf53f2c18edabf945ed8e70 # v4.3.2 From 949bf63246c425cc92512af6abba07779e89b03b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:02:52 +0100 Subject: [PATCH 71/89] build(deps): bump shivammathur/setup-php from 2.29.0 to 2.30.4 (#1139) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/construct-vcpkg-info.yml | 2 +- .github/workflows/documentation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/construct-vcpkg-info.yml b/.github/workflows/construct-vcpkg-info.yml index 18a92e24bd..14d63d364a 100644 --- a/.github/workflows/construct-vcpkg-info.yml +++ b/.github/workflows/construct-vcpkg-info.yml @@ -20,7 +20,7 @@ jobs: egress-policy: audit - name: Setup PHP - uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # v2 + uses: shivammathur/setup-php@c665c7a15b5295c2488ac8a87af9cb806cd72198 # v2 with: php-version: '8.1' diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 68658a10af..856cd58b8f 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -30,7 +30,7 @@ jobs: egress-policy: audit - name: Setup PHP - uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # v2 + uses: shivammathur/setup-php@c665c7a15b5295c2488ac8a87af9cb806cd72198 # v2 with: php-version: '8.0' From b80b44fea48343c22f1796f23f283c40fae8b023 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:03:02 +0100 Subject: [PATCH 72/89] build(deps): bump docker/build-push-action from 5.1.0 to 5.3.0 (#1140) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0625bc0929..f7324ba5b3 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -47,7 +47,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push - uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: push: true tags: brainboxdotcc/dpp From d69f373a7159b1f039bd0c162faa28e271fcbf76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:03:15 +0100 Subject: [PATCH 73/89] build(deps): bump step-security/harden-runner from 2.7.0 to 2.7.1 (#1141) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/codeql.yml | 2 +- .github/workflows/construct-vcpkg-info.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/docker.yml | 2 +- .github/workflows/documentation-check.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/gitguardian.yml | 2 +- .github/workflows/labeler.yml | 2 +- .github/workflows/scorecard.yml | 2 +- .github/workflows/sitemap.yml | 2 +- .github/workflows/stale.yml | 2 +- .github/workflows/target-master.yml | 2 +- .github/workflows/test-docs-examples.yml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1aa3e3a05e..c703480ee0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - { arch: 'arm64', concurrency: 4, os: [self-hosted, linux, ARM64], package: g++-12, cpp-version: g++-12, cmake-flags: '', cpack: 'yes', ctest: 'no' } steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit @@ -117,7 +117,7 @@ jobs: - { arch: 'arm64', concurrency: 2, os: [self-hosted, ARM64, macOS], cpp-version: clang++-15, cmake-flags: ''} steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit @@ -166,7 +166,7 @@ jobs: runs-on: ${{matrix.cfg.os}} steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit @@ -231,7 +231,7 @@ jobs: runs-on: ${{matrix.cfg.os}} steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 82684a0691..83de763be1 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -41,7 +41,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/construct-vcpkg-info.yml b/.github/workflows/construct-vcpkg-info.yml index 14d63d364a..17862fcadd 100644 --- a/.github/workflows/construct-vcpkg-info.yml +++ b/.github/workflows/construct-vcpkg-info.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index e9ecaf4427..bd74c3d5ec 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f7324ba5b3..a9c723dde0 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -22,7 +22,7 @@ jobs: cancel-in-progress: false steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/documentation-check.yml b/.github/workflows/documentation-check.yml index fee18fd920..cb216a5a24 100644 --- a/.github/workflows/documentation-check.yml +++ b/.github/workflows/documentation-check.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 856cd58b8f..1351814535 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 8e519a7186..5029b6c490 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -14,7 +14,7 @@ jobs: cancel-in-progress: true steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 0027d6a3f2..4479375c82 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 77b426090d..bf562859e2 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/sitemap.yml b/.github/workflows/sitemap.yml index b5ee2028e0..588fb1a052 100644 --- a/.github/workflows/sitemap.yml +++ b/.github/workflows/sitemap.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d11167f341..bd479cfb61 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/target-master.yml b/.github/workflows/target-master.yml index f92c20a53a..2d5ee1e1f4 100644 --- a/.github/workflows/target-master.yml +++ b/.github/workflows/target-master.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit diff --git a/.github/workflows/test-docs-examples.yml b/.github/workflows/test-docs-examples.yml index 7a9bff2112..423defd86f 100644 --- a/.github/workflows/test-docs-examples.yml +++ b/.github/workflows/test-docs-examples.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 with: egress-policy: audit From 941dc273d3edf294e8f890e003a5f52f90a4a036 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:03:24 +0100 Subject: [PATCH 74/89] build(deps): bump doxygen-awesome-css from `5b27b3a` to `9f97817` (#1143) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- doxygen-awesome-css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doxygen-awesome-css b/doxygen-awesome-css index 5b27b3a747..9f97817e70 160000 --- a/doxygen-awesome-css +++ b/doxygen-awesome-css @@ -1 +1 @@ -Subproject commit 5b27b3a747ca1e559fa54149762cca0bad6036fb +Subproject commit 9f97817e703aa2c15503067b2a72c97f9d37f46e From bf63f66eb1ce79c06e2fb38537c75a89b118f755 Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Wed, 1 May 2024 08:03:39 -0400 Subject: [PATCH 75/89] feat: poll support (#1136) --- include/dpp/cluster.h | 66 +++++ include/dpp/cluster_coro_calls.h | 52 ++++ include/dpp/dispatcher.h | 66 +++++ include/dpp/event.h | 2 + include/dpp/message.h | 294 ++++++++++++++++++-- include/dpp/restrequest.h | 33 +++ src/dpp/cluster/message.cpp | 32 +++ src/dpp/cluster_coro_calls.cpp | 16 ++ src/dpp/discordevents.cpp | 2 + src/dpp/events/message_poll_vote_add.cpp | 53 ++++ src/dpp/events/message_poll_vote_remove.cpp | 53 ++++ src/dpp/message.cpp | 172 +++++++++++- src/unittest/test.cpp | 95 ++++++- src/unittest/test.h | 3 + 14 files changed, 919 insertions(+), 20 deletions(-) create mode 100644 src/dpp/events/message_poll_vote_add.cpp create mode 100644 src/dpp/events/message_poll_vote_remove.cpp diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index d7b7e27469..b27d068e9d 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -992,6 +992,24 @@ class DPP_EXPORT cluster { */ event_router_t on_message_create; + /** + * @brief Called when a vote is added to a message poll. + * + * @see https://discord.com/developers/docs/topics/gateway-events#message-poll-vote-add + * @note Use operator() to attach a lambda to this event, and the detach method to detach the listener using the returned ID. + * The function signature for this event takes a single `const` reference of type message_poll_vote_add_t&, and returns void. + */ + event_router_t on_message_poll_vote_add; + + /** + * @brief Called when a vote is removed from a message poll. + * + * @see https://discord.com/developers/docs/topics/gateway-events#message-poll-vote-remove + * @note Use operator() to attach a lambda to this event, and the detach method to detach the listener using the returned ID. + * The function signature for this event takes a single `const` reference of type message_poll_vote_remove_t&, and returns void. + */ + event_router_t on_message_poll_vote_remove; + /** * @brief Called when a guild audit log entry is created. * @@ -1948,6 +1966,54 @@ class DPP_EXPORT cluster { */ void message_delete_bulk(const std::vector &message_ids, snowflake channel_id, command_completion_event_t callback = utility::log_error()); + /** + * @brief Get a list of users that voted for this specific answer. + * + * @param m Message that contains the poll to retrieve the answers from + * @param answer_id ID of the answer to retrieve votes from (see poll_answer::answer_id) + * @param after Users after this ID should be retrieved if this is set to non-zero + * @param limit This number of users maximum should be returned, up to 100 + * @param callback Function to call when the API call completes. + * @see https://discord.com/developers/docs/resources/poll#get-answer-voters + * On success the callback will contain a dpp::user_map object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void poll_get_answer_voters(const message& m, uint32_t answer_id, snowflake after, uint64_t limit, command_completion_event_t callback = utility::log_error()); + + /** + * @brief Get a list of users that voted for this specific answer. + * + * @param message_id ID of the message with the poll to retrieve the answers from + * @param channel_id ID of the channel with the poll to retrieve the answers from + * @param answer_id ID of the answer to retrieve votes from (see poll_answer::answer_id) + * @param after Users after this ID should be retrieved if this is set to non-zero + * @param limit This number of users maximum should be returned, up to 100 + * @param callback Function to call when the API call completes. + * @see https://discord.com/developers/docs/resources/poll#get-answer-voters + * On success the callback will contain a dpp::user_map object in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void poll_get_answer_voters(snowflake message_id, snowflake channel_id, uint32_t answer_id, snowflake after, uint64_t limit, command_completion_event_t callback = utility::log_error()); + + /** + * @brief Immediately end a poll. + * + * @param m Message that contains the poll + * @param callback Function to call when the API call completes. + * @see https://discord.com/developers/docs/resources/poll#end-poll + * On success the callback will contain a dpp::message object representing the message containing the poll in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void poll_end(const message &m, command_completion_event_t callback = utility::log_error()); + + /** + * @brief Immediately end a poll. + * + * @param message_id ID of the message with the poll to end + * @param channel_id ID of the channel with the poll to end + * @param callback Function to call when the API call completes. + * @see https://discord.com/developers/docs/resources/poll#end-poll + * On success the callback will contain a dpp::message object representing the message containing the poll in confirmation_callback_t::value. On failure, the value is undefined and confirmation_callback_t::is_error() method will return true. You can obtain full error details with confirmation_callback_t::get_error(). + */ + void poll_end(snowflake message_id, snowflake channel_id, command_completion_event_t callback = utility::log_error()); + /** * @brief Get a channel * diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index f5a41fa1ea..1e4af10fe5 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -1621,6 +1621,58 @@ */ [[nodiscard]] async co_message_unpin(snowflake channel_id, snowflake message_id); +/** + * @brief Get a list of users that voted for this specific answer. + * + * @param m Message that contains the poll to retrieve the answers from + * @param answer_id ID of the answer to retrieve votes from (see poll_answer::answer_id) + * @param after Users after this ID should be retrieved if this is set to non-zero + * @param limit This number of users maximum should be returned, up to 100 + * @return user_map returned object on completion + * @see dpp::cluster::poll_get_answer_voters + * @see https://discord.com/developers/docs/resources/poll#get-answer-voters + * \memberof dpp::cluster + */ +[[nodiscard]] async co_poll_get_answer_voters(const message& m, uint32_t answer_id, snowflake after, uint64_t limit); + +/** + * @brief Get a list of users that voted for this specific answer. + * + * @param message_id ID of the message with the poll to retrieve the answers from + * @param channel_id ID of the channel with the poll to retrieve the answers from + * @param answer_id ID of the answer to retrieve votes from (see poll_answer::answer_id) + * @param after Users after this ID should be retrieved if this is set to non-zero + * @param limit This number of users maximum should be returned, up to 100 + * @return user_map returned object on completion + * @see dpp::cluster::poll_get_answer_voters + * @see https://discord.com/developers/docs/resources/poll#get-answer-voters + * \memberof dpp::cluster + */ +[[nodiscard]] async co_poll_get_answer_voters(snowflake message_id, snowflake channel_id, uint32_t answer_id, snowflake after, uint64_t limit); + +/** + * @brief Immediately end a poll. + * + * @param m Message that contains the poll + * @return message returned object on completion + * @see dpp::cluster::poll_end + * @see https://discord.com/developers/docs/resources/poll#end-poll + * \memberof dpp::cluster + */ +[[nodiscard]] async co_poll_end(const message &m); + +/** + * @brief Immediately end a poll. + * + * @param message_id ID of the message with the poll to end + * @param channel_id ID of the channel with the poll to end + * @return message returned object on completion + * @see dpp::cluster::poll_end + * @see https://discord.com/developers/docs/resources/poll#end-poll + * \memberof dpp::cluster + */ +[[nodiscard]] async co_poll_end(snowflake message_id, snowflake channel_id); + /** * @brief Get a channel's pins * @see dpp::cluster::channel_pins_get diff --git a/include/dpp/dispatcher.h b/include/dpp/dispatcher.h index fef838fba7..6310aef3d4 100644 --- a/include/dpp/dispatcher.h +++ b/include/dpp/dispatcher.h @@ -1687,6 +1687,72 @@ struct DPP_EXPORT message_create_t : public event_dispatch_t { void reply(message&& msg, bool mention_replied_user = false, command_completion_event_t callback = utility::log_error()) const; }; +/** + * @brief Message poll vote add + */ +struct DPP_EXPORT message_poll_vote_add_t : public event_dispatch_t { + using event_dispatch_t::event_dispatch_t; + using event_dispatch_t::operator=; + + /** + * @brief ID of the user who added the vote + */ + snowflake user_id; + + /** + * @brief ID of the channel containing the vote + */ + snowflake channel_id; + + /** + * @brief ID of the message containing the vote + */ + snowflake message_id; + + /** + * @brief ID of the guild containing the vote or 0 for DMs + */ + snowflake guild_id; + + /** + * @brief ID of the answer in the message poll object + */ + uint32_t answer_id; +}; + +/** + * @brief Message poll vote remove + */ +struct DPP_EXPORT message_poll_vote_remove_t : public event_dispatch_t { + using event_dispatch_t::event_dispatch_t; + using event_dispatch_t::operator=; + + /** + * @brief ID of the user who added the vote + */ + snowflake user_id; + + /** + * @brief ID of the channel containing the vote + */ + snowflake channel_id; + + /** + * @brief ID of the message containing the vote + */ + snowflake message_id; + + /** + * @brief ID of the guild containing the vote or 0 for DMs + */ + snowflake guild_id; + + /** + * @brief ID of the answer in the message poll object + */ + uint32_t answer_id; +}; + /** * @brief Guild audit log entry create */ diff --git a/include/dpp/event.h b/include/dpp/event.h index fe6df9bb45..6921586755 100644 --- a/include/dpp/event.h +++ b/include/dpp/event.h @@ -100,6 +100,8 @@ event_decl(message_create,MESSAGE_CREATE); event_decl(message_update,MESSAGE_UPDATE); event_decl(message_delete,MESSAGE_DELETE); event_decl(message_delete_bulk,MESSAGE_DELETE_BULK); +event_decl(message_poll_vote_add,MESSAGE_POLL_VOTE_ADD); +event_decl(message_poll_vote_remove,MESSAGE_POLL_VOTE_REMOVE); /* Presence/typing */ event_decl(presence_update,PRESENCE_UPDATE); diff --git a/include/dpp/message.h b/include/dpp/message.h index 6455540e62..d64b481e82 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -79,14 +79,14 @@ enum component_type : uint8_t { }; /** - * @brief An emoji for a component (select menus included). + * @brief An emoji reference for a component (select menus included) or a poll. * - * To set an emoji on your button, you must set one of either the name or id fields. - * The easiest way is to use the dpp::component::set_emoji method. + * To set an emoji on your button or poll answer, you must set one of either the name or id fields. + * The easiest way for buttons is to use the dpp::component::set_emoji method. * * @note This is a **very** scaled down version of dpp::emoji, we advise that you refrain from using this. */ -struct component_emoji { +struct partial_emoji { /** * @brief The name of the emoji. * @@ -94,7 +94,7 @@ struct component_emoji { * actual unicode value of the emoji e.g. "😄" * and not for example ":smile:" */ - std::string name{""}; + std::string name{}; /** * @brief The emoji ID value for emojis that are custom @@ -115,6 +115,13 @@ struct component_emoji { bool animated{false}; }; +/** + * @brief An emoji for a component. Alias to partial_emoji, for backwards compatibility. + * + * @see partial_emoji + */ +using component_emoji = partial_emoji; + /** * @brief The data for a file attached to a message. * @@ -247,7 +254,7 @@ struct DPP_EXPORT select_option : public json_interface { /** * @brief The emoji for the select option. */ - component_emoji emoji; + partial_emoji emoji; /** * @brief Construct a new select option object @@ -449,7 +456,7 @@ class DPP_EXPORT component : public json_interface { /** * @brief The emoji for this component. */ - component_emoji emoji; + partial_emoji emoji; /** * @brief Constructor @@ -1365,39 +1372,267 @@ struct DPP_EXPORT sticker_pack : public managed, public json_interface stickers; + std::map stickers{}; /** * @brief Name of the sticker pack. */ - std::string name; + std::string name{}; /** * @brief ID of the pack's SKU. */ - snowflake sku_id; + snowflake sku_id{0}; /** * @brief Optional: ID of a sticker in the pack which is shown as the pack's icon. */ - snowflake cover_sticker_id; + snowflake cover_sticker_id{0}; /** * @brief Description of the sticker pack. */ - std::string description; + std::string description{}; /** * @brief ID of the sticker pack's banner image. */ - snowflake banner_asset_id; + snowflake banner_asset_id{}; +}; + +/** + * @brief Poll layout types + * + * @note At the time of writing Discord only has 1, "The, uhm, default layout type." + * @see https://discord.com/developers/docs/resources/poll#layout-type + */ +enum poll_layout_type { + /** + * @brief According to Discord, quote, "The, uhm, default layout type." + */ + pl_default = 1 +}; + +/** + * @brief Structure representing a poll media, for example the poll question or a possible poll answer. + * + * @see https://discord.com/developers/docs/resources/poll#poll-media-object-poll-media-object-structure + */ +struct poll_media { + /** + * @brief Text of the media + */ + std::string text{}; + + /** + * @brief Emoji of the media. + */ + partial_emoji emoji{}; +}; + +/** + * @brief Represents an answer in a poll. + * + * @see https://discord.com/developers/docs/resources/poll#poll-answer-object-poll-answer-object-structure + */ +struct poll_answer { + /** + * @brief ID of the answer. Only sent by the Discord API, this is a dead field when creating a poll. + * + * @warn At the time of writing the Discord API warns users not to rely on anything regarding sequence or "first value" of this field. + */ + uint32_t id{0}; + + /** + * @brief Data of the answer. + * + * @see poll_media + */ + poll_media media{}; +}; + +/** + * @brief Represents the results of a poll + * + * @see https://discord.com/developers/docs/resources/poll#poll-results-object-poll-results-object-structure + */ +struct poll_results { + /** + * @brief Represents a reference to an answer and its count of votes + * + * @see https://discord.com/developers/docs/resources/poll#poll-results-object-poll-answer-count-object-structure + */ + struct answer_count { + /** + * @brief ID of the answer. Relates to an answer in the answers field + * + * @see poll_answer::answer_id + */ + uint32_t answer_id{0}; + + /** + * @brief Number of votes for this answer + */ + uint32_t count{0}; + + /** + * @brief Whether the current user voted + */ + bool me_voted{false}; + }; + + /** + * @brief Whether the poll has finalized, and the answers are precisely counted + * + * @note Discord states that due to the way they count and cache answers, + * while a poll is running the count of answers might not be accurate. + */ + bool is_finalized{false}; + + /** + * @brief Count of votes for each answer. If an answer is not present in this list, + * then its vote count is 0 + */ + std::map answer_counts; +}; + +/** + * @brief Represents a poll. + * + * @see https://discord.com/developers/docs/resources/poll + */ +struct DPP_EXPORT poll { + /** + * @brief Poll question. At the time of writing only the text field is supported by Discord + * + * @see media + */ + poll_media question{}; + + /** + * @brief List of answers of the poll. + * + * @note At the time of writing this can contain up to 10 answers + * @see answer + */ + std::map answers{}; + + /** + * @brief When retriving a poll from the API, this is the timestamp at which the poll will expire. + * When creating a poll, this is the number of hours the poll should be up for, up to 7 days (168 hours), and this field will be rounded. + */ + double expiry{24.0}; + + /** + * @brief Whether a user can select multiple answers + */ + bool allow_multiselect{false}; + + /** + * @brief Layout type of the poll. Defaults to, well, pl_default + * + * @see poll_layout_type + */ + poll_layout_type layout_type{pl_default}; + + /** + * @brief The (optional) results of the poll. This field may or may not be present, and its absence means "unknown results", not "no results". + * + * @note Quote from Discord: "The results field may be not present in certain responses where, as an implementation detail, + * we do not fetch the poll results in our backend. This should be treated as "unknown results", + * as opposed to "no results". You can keep using the results if you have previously received them through other means." + * + * @see https://discord.com/developers/docs/resources/poll#poll-results-object + */ + std::optional results{std::nullopt}; /** - * @brief Construct a new sticker pack object + * @brief Set the question for this poll + * + * @param text Text for the question + * @return self for method chaining + */ + poll& set_question(const std::string& text); + + /** + * @brief Set the duration of the poll in hours + * + * @param hours Duration of the poll in hours, max 7 days (168 hours) at the time of writing + * @return self for method chaining + */ + poll& set_duration(uint32_t hours) noexcept; + + /** + * @brief Set the duration of the poll in hours + * + * @param hours Duration of the poll in hours + * @return self for method chaining + */ + poll& set_allow_multiselect(bool allow) noexcept; + + /** + * @brief Add an answer to this poll + * + * @note At the time of writing this, a poll can have up to 10 answers + * @param media Data of the answer + * @return self for method chaining + */ + poll& add_answer(const poll_media& media); + + /** + * @brief Add an answer to this poll + * + * @note At the time of writing this, a poll can have up to 10 answers + * @param text Text for the answer + * @param emoji_id Optional emoji + * @param is_animated Whether the emoji is animated + * @return self for method chaining */ - sticker_pack(); + poll& add_answer(const std::string& text, snowflake emoji_id = 0, bool is_animated = false); - virtual ~sticker_pack() = default; + /** + * @brief Add an answer to this poll + * + * @note At the time of writing this, a poll can have up to 10 answers + * @param text Text for the answer + * @param emoji Optional emoji + * @return self for method chaining + */ + poll& add_answer(const std::string& text, const std::string& emoji); + + /** + * @brief Add an answer to this poll + * + * @note At the time of writing this, a poll can have up to 10 answers + * @param text Text for the answer + * @param e Optional emoji + * @return self for method chaining + */ + poll& add_answer(const std::string& text, const emoji& e); + + /** + * @brief Helper to get the question text + * + * @return question.text + */ + [[nodiscard]] const std::string& get_question_text() const noexcept; + + /** + * @brief Helper to find an answer by ID + * + * @param id ID to find + * @return Pointer to the answer with the matching ID, or nullptr if not found + */ + [[nodiscard]] const poll_media* find_answer(uint32_t id) const noexcept; + + /** + * @brief Helper to find the vote count in the results + * + * @param answer_id ID of the answer to find + * @return std::optional Optional count of votes. An empty optional means Discord did not send the results, it does not mean 0. It can also mean the poll does not have an answer with this ID + * @see https://discord.com/developers/docs/resources/poll#poll-results-object + */ + [[nodiscard]] std::optional get_vote_count(uint32_t answer_id) const noexcept; }; /** @@ -1989,6 +2224,11 @@ struct DPP_EXPORT message : public managed, json_interface { */ bool mention_everyone; + /** + * @brief Optional poll attached to this message + */ + std::optional attached_poll; + /** * @brief Construct a new message object */ @@ -2316,6 +2556,28 @@ struct DPP_EXPORT message : public managed, json_interface { * @return string of URL to message */ std::string get_url() const; + + /** + * @brief Convenience method to set the poll + * + * @return message& Self reference for method chaining + */ + message& set_poll(const poll& p); + + /** + * @brief Convenience method to get the poll attached to this message + * + * @throw std::bad_optional_access if has_poll() == false + * @return const poll& Poll attached to this object + */ + [[nodiscard]] const poll& get_poll() const; + + /** + * @brief Method to check if the message has a poll + * + * @return bool Whether the message has a poll + */ + [[nodiscard]] bool has_poll() const noexcept; }; /** diff --git a/include/dpp/restrequest.h b/include/dpp/restrequest.h index e948713b17..93fdd27071 100644 --- a/include/dpp/restrequest.h +++ b/include/dpp/restrequest.h @@ -144,6 +144,7 @@ template<> inline void rest_request_list(dpp::cluster* c, const char* ba } }); } + /** * @brief Templated REST request helper to save on typing (for returned lists, specialised for voiceregions) * @@ -172,6 +173,7 @@ template<> inline void rest_request_list(dpp::cluster* c, const cha } }); } + /** * @brief Templated REST request helper to save on typing (for returned lists, specialised for bans) * @@ -201,6 +203,7 @@ template<> inline void rest_request_list(dpp::cluster* c, const char* basep } }); } + /** * @brief Templated REST request helper to save on typing (for returned lists, specialised for sticker packs) * @@ -232,6 +235,36 @@ template<> inline void rest_request_list(dpp::cluster* c, const ch }); } +/** + * @brief Templated REST request helper to save on typing (for returned lists) + * + * @tparam T singular type to return in lambda callback + * @tparam T map type to return in lambda callback + * @param c calling cluster + * @param basepath base path for API call + * @param major major API function + * @param minor minor API function + * @param method HTTP method + * @param postdata Post data or empty string + * @param key Key name of elements in the json list + * @param root Root element to look for + * @param callback Callback lambda + */ +template inline void rest_request_list(dpp::cluster* c, const char* basepath, const std::string &major, const std::string &minor, http_method method, const std::string& postdata, command_completion_event_t callback, const std::string& key, const std::string& root) { + c->post_rest(basepath, major, minor, method, postdata, [c, root, key, callback](json &j, const http_request_completion_t& http) { + std::unordered_map list; + confirmation_callback_t e(c, confirmation(), http); + if (!e.is_error()) { + for (auto & curr_item : j[root]) { + list[snowflake_not_null(&curr_item, key.c_str())] = T().fill_from_json(&curr_item); + } + } + if (callback) { + callback(confirmation_callback_t(c, list, http)); + } + }); +} + /** * @brief Templated REST request helper to save on typing (for returned lists, specialised for objects which doesn't have ids) * diff --git a/src/dpp/cluster/message.cpp b/src/dpp/cluster/message.cpp index 06fc23faba..824060c3e0 100644 --- a/src/dpp/cluster/message.cpp +++ b/src/dpp/cluster/message.cpp @@ -172,6 +172,38 @@ void cluster::message_unpin(snowflake channel_id, snowflake message_id, command_ } +void cluster::poll_get_answer_voters(const message& m, uint32_t answer_id, snowflake after, uint64_t limit, command_completion_event_t callback) { + std::map parameters { + {"limit", std::to_string(limit > 100 ? 100 : limit)} + }; + + if (after > 0) { + parameters["after"] = after; + } + rest_request_list(this, API_PATH "/channels", std::to_string(m.channel_id), "polls/" + std::to_string(m.id) + "/answers/" + std::to_string(answer_id) + utility::make_url_parameters(parameters), m_get, "", std::move(callback), "id", "users"); +} + +void cluster::poll_get_answer_voters(snowflake message_id, snowflake channel_id, uint32_t answer_id, snowflake after, uint64_t limit, command_completion_event_t callback) { + std::map parameters { + {"limit", std::to_string(limit > 100 ? 100 : limit)} + }; + + if (after > 0) { + parameters["after"] = after; + } + rest_request_list(this, API_PATH "/channels", std::to_string(channel_id), "polls/" + std::to_string(message_id) + "/answers/" + std::to_string(answer_id) + utility::make_url_parameters(parameters), m_get, "", std::move(callback), "id", "users"); +} + + +void cluster::poll_end(const message &m, command_completion_event_t callback) { + rest_request(this, API_PATH "/channels", std::to_string(m.channel_id), "polls/" + std::to_string(m.id) + "/expire", m_post, "", std::move(callback)); +} + +void cluster::poll_end(snowflake message_id, snowflake channel_id, command_completion_event_t callback) { + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "polls/" + std::to_string(message_id) + "/expire", m_post, "", std::move(callback)); +} + + void cluster::channel_pins_get(snowflake channel_id, command_completion_event_t callback) { rest_request_list(this, API_PATH "/channels", std::to_string(channel_id), "pins", m_get, "", callback); } diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp index dbf3da3757..dee4daef50 100644 --- a/src/dpp/cluster_coro_calls.cpp +++ b/src/dpp/cluster_coro_calls.cpp @@ -531,6 +531,22 @@ async cluster::co_message_unpin(snowflake channel_id, s return async{ this, static_cast(&cluster::message_unpin), channel_id, message_id }; } +async cluster::co_poll_get_answer_voters(const message& m, uint32_t answer_id, snowflake after, uint64_t limit) { + return async{ this, static_cast(&cluster::poll_get_answer_voters), m, answer_id, after, limit }; +} + +async cluster::co_poll_get_answer_voters(snowflake message_id, snowflake channel_id, uint32_t answer_id, snowflake after, uint64_t limit) { + return async{ this, static_cast(&cluster::poll_get_answer_voters), message_id, channel_id, answer_id, after, limit }; +} + +async cluster::co_poll_end(const message &m) { + return async{ this, static_cast(&cluster::poll_end), m }; +} + +async cluster::co_poll_end(snowflake message_id, snowflake channel_id) { + return async{ this, static_cast(&cluster::poll_end), message_id, channel_id }; +} + async cluster::co_channel_pins_get(snowflake channel_id) { return async{ this, static_cast(&cluster::channel_pins_get), channel_id }; } diff --git a/src/dpp/discordevents.cpp b/src/dpp/discordevents.cpp index 72c9596b77..bdaa51afe4 100644 --- a/src/dpp/discordevents.cpp +++ b/src/dpp/discordevents.cpp @@ -363,6 +363,8 @@ static const std::map event_map = { { "MESSAGE_REACTION_REMOVE", make_static_event() }, { "MESSAGE_REACTION_REMOVE_ALL", make_static_event() }, { "MESSAGE_REACTION_REMOVE_EMOJI", make_static_event() }, + { "MESSAGE_POLL_VOTE_ADD", make_static_event() }, + { "MESSAGE_POLL_VOTE_REMOVE", make_static_event() }, { "CHANNEL_PINS_UPDATE", make_static_event() }, { "GUILD_BAN_ADD", make_static_event() }, { "GUILD_BAN_REMOVE", make_static_event() }, diff --git a/src/dpp/events/message_poll_vote_add.cpp b/src/dpp/events/message_poll_vote_add.cpp new file mode 100644 index 0000000000..319d809e9c --- /dev/null +++ b/src/dpp/events/message_poll_vote_add.cpp @@ -0,0 +1,53 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ +#include +#include +#include +#include +#include + + +namespace dpp::events { + + +/** + * @brief Handle event + * + * @param client Websocket client (current shard) + * @param j JSON data for the event + * @param raw Raw JSON string + */ +void message_poll_vote_add::handle(discord_client* client, json &j, const std::string &raw) { + + if (!client->creator->on_message_poll_vote_add.empty()) { + json d = j["d"]; + dpp::message_poll_vote_add_t vote(client, raw); + vote.user_id = snowflake_not_null(&j, "user_id"); + vote.message_id = snowflake_not_null(&j, "message_id"); + vote.channel_id = snowflake_not_null(&j, "channel_id"); + vote.guild_id = snowflake_not_null(&j, "guild_id"); + vote.answer_id = int32_not_null(&j, "answer_id"); + client->creator->on_message_poll_vote_add.call(vote); + } +} + +}; diff --git a/src/dpp/events/message_poll_vote_remove.cpp b/src/dpp/events/message_poll_vote_remove.cpp new file mode 100644 index 0000000000..55c243e767 --- /dev/null +++ b/src/dpp/events/message_poll_vote_remove.cpp @@ -0,0 +1,53 @@ +/************************************************************************************ + * + * 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. + * + ************************************************************************************/ +#include +#include +#include +#include +#include + + +namespace dpp::events { + + +/** + * @brief Handle event + * + * @param client Websocket client (current shard) + * @param j JSON data for the event + * @param raw Raw JSON string + */ +void message_poll_vote_remove::handle(discord_client* client, json &j, const std::string &raw) { + + if (!client->creator->on_message_poll_vote_add.empty()) { + json d = j["d"]; + dpp::message_poll_vote_remove_t vote(client, raw); + vote.user_id = snowflake_not_null(&j, "user_id"); + vote.message_id = snowflake_not_null(&j, "message_id"); + vote.channel_id = snowflake_not_null(&j, "channel_id"); + vote.guild_id = snowflake_not_null(&j, "guild_id"); + vote.answer_id = int32_not_null(&j, "answer_id"); + client->creator->on_message_poll_vote_remove.call(vote); + } +} + +}; diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index 31e53ea3fb..ed7709a413 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -485,6 +485,155 @@ component &component::add_default_value(const snowflake id, const component_defa return *this; } +namespace { + +poll_media get_poll_media(const nlohmann::json& obj, std::string_view key) { + poll_media retval{}; + + if (auto it = obj.find(key); it != obj.end()) { + const json& media_json = *it; + + retval.text = string_not_null(&media_json, "text"); + if (it = media_json.find("emoji"); it != media_json.end()) { + const json& emoji_json = *it; + + retval.emoji.animated = bool_not_null(&emoji_json, "animated"); + retval.emoji.name = string_not_null(&emoji_json, "name"); + retval.emoji.id = snowflake_not_null(&emoji_json, "id"); + } + } + return retval; +}; + +json make_json(const poll_media &media) { + json retval{}; + + if (media.emoji.id != 0) { + json& emoji_json = retval["emoji"]; + emoji_json["id"] = media.emoji.id; + emoji_json["animated"] = media.emoji.animated; + } else if (!media.emoji.name.empty()) { + json& emoji_json = retval["emoji"]; + emoji_json["name"] = media.emoji.name; + emoji_json["animated"] = media.emoji.animated; + } + retval["text"] = media.text; + return retval; +} + +} + +void from_json(const nlohmann::json& j, poll& p) { + p.question = get_poll_media(j, "question"); + if (auto it = j.find("answers"); it != j.end() && it->is_array()) { + for (const json& element : *it) { + auto id = int32_not_null(&element, "answer_id"); + p.answers.emplace(id, poll_answer{ + id, + get_poll_media(element, "poll_media") + }); + } + } + p.expiry = double_not_null(&j, "expiry"); + p.allow_multiselect = bool_not_null(&j, "allow_multiselect"); + p.layout_type = static_cast(int32_not_null(&j, "layout_type")); + if (auto it = j.find("results"); it != j.end()) { + const json& results_json = *it; + poll_results p_results{}; + + p_results.is_finalized = bool_not_null(&results_json, "is_finalized"); + if (it = results_json.find("answer_counts"); it != results_json.end() && it->is_array()) { + for (const json& answer_count_json : *it) { + auto id = int32_not_null(&answer_count_json, "id"); + p_results.answer_counts.emplace(id, poll_results::answer_count{ + id, + int32_not_null(&answer_count_json, "count"), + bool_not_null(&answer_count_json, "me_voted") + }); + } + } + p.results = std::move(p_results); + } +} + +void to_json(json& j, const poll &p) { + j["question"] = make_json(p.question); + + json& answers_json = j["answers"]; + for (const auto& [_, answer] : p.answers) { + answers_json.emplace_back()["poll_media"] = make_json(answer.media); + } + /* When sending a poll object expiry is a duration in hours so we clamp it to positive and round */ + j["duration"] = (p.expiry < 0.0 ? uint32_t{0} : static_cast(p.expiry + 0.5)); + j["allow_multiselect"] = p.allow_multiselect; + j["layout_type"] = static_cast(p.layout_type); +} + +poll& poll::set_question(const std::string& text) { + question.text = text; + return *this; +} + +poll& poll::set_duration(uint32_t hours) noexcept { + expiry = static_cast(hours); + return *this; +} + +poll& poll::set_allow_multiselect(bool allow) noexcept { + allow_multiselect = allow; + return *this; +} + +poll& poll::add_answer(const poll_media& media) { + uint32_t max = 0; + for (const auto &pair : answers) { + if (pair.first > max) { + max = pair.first; + } + } + answers.emplace(max + 1, poll_answer{max + 1, media}); + return *this; +} + +poll& poll::add_answer(const std::string& text, snowflake emoji_id, bool is_animated) { + return add_answer(poll_media{text, partial_emoji{{}, emoji_id, is_animated}}); +} + +poll& poll::add_answer(const std::string& text, const std::string& emoji) { + return add_answer(poll_media{text, partial_emoji{emoji, {}, false}}); +} + +poll& poll::add_answer(const std::string& text, const emoji& e) { + return add_answer(poll_media{text, partial_emoji{e.name, e.id, e.is_animated()}}); +} + +const std::string& poll::get_question_text() const noexcept { + return question.text; +} + +const poll_media *poll::find_answer(uint32_t id) const noexcept { + if (auto it = answers.find(id); it != answers.end()) { + return &it->second.media; + } + return nullptr; +} + +std::optional poll::get_vote_count(uint32_t answer_id) const noexcept { + if (!results.has_value()) { + return std::nullopt; + } + if (auto it = results->answer_counts.find(answer_id); it != results->answer_counts.end()) { + return it->second.count; + } + /* Answers not present can mean 0 */ + if (find_answer(answer_id) == nullptr) { + return std::nullopt; + } + return 0; +} + + + embed::~embed() = default; embed::embed() : timestamp(0) { @@ -617,6 +766,19 @@ message& message::set_guild_id(snowflake _guild_id) { return *this; } +message& message::set_poll(const poll& p) { + attached_poll = p; + return *this; +} + +const poll &message::get_poll() const { + return attached_poll.value(); +} + +bool message::has_poll() const noexcept { + return attached_poll.has_value(); +} + message::message(const std::string &_content, message_type t) : message() { content = utility::utf8substr(_content, 0, 4000); type = t; @@ -1052,6 +1214,10 @@ json message::to_json(bool with_id, bool is_interaction_response) const { j["embeds"].push_back(e); } + if (attached_poll.has_value()) { + dpp::to_json(j["poll"], *attached_poll); + } + return j; } @@ -1230,6 +1396,9 @@ message& message::fill_from_json(json* d, cache_policy_t cp) { message_reference.message_id = snowflake_not_null(&mr, "message_id"); message_reference.fail_if_not_exists = bool_not_null(&mr, "fail_if_not_exists"); } + if (auto it = d->find("poll"); it != d->end()) { + from_json(*it, attached_poll.emplace()); + } return *this; } @@ -1294,9 +1463,6 @@ json sticker::to_json_impl(bool with_id) const { return j; } -sticker_pack::sticker_pack() : managed(0), sku_id(0), cover_sticker_id(0), banner_asset_id(0) { -} - sticker_pack& sticker_pack::fill_from_json_impl(nlohmann::json* j) { this->id = snowflake_not_null(j, "id"); this->sku_id = snowflake_not_null(j, "sku_id"); diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index 1b76713535..1d12d64d28 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -2093,7 +2093,7 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b } }); } - + set_test(THREAD_CREATE, false); if (!offline) { bot.thread_create("thread test", TEST_TEXT_CHANNEL_ID, 60, dpp::channel_type::CHANNEL_PUBLIC_THREAD, true, 60, [&](const dpp::confirmation_callback_t &event) { @@ -2105,6 +2105,99 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b }); } + start_test(POLL_CREATE); + if (!offline) { + dpp::message poll_msg{}; + + poll_msg.set_poll(dpp::poll{} + .set_question("hello!") + .add_answer("one", dpp::unicode_emoji::one) + .add_answer("two", dpp::unicode_emoji::two) + .add_answer("three", dpp::unicode_emoji::three) + .add_answer("four") + .set_duration(48) + .set_allow_multiselect(true) + ).set_channel_id(TEST_TEXT_CHANNEL_ID); + + bot.message_create(poll_msg, [&bot, poll_msg](const dpp::confirmation_callback_t& result) { + if (result.is_error()) { + set_status(POLL_CREATE, ts_failed, result.get_error().human_readable); + return; + } + + const dpp::message& m = std::get(result.value); + + if (!m.attached_poll.has_value()) { + set_status(POLL_CREATE, ts_failed, "poll missing in received message"); + return; + } + + if (m.attached_poll->find_answer(std::numeric_limits::max()) != nullptr) { + set_status(POLL_CREATE, ts_failed, "poll::find_answer failed to return nullptr"); + return; + } + + std::array correct = {false, false, false, false}; + int i = 0; + for (const auto& [_, answer] : m.attached_poll->answers) { + if (m.attached_poll->find_answer(answer.id) != &answer.media) { + set_status(POLL_CREATE, ts_failed, "poll::find_answer failed to return valid answer"); + return; + } + if (answer.media.text == "one" && answer.media.emoji.name == dpp::unicode_emoji::one) { + if (correct[i]) { + set_status(POLL_CREATE, ts_failed, "poll answer found twice"); + return; + } + correct[i] = true; + } + if (answer.media.text == "two" && answer.media.emoji.name == dpp::unicode_emoji::two) { + if (correct[i]) { + set_status(POLL_CREATE, ts_failed, "poll answer found twice"); + return; + } + correct[i] = true; + } + if (answer.media.text == "three" && answer.media.emoji.name == dpp::unicode_emoji::three) { + if (correct[i]) { + set_status(POLL_CREATE, ts_failed, "poll answer found twice"); + return; + } + correct[i] = true; + } + if (answer.media.text == "four" && answer.media.emoji.name.empty()) { + if (correct[i]) { + set_status(POLL_CREATE, ts_failed, "poll answer found twice"); + return; + } + correct[i] = true; + bot.poll_get_answer_voters(m, answer.id, 0, 100, [m, &bot](const dpp::confirmation_callback_t& result) { + if (result.is_error()) { + set_status(POLL_CREATE, ts_failed, "poll_get_answer_voters: " + result.get_error().human_readable); + return; + } + + start_test(POLL_END); + bot.poll_end(m, [message_id = m.id, channel_id = m.channel_id, &bot](const dpp::confirmation_callback_t& result) { + if (result.is_error()) { + set_status(POLL_END, ts_failed, result.get_error().human_readable); + return; + } + set_status(POLL_END, ts_success); + bot.message_delete(message_id, channel_id); + }); + }); + } + ++i; + } + if (correct == std::array{true, true, true, true}) { + set_status(POLL_CREATE, ts_success); + } else { + set_status(POLL_CREATE, ts_failed, "failed to find the submitted answers"); + } + }); + } + set_test(MEMBER_GET, false); if (!offline) { bot.guild_get_member(TEST_GUILD_ID, TEST_USER_ID, [](const dpp::confirmation_callback_t &event){ diff --git a/src/unittest/test.h b/src/unittest/test.h index 2cdb80ac77..51a707a06e 100644 --- a/src/unittest/test.h +++ b/src/unittest/test.h @@ -233,6 +233,9 @@ DPP_TEST(VOICESEND, "Send audio to voice channel", tf_online | tf_extended); // DPP_TEST(MESSAGEPIN, "Pinning a channel message", tf_online | tf_extended); DPP_TEST(MESSAGEUNPIN, "Unpinning a channel message", tf_online | tf_extended); +DPP_TEST(POLL_CREATE, "Creating a poll", tf_online); +DPP_TEST(POLL_END, "Ending a poll", tf_online); + DPP_TEST(THREAD_MEMBER_ADD, "cluster::thread_member_add", tf_online | tf_extended); DPP_TEST(THREAD_MEMBER_GET, "cluster::thread_member_get", tf_online | tf_extended); DPP_TEST(THREAD_MEMBERS_GET, "cluster::thread_members_get", tf_online | tf_extended); From 698c14ff4732e5b5ca1a327c696c6fc9f4c6e173 Mon Sep 17 00:00:00 2001 From: Neko Life Date: Wed, 1 May 2024 23:39:04 +0700 Subject: [PATCH 76/89] fix: fix uncleared track meta on stop audio (#1127) --- src/dpp/discordvoiceclient.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/dpp/discordvoiceclient.cpp b/src/dpp/discordvoiceclient.cpp index 5e514d7331..8727992a1c 100644 --- a/src/dpp/discordvoiceclient.cpp +++ b/src/dpp/discordvoiceclient.cpp @@ -692,6 +692,8 @@ dpp::utility::uptime discord_voice_client::get_remaining() { discord_voice_client& discord_voice_client::stop_audio() { std::lock_guard lock(this->stream_mutex); outbuf.clear(); + track_meta.clear(); + tracks = 0; return *this; } @@ -847,7 +849,7 @@ void discord_voice_client::write_ready() std::lock_guard lock(this->stream_mutex); if (!this->paused && outbuf.size()) { type = send_audio_type; - if (outbuf[0].packet.size() == 2 && (*((uint16_t*)(outbuf[0].packet.data()))) == AUDIO_TRACK_MARKER) { + if (outbuf[0].packet.size() == sizeof(uint16_t) && (*((uint16_t*)(outbuf[0].packet.data()))) == AUDIO_TRACK_MARKER) { outbuf.erase(outbuf.begin()); track_marker_found = true; if (tracks > 0) { @@ -1165,20 +1167,29 @@ uint32_t discord_voice_client::get_tracks_remaining() { discord_voice_client& discord_voice_client::skip_to_next_marker() { std::lock_guard lock(this->stream_mutex); - /* Keep popping the first entry off the outbuf until the first entry is a track marker */ - while (!outbuf.empty() && outbuf[0].packet.size() != sizeof(uint16_t) && (*((uint16_t*)(outbuf[0].packet.data()))) != AUDIO_TRACK_MARKER) { - outbuf.erase(outbuf.begin()); - } - if (outbuf.size()) { - /* Remove the actual track marker out of the buffer */ - outbuf.erase(outbuf.begin()); + if (!outbuf.empty()) { + /* Find the first marker to skip to */ + auto i = std::find_if(outbuf.begin(), outbuf.end(), [](const voice_out_packet &v){ + return v.packet.size() == sizeof(uint16_t) && (*((uint16_t*)(v.packet.data()))) == AUDIO_TRACK_MARKER; + }); + + if (i != outbuf.end()) { + /* Skip queued packets until including found marker */ + outbuf.erase(outbuf.begin(), i+1); + } else { + /* No market found, skip the whole queue */ + outbuf.clear(); + } } + if (tracks > 0) { tracks--; } + if (!track_meta.empty()) { track_meta.erase(track_meta.begin()); } + return *this; } From 2522c214cc6641b5b125d8dfcc5396dbe91c0ed8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 18:02:10 +0100 Subject: [PATCH 77/89] build(deps): bump ubuntu from `80ef4a4` to `71b82b8` (#1130) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index e353f81393..416d640a81 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:focal@sha256:80ef4a44043dec4490506e6cc4289eeda2d106a70148b74b5ae91ee670e9c35d +FROM ubuntu:focal@sha256:71b82b8e734f5cd0b3533a16f40ca1271f28d87343972bb4cd6bd6c38f1bd38e ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --no-install-recommends -y libssl-dev zlib1g-dev libsodium-dev libopus-dev cmake pkg-config g++ gcc git make && apt-get clean && rm -rf /var/lib/apt/lists/* From 70077e8d84621893be079e07b6a01a554a9a27eb Mon Sep 17 00:00:00 2001 From: Nidhoegger <117999161+Nidhoegger@users.noreply.github.com> Date: Wed, 1 May 2024 19:13:50 +0200 Subject: [PATCH 78/89] fix: Signal Handlers on Non-Windows Platforms in sslclient (#1123) Co-authored-by: Craig Edwards (Brain) --- src/dpp/sslclient.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index 428bdebe32..f9aa2df1ac 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -223,6 +223,18 @@ int connect_with_timeout(dpp::socket sockfd, const struct sockaddr *addr, sockle #endif } +#ifndef _WIN32 +void set_signal_handler(int signal) +{ + struct sigaction sa; + sigaction(signal, nullptr, &sa); + if (sa.sa_flags == 0 && sa.sa_handler == nullptr) { + sa = {}; + sigaction(signal, &sa, nullptr); + } +} +#endif + ssl_client::ssl_client(const std::string &_hostname, const std::string &_port, bool plaintext_downgrade, bool reuse) : nonblocking(false), sfd(INVALID_SOCKET), @@ -237,11 +249,11 @@ ssl_client::ssl_client(const std::string &_hostname, const std::string &_port, b keepalive(reuse) { #ifndef WIN32 - signal(SIGALRM, SIG_IGN); + set_signal_handler(SIGALRM); + set_signal_handler(SIGXFSZ); + set_signal_handler(SIGCHLD); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); - signal(SIGCHLD, SIG_IGN); - signal(SIGXFSZ, SIG_IGN); #else // Set up winsock. WSADATA wsadata; From 4992cac0d9160e1d67e08f073112e0806ab3d96a Mon Sep 17 00:00:00 2001 From: "Craig Edwards (Brain)" Date: Wed, 1 May 2024 22:17:00 +0100 Subject: [PATCH 79/89] fix: error in logging with malformed json that doesnt fit the structure for an error (#1126) --- src/dpp/utility.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/dpp/utility.cpp b/src/dpp/utility.cpp index 321bad46d4..0b07ec0e8f 100644 --- a/src/dpp/utility.cpp +++ b/src/dpp/utility.cpp @@ -638,11 +638,19 @@ std::function log_error() { return [](const dpp::confirmation_callback_t& detail) { if (detail.is_error()) { if (detail.bot) { - error_info e = detail.get_error(); - detail.bot->log( - dpp::ll_error, - "Error: " + e.human_readable - ); + try { + error_info e = detail.get_error(); + detail.bot->log( + dpp::ll_error, + "Error: " + e.human_readable + ); + } + catch (const std::exception& e) { + detail.bot->log( + dpp::ll_error, + "Error: " + std::string(e.what()) + ); + } } } }; From 709a2c21cc50b9856e3c0b0f39f9212ff740d2ef Mon Sep 17 00:00:00 2001 From: Archie Jaskowicz Date: Fri, 3 May 2024 00:40:22 +0100 Subject: [PATCH 80/89] ci: Mac runner removal (#1144) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c703480ee0..a771b91465 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,10 +111,10 @@ jobs: strategy: fail-fast: false # Don't fail everything if one fails. We want to test each OS/Compiler individually matrix: - # arm64 is a self-hosted runner on a Mac M2 Mini, ran inside a virtual machine by Archie Jaskowicz. + # arm64 is a self-hosted runner on a Mac M2 Mini, ran inside a virtual machine by Archie Jaskowicz. NOTE: This runner no longer exists. It may come back in a few months. cfg: - { arch: 'x64', concurrency: 3, os: macos-latest, cpp-version: clang++-14, cmake-flags: ''} - - { arch: 'arm64', concurrency: 2, os: [self-hosted, ARM64, macOS], cpp-version: clang++-15, cmake-flags: ''} +# - { arch: 'arm64', concurrency: 2, os: [self-hosted, ARM64, macOS], cpp-version: clang++-15, cmake-flags: ''} steps: - name: Harden Runner uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1 From 1edf81621ae8b7bd435c258b80be864a2c7ec8af Mon Sep 17 00:00:00 2001 From: "Craig Edwards (Brain)" Date: Fri, 10 May 2024 13:02:29 +0100 Subject: [PATCH 81/89] FIX: QOL: non fatal utf8 handling. (#1147) --- doxygen-awesome-css | 2 +- include/dpp/cluster_sync_calls.h | 64 ++++++++++++++++++++++++++++++++ include/dpp/json_interface.h | 4 +- include/dpp/nlohmann/json.hpp | 2 +- src/dpp/auditlog.cpp | 4 +- src/dpp/cluster.cpp | 2 +- src/dpp/cluster/appcommand.cpp | 8 ++-- src/dpp/cluster/channel.cpp | 8 ++-- src/dpp/cluster/confirmation.cpp | 61 ++++++++++++++++-------------- src/dpp/cluster/dm.cpp | 4 +- src/dpp/cluster/guild.cpp | 8 ++-- src/dpp/cluster/guild_member.cpp | 8 ++-- src/dpp/cluster/message.cpp | 4 +- src/dpp/cluster/role.cpp | 4 +- src/dpp/cluster/template.cpp | 6 +-- src/dpp/cluster/thread.cpp | 6 +-- src/dpp/cluster/user.cpp | 6 +-- src/dpp/cluster/webhook.cpp | 4 +- src/dpp/cluster_sync_calls.cpp | 16 ++++++++ src/dpp/discordclient.cpp | 2 +- src/dpp/discordevents.cpp | 2 +- src/dpp/discordvoiceclient.cpp | 10 ++--- src/dpp/guild.cpp | 2 +- src/dpp/integration.cpp | 2 +- src/dpp/message.cpp | 7 +++- src/dpp/role.cpp | 7 +++- src/unittest/test.cpp | 9 +++++ src/unittest/test.h | 1 + 28 files changed, 184 insertions(+), 79 deletions(-) diff --git a/doxygen-awesome-css b/doxygen-awesome-css index 9f97817e70..5b27b3a747 160000 --- a/doxygen-awesome-css +++ b/doxygen-awesome-css @@ -1 +1 @@ -Subproject commit 9f97817e703aa2c15503067b2a72c97f9d37f46e +Subproject commit 5b27b3a747ca1e559fa54149762cca0bad6036fb diff --git a/include/dpp/cluster_sync_calls.h b/include/dpp/cluster_sync_calls.h index 505c80029d..e2844018e0 100644 --- a/include/dpp/cluster_sync_calls.h +++ b/include/dpp/cluster_sync_calls.h @@ -1984,6 +1984,70 @@ message_map messages_get_sync(snowflake channel_id, snowflake around, snowflake */ confirmation message_unpin_sync(snowflake channel_id, snowflake message_id); +/** + * @brief Get a list of users that voted for this specific answer. + * + * @param m Message that contains the poll to retrieve the answers from + * @param answer_id ID of the answer to retrieve votes from (see poll_answer::answer_id) + * @param after Users after this ID should be retrieved if this is set to non-zero + * @param limit This number of users maximum should be returned, up to 100 + * @return user_map returned object on completion + * @see dpp::cluster::poll_get_answer_voters + * @see https://discord.com/developers/docs/resources/poll#get-answer-voters + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +user_map poll_get_answer_voters_sync(const message& m, uint32_t answer_id, snowflake after, uint64_t limit); + +/** + * @brief Get a list of users that voted for this specific answer. + * + * @param message_id ID of the message with the poll to retrieve the answers from + * @param channel_id ID of the channel with the poll to retrieve the answers from + * @param answer_id ID of the answer to retrieve votes from (see poll_answer::answer_id) + * @param after Users after this ID should be retrieved if this is set to non-zero + * @param limit This number of users maximum should be returned, up to 100 + * @return user_map returned object on completion + * @see dpp::cluster::poll_get_answer_voters + * @see https://discord.com/developers/docs/resources/poll#get-answer-voters + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +user_map poll_get_answer_voters_sync(snowflake message_id, snowflake channel_id, uint32_t answer_id, snowflake after, uint64_t limit); + +/** + * @brief Immediately end a poll. + * + * @param m Message that contains the poll + * @return message returned object on completion + * @see dpp::cluster::poll_end + * @see https://discord.com/developers/docs/resources/poll#end-poll + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +message poll_end_sync(const message &m); + +/** + * @brief Immediately end a poll. + * + * @param message_id ID of the message with the poll to end + * @param channel_id ID of the channel with the poll to end + * @return message returned object on completion + * @see dpp::cluster::poll_end + * @see https://discord.com/developers/docs/resources/poll#end-poll + * \memberof dpp::cluster + * @throw dpp::rest_exception upon failure to execute REST function + * @warning This function is a blocking (synchronous) call and should only be used from within a separate thread. + * Avoid direct use of this function inside an event handler. + */ +message poll_end_sync(snowflake message_id, snowflake channel_id); + /** * @brief Get a channel's pins * @see dpp::cluster::channel_pins_get diff --git a/include/dpp/json_interface.h b/include/dpp/json_interface.h index 08d1d0db50..0fd209ed00 100644 --- a/include/dpp/json_interface.h +++ b/include/dpp/json_interface.h @@ -21,7 +21,7 @@ #pragma once #include -#include +#include namespace dpp { @@ -66,7 +66,7 @@ struct json_interface { */ template ().to_json_impl(bool{}))> std::string build_json(bool with_id = false) const { - return to_json(with_id).dump(); + return to_json(with_id).dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } }; diff --git a/include/dpp/nlohmann/json.hpp b/include/dpp/nlohmann/json.hpp index 4d1a37ad7c..6f018a033b 100644 --- a/include/dpp/nlohmann/json.hpp +++ b/include/dpp/nlohmann/json.hpp @@ -24300,7 +24300,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) { - return j.dump(); + return j.dump(-1, ' ', false, json::error_handler_t::ignore); } inline namespace literals diff --git a/src/dpp/auditlog.cpp b/src/dpp/auditlog.cpp index c1480938f1..9abc95f121 100644 --- a/src/dpp/auditlog.cpp +++ b/src/dpp/auditlog.cpp @@ -42,10 +42,10 @@ audit_entry &audit_entry::fill_from_json_impl(nlohmann::json *j) { audit_change ac; ac.key = string_not_null(&change, "key"); if (change.find("new_value") != change.end()) { - ac.new_value = change["new_value"].dump(); + ac.new_value = change["new_value"].dump(-1, ' ', false, json::error_handler_t::replace); } if (change.find("old_value") != change.end()) { - ac.old_value = change["old_value"].dump(); + ac.old_value = change["old_value"].dump(-1, ' ', false, json::error_handler_t::replace); } this->changes.push_back(ac); } diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index 6966e70bb0..96b9d56421 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -317,7 +317,7 @@ json error_response(const std::string& message, http_request_completion_t& rv) }}, {"message", message} }); - rv.body = j.dump(); + rv.body = j.dump(-1, ' ', false, json::error_handler_t::replace); return j; } diff --git a/src/dpp/cluster/appcommand.cpp b/src/dpp/cluster/appcommand.cpp index 15a2bb1416..80c3308447 100644 --- a/src/dpp/cluster/appcommand.cpp +++ b/src/dpp/cluster/appcommand.cpp @@ -28,7 +28,7 @@ void cluster::global_bulk_command_create(const std::vector &comman for (auto & s : commands) { j.push_back(s.to_json(false)); } - rest_request_list(this, API_PATH "/applications", std::to_string(commands.size() > 0 && commands[0].application_id ? commands[0].application_id : me.id), "commands", m_put, j.dump(), callback); + rest_request_list(this, API_PATH "/applications", std::to_string(commands.size() > 0 && commands[0].application_id ? commands[0].application_id : me.id), "commands", m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::global_bulk_command_delete(command_completion_event_t callback) { @@ -60,7 +60,7 @@ void cluster::guild_bulk_command_create(const std::vector &command for (auto & s : commands) { j.push_back(s.to_json(false)); } - rest_request_list(this, API_PATH "/applications", std::to_string(commands.size() > 0 && commands[0].application_id ? commands[0].application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands", m_put, j.dump(), callback); + rest_request_list(this, API_PATH "/applications", std::to_string(commands.size() > 0 && commands[0].application_id ? commands[0].application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands", m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::guild_bulk_command_delete(snowflake guild_id, command_completion_event_t callback) { @@ -85,7 +85,7 @@ void cluster::guild_bulk_command_edit_permissions(const std::vector(this, API_PATH "/applications", std::to_string(me.id), "guilds/" + std::to_string(guild_id) + "/commands/permissions", m_put, j.dump(), callback); + rest_request_list(this, API_PATH "/applications", std::to_string(me.id), "guilds/" + std::to_string(guild_id) + "/commands/permissions", m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::guild_command_create(const slashcommand &s, snowflake guild_id, command_completion_event_t callback) { @@ -116,7 +116,7 @@ void cluster::guild_command_edit_permissions(const slashcommand &s, snowflake gu j["permissions"].push_back(jperm); } } - rest_request(this, API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands/" + std::to_string(s.id) + "/permissions", m_put, j.dump(), callback); + rest_request(this, API_PATH "/applications", std::to_string(s.application_id ? s.application_id : me.id), "guilds/" + std::to_string(guild_id) + "/commands/" + std::to_string(s.id) + "/permissions", m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::guild_command_get(snowflake id, snowflake guild_id, command_completion_event_t callback) { diff --git a/src/dpp/cluster/channel.cpp b/src/dpp/cluster/channel.cpp index 388547f034..496169c11c 100644 --- a/src/dpp/cluster/channel.cpp +++ b/src/dpp/cluster/channel.cpp @@ -43,7 +43,7 @@ void cluster::channel_edit_permissions(const class channel &c, const snowflake o void cluster::channel_edit_permissions(const snowflake channel_id, const snowflake overwrite_id, const uint64_t allow, const uint64_t deny, const bool member, command_completion_event_t callback) { json j({ {"allow", std::to_string(allow)}, {"deny", std::to_string(deny)}, {"type", member ? 1 : 0} }); - rest_request(this, API_PATH "/channels", std::to_string(channel_id), "permissions/" + std::to_string(overwrite_id), m_put, j.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "permissions/" + std::to_string(overwrite_id), m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::channel_edit_positions(const std::vector &c, command_completion_event_t callback) { @@ -61,7 +61,7 @@ void cluster::channel_edit_positions(const std::vector &c, command_comp } j.push_back(cj); } - rest_request(this, API_PATH "/guilds", std::to_string(c[0].guild_id), "channels/" + std::to_string(c[0].id), m_patch, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(c[0].guild_id), "channels/" + std::to_string(c[0].id), m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::channel_edit(const class channel &c, command_completion_event_t callback) { @@ -70,7 +70,7 @@ void cluster::channel_edit(const class channel &c, command_completion_event_t ca void cluster::channel_follow_news(const class channel &c, snowflake target_channel_id, command_completion_event_t callback) { json j({ {"webhook_channel_id", target_channel_id} }); - rest_request(this, API_PATH "/channels", std::to_string(c.id), "followers", m_post, j.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(c.id), "followers", m_post, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::channel_get(snowflake c, command_completion_event_t callback) { @@ -100,7 +100,7 @@ void cluster::channels_get(snowflake guild_id, command_completion_event_t callba void cluster::channel_set_voice_status(snowflake channel_id, const std::string& status, command_completion_event_t callback) { json j({ {"status", status} }); - rest_request(this, API_PATH "/channels", std::to_string(channel_id), "voice-status", m_put, j.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "voice-status", m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } } // namespace dpp diff --git a/src/dpp/cluster/confirmation.cpp b/src/dpp/cluster/confirmation.cpp index 0589705752..07072ccaf2 100644 --- a/src/dpp/cluster/confirmation.cpp +++ b/src/dpp/cluster/confirmation.cpp @@ -121,39 +121,44 @@ std::vector find_errors_in_object(const std::string& obj, const st error_info confirmation_callback_t::get_error() const { if (is_error()) { - json j = json::parse(this->http_info.body); - error_info e; - - set_int32_not_null(&j, "code", e.code); - set_string_not_null(&j, "message", e.message); - json& errors = j["errors"]; - for (auto obj = errors.begin(); obj != errors.end(); ++obj) { - std::vector sub_errors; - std::string field = isdigit(*obj.key().c_str()) ? "[" + obj.key() + "]" : obj.key(); - - sub_errors = find_errors_in_object({}, field, *obj); - - if (!sub_errors.empty()) { - e.errors.reserve(e.errors.capacity() + sub_errors.size()); - std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors)); + try { + json j = json::parse(this->http_info.body); + error_info e; + + set_int32_not_null(&j, "code", e.code); + set_string_not_null(&j, "message", e.message); + json &errors = j["errors"]; + for (auto obj = errors.begin(); obj != errors.end(); ++obj) { + std::vector sub_errors; + std::string field = isdigit(*obj.key().c_str()) ? "[" + obj.key() + "]" : obj.key(); + + sub_errors = find_errors_in_object({}, field, *obj); + + if (!sub_errors.empty()) { + e.errors.reserve(e.errors.capacity() + sub_errors.size()); + std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors)); + } } - } - e.human_readable = std::to_string(e.code) + ": " + e.message; - std::string prefix = e.errors.size() == 1 ? " " : "\n\t"; - for (const auto& error : e.errors) { - if (error.object.empty()) { - /* A singular field with an error in an unnamed object */ - e.human_readable += prefix + "- " + error.field + ": " + error.reason + " (" + error.code + ")"; - } else { - /* An object field that caused an error */ - e.human_readable += prefix + "- " + error.object + '.' + error.field + ": " + error.reason + " (" + error.code + ")"; + e.human_readable = std::to_string(e.code) + ": " + e.message; + std::string prefix = e.errors.size() == 1 ? " " : "\n\t"; + for (const auto &error: e.errors) { + if (error.object.empty()) { + /* A singular field with an error in an unnamed object */ + e.human_readable += prefix + "- " + error.field + ": " + error.reason + " (" + error.code + ")"; + } else { + /* An object field that caused an error */ + e.human_readable += prefix + "- " + error.object + '.' + error.field + ": " + error.reason + " (" + error.code + ")"; + } } - } - return e; + return e; + } + catch (const std::exception &e) { + return {}; + } } - return error_info(); + return {}; } } // namespace dpp diff --git a/src/dpp/cluster/dm.cpp b/src/dpp/cluster/dm.cpp index 48a381c9d6..cba8af9654 100644 --- a/src/dpp/cluster/dm.cpp +++ b/src/dpp/cluster/dm.cpp @@ -23,7 +23,7 @@ namespace dpp { void cluster::create_dm_channel(snowflake user_id, command_completion_event_t callback) { - rest_request(this, API_PATH "/users", "@me", "channels", m_post, json({{"recipient_id", std::to_string(user_id)}}).dump(), callback); + rest_request(this, API_PATH "/users", "@me", "channels", m_post, json({{"recipient_id", std::to_string(user_id)}}).dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::current_user_get_dms(command_completion_event_t callback) { @@ -56,7 +56,7 @@ void cluster::gdm_add(snowflake channel_id, snowflake user_id, const std::string json params; params["access_token"] = access_token; params["nick"] = nick; - rest_request(this, API_PATH "/channels", std::to_string(channel_id), "recipients/" + std::to_string(user_id), m_put, params.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "recipients/" + std::to_string(user_id), m_put, params.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::gdm_remove(snowflake channel_id, snowflake user_id, command_completion_event_t callback) { diff --git a/src/dpp/cluster/guild.cpp b/src/dpp/cluster/guild.cpp index 87f73371c4..bf58372f69 100644 --- a/src/dpp/cluster/guild.cpp +++ b/src/dpp/cluster/guild.cpp @@ -24,7 +24,7 @@ namespace dpp { void cluster::guild_current_member_edit(snowflake guild_id, const std::string &nickname, command_completion_event_t callback) { - std::string o = (nickname.empty() ? json({{"nick", json::value_t::null }}) : json({{"nick", nickname }})).dump(); + std::string o = (nickname.empty() ? json({{"nick", json::value_t::null }}) : json({{"nick", nickname }})).dump(-1, ' ', false, json::error_handler_t::replace); rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/@me", m_patch, o, callback); } @@ -52,7 +52,7 @@ void cluster::guild_ban_add(snowflake guild_id, snowflake user_id, uint32_t dele } } } - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "bans/" + std::to_string(user_id), m_put, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "bans/" + std::to_string(user_id), m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } @@ -140,7 +140,7 @@ void cluster::guild_begin_prune(snowflake guild_id, const struct prune& pruneinf void cluster::guild_set_nickname(snowflake guild_id, const std::string &nickname, command_completion_event_t callback) { - std::string o = (nickname.empty() ? json({{"nick", json::value_t::null }}) : json({{"nick", nickname }})).dump(); + std::string o = (nickname.empty() ? json({{"nick", json::value_t::null }}) : json({{"nick", nickname }})).dump(-1, ' ', false, json::error_handler_t::replace); rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/@me/nick", m_patch, o, callback); } @@ -165,7 +165,7 @@ void cluster::guild_get_welcome_screen(snowflake guild_id, command_completion_ev void cluster::guild_edit_welcome_screen(snowflake guild_id, const struct welcome_screen& welcome_screen, bool enabled, command_completion_event_t callback) { json j = welcome_screen.to_json(); j["enabled"] = enabled; - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "welcome-screen", m_patch, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "welcome-screen", m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } diff --git a/src/dpp/cluster/guild_member.cpp b/src/dpp/cluster/guild_member.cpp index 5921d5a2b1..28e3b953b0 100644 --- a/src/dpp/cluster/guild_member.cpp +++ b/src/dpp/cluster/guild_member.cpp @@ -25,7 +25,7 @@ namespace dpp { void cluster::guild_add_member(const guild_member& gm, const std::string &access_token, command_completion_event_t callback) { json j = gm.to_json(); j["access_token"] = access_token; - rest_request(this, API_PATH "/guilds", std::to_string(gm.guild_id), "members/" + std::to_string(gm.user_id), m_put, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(gm.guild_id), "members/" + std::to_string(gm.user_id), m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } @@ -93,13 +93,13 @@ void cluster::guild_member_timeout(snowflake guild_id, snowflake user_id, time_t j["communication_disabled_until"] = json::value_t::null; } - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::guild_member_timeout_remove(snowflake guild_id, snowflake user_id, command_completion_event_t callback) { json j; j["communication_disabled_until"] = json::value_t::null; - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } @@ -122,7 +122,7 @@ void cluster::guild_member_move(const snowflake channel_id, const snowflake guil j["channel_id"] = json::value_t::null; } - this->post_rest(API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(), [this, guild_id, user_id, callback](json &j, const http_request_completion_t& http) { + this->post_rest(API_PATH "/guilds", std::to_string(guild_id), "members/" + std::to_string(user_id), m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), [this, guild_id, user_id, callback](json &j, const http_request_completion_t& http) { if (callback) { callback(confirmation_callback_t(this, guild_member().fill_from_json(&j, guild_id, user_id), http)); } diff --git a/src/dpp/cluster/message.cpp b/src/dpp/cluster/message.cpp index 824060c3e0..e1d4943b59 100644 --- a/src/dpp/cluster/message.cpp +++ b/src/dpp/cluster/message.cpp @@ -66,7 +66,7 @@ void cluster::message_delete_bulk(const std::vector& message_ids, sno for (auto & m : message_ids) { j["messages"].push_back(std::to_string(m)); } - rest_request(this, API_PATH "/channels", std::to_string(channel_id), "messages/bulk-delete", m_post, j.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "messages/bulk-delete", m_post, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } @@ -122,7 +122,7 @@ void cluster::message_edit(const message &m, command_completion_event_t callback void cluster::message_edit_flags(const message &m, command_completion_event_t callback) { this->post_rest_multipart(API_PATH "/channels", std::to_string(m.channel_id), "messages/" + std::to_string(m.id), m_patch, nlohmann::json{ {"flags", m.flags}, - }.dump(), [this, callback](json &j, const http_request_completion_t& http) { + }.dump(-1, ' ', false, json::error_handler_t::replace), [this, callback](json &j, const http_request_completion_t& http) { if (callback) { callback(confirmation_callback_t(this, message(this).fill_from_json(&j), http)); } diff --git a/src/dpp/cluster/role.cpp b/src/dpp/cluster/role.cpp index 1ff58bbf1d..2a2065a8f2 100644 --- a/src/dpp/cluster/role.cpp +++ b/src/dpp/cluster/role.cpp @@ -43,7 +43,7 @@ void cluster::roles_edit_position(snowflake guild_id, const std::vector &r for (auto & r : roles) { j.push_back({ {"id", r.id}, {"position", r.position} }); } - rest_request_list(this, API_PATH "/guilds", std::to_string(guild_id), "roles", m_patch, j.dump(), callback); + rest_request_list(this, API_PATH "/guilds", std::to_string(guild_id), "roles", m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::roles_get(snowflake guild_id, command_completion_event_t callback) { @@ -59,7 +59,7 @@ void cluster::application_role_connection_update(snowflake application_id, const for (const auto &conn_metadata : connection_metadata) { j.push_back(conn_metadata.to_json()); } - rest_request_vector(this, API_PATH "/applications", std::to_string(application_id), "role-connections/metadata", m_put, j.dump(), callback); + rest_request_vector(this, API_PATH "/applications", std::to_string(application_id), "role-connections/metadata", m_put, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::user_application_role_connection_get(snowflake application_id, command_completion_event_t callback) { diff --git a/src/dpp/cluster/template.cpp b/src/dpp/cluster/template.cpp index edda3b3536..f0503ff83f 100644 --- a/src/dpp/cluster/template.cpp +++ b/src/dpp/cluster/template.cpp @@ -25,13 +25,13 @@ namespace dpp { void cluster::guild_create_from_template(const std::string &code, const std::string &name, command_completion_event_t callback) { json params({{"name", name}}); - rest_request(this, API_PATH "/guilds", "templates", code, m_post, params.dump(), callback); + rest_request(this, API_PATH "/guilds", "templates", code, m_post, params.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::guild_template_create(snowflake guild_id, const std::string &name, const std::string &description, command_completion_event_t callback) { json params({{"name", name}, {"description", description}}); - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "templates", m_post, params.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "templates", m_post, params.dump(-1, ' ', false, json::error_handler_t::replace), callback); } @@ -42,7 +42,7 @@ void cluster::guild_template_delete(snowflake guild_id, const std::string &code, void cluster::guild_template_modify(snowflake guild_id, const std::string &code, const std::string &name, const std::string &description, command_completion_event_t callback) { json params({{"name", name}, {"description", description}}); - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "templates/" + code, m_patch, params.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "templates/" + code, m_patch, params.dump(-1, ' ', false, json::error_handler_t::replace), callback); } diff --git a/src/dpp/cluster/thread.cpp b/src/dpp/cluster/thread.cpp index 45b500e961..b3c109406e 100644 --- a/src/dpp/cluster/thread.cpp +++ b/src/dpp/cluster/thread.cpp @@ -138,7 +138,7 @@ void cluster::thread_create_in_forum(const std::string& thread_name, snowflake c break; } - this->post_rest_multipart(API_PATH "/channels", std::to_string(channel_id), "threads", m_post, j.dump(), [this, callback](json &j, const http_request_completion_t& http) { + this->post_rest_multipart(API_PATH "/channels", std::to_string(channel_id), "threads", m_post, j.dump(-1, ' ', false, json::error_handler_t::replace), [this, callback](json &j, const http_request_completion_t& http) { if (callback) { auto t = thread().fill_from_json(&j); confirmation_callback_t e(this, confirmation(), http); @@ -161,7 +161,7 @@ void cluster::thread_create(const std::string& thread_name, snowflake channel_id {"invitable", invitable}, {"rate_limit_per_user", rate_limit_per_user} }); - rest_request(this, API_PATH "/channels", std::to_string(channel_id), "threads", m_post, j.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "threads", m_post, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::thread_edit(const thread &t, command_completion_event_t callback) @@ -176,7 +176,7 @@ void cluster::thread_create_with_message(const std::string& thread_name, snowfla {"auto_archive_duration", auto_archive_duration}, {"rate_limit_per_user", rate_limit_per_user} }); - rest_request(this, API_PATH "/channels", std::to_string(channel_id), "messages/" + std::to_string(message_id) + "/threads", m_post, j.dump(), callback); + rest_request(this, API_PATH "/channels", std::to_string(channel_id), "messages/" + std::to_string(message_id) + "/threads", m_post, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::thread_member_add(snowflake thread_id, snowflake user_id, command_completion_event_t callback) { diff --git a/src/dpp/cluster/user.cpp b/src/dpp/cluster/user.cpp index a430f18a10..b3cf763bb8 100644 --- a/src/dpp/cluster/user.cpp +++ b/src/dpp/cluster/user.cpp @@ -41,7 +41,7 @@ void cluster::current_user_edit(const std::string &nickname, const std::string& } j["avatar"] = "data:" + mimetypes.find(type)->second + ";base64," + base64_encode((unsigned char const*)image_blob.data(), (unsigned int)image_blob.length()); } - rest_request(this, API_PATH "/users", "@me", "", m_patch, j.dump(), callback); + rest_request(this, API_PATH "/users", "@me", "", m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::current_application_get(command_completion_event_t callback) { @@ -65,7 +65,7 @@ void cluster::current_user_set_voice_state(snowflake guild_id, snowflake channel } else { j["request_to_speak_timestamp"] = json::value_t::null; } - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "/voice-states/@me", m_patch, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "/voice-states/@me", m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::user_set_voice_state(snowflake user_id, snowflake guild_id, snowflake channel_id, bool suppress, command_completion_event_t callback) { @@ -73,7 +73,7 @@ void cluster::user_set_voice_state(snowflake user_id, snowflake guild_id, snowfl {"channel_id", channel_id}, {"suppress", suppress} }); - rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "/voice-states/" + std::to_string(user_id), m_patch, j.dump(), callback); + rest_request(this, API_PATH "/guilds", std::to_string(guild_id), "/voice-states/" + std::to_string(user_id), m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::current_user_connections_get(command_completion_event_t callback) { diff --git a/src/dpp/cluster/webhook.cpp b/src/dpp/cluster/webhook.cpp index 52b895c77c..5231d19e40 100644 --- a/src/dpp/cluster/webhook.cpp +++ b/src/dpp/cluster/webhook.cpp @@ -63,7 +63,7 @@ void cluster::edit_webhook_with_token(const class webhook& wh, command_completio if (jwh.find("channel_id") != jwh.end()) { jwh.erase(jwh.find("channel_id")); } - rest_request(this, API_PATH "/webhooks", std::to_string(wh.id), utility::url_encode(wh.token), m_patch, jwh.dump(), callback); + rest_request(this, API_PATH "/webhooks", std::to_string(wh.id), utility::url_encode(wh.token), m_patch, jwh.dump(-1, ' ', false, json::error_handler_t::replace), callback); } void cluster::execute_webhook(const class webhook &wh, const struct message& m, bool wait, snowflake thread_id, const std::string& thread_name, command_completion_event_t callback) { @@ -83,7 +83,7 @@ void cluster::execute_webhook(const class webhook &wh, const struct message& m, if (!wh.name.empty()) { j["username"] = wh.name; } - body = j.dump(); + body = j.dump(-1, ' ', false, json::error_handler_t::replace); } this->post_rest_multipart(API_PATH "/webhooks", std::to_string(wh.id), utility::url_encode(!wh.token.empty() ? wh.token : token) + parameters, m_post, !body.empty() ? body : m.build_json(false), [this, callback](json &j, const http_request_completion_t& http) { diff --git a/src/dpp/cluster_sync_calls.cpp b/src/dpp/cluster_sync_calls.cpp index 3dc14c2201..368c8b8744 100644 --- a/src/dpp/cluster_sync_calls.cpp +++ b/src/dpp/cluster_sync_calls.cpp @@ -529,6 +529,22 @@ confirmation cluster::message_unpin_sync(snowflake channel_id, snowflake message return dpp::sync(this, static_cast(&cluster::message_unpin), channel_id, message_id); } +user_map cluster::poll_get_answer_voters_sync(const message& m, uint32_t answer_id, snowflake after, uint64_t limit) { + return dpp::sync(this, static_cast(&cluster::poll_get_answer_voters), m, answer_id, after, limit); +} + +user_map cluster::poll_get_answer_voters_sync(snowflake message_id, snowflake channel_id, uint32_t answer_id, snowflake after, uint64_t limit) { + return dpp::sync(this, static_cast(&cluster::poll_get_answer_voters), message_id, channel_id, answer_id, after, limit); +} + +message cluster::poll_end_sync(const message &m) { + return dpp::sync(this, static_cast(&cluster::poll_end), m); +} + +message cluster::poll_end_sync(snowflake message_id, snowflake channel_id) { + return dpp::sync(this, static_cast(&cluster::poll_end), message_id, channel_id); +} + message_map cluster::channel_pins_get_sync(snowflake channel_id) { return dpp::sync(this, static_cast(&cluster::channel_pins_get), channel_id); } diff --git a/src/dpp/discordclient.cpp b/src/dpp/discordclient.cpp index c1ba3a2a9c..401d9cd610 100644 --- a/src/dpp/discordclient.cpp +++ b/src/dpp/discordclient.cpp @@ -638,7 +638,7 @@ discord_client& discord_client::connect_voice(snowflake guild_id, snowflake chan std::string discord_client::jsonobj_to_string(const nlohmann::json& json) { if (protocol == ws_json) { - return json.dump(); + return json.dump(-1, ' ', false, json::error_handler_t::replace); } else { return etf->build(json); } diff --git a/src/dpp/discordevents.cpp b/src/dpp/discordevents.cpp index bdaa51afe4..d8ae63cded 100644 --- a/src/dpp/discordevents.cpp +++ b/src/dpp/discordevents.cpp @@ -431,7 +431,7 @@ void discord_client::handle_event(const std::string &event, json &j, const std:: ev_iter->second->handle(this, j, raw); } } else { - log(dpp::ll_debug, "Unhandled event: " + event + ", " + j.dump()); + log(dpp::ll_debug, "Unhandled event: " + event + ", " + j.dump(-1, ' ', false, json::error_handler_t::replace)); } } diff --git a/src/dpp/discordvoiceclient.cpp b/src/dpp/discordvoiceclient.cpp index 8727992a1c..88932cca32 100644 --- a/src/dpp/discordvoiceclient.cpp +++ b/src/dpp/discordvoiceclient.cpp @@ -550,7 +550,7 @@ bool discord_voice_client::handle_frame(const std::string &data) } } }; - this->write(obj.dump()); + this->write(obj.dump(-1, ' ', false, json::error_handler_t::replace)); } else { log(dpp::ll_debug, "Connecting new voice session..."); json obj = { @@ -565,7 +565,7 @@ bool discord_voice_client::handle_frame(const std::string &data) } } }; - this->write(obj.dump()); + this->write(obj.dump(-1, ' ', false, json::error_handler_t::replace)); } this->connect_time = time(nullptr); } @@ -655,7 +655,7 @@ bool discord_voice_client::handle_frame(const std::string &data) } } } - }).dump()); + }).dump(-1, ' ', false, json::error_handler_t::replace)); } } break; @@ -1084,7 +1084,7 @@ void discord_voice_client::one_second_timer() if (this->heartbeat_interval) { /* Check if we're due to emit a heartbeat */ if (time(nullptr) > last_heartbeat + ((heartbeat_interval / 1000.0) * 0.75)) { - queue_message(json({{"op", 3}, {"d", rand()}}).dump(), true); + queue_message(json({{"op", 3}, {"d", rand()}}).dump(-1, ' ', false, json::error_handler_t::replace), true); last_heartbeat = time(nullptr); } } @@ -1307,7 +1307,7 @@ discord_voice_client& discord_voice_client::speak() { {"delay", 0}, {"ssrc", ssrc} }} - }).dump(), true); + }).dump(-1, ' ', false, json::error_handler_t::replace), true); sending = true; } return *this; diff --git a/src/dpp/guild.cpp b/src/dpp/guild.cpp index 236e05869d..2e0729e7b2 100644 --- a/src/dpp/guild.cpp +++ b/src/dpp/guild.cpp @@ -781,7 +781,7 @@ guild_widget& guild_widget::fill_from_json_impl(nlohmann::json* j) { } json guild_widget::to_json_impl(bool with_id) const { - return json({{"channel_id", channel_id}, {"enabled", enabled}}).dump(); + return json({{"channel_id", channel_id}, {"enabled", enabled}}).dump(-1, ' ', false, json::error_handler_t::replace); } diff --git a/src/dpp/integration.cpp b/src/dpp/integration.cpp index f17239dd8a..c8e870fde1 100644 --- a/src/dpp/integration.cpp +++ b/src/dpp/integration.cpp @@ -110,7 +110,7 @@ json integration::to_json_impl(bool with_id) const { { "expire_behavior", (flags & if_expire_kick) ? 1 : 0 }, { "expire_grace_period", expire_grace_period }, { "enable_emoticons", emoticons_enabled() } - }).dump(); + }).dump(-1, ' ', false, json::error_handler_t::replace); } bool integration::emoticons_enabled() const { diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index ed7709a413..57ec118b60 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -1497,7 +1497,12 @@ json sticker_pack::to_json_impl(bool with_id) const { j["description"] = description; j["stickers"] = json::array(); for (auto& s : stickers) { - j["stickers"].push_back(json::parse(s.second.build_json(with_id))); + try { + j["stickers"].push_back(json::parse(s.second.build_json(with_id))); + } + catch (const std::exception &e) { + /* Protection against malformed json in sticker */ + } } return j; } diff --git a/src/dpp/role.cpp b/src/dpp/role.cpp index 99e87ffec1..89643f210f 100644 --- a/src/dpp/role.cpp +++ b/src/dpp/role.cpp @@ -474,7 +474,12 @@ json application_role_connection::to_json_impl(bool with_id) const { j["platform_username"] = platform_username; } if (std::holds_alternative(metadata)) { - j["metadata"] = json::parse(std::get(metadata).build_json()); + try { + j["metadata"] = json::parse(std::get(metadata).build_json()); + } + catch (const std::exception &e) { + /* Protection against malformed json in metadata */ + } } return j; } diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index 1d12d64d28..369e417f40 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -957,6 +957,15 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b } }); + if (!offline) { + start_test(INVALIDUTF8); + bot.message_create(dpp::message(TEST_TEXT_CHANNEL_ID, "ä\xA9ü"), [](const auto &cc) { + set_status(INVALIDUTF8, ts_success); + }); + } else { + set_status(INVALIDUTF8, ts_skipped); + } + dpp::utility::iconhash i; std::string dummyval("fcffffffffffff55acaaaaaaaaaaaa66"); i = dummyval; diff --git a/src/unittest/test.h b/src/unittest/test.h index 51a707a06e..cb34b207da 100644 --- a/src/unittest/test.h +++ b/src/unittest/test.h @@ -149,6 +149,7 @@ DPP_TEST(FORUM_CREATION, "create a forum channel", tf_online); DPP_TEST(FORUM_CHANNEL_GET, "retrieve the created forum channel", tf_online); DPP_TEST(FORUM_CHANNEL_DELETE, "delete the created forum channel", tf_online); DPP_TEST(ERRORS, "Human readable error translation", tf_offline); +DPP_TEST(INVALIDUTF8, "Invalid UTF-8 handling", tf_online); DPP_TEST(GUILD_EDIT, "cluster::guild_edit", tf_online); DPP_TEST(GUILD_BAN_CREATE, "cluster::guild_ban_add ban three deleted discord accounts", tf_online); From b1e9fb1698d523e25e7dcab12f93718c8efe1ea1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 22:18:00 +0100 Subject: [PATCH 82/89] build(deps): bump ubuntu from `71b82b8` to `874aca5` (#1145) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Archie Jaskowicz --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 416d640a81..53ab7031f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:focal@sha256:71b82b8e734f5cd0b3533a16f40ca1271f28d87343972bb4cd6bd6c38f1bd38e +FROM ubuntu:focal@sha256:874aca52f79ae5f8258faff03e10ce99ae836f6e7d2df6ecd3da5c1cad3a912b ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --no-install-recommends -y libssl-dev zlib1g-dev libsodium-dev libopus-dev cmake pkg-config g++ gcc git make && apt-get clean && rm -rf /var/lib/apt/lists/* From fa5d7d56d349fb7dfcc67afaec7496d5bbcf645e Mon Sep 17 00:00:00 2001 From: "Craig Edwards (Brain)" Date: Fri, 10 May 2024 22:33:01 +0100 Subject: [PATCH 83/89] FIX: Silence GUILD_SOUNDBOARD_* websocket events, currently undocumented (#1148) --- src/dpp/discordevents.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dpp/discordevents.cpp b/src/dpp/discordevents.cpp index d8ae63cded..2079be749c 100644 --- a/src/dpp/discordevents.cpp +++ b/src/dpp/discordevents.cpp @@ -403,6 +403,9 @@ static const std::map event_map = { { "EMBEDDED_ACTIVITY_UPDATE", nullptr }, { "GUILD_APPLICATION_COMMAND_INDEX_UPDATE", nullptr }, { "CHANNEL_TOPIC_UPDATE", nullptr }, + { "GUILD_SOUNDBOARD_SOUND_CREATE", nullptr }, + { "GUILD_SOUNDBOARD_SOUND_DELETE", nullptr }, + { "GUILD_SOUNDBOARD_SOUNDS_UPDATE", nullptr }, { "VOICE_CHANNEL_STATUS_UPDATE", nullptr }, { "GUILD_SCHEDULED_EVENT_CREATE", make_static_event() }, { "GUILD_SCHEDULED_EVENT_UPDATE", make_static_event() }, From 52cb596b45f50d6fb76e4a846371b8343a935bd5 Mon Sep 17 00:00:00 2001 From: DPP VCPKG Bot Date: Fri, 10 May 2024 22:39:30 +0000 Subject: [PATCH 84/89] [bot] VCPKG info update [skip ci] --- vcpkg/ports/dpp/portfile.cmake | 2 +- vcpkg/ports/dpp/vcpkg.json | 2 +- vcpkg/versions/baseline.json | 2766 ++++++++++++++++++-------------- vcpkg/versions/d-/dpp.json | 5 + 4 files changed, 1534 insertions(+), 1241 deletions(-) diff --git a/vcpkg/ports/dpp/portfile.cmake b/vcpkg/ports/dpp/portfile.cmake index daddf98ad5..af8d57e936 100644 --- a/vcpkg/ports/dpp/portfile.cmake +++ b/vcpkg/ports/dpp/portfile.cmake @@ -2,7 +2,7 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO brainboxdotcc/DPP REF "v${VERSION}" - SHA512 fcb9b8181827fc63fb2f9aff44e697d18a0bfd94714888492a63a04e0112f42f9506bfab8181e822aa5ce85e6b6a8aa44e0774baeac3e52c3f41348cbf55a76a + SHA512 4842e5e688893275e524f998bdcac1d308165a02c280f69eaa898aa8f9986a97fe687e20e3428f30777c49f1feb47905da462bbdba8c9a5ea00067e560208f91 ) vcpkg_cmake_configure( diff --git a/vcpkg/ports/dpp/vcpkg.json b/vcpkg/ports/dpp/vcpkg.json index 1f7df2cf68..5d21e83d5f 100644 --- a/vcpkg/ports/dpp/vcpkg.json +++ b/vcpkg/ports/dpp/vcpkg.json @@ -1,6 +1,6 @@ { "name": "dpp", - "version": "10.0.29", + "version": "10.0.30", "description": "D++ Extremely Lightweight C++ Discord Library.", "homepage": "https://dpp.dev/", "license": "Apache-2.0", diff --git a/vcpkg/versions/baseline.json b/vcpkg/versions/baseline.json index c3a00e491e..7e91f07b2a 100644 --- a/vcpkg/versions/baseline.json +++ b/vcpkg/versions/baseline.json @@ -6,18 +6,18 @@ }, "7zip": { "baseline": "23.01", - "port-version": 1 + "port-version": 2 }, "ableton": { "baseline": "3.0.6", "port-version": 2 }, "ableton-link": { - "baseline": "3.0.6", - "port-version": 1 + "baseline": "3.1.1", + "port-version": 0 }, "abseil": { - "baseline": "20230802.1", + "baseline": "20240116.2", "port-version": 0 }, "absent": { @@ -25,19 +25,19 @@ "port-version": 3 }, "ace": { - "baseline": "7.1.2", - "port-version": 1 + "baseline": "7.1.4", + "port-version": 0 }, "acl": { "baseline": "2.3.1", - "port-version": 1 + "port-version": 2 }, "activemq-cpp": { "baseline": "3.9.5", "port-version": 15 }, "ada-url": { - "baseline": "2.7.4", + "baseline": "2.7.7", "port-version": 0 }, "ade": { @@ -45,8 +45,8 @@ "port-version": 0 }, "adios2": { - "baseline": "2.8.3", - "port-version": 1 + "baseline": "2.9.2", + "port-version": 0 }, "advobfuscator": { "baseline": "2020-06-26", @@ -61,8 +61,8 @@ "port-version": 1 }, "aklomp-base64": { - "baseline": "2023-01-06", - "port-version": 1 + "baseline": "0.5.1", + "port-version": 0 }, "alac": { "baseline": "2017-11-03-c38887c5", @@ -77,11 +77,11 @@ "port-version": 0 }, "aliyun-oss-c-sdk": { - "baseline": "3.10.0", - "port-version": 3 + "baseline": "3.10.1", + "port-version": 0 }, "allegro5": { - "baseline": "5.2.9.0", + "baseline": "5.2.9.1", "port-version": 0 }, "alpaca": { @@ -89,20 +89,20 @@ "port-version": 0 }, "alpaka": { - "baseline": "1.0.0", + "baseline": "1.1.0", "port-version": 0 }, "alsa": { - "baseline": "1.2.10", - "port-version": 0 + "baseline": "1.2.11", + "port-version": 1 }, "amd-adl-sdk": { "baseline": "17.1", "port-version": 0 }, "amd-amf": { - "baseline": "1.4.29", - "port-version": 0 + "baseline": "1.4.33", + "port-version": 1 }, "ampl-asl": { "baseline": "2020-11-11", @@ -113,7 +113,7 @@ "port-version": 4 }, "amqpcpp": { - "baseline": "4.3.23", + "baseline": "4.3.26", "port-version": 0 }, "anari": { @@ -133,11 +133,11 @@ "port-version": 7 }, "ankurvdev-embedresource": { - "baseline": "0.0.10", + "baseline": "0.0.11", "port-version": 0 }, "annoy": { - "baseline": "1.17.2", + "baseline": "1.17.3", "port-version": 0 }, "antlr4": { @@ -153,15 +153,15 @@ "port-version": 2 }, "aom": { - "baseline": "3.7.0", - "port-version": 0 + "baseline": "3.8.1", + "port-version": 1 }, "apache-datasketches": { - "baseline": "4.1.0", + "baseline": "5.0.2", "port-version": 0 }, "approval-tests-cpp": { - "baseline": "10.12.2", + "baseline": "10.13.0", "port-version": 0 }, "apr": { @@ -172,6 +172,10 @@ "baseline": "1.6.3", "port-version": 0 }, + "apriltag": { + "baseline": "3.4.0", + "port-version": 0 + }, "apsi": { "baseline": "0.11.0", "port-version": 0 @@ -194,7 +198,7 @@ }, "argh": { "baseline": "1.3.2", - "port-version": 0 + "port-version": 1 }, "argon2": { "baseline": "20190702", @@ -221,24 +225,24 @@ "port-version": 0 }, "aricpp": { - "baseline": "1.1.2", + "baseline": "1.1.3", "port-version": 0 }, "armadillo": { - "baseline": "12.4.1", - "port-version": 0 + "baseline": "12.6.6", + "port-version": 1 }, "arpack-ng": { - "baseline": "3.9.0", - "port-version": 1 + "baseline": "3.9.1", + "port-version": 0 }, "arrayfire": { "baseline": "3.8.0", "port-version": 5 }, "arrow": { - "baseline": "14.0.1", - "port-version": 2 + "baseline": "16.0.0", + "port-version": 1 }, "arsenalgear": { "baseline": "2.1.0", @@ -249,13 +253,17 @@ "port-version": 0 }, "asio": { - "baseline": "1.28.2", + "baseline": "1.30.2", "port-version": 0 }, "asio-grpc": { - "baseline": "2.7.0", + "baseline": "3.1.0", "port-version": 0 }, + "asiochan": { + "baseline": "2022-11-25", + "port-version": 1 + }, "asiosdk": { "baseline": "2.3.3", "port-version": 7 @@ -269,13 +277,17 @@ "port-version": 1 }, "assimp": { - "baseline": "5.3.1", - "port-version": 3 + "baseline": "5.4.0", + "port-version": 0 }, "async-mqtt": { - "baseline": "3.0.0", + "baseline": "5.1.1", "port-version": 0 }, + "async-simple": { + "baseline": "1.3", + "port-version": 1 + }, "asynch": { "baseline": "2019-09-21", "port-version": 3 @@ -286,42 +298,46 @@ }, "at-spi2-atk": { "baseline": "2.38.0", - "port-version": 0 + "port-version": 1 }, "at-spi2-core": { "baseline": "2.44.1", - "port-version": 2 + "port-version": 3 }, "atk": { "baseline": "2.38.0", "port-version": 8 }, "atkmm": { - "baseline": "2.36.1", - "port-version": 2 + "baseline": "2.36.3", + "port-version": 0 }, "atl": { "baseline": "0", "port-version": 0 }, + "atliac-minitest": { + "baseline": "1.0.0", + "port-version": 0 + }, "atlmfc": { "baseline": "0", "port-version": 3 }, "atomic-queue": { - "baseline": "2021-05-03", + "baseline": "1.6.3", "port-version": 0 }, "attr": { - "baseline": "2.5.1", - "port-version": 1 + "baseline": "2.5.2", + "port-version": 0 }, "aubio": { "baseline": "2022-01-26", "port-version": 1 }, "audiofile": { - "baseline": "1.1.0", + "baseline": "1.1.1", "port-version": 0 }, "aurora": { @@ -334,10 +350,10 @@ }, "autodock-vina": { "baseline": "1.2.5", - "port-version": 1 + "port-version": 2 }, "avcpp": { - "baseline": "2.1.0", + "baseline": "2.3.0", "port-version": 0 }, "avisynthplus": { @@ -352,60 +368,64 @@ "baseline": "1.11.3", "port-version": 0 }, + "awlib": { + "baseline": "2024-04-06", + "port-version": 0 + }, "aws-c-auth": { - "baseline": "0.7.8", + "baseline": "0.7.16", "port-version": 0 }, "aws-c-cal": { - "baseline": "0.6.9", + "baseline": "0.6.10", "port-version": 0 }, "aws-c-common": { - "baseline": "0.9.10", + "baseline": "0.9.14", "port-version": 0 }, "aws-c-compression": { - "baseline": "0.2.17", + "baseline": "0.2.18", "port-version": 0 }, "aws-c-event-stream": { - "baseline": "0.3.2", + "baseline": "0.4.2", "port-version": 0 }, "aws-c-http": { - "baseline": "0.7.14", + "baseline": "0.8.1", "port-version": 0 }, "aws-c-io": { - "baseline": "0.13.36", + "baseline": "0.14.6", "port-version": 0 }, "aws-c-mqtt": { - "baseline": "0.9.10", + "baseline": "0.10.3", "port-version": 0 }, "aws-c-s3": { - "baseline": "0.4.3", + "baseline": "0.5.4", "port-version": 0 }, "aws-c-sdkutils": { - "baseline": "0.1.12", + "baseline": "0.1.15", "port-version": 0 }, "aws-checksums": { - "baseline": "0.1.17", + "baseline": "0.1.18", "port-version": 0 }, "aws-crt-cpp": { - "baseline": "0.24.8", + "baseline": "0.26.4", "port-version": 0 }, "aws-lambda-cpp": { - "baseline": "0.2.9", + "baseline": "0.2.10", "port-version": 0 }, "aws-sdk-cpp": { - "baseline": "1.11.215", + "baseline": "1.11.285", "port-version": 1 }, "azmq": { @@ -413,32 +433,36 @@ "port-version": 0 }, "azure-c-shared-utility": { - "baseline": "2023-08-07", - "port-version": 0 + "baseline": "2024-03-04", + "port-version": 1 }, "azure-core-amqp-cpp": { - "baseline": "1.0.0-beta.5", + "baseline": "1.0.0-beta.9", "port-version": 0 }, "azure-core-cpp": { - "baseline": "1.10.3", - "port-version": 2 + "baseline": "1.12.0", + "port-version": 0 }, "azure-core-tracing-opentelemetry-cpp": { "baseline": "1.0.0-beta.4", - "port-version": 1 + "port-version": 3 + }, + "azure-data-tables-cpp": { + "baseline": "1.0.0-beta.2", + "port-version": 0 }, "azure-identity-cpp": { "baseline": "1.6.0", - "port-version": 0 + "port-version": 1 }, "azure-iot-sdk-c": { - "baseline": "2023-08-07", + "baseline": "2024-03-04", "port-version": 0 }, "azure-kinect-sensor-sdk": { "baseline": "1.4.1", - "port-version": 5 + "port-version": 6 }, "azure-macro-utils-c": { "baseline": "2022-01-21", @@ -446,39 +470,39 @@ }, "azure-messaging-eventhubs-checkpointstore-blob-cpp": { "baseline": "1.0.0-beta.1", - "port-version": 0 + "port-version": 2 }, "azure-messaging-eventhubs-cpp": { - "baseline": "1.0.0-beta.4", + "baseline": "1.0.0-beta.8", "port-version": 0 }, "azure-security-attestation-cpp": { "baseline": "1.1.0", - "port-version": 1 + "port-version": 3 }, "azure-security-keyvault-administration-cpp": { - "baseline": "4.0.0-beta.3", + "baseline": "4.0.0-beta.4", "port-version": 1 }, "azure-security-keyvault-certificates-cpp": { - "baseline": "4.2.0", + "baseline": "4.2.1", "port-version": 1 }, "azure-security-keyvault-keys-cpp": { - "baseline": "4.4.0", + "baseline": "4.4.1", "port-version": 1 }, "azure-security-keyvault-secrets-cpp": { - "baseline": "4.2.0", + "baseline": "4.2.1", "port-version": 1 }, "azure-storage-blobs-cpp": { "baseline": "12.10.0", - "port-version": 0 + "port-version": 1 }, "azure-storage-common-cpp": { "baseline": "12.5.0", - "port-version": 0 + "port-version": 1 }, "azure-storage-cpp": { "baseline": "7.5.0", @@ -486,26 +510,26 @@ }, "azure-storage-files-datalake-cpp": { "baseline": "12.9.0", - "port-version": 0 + "port-version": 1 }, "azure-storage-files-shares-cpp": { "baseline": "12.8.0", - "port-version": 0 + "port-version": 1 }, "azure-storage-queues-cpp": { "baseline": "12.2.0", - "port-version": 0 + "port-version": 1 }, "azure-uamqp-c": { - "baseline": "2023-08-07", + "baseline": "2024-03-04", "port-version": 0 }, "azure-uhttp-c": { - "baseline": "2023-08-07", + "baseline": "2024-03-04", "port-version": 0 }, "azure-umqtt-c": { - "baseline": "2023-08-03", + "baseline": "2024-03-04", "port-version": 0 }, "b64": { @@ -513,11 +537,11 @@ "port-version": 2 }, "backward-cpp": { - "baseline": "1.6", + "baseline": "2023-11-24", "port-version": 1 }, "baresip-libre": { - "baseline": "3.7.0", + "baseline": "3.11.0", "port-version": 0 }, "basisu": { @@ -529,15 +553,15 @@ "port-version": 3 }, "bddisasm": { - "baseline": "1.34.10", + "baseline": "2.1.0", "port-version": 0 }, "bde": { - "baseline": "3.123.0.0", + "baseline": "3.124.0.0", "port-version": 0 }, "bdwgc": { - "baseline": "8.2.4", + "baseline": "8.2.6", "port-version": 0 }, "beast": { @@ -550,10 +574,10 @@ }, "benchmark": { "baseline": "1.8.3", - "port-version": 0 + "port-version": 3 }, "bento4": { - "baseline": "1.6.0-640", + "baseline": "1.6.0-641", "port-version": 0 }, "berkeleydb": { @@ -566,26 +590,26 @@ }, "bext-di": { "baseline": "1.3.0", - "port-version": 0 + "port-version": 1 }, "bext-mp": { "baseline": "2023-03-02", "port-version": 0 }, "bext-sml": { - "baseline": "1.1.5", + "baseline": "1.1.9", "port-version": 0 }, "bext-sml2": { - "baseline": "2023-09-20", + "baseline": "2024-02-02", "port-version": 0 }, "bext-ut": { - "baseline": "1.1.9", - "port-version": 2 + "baseline": "2.0.1", + "port-version": 0 }, "bext-wintls": { - "baseline": "0.9.7", + "baseline": "0.9.8", "port-version": 0 }, "bfgroup-lyra": { @@ -637,16 +661,16 @@ "port-version": 0 }, "blake3": { - "baseline": "1.5.0", + "baseline": "1.5.1", "port-version": 0 }, "blas": { - "baseline": "2023-03-25", + "baseline": "2023-04-14", "port-version": 0 }, "blaze": { "baseline": "3.8.2", - "port-version": 0 + "port-version": 1 }, "blend2d": { "baseline": "2023-06-16", @@ -658,7 +682,7 @@ }, "blitz": { "baseline": "2020-03-25", - "port-version": 5 + "port-version": 6 }, "bloomberg-quantum": { "baseline": "2023-02-03", @@ -673,627 +697,647 @@ "port-version": 0 }, "boinc": { - "baseline": "7.24.1", + "baseline": "8.0.0", "port-version": 0 }, "bond": { "baseline": "10.0.0", - "port-version": 1 + "port-version": 3 }, "boolinq": { "baseline": "3.0.4", "port-version": 0 }, "boost": { - "baseline": "1.83.0", - "port-version": 1 + "baseline": "1.85.0", + "port-version": 0 }, "boost-accumulators": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-algorithm": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-align": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-any": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-array": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-asio": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-assert": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-assign": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-atomic": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-beast": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-bimap": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-bind": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-build": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-callable-traits": { - "baseline": "1.83.0", + "baseline": "1.85.0", + "port-version": 0 + }, + "boost-charconv": { + "baseline": "1.85.0", "port-version": 0 }, "boost-chrono": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-circular-buffer": { - "baseline": "1.83.0", + "baseline": "1.85.0", + "port-version": 0 + }, + "boost-cmake": { + "baseline": "1.85.0", + "port-version": 0 + }, + "boost-cobalt": { + "baseline": "1.85.0", "port-version": 0 }, "boost-compat": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-compatibility": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-compute": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-concept-check": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-config": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-container": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-container-hash": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-context": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-contract": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-conversion": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-convert": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-core": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-coroutine": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-coroutine2": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-crc": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-date-time": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-describe": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-detail": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-dll": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-dynamic-bitset": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-endian": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-exception": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-fiber": { - "baseline": "1.83.0", - "port-version": 1 + "baseline": "1.85.0", + "port-version": 0 }, "boost-filesystem": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-flyweight": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-foreach": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-format": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-function": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-function-types": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-functional": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-fusion": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-geometry": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-gil": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-graph": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-graph-parallel": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-hana": { - "baseline": "1.83.0", + "baseline": "1.85.0", + "port-version": 0 + }, + "boost-headers": { + "baseline": "1.85.0", "port-version": 0 }, "boost-heap": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-histogram": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-hof": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-icl": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-integer": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-interprocess": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-interval": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-intrusive": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-io": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-iostreams": { - "baseline": "1.83.0", - "port-version": 1 + "baseline": "1.85.0", + "port-version": 0 }, "boost-iterator": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-json": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-lambda": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-lambda2": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-leaf": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-lexical-cast": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-local-function": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-locale": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-lockfree": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-log": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-logic": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-math": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-metaparse": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, - "boost-modular-build-helper": { - "baseline": "1.83.0", - "port-version": 1 - }, "boost-move": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-mp11": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-mpi": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-mpl": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-msm": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-multi-array": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-multi-index": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-multiprecision": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-mysql": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-nowide": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-numeric-conversion": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-odeint": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-optional": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-outcome": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-parameter": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-parameter-python": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-pfr": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-phoenix": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-poly-collection": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-polygon": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-pool": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-predef": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-preprocessor": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-process": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-program-options": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-property-map": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-property-map-parallel": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-property-tree": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-proto": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-ptr-container": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-python": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-qvm": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-random": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-range": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-ratio": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-rational": { - "baseline": "1.83.0", + "baseline": "1.85.0", + "port-version": 0 + }, + "boost-redis": { + "baseline": "1.85.0", "port-version": 0 }, "boost-regex": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-safe-numerics": { - "baseline": "1.83.0", + "baseline": "1.85.0", + "port-version": 0 + }, + "boost-scope": { + "baseline": "1.85.0", "port-version": 0 }, "boost-scope-exit": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-serialization": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-signals2": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-smart-ptr": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-sort": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-spirit": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-stacktrace": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-statechart": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-static-assert": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-static-string": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-stl-interfaces": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-system": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-test": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-thread": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-throw-exception": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-timer": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-tokenizer": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-tti": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-tuple": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-type-erasure": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-type-index": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-type-traits": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-typeof": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-ublas": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-uninstall": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-units": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-unordered": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-url": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-utility": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-uuid": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-variant": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-variant2": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-vcpkg-helpers": { - "baseline": "1.83.0", + "baseline": "1.84.0", "port-version": 0 }, "boost-vmd": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-wave": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-winapi": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-xpressive": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boost-yap": { - "baseline": "1.83.0", + "baseline": "1.85.0", "port-version": 0 }, "boringssl": { @@ -1301,8 +1345,8 @@ "port-version": 0 }, "botan": { - "baseline": "3.1.1", - "port-version": 1 + "baseline": "3.3.0", + "port-version": 0 }, "box2d": { "baseline": "2.4.1", @@ -1310,11 +1354,11 @@ }, "braft": { "baseline": "2021-26-04", - "port-version": 1 + "port-version": 4 }, "breakpad": { - "baseline": "2022-07-12", - "port-version": 6 + "baseline": "2023-06-01", + "port-version": 0 }, "brigand": { "baseline": "1.3.0", @@ -1326,7 +1370,7 @@ }, "brpc": { "baseline": "1.6.1", - "port-version": 0 + "port-version": 3 }, "brunocodutra-metal": { "baseline": "2.1.4", @@ -1337,7 +1381,7 @@ "port-version": 0 }, "bshoshany-thread-pool": { - "baseline": "3.5.0", + "baseline": "4.1.0", "port-version": 0 }, "bsio": { @@ -1381,7 +1425,7 @@ "port-version": 5 }, "c-ares": { - "baseline": "1.19.1", + "baseline": "1.28.1", "port-version": 0 }, "c-dbg-macro": { @@ -1401,7 +1445,7 @@ "port-version": 0 }, "cachelib": { - "baseline": "2023.05.08.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "caf": { @@ -1413,15 +1457,15 @@ "port-version": 8 }, "cairo": { - "baseline": "1.17.8", - "port-version": 4 + "baseline": "1.18.0", + "port-version": 1 }, "cairomm": { "baseline": "1.17.1", "port-version": 1 }, "calceph": { - "baseline": "3.5.4", + "baseline": "4.0.0", "port-version": 0 }, "camport3": { @@ -1433,15 +1477,15 @@ "port-version": 0 }, "capnproto": { - "baseline": "1.0.1", + "baseline": "1.0.2", "port-version": 0 }, "capstone": { "baseline": "5.0.1", - "port-version": 0 + "port-version": 1 }, "cargs": { - "baseline": "1.0.3", + "baseline": "1.1.0", "port-version": 0 }, "cartographer": { @@ -1461,7 +1505,11 @@ "port-version": 2 }, "catch2": { - "baseline": "3.4.0", + "baseline": "3.6.0", + "port-version": 0 + }, + "cblas": { + "baseline": "2024-03-19", "port-version": 0 }, "cccapstone": { @@ -1478,14 +1526,14 @@ }, "cctag": { "baseline": "1.0.2", - "port-version": 5 + "port-version": 6 }, "cctz": { - "baseline": "2.3", - "port-version": 6 + "baseline": "2.4", + "port-version": 0 }, "cdt": { - "baseline": "1.3.0", + "baseline": "1.4.0", "port-version": 0 }, "celero": { @@ -1502,22 +1550,22 @@ }, "ceres": { "baseline": "2.1.0", - "port-version": 4 + "port-version": 5 }, "cfitsio": { "baseline": "3.49", "port-version": 5 }, "cgal": { - "baseline": "5.6", + "baseline": "5.6.1", "port-version": 0 }, "cgicc": { - "baseline": "3.2.19", - "port-version": 7 + "baseline": "3.2.20", + "port-version": 0 }, "cglm": { - "baseline": "0.9.1", + "baseline": "0.9.4", "port-version": 0 }, "cgltf": { @@ -1534,7 +1582,7 @@ }, "chakracore": { "baseline": "2022-11-09", - "port-version": 5 + "port-version": 7 }, "charls": { "baseline": "2.4.2", @@ -1550,7 +1598,7 @@ }, "chipmunk": { "baseline": "7.0.3", - "port-version": 6 + "port-version": 7 }, "chmlib": { "baseline": "0.40", @@ -1586,23 +1634,23 @@ }, "civetweb": { "baseline": "1.16", - "port-version": 1 + "port-version": 2 }, "cjson": { - "baseline": "1.7.16", + "baseline": "1.7.17", "port-version": 0 }, "clamav": { - "baseline": "0.103.0", - "port-version": 4 + "baseline": "0.103.11", + "port-version": 0 }, "clap-cleveraudio": { - "baseline": "1.1.10", + "baseline": "1.2.0", "port-version": 0 }, "clapack": { "baseline": "3.2.1", - "port-version": 22 + "port-version": 23 }, "clara": { "baseline": "1.1.5", @@ -1616,6 +1664,10 @@ "baseline": "1.6.1", "port-version": 0 }, + "cld3": { + "baseline": "3.0.14", + "port-version": 2 + }, "clfft": { "baseline": "2.12.2", "port-version": 6 @@ -1625,11 +1677,11 @@ "port-version": 0 }, "cli11": { - "baseline": "2.3.2", + "baseline": "2.4.1", "port-version": 0 }, "clickhouse-cpp": { - "baseline": "2.4.0", + "baseline": "2.5.1", "port-version": 0 }, "clipboardxx": { @@ -1641,7 +1693,7 @@ "port-version": 2 }, "clipper2": { - "baseline": "1.2.2", + "baseline": "1.3.0", "port-version": 1 }, "clockutils": { @@ -1664,10 +1716,6 @@ "baseline": "0.30.3", "port-version": 0 }, - "cmcstl2": { - "baseline": "2019-07-20", - "port-version": 3 - }, "cminpack": { "baseline": "1.3.8", "port-version": 4 @@ -1677,8 +1725,8 @@ "port-version": 3 }, "cnats": { - "baseline": "3.7.0", - "port-version": 1 + "baseline": "3.8.0", + "port-version": 0 }, "cnl": { "baseline": "1.1.7", @@ -1693,8 +1741,8 @@ "port-version": 1 }, "coin": { - "baseline": "4.0.0", - "port-version": 7 + "baseline": "4.0.2", + "port-version": 2 }, "coin-or-buildtools": { "baseline": "2023-02-02", @@ -1726,7 +1774,7 @@ }, "collada-dom": { "baseline": "2.5.0", - "port-version": 10 + "port-version": 11 }, "colmap": { "baseline": "2023-10-01", @@ -1761,7 +1809,7 @@ "port-version": 0 }, "configcat": { - "baseline": "3.1.1", + "baseline": "4.0.1", "port-version": 0 }, "console-bridge": { @@ -1789,7 +1837,7 @@ "port-version": 3 }, "copypp": { - "baseline": "0.2.0", + "baseline": "0.3.0", "port-version": 0 }, "coroutine": { @@ -1800,6 +1848,10 @@ "baseline": "2020.06", "port-version": 8 }, + "correlation-vector-cpp": { + "baseline": "1.0", + "port-version": 0 + }, "cpp-async": { "baseline": "1.1.0", "port-version": 0 @@ -1809,11 +1861,11 @@ "port-version": 0 }, "cpp-httplib": { - "baseline": "0.14.1", + "baseline": "0.15.3", "port-version": 0 }, "cpp-ipc": { - "baseline": "1.2.0", + "baseline": "1.3.0", "port-version": 0 }, "cpp-jwt": { @@ -1825,7 +1877,7 @@ "port-version": 9 }, "cpp-peglib": { - "baseline": "1.8.5", + "baseline": "1.8.6", "port-version": 0 }, "cpp-redis": { @@ -1845,12 +1897,12 @@ "port-version": 0 }, "cppad": { - "baseline": "20230000.0", + "baseline": "20240000.2", "port-version": 0 }, "cppcms": { "baseline": "1.2.1", - "port-version": 6 + "port-version": 7 }, "cppcodec": { "baseline": "0.2", @@ -1893,7 +1945,7 @@ "port-version": 0 }, "cppslippi": { - "baseline": "1.3.3.14", + "baseline": "1.4.3.16", "port-version": 0 }, "cpptoml": { @@ -1901,7 +1953,7 @@ "port-version": 4 }, "cpptrace": { - "baseline": "0.3.1", + "baseline": "0.5.4", "port-version": 0 }, "cppunit": { @@ -1913,7 +1965,7 @@ "port-version": 3 }, "cppwinrt": { - "baseline": "2.0.230207.1", + "baseline": "2.0.240111.5", "port-version": 0 }, "cppxaml": { @@ -1926,14 +1978,14 @@ }, "cpr": { "baseline": "1.10.5", - "port-version": 1 + "port-version": 2 }, "cpu-features": { "baseline": "0.9.0", "port-version": 0 }, "cpuid": { - "baseline": "0.6.2", + "baseline": "0.6.4", "port-version": 0 }, "cpuinfo": { @@ -1945,8 +1997,8 @@ "port-version": 2 }, "crashpad": { - "baseline": "2022-09-05", - "port-version": 4 + "baseline": "2024-04-11", + "port-version": 0 }, "crashrpt": { "baseline": "1.4.3", @@ -1969,7 +2021,7 @@ "port-version": 3 }, "crow": { - "baseline": "1.0-5", + "baseline": "1.1.0", "port-version": 0 }, "cryptopp": { @@ -1990,7 +2042,7 @@ }, "ctbignum": { "baseline": "2019-08-02", - "port-version": 3 + "port-version": 4 }, "ctemplate": { "baseline": "2020-09-14", @@ -2005,7 +2057,7 @@ "port-version": 2 }, "ctre": { - "baseline": "3.8", + "baseline": "3.8.1", "port-version": 0 }, "ctstraffic": { @@ -2025,20 +2077,20 @@ "port-version": 13 }, "cuda-api-wrappers": { - "baseline": "0.6.6", + "baseline": "0.6.9", "port-version": 0 }, "cudnn": { "baseline": "7.6.5", - "port-version": 10 + "port-version": 11 }, "cunit": { "baseline": "2.1.3", "port-version": 8 }, "curl": { - "baseline": "8.4.0", - "port-version": 0 + "baseline": "8.7.1", + "port-version": 3 }, "curlpp": { "baseline": "2018-06-15", @@ -2053,7 +2105,11 @@ "port-version": 2 }, "cwalk": { - "baseline": "1.2.7", + "baseline": "1.2.9", + "port-version": 0 + }, + "cwapi3d": { + "baseline": "30.475.1", "port-version": 0 }, "cxxgraph": { @@ -2061,24 +2117,24 @@ "port-version": 0 }, "cxxopts": { - "baseline": "3.1.1", + "baseline": "3.2.1", "port-version": 0 }, "cyclonedds": { - "baseline": "0.10.3", + "baseline": "0.10.4", "port-version": 0 }, "cyclonedds-cxx": { - "baseline": "0.10.2", - "port-version": 1 + "baseline": "0.10.4", + "port-version": 0 }, "czmq": { "baseline": "4.2.1", "port-version": 4 }, "d3d12-memory-allocator": { - "baseline": "2021-05-05", - "port-version": 1 + "baseline": "2.0.1", + "port-version": 0 }, "d3dx12": { "baseline": "may2021", @@ -2086,7 +2142,7 @@ }, "darknet": { "baseline": "2022-03-06", - "port-version": 3 + "port-version": 4 }, "darts-clone": { "baseline": "1767ab87cffe", @@ -2097,27 +2153,31 @@ "port-version": 3 }, "dataframe": { - "baseline": "2.1.0", + "baseline": "3.1.0", "port-version": 0 }, "date": { "baseline": "3.0.1", "port-version": 5 }, + "datraw": { + "baseline": "1.0.9", + "port-version": 0 + }, "dav1d": { - "baseline": "1.3.0", - "port-version": 1 + "baseline": "1.4.0", + "port-version": 0 }, "daw-header-libraries": { - "baseline": "2.96.1", + "baseline": "2.106.0", "port-version": 0 }, "daw-json-link": { - "baseline": "3.20.1", + "baseline": "3.24.0", "port-version": 0 }, "daw-utf-range": { - "baseline": "2.2.3", + "baseline": "2.2.4", "port-version": 0 }, "daxa": { @@ -2142,11 +2202,11 @@ }, "dbus": { "baseline": "1.15.8", - "port-version": 2 + "port-version": 4 }, "dcmtk": { - "baseline": "3.6.7", - "port-version": 6 + "baseline": "3.6.8", + "port-version": 5 }, "debug-assert": { "baseline": "1.3.3", @@ -2166,42 +2226,46 @@ }, "devil": { "baseline": "1.8.0", - "port-version": 11 + "port-version": 13 }, "dimcli": { - "baseline": "7.1.0", + "baseline": "7.2.0", "port-version": 0 }, "directx-dxc": { - "baseline": "2023-08-14", + "baseline": "2024-03-29", "port-version": 0 }, "directx-headers": { - "baseline": "1.610.2", + "baseline": "1.613.0", "port-version": 0 }, - "directxmath": { - "baseline": "2022-12-12", + "directx12-agility": { + "baseline": "1.613.0", "port-version": 0 }, + "directxmath": { + "baseline": "2024-02-14", + "port-version": 1 + }, "directxmesh": { - "baseline": "2023-10-28", + "baseline": "2024-02-21", "port-version": 0 }, "directxsdk": { "baseline": "jun10", - "port-version": 7 + "port-version": 8 }, "directxtex": { - "baseline": "2023-10-28", + "baseline": "2024-03-06", "port-version": 0 }, "directxtk": { - "baseline": "2023-10-28", + "baseline": "2024-02-21", "port-version": 0 }, "directxtk12": { - "baseline": "2023-10-28", + "baseline": "2024-02-21", "port-version": 0 }, "dirent": { @@ -2214,10 +2278,10 @@ }, "discord-rpc": { "baseline": "3.4.0", - "port-version": 3 + "port-version": 4 }, "discordcoreapi": { - "baseline": "2.0.3", + "baseline": "2.0.6", "port-version": 0 }, "discount": { @@ -2238,15 +2302,19 @@ }, "dlib": { "baseline": "19.24", - "port-version": 3 + "port-version": 4 + }, + "dlpack": { + "baseline": "0.8", + "port-version": 0 }, "dmlc": { "baseline": "2022-06-22", "port-version": 0 }, "docopt": { - "baseline": "2018-11-01", - "port-version": 3 + "baseline": "2022-03-15", + "port-version": 1 }, "doctest": { "baseline": "2.4.11", @@ -2265,11 +2333,15 @@ "port-version": 1 }, "dpp": { - "baseline": "10.0.29", + "baseline": "10.0.30", "port-version": 0 }, "draco": { - "baseline": "1.5.6", + "baseline": "1.5.7", + "port-version": 0 + }, + "drekar-launch-process-cpp": { + "baseline": "0.1.0", "port-version": 0 }, "drlibs": { @@ -2277,7 +2349,7 @@ "port-version": 0 }, "drogon": { - "baseline": "1.9.1", + "baseline": "1.9.4", "port-version": 0 }, "dstorage": { @@ -2302,7 +2374,7 @@ }, "duktape": { "baseline": "2.7.0", - "port-version": 0 + "port-version": 1 }, "dumb": { "baseline": "2.0.3", @@ -2310,7 +2382,7 @@ }, "dv-processing": { "baseline": "1.7.9", - "port-version": 0 + "port-version": 1 }, "dx": { "baseline": "1.0.1", @@ -2318,7 +2390,7 @@ }, "dxsdk-d3dx": { "baseline": "9.29.952.8", - "port-version": 6 + "port-version": 7 }, "dxut": { "baseline": "11.31", @@ -2358,15 +2430,15 @@ }, "easyloggingpp": { "baseline": "9.97.1", - "port-version": 0 + "port-version": 1 }, "eathread": { "baseline": "1.32.09", "port-version": 5 }, "ebml": { - "baseline": "1.4.4", - "port-version": 1 + "baseline": "1.4.5", + "port-version": 0 }, "ecal": { "baseline": "5.12.0", @@ -2389,7 +2461,7 @@ "port-version": 0 }, "edflib": { - "baseline": "1.24", + "baseline": "1.25", "port-version": 0 }, "edlib": { @@ -2413,12 +2485,12 @@ "port-version": 0 }, "egl-registry": { - "baseline": "2022-09-20", + "baseline": "2024-01-25", "port-version": 0 }, "eigen3": { "baseline": "3.4.0", - "port-version": 3 + "port-version": 4 }, "elements": { "baseline": "2022-12-07", @@ -2434,7 +2506,7 @@ }, "embree3": { "baseline": "3.13.5", - "port-version": 2 + "port-version": 3 }, "enet": { "baseline": "1.3.17", @@ -2442,7 +2514,7 @@ }, "enkits": { "baseline": "1.11", - "port-version": 1 + "port-version": 2 }, "ensmallen": { "baseline": "2.19.1", @@ -2453,7 +2525,7 @@ "port-version": 5 }, "entt": { - "baseline": "3.12.2", + "baseline": "3.13.2", "port-version": 0 }, "epsilon": { @@ -2469,12 +2541,12 @@ "port-version": 1 }, "etcd-cpp-apiv3": { - "baseline": "0.15.3", + "baseline": "0.15.4", "port-version": 0 }, "etl": { - "baseline": "20.38.0", - "port-version": 0 + "baseline": "20.38.10", + "port-version": 1 }, "eve": { "baseline": "2023.2.15", @@ -2482,19 +2554,19 @@ }, "eventpp": { "baseline": "0.1.3", - "port-version": 0 + "port-version": 1 }, "evpp": { "baseline": "0.7.0", - "port-version": 7 + "port-version": 8 }, "exiv2": { "baseline": "0.28.1", - "port-version": 0 + "port-version": 1 }, "expat": { - "baseline": "2.5.0", - "port-version": 3 + "baseline": "2.6.2", + "port-version": 0 }, "expected-lite": { "baseline": "0.6.3", @@ -2505,7 +2577,7 @@ "port-version": 2 }, "ezc3d": { - "baseline": "1.5.0", + "baseline": "1.5.7", "port-version": 0 }, "ezfoundation": { @@ -2513,7 +2585,7 @@ "port-version": 0 }, "faad2": { - "baseline": "2.10.1", + "baseline": "2.11.1", "port-version": 0 }, "fadbad": { @@ -2526,7 +2598,7 @@ }, "fakeit": { "baseline": "2.4.0", - "port-version": 1 + "port-version": 2 }, "fameta-counter": { "baseline": "2021-02-13", @@ -2545,7 +2617,7 @@ "port-version": 2 }, "fast-float": { - "baseline": "5.2.0", + "baseline": "6.1.1", "port-version": 0 }, "fastcdr": { @@ -2561,11 +2633,11 @@ "port-version": 4 }, "fastgltf": { - "baseline": "0.6.1", - "port-version": 1 + "baseline": "0.7.1", + "port-version": 0 }, "fastio": { - "baseline": "2023-07-06", + "baseline": "2023-11-06", "port-version": 0 }, "fastlz": { @@ -2580,6 +2652,10 @@ "baseline": "2.7.0", "port-version": 5 }, + "faudio": { + "baseline": "24.03", + "port-version": 0 + }, "fawdlstty-libfv": { "baseline": "0.0.8", "port-version": 0 @@ -2589,7 +2665,7 @@ "port-version": 0 }, "fbthrift": { - "baseline": "2023.10.02.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "fcl": { @@ -2598,18 +2674,18 @@ }, "fdk-aac": { "baseline": "2.0.2", - "port-version": 2 + "port-version": 3 }, "fdlibm": { "baseline": "5.3", "port-version": 7 }, "ffmpeg": { - "baseline": "6.1", - "port-version": 1 + "baseline": "6.1.1", + "port-version": 3 }, "ffnvcodec": { - "baseline": "11.1.5.3", + "baseline": "12.1.14.0", "port-version": 0 }, "fftw3": { @@ -2633,7 +2709,7 @@ "port-version": 0 }, "fizz": { - "baseline": "2023.10.02.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "flagpp": { @@ -2669,15 +2745,15 @@ "port-version": 0 }, "flatbuffers": { - "baseline": "23.5.26", - "port-version": 1 + "baseline": "24.3.25", + "port-version": 0 }, "flatbush": { "baseline": "1.2.0", "port-version": 0 }, "flecs": { - "baseline": "3.2.9", + "baseline": "3.2.11", "port-version": 0 }, "flint": { @@ -2685,15 +2761,15 @@ "port-version": 0 }, "fltk": { - "baseline": "1.3.8", - "port-version": 5 + "baseline": "1.3.9", + "port-version": 0 }, "fluidlite": { "baseline": "2023-04-18", "port-version": 0 }, "fluidsynth": { - "baseline": "2.3.4", + "baseline": "2.3.5", "port-version": 0 }, "flux": { @@ -2713,11 +2789,11 @@ "port-version": 2 }, "fmt": { - "baseline": "10.1.1", - "port-version": 0 + "baseline": "10.2.1", + "port-version": 2 }, "folly": { - "baseline": "2023.10.02.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "font-chef": { @@ -2752,10 +2828,6 @@ "baseline": "2021-02-21", "port-version": 2 }, - "fplus": { - "baseline": "0.2.20-p0", - "port-version": 0 - }, "freealut": { "baseline": "1.1.0", "port-version": 4 @@ -2766,14 +2838,14 @@ }, "freeimage": { "baseline": "3.18.0", - "port-version": 25 + "port-version": 26 }, "freeopcua": { "baseline": "20190125", "port-version": 7 }, "freerdp": { - "baseline": "2.11.2", + "baseline": "3.4.0", "port-version": 1 }, "freetds": { @@ -2781,12 +2853,12 @@ "port-version": 2 }, "freetype": { - "baseline": "2.12.1", - "port-version": 4 + "baseline": "2.13.2", + "port-version": 1 }, "freetype-gl": { "baseline": "2022-01-17", - "port-version": 2 + "port-version": 3 }, "freexl": { "baseline": "2.0.0", @@ -2801,8 +2873,8 @@ "port-version": 0 }, "frugally-deep": { - "baseline": "0.15.24", - "port-version": 0 + "baseline": "0.15.31", + "port-version": 1 }, "fruit": { "baseline": "3.7.1", @@ -2817,7 +2889,11 @@ "port-version": 0 }, "function2": { - "baseline": "4.2.3", + "baseline": "4.2.4", + "port-version": 0 + }, + "functionalplus": { + "baseline": "0.2.24", "port-version": 0 }, "functions-framework-cpp": { @@ -2834,11 +2910,11 @@ }, "g2o": { "baseline": "2020-02-07", - "port-version": 4 + "port-version": 6 }, "g3log": { - "baseline": "2.3", - "port-version": 1 + "baseline": "2.4", + "port-version": 0 }, "gainput": { "baseline": "1.0.0", @@ -2881,11 +2957,11 @@ "port-version": 0 }, "gdal": { - "baseline": "3.8.1", + "baseline": "3.8.5", "port-version": 0 }, "gdcm": { - "baseline": "3.0.22", + "baseline": "3.0.23", "port-version": 0 }, "gdcm2": { @@ -2894,7 +2970,7 @@ }, "gdk-pixbuf": { "baseline": "2.42.10", - "port-version": 2 + "port-version": 6 }, "gemmlowp": { "baseline": "2021-09-28", @@ -2914,15 +2990,15 @@ }, "geos": { "baseline": "3.11.3", - "port-version": 0 + "port-version": 1 }, "geotrans": { "baseline": "3.9", "port-version": 1 }, "getdns": { - "baseline": "1.7.0", - "port-version": 3 + "baseline": "1.7.3", + "port-version": 0 }, "getopt": { "baseline": "0", @@ -2933,12 +3009,12 @@ "port-version": 0 }, "gettext": { - "baseline": "0.21.1", - "port-version": 3 + "baseline": "0.22.5", + "port-version": 0 }, "gettext-libintl": { - "baseline": "0.21.1", - "port-version": 1 + "baseline": "0.22.5", + "port-version": 0 }, "gettimeofday": { "baseline": "2017-10-14", @@ -2957,16 +3033,16 @@ "port-version": 3 }, "giflib": { - "baseline": "5.2.1", - "port-version": 3 + "baseline": "5.2.2", + "port-version": 0 }, "ginkgo": { "baseline": "1.7.0", "port-version": 0 }, "gklib": { - "baseline": "2022-07-27", - "port-version": 2 + "baseline": "2023-03-27", + "port-version": 0 }, "gl2ps": { "baseline": "1.4.2", @@ -2974,14 +3050,14 @@ }, "gl3w": { "baseline": "2018-05-31", - "port-version": 4 + "port-version": 5 }, "glad": { "baseline": "0.1.36", "port-version": 0 }, "glaze": { - "baseline": "1.9.2", + "baseline": "2.6.1", "port-version": 0 }, "glbinding": { @@ -2993,23 +3069,27 @@ "port-version": 3 }, "glfw3": { - "baseline": "3.3.8", - "port-version": 3 + "baseline": "3.4", + "port-version": 0 }, "gli": { "baseline": "2021-07-06", "port-version": 2 }, "glib": { - "baseline": "2.78.1", + "baseline": "2.78.4", + "port-version": 1 + }, + "glib-networking": { + "baseline": "2.78.0", "port-version": 0 }, "glibmm": { - "baseline": "2.76.0", - "port-version": 1 + "baseline": "2.78.1", + "port-version": 0 }, "glm": { - "baseline": "0.9.9.8", + "baseline": "1.0.1", "port-version": 2 }, "globjects": { @@ -3017,19 +3097,19 @@ "port-version": 6 }, "glog": { - "baseline": "0.6.0", - "port-version": 3 + "baseline": "0.7.0", + "port-version": 1 }, "gloo": { "baseline": "20201203", - "port-version": 2 + "port-version": 3 }, "glpk": { "baseline": "5.0", - "port-version": 2 + "port-version": 3 }, "glslang": { - "baseline": "13.1.1", + "baseline": "14.2.0", "port-version": 0 }, "glui": { @@ -3041,23 +3121,23 @@ "port-version": 6 }, "gmmlib": { - "baseline": "22.3.12", + "baseline": "22.3.17", "port-version": 0 }, "gmp": { - "baseline": "6.2.1", - "port-version": 21 + "baseline": "6.3.0", + "port-version": 0 }, "gmsh": { - "baseline": "4.11.1", + "baseline": "4.12.2", "port-version": 0 }, "gobject-introspection": { "baseline": "1.72.0", - "port-version": 6 + "port-version": 8 }, "google-cloud-cpp": { - "baseline": "2.19.0", + "baseline": "2.24.0", "port-version": 0 }, "google-cloud-cpp-common": { @@ -3081,7 +3161,7 @@ "port-version": 1 }, "gpgme": { - "baseline": "1.22.0", + "baseline": "1.23.2", "port-version": 0 }, "gpgmm": { @@ -3102,7 +3182,7 @@ }, "graphicsmagick": { "baseline": "1.3.41", - "port-version": 0 + "port-version": 1 }, "graphite2": { "baseline": "1.3.14", @@ -3113,8 +3193,8 @@ "port-version": 4 }, "graphviz": { - "baseline": "9.0.0", - "port-version": 2 + "baseline": "10.0.1", + "port-version": 1 }, "greatest": { "baseline": "1.5.0", @@ -3122,7 +3202,7 @@ }, "grpc": { "baseline": "1.51.1", - "port-version": 1 + "port-version": 3 }, "grppi": { "baseline": "0.4.0", @@ -3146,15 +3226,15 @@ }, "gstreamer": { "baseline": "1.22.5", - "port-version": 5 + "port-version": 8 }, "gtest": { "baseline": "1.14.0", - "port-version": 0 + "port-version": 1 }, "gtk": { "baseline": "4.10.5", - "port-version": 1 + "port-version": 2 }, "gtk3": { "baseline": "3.24.38", @@ -3170,26 +3250,26 @@ }, "gts": { "baseline": "0.7.6", - "port-version": 8 + "port-version": 9 }, "gtsam": { "baseline": "4.2a9", - "port-version": 0 + "port-version": 1 }, "guetzli": { "baseline": "2020-09-14", "port-version": 2 }, "guile": { - "baseline": "3.0.8", - "port-version": 1 + "baseline": "3.0.9", + "port-version": 0 }, "guilite": { "baseline": "2022-05-05", "port-version": 0 }, "gul14": { - "baseline": "2.9.2", + "baseline": "2.11.2", "port-version": 0 }, "gumbo": { @@ -3257,24 +3337,24 @@ "port-version": 0 }, "h5py-lzf": { - "baseline": "2019-12-04", - "port-version": 3 + "baseline": "2022-05-24", + "port-version": 0 }, "halide": { - "baseline": "16.0.0", - "port-version": 1 + "baseline": "17.0.1", + "port-version": 0 }, "happly": { "baseline": "2021-03-19", "port-version": 0 }, "hareflow": { - "baseline": "0.1.0", - "port-version": 1 + "baseline": "0.1.1", + "port-version": 0 }, "harfbuzz": { - "baseline": "8.2.1", - "port-version": 3 + "baseline": "8.4.0", + "port-version": 1 }, "hash-library": { "baseline": "8", @@ -3304,8 +3384,12 @@ "baseline": "15", "port-version": 0 }, + "hello-imgui": { + "baseline": "1.4.2", + "port-version": 1 + }, "hexl": { - "baseline": "1.2.4", + "baseline": "1.2.5", "port-version": 0 }, "hffix": { @@ -3321,25 +3405,29 @@ "port-version": 0 }, "highfive": { - "baseline": "2.7.1", - "port-version": 1 + "baseline": "2.9.0", + "port-version": 0 }, "highs": { "baseline": "1.6.0", "port-version": 1 }, "highway": { - "baseline": "1.0.7", + "baseline": "1.1.0", "port-version": 0 }, "hikogui": { "baseline": "0.8.1", - "port-version": 0 + "port-version": 2 }, "hiredis": { "baseline": "1.2.0", "port-version": 0 }, + "hjson-cpp": { + "baseline": "2.4.1", + "port-version": 0 + }, "hnswlib": { "baseline": "0.8.0", "port-version": 0 @@ -3350,7 +3438,7 @@ }, "hpx": { "baseline": "1.9.1", - "port-version": 0 + "port-version": 1 }, "http-parser": { "baseline": "2.9.4", @@ -3362,10 +3450,10 @@ }, "hunspell": { "baseline": "1.7.2", - "port-version": 0 + "port-version": 1 }, "hwloc": { - "baseline": "2.9.3", + "baseline": "2.10.0", "port-version": 0 }, "hyperscan": { @@ -3381,12 +3469,12 @@ "port-version": 1 }, "iceoryx": { - "baseline": "2.0.3", + "baseline": "2.0.5", "port-version": 0 }, "icu": { - "baseline": "73.1", - "port-version": 2 + "baseline": "74.2", + "port-version": 1 }, "ideviceinstaller": { "baseline": "2023-07-21", @@ -3397,7 +3485,7 @@ "port-version": 0 }, "idyntree": { - "baseline": "10.0.0", + "baseline": "12.1.0", "port-version": 0 }, "if97": { @@ -3413,8 +3501,8 @@ "port-version": 4 }, "ignition-cmake2": { - "baseline": "2.16.0", - "port-version": 2 + "baseline": "2.17.1", + "port-version": 0 }, "ignition-common1": { "baseline": "1.1.1", @@ -3481,7 +3569,7 @@ "port-version": 0 }, "igraph": { - "baseline": "0.10.8", + "baseline": "0.10.12", "port-version": 0 }, "iir1": { @@ -3501,20 +3589,20 @@ "port-version": 0 }, "imageinfo": { - "baseline": "2023-01-31", + "baseline": "2024-02-21", "port-version": 0 }, "imath": { - "baseline": "3.1.9", - "port-version": 1 + "baseline": "3.1.11", + "port-version": 0 }, "imgui": { - "baseline": "1.90", + "baseline": "1.90.2", "port-version": 0 }, "imgui-node-editor": { "baseline": "0.9.3", - "port-version": 0 + "port-version": 1 }, "imgui-sfml": { "baseline": "2.6", @@ -3541,15 +3629,15 @@ "port-version": 0 }, "influxdb-cxx": { - "baseline": "0.7.1", - "port-version": 1 + "baseline": "0.7.2", + "port-version": 0 }, "infoware": { "baseline": "2023-04-12", "port-version": 0 }, "inih": { - "baseline": "57", + "baseline": "58", "port-version": 0 }, "iniparser": { @@ -3580,6 +3668,10 @@ "baseline": "2020-09-14", "port-version": 5 }, + "iowa-hills-dsp": { + "baseline": "0.1.0", + "port-version": 0 + }, "irrlicht": { "baseline": "1.8.5", "port-version": 0 @@ -3602,7 +3694,7 @@ }, "itk": { "baseline": "5.3rc02", - "port-version": 0 + "port-version": 1 }, "itpp": { "baseline": "4.3.1", @@ -3613,8 +3705,8 @@ "port-version": 0 }, "ixwebsocket": { - "baseline": "11.4.4", - "port-version": 2 + "baseline": "11.4.5", + "port-version": 0 }, "jack2": { "baseline": "1.9.22", @@ -3629,7 +3721,7 @@ "port-version": 1 }, "jasper": { - "baseline": "4.1.0", + "baseline": "4.2.1", "port-version": 0 }, "jbig2dec": { @@ -3644,6 +3736,10 @@ "baseline": "5.3.0", "port-version": 1 }, + "jhasse-poly2tri": { + "baseline": "2023-12-27", + "port-version": 0 + }, "jinja2cpplight": { "baseline": "2018-05-08", "port-version": 3 @@ -3653,8 +3749,8 @@ "port-version": 1 }, "joltphysics": { - "baseline": "4.0.0", - "port-version": 0 + "baseline": "5.0.0", + "port-version": 1 }, "josuttis-jthread": { "baseline": "2020-07-21", @@ -3665,11 +3761,11 @@ "port-version": 2 }, "json-c": { - "baseline": "2022-06-26", - "port-version": 3 + "baseline": "2023-08-12", + "port-version": 0 }, "json-dto": { - "baseline": "0.3.1", + "baseline": "0.3.3", "port-version": 0 }, "json-rpc-cxx": { @@ -3677,12 +3773,12 @@ "port-version": 0 }, "json-schema-validator": { - "baseline": "2.2.0", - "port-version": 0 + "baseline": "2.3.0", + "port-version": 2 }, "json-spirit": { "baseline": "4.1.0", - "port-version": 4 + "port-version": 5 }, "json11": { "baseline": "2017-06-20", @@ -3690,26 +3786,30 @@ }, "json5-parser": { "baseline": "1.0.0", - "port-version": 5 + "port-version": 6 }, "jsoncons": { - "baseline": "0.171.0", + "baseline": "0.175.0", "port-version": 0 }, "jsoncpp": { "baseline": "1.9.5", - "port-version": 2 + "port-version": 4 }, "jsonifier": { - "baseline": "0.9.92", + "baseline": "0.9.95", "port-version": 0 }, "jsonnet": { "baseline": "0.20.0", "port-version": 0 }, + "juce": { + "baseline": "7.0.12", + "port-version": 0 + }, "jwt-cpp": { - "baseline": "0.6.0", + "baseline": "0.7.0", "port-version": 0 }, "jxrlib": { @@ -3721,19 +3821,15 @@ "port-version": 1 }, "kangaru": { - "baseline": "4.3.1", + "baseline": "4.3.2", "port-version": 0 }, "kcp": { "baseline": "1.7", "port-version": 0 }, - "kd-soap": { - "baseline": "2.1.1", - "port-version": 1 - }, "kdalgorithms": { - "baseline": "1.2", + "baseline": "1.3", "port-version": 0 }, "kdbindings": { @@ -3741,12 +3837,16 @@ "port-version": 0 }, "kddockwidgets": { - "baseline": "1.5.0", + "baseline": "2.0.0", + "port-version": 0 + }, + "kdsoap": { + "baseline": "2.2.0", "port-version": 0 }, "kealib": { - "baseline": "1.5.2", - "port-version": 1 + "baseline": "1.5.3", + "port-version": 0 }, "keccak-tiny": { "baseline": "2014-09-08", @@ -3754,6 +3854,10 @@ }, "kenlm": { "baseline": "20230531", + "port-version": 1 + }, + "kerbal": { + "baseline": "2024.4.1", "port-version": 0 }, "keystone": { @@ -3913,8 +4017,8 @@ "port-version": 0 }, "kfr": { - "baseline": "5.0.1", - "port-version": 1 + "baseline": "6.0.2", + "port-version": 0 }, "kinectsdk1": { "baseline": "1.8", @@ -3929,7 +4033,7 @@ "port-version": 0 }, "kissnet": { - "baseline": "2023-02-04", + "baseline": "2024-01-20", "port-version": 0 }, "klein": { @@ -3941,13 +4045,17 @@ "port-version": 1 }, "krabsetw": { - "baseline": "4.3.1", + "baseline": "4.3.2", "port-version": 0 }, - "ktx": { - "baseline": "4.3.0-alpha3", + "krb5": { + "baseline": "1.21.2", "port-version": 0 }, + "ktx": { + "baseline": "4.3.1", + "port-version": 1 + }, "kubazip": { "baseline": "0.2.6", "port-version": 0 @@ -3973,24 +4081,24 @@ "port-version": 0 }, "lapack": { - "baseline": "2022-02-22", - "port-version": 2 + "baseline": "2023-06-10", + "port-version": 0 }, "lapack-reference": { "baseline": "3.11.0", - "port-version": 1 + "port-version": 6 }, "lastools": { "baseline": "2.0.2+20230206", "port-version": 1 }, "laszip": { - "baseline": "3.4.3", - "port-version": 1 + "baseline": "3.4.4", + "port-version": 0 }, "launch-darkly-server": { "baseline": "2.8.6", - "port-version": 1 + "port-version": 2 }, "lazy-importer": { "baseline": "2023-08-03", @@ -4018,15 +4126,15 @@ }, "lensfun": { "baseline": "0.3.4", - "port-version": 1 + "port-version": 2 }, "leptonica": { - "baseline": "1.83.1", + "baseline": "1.84.1", "port-version": 0 }, "lerc": { - "baseline": "4.0", - "port-version": 1 + "baseline": "4.0.4", + "port-version": 0 }, "lest": { "baseline": "1.35.1", @@ -4054,7 +4162,7 @@ }, "libadwaita": { "baseline": "1.3.2", - "port-version": 1 + "port-version": 2 }, "libaes-siv": { "baseline": "2020-10-15", @@ -4065,15 +4173,15 @@ "port-version": 9 }, "libalkimia": { - "baseline": "8.1.70", - "port-version": 2 + "baseline": "8.1.72", + "port-version": 0 }, "libao": { "baseline": "1.2.2", "port-version": 5 }, "libarchive": { - "baseline": "3.6.2", + "baseline": "3.7.2", "port-version": 0 }, "libass": { @@ -4081,19 +4189,19 @@ "port-version": 0 }, "libassert": { - "baseline": "1.2.2", + "baseline": "2.0.2", "port-version": 0 }, "libassuan": { - "baseline": "2.5.6", + "baseline": "2.5.7", "port-version": 0 }, "libatomic-ops": { - "baseline": "7.8.0", + "baseline": "7.8.2", "port-version": 0 }, "libavif": { - "baseline": "1.0.1", + "baseline": "1.0.4", "port-version": 0 }, "libb2": { @@ -4101,20 +4209,20 @@ "port-version": 6 }, "libbacktrace": { - "baseline": "2021-03-14", - "port-version": 1 + "baseline": "2023-11-30", + "port-version": 0 }, "libbf": { "baseline": "1.0.0", "port-version": 4 }, "libbson": { - "baseline": "1.25.1", - "port-version": 1 + "baseline": "1.27.1", + "port-version": 0 }, "libcaer": { "baseline": "3.3.15", - "port-version": 0 + "port-version": 1 }, "libcanberra": { "baseline": "0.30", @@ -4122,10 +4230,10 @@ }, "libcap": { "baseline": "2.69", - "port-version": 2 + "port-version": 5 }, "libcbor": { - "baseline": "0.10.2", + "baseline": "0.11.0", "port-version": 0 }, "libcds": { @@ -4149,7 +4257,7 @@ "port-version": 0 }, "libcoro": { - "baseline": "0.9", + "baseline": "0.11.1", "port-version": 0 }, "libcorrect": { @@ -4181,7 +4289,7 @@ "port-version": 0 }, "libdatachannel": { - "baseline": "0.19.4", + "baseline": "0.20.3", "port-version": 0 }, "libdatrie": { @@ -4189,31 +4297,31 @@ "port-version": 1 }, "libdc1394": { - "baseline": "2.2.6", - "port-version": 1 + "baseline": "2.2.7", + "port-version": 0 }, "libde265": { - "baseline": "1.0.14", + "baseline": "1.0.15", "port-version": 0 }, "libdeflate": { - "baseline": "1.19", - "port-version": 1 + "baseline": "1.20", + "port-version": 0 }, "libdisasm": { "baseline": "0.23", - "port-version": 10 + "port-version": 11 }, "libdivide": { "baseline": "5.0", "port-version": 1 }, "libdjinterop": { - "baseline": "0.20.1", + "baseline": "0.20.3", "port-version": 0 }, "libdmx": { - "baseline": "1.1.4", + "baseline": "1.1.5", "port-version": 0 }, "libdshowcapture": { @@ -4221,15 +4329,15 @@ "port-version": 3 }, "libdwarf": { - "baseline": "0.8.0", - "port-version": 0 + "baseline": "0.9.1", + "port-version": 1 }, "libe57": { "baseline": "1.1.332", "port-version": 4 }, "libe57format": { - "baseline": "3.0.0", + "baseline": "3.1.1", "port-version": 0 }, "libebur128": { @@ -4237,13 +4345,17 @@ "port-version": 2 }, "libenvpp": { - "baseline": "1.3.0", + "baseline": "1.4.0", "port-version": 0 }, "libepoxy": { "baseline": "1.5.10", "port-version": 2 }, + "liberasurecode": { + "baseline": "1.6.3", + "port-version": 0 + }, "libev": { "baseline": "4.33", "port-version": 2 @@ -4253,11 +4365,11 @@ "port-version": 0 }, "libeventheader-decode": { - "baseline": "1.2.1", + "baseline": "1.3.3", "port-version": 0 }, "libeventheader-tracepoint": { - "baseline": "1.2.1", + "baseline": "1.3.3", "port-version": 0 }, "libevhtp": { @@ -4266,38 +4378,42 @@ }, "libexif": { "baseline": "0.6.24", - "port-version": 1 + "port-version": 3 }, "libfabric": { "baseline": "1.13.2", "port-version": 2 }, "libffi": { - "baseline": "3.4.4", - "port-version": 6 + "baseline": "3.4.6", + "port-version": 0 }, "libfido2": { - "baseline": "1.13.0", + "baseline": "1.14.0", "port-version": 0 }, "libflac": { "baseline": "1.4.3", - "port-version": 0 + "port-version": 2 }, "libfontenc": { "baseline": "1.1.4", "port-version": 0 }, + "libfork": { + "baseline": "3.7.1", + "port-version": 0 + }, "libfort": { "baseline": "0.4.2", "port-version": 1 }, "libfreenect2": { "baseline": "0.2.1", - "port-version": 0 + "port-version": 1 }, "libfs": { - "baseline": "1.0.8", + "baseline": "1.0.9", "port-version": 0 }, "libftdi": { @@ -4308,33 +4424,37 @@ "baseline": "1.5", "port-version": 4 }, + "libfuse": { + "baseline": "3.16.2", + "port-version": 0 + }, "libgcrypt": { "baseline": "1.10.2", "port-version": 0 }, "libgd": { "baseline": "2.3.3", - "port-version": 2 + "port-version": 3 }, "libgeotiff": { "baseline": "1.7.1", "port-version": 3 }, "libgig": { - "baseline": "4.3.0", + "baseline": "4.4.1", "port-version": 0 }, "libgit2": { - "baseline": "1.6.4", - "port-version": 1 + "baseline": "1.8.0", + "port-version": 0 }, "libgme": { "baseline": "0.6.3", "port-version": 0 }, "libgnutls": { - "baseline": "3.8.1", - "port-version": 1 + "baseline": "3.8.5", + "port-version": 0 }, "libgo": { "baseline": "3.1", @@ -4345,8 +4465,8 @@ "port-version": 0 }, "libgpiod": { - "baseline": "2.0.2", - "port-version": 1 + "baseline": "2.1", + "port-version": 0 }, "libgpod": { "baseline": "2019-08-29", @@ -4362,26 +4482,26 @@ }, "libgwenhywfar": { "baseline": "5.6.0", - "port-version": 4 + "port-version": 5 }, "libgxps": { "baseline": "0.3.2", - "port-version": 2 + "port-version": 3 }, "libharu": { "baseline": "2.4.4", - "port-version": 0 + "port-version": 1 }, "libhdfs3": { "baseline": "2019-11-05", - "port-version": 5 + "port-version": 6 }, "libheif": { - "baseline": "1.17.5", - "port-version": 0 + "baseline": "1.17.6", + "port-version": 1 }, "libhsplasma": { - "baseline": "2023-05-08", + "baseline": "2024-03-07", "port-version": 0 }, "libhv": { @@ -4402,12 +4522,16 @@ }, "libiconv": { "baseline": "1.17", - "port-version": 1 + "port-version": 3 }, "libics": { "baseline": "1.6.6", "port-version": 0 }, + "libid3tag": { + "baseline": "0.16.3", + "port-version": 0 + }, "libideviceactivation": { "baseline": "2023-05-01", "port-version": 1 @@ -4434,23 +4558,23 @@ }, "libirecovery": { "baseline": "2023-05-13", - "port-version": 1 + "port-version": 2 }, "libjpeg-turbo": { - "baseline": "3.0.1", + "baseline": "3.0.2", "port-version": 0 }, "libjuice": { - "baseline": "1.3.1", - "port-version": 0 + "baseline": "1.3.4", + "port-version": 1 }, "libjxl": { - "baseline": "0.8.2", - "port-version": 1 + "baseline": "0.10.2", + "port-version": 2 }, "libkeyfinder": { - "baseline": "2.2.6", - "port-version": 1 + "baseline": "2.2.8", + "port-version": 0 }, "libkml": { "baseline": "1.3.0", @@ -4458,7 +4582,7 @@ }, "liblas": { "baseline": "1.8.1", - "port-version": 13 + "port-version": 14 }, "liblbfgs": { "baseline": "1.10", @@ -4477,8 +4601,8 @@ "port-version": 1 }, "liblo": { - "baseline": "0.31", - "port-version": 4 + "baseline": "0.32", + "port-version": 0 }, "liblrc": { "baseline": "1.0.0", @@ -4492,28 +4616,32 @@ "baseline": "3.3.2", "port-version": 0 }, + "liblzf": { + "baseline": "3.6", + "port-version": 1 + }, "liblzma": { "baseline": "5.4.4", "port-version": 0 }, "libmad": { - "baseline": "0.15.1", - "port-version": 13 + "baseline": "0.16.4", + "port-version": 3 }, "libmagic": { "baseline": "5.45", - "port-version": 1 + "port-version": 2 }, "libmariadb": { "baseline": "3.3.1", "port-version": 3 }, "libmaxminddb": { - "baseline": "1.7.1", + "baseline": "1.9.1", "port-version": 0 }, "libmediainfo": { - "baseline": "23.10", + "baseline": "24.3", "port-version": 0 }, "libmesh": { @@ -4525,8 +4653,12 @@ "port-version": 2 }, "libmicrohttpd": { - "baseline": "0.9.77", - "port-version": 2 + "baseline": "1.0.1", + "port-version": 1 + }, + "libmidi2": { + "baseline": "0.10", + "port-version": 0 }, "libmikmod": { "baseline": "3.3.11.1", @@ -4542,15 +4674,15 @@ }, "libmodplug": { "baseline": "0.8.9.0", - "port-version": 10 + "port-version": 11 }, "libmorton": { "baseline": "0.2.12", "port-version": 0 }, "libmount": { - "baseline": "2.38", - "port-version": 2 + "baseline": "2.40", + "port-version": 0 }, "libmpeg2": { "baseline": "0.5.1", @@ -4565,20 +4697,24 @@ "port-version": 0 }, "libmupdf": { - "baseline": "1.22.1", - "port-version": 1 + "baseline": "1.23.11", + "port-version": 0 }, "libmysql": { "baseline": "8.0.34", - "port-version": 0 + "port-version": 1 }, "libnice": { "baseline": "0.1.21", - "port-version": 1 + "port-version": 2 }, "libnice-gst": { "baseline": "0.1.21", - "port-version": 3 + "port-version": 4 + }, + "libnick": { + "baseline": "2024.3.1", + "port-version": 0 }, "libnoise": { "baseline": "1.0.0", @@ -4621,28 +4757,36 @@ "port-version": 1 }, "libopenmpt": { - "baseline": "0.6.12", + "baseline": "0.7.4", "port-version": 0 }, "libopensp": { "baseline": "1.5.2", - "port-version": 2 + "port-version": 3 }, "libopnmidi": { "baseline": "1.5.1", - "port-version": 1 + "port-version": 2 }, "libopusenc": { "baseline": "0.2.1", "port-version": 3 }, + "liborigin": { + "baseline": "3.0.2", + "port-version": 1 + }, + "libosdp": { + "baseline": "3.0.5", + "port-version": 0 + }, "libosip2": { "baseline": "5.3.1", "port-version": 0 }, "libosmium": { "baseline": "2.20.0", - "port-version": 0 + "port-version": 1 }, "libosmscout": { "baseline": "1.1.1", @@ -4665,7 +4809,7 @@ "port-version": 2 }, "libphonenumber": { - "baseline": "8.13.23", + "baseline": "8.13.31", "port-version": 0 }, "libplist": { @@ -4677,19 +4821,19 @@ "port-version": 1 }, "libpng": { - "baseline": "1.6.40", - "port-version": 0 + "baseline": "1.6.43", + "port-version": 1 }, "libpopt": { "baseline": "1.16", "port-version": 16 }, "libpq": { - "baseline": "16.0", + "baseline": "16.2", "port-version": 1 }, "libpqxx": { - "baseline": "7.8.1", + "baseline": "7.9.0", "port-version": 0 }, "libprotobuf-mutator": { @@ -4700,13 +4844,17 @@ "baseline": "0.4.18", "port-version": 3 }, + "libpsl": { + "baseline": "0.21.5", + "port-version": 0 + }, "libqcow": { "baseline": "20221124", "port-version": 1 }, "libqglviewer": { "baseline": "2.9.1", - "port-version": 1 + "port-version": 3 }, "libqrencode": { "baseline": "4.1.1", @@ -4717,27 +4865,27 @@ "port-version": 0 }, "librabbitmq": { - "baseline": "0.11.0", - "port-version": 2 + "baseline": "0.14.0", + "port-version": 0 }, "libraqm": { "baseline": "0.10.1", "port-version": 0 }, "libraw": { - "baseline": "0.21.1", - "port-version": 2 + "baseline": "0.21.2", + "port-version": 0 }, "librdkafka": { "baseline": "2.3.0", "port-version": 0 }, "libredwg": { - "baseline": "0.12.5.5178", - "port-version": 1 + "baseline": "0.13.3", + "port-version": 0 }, "libremidi": { - "baseline": "4.2.4", + "baseline": "4.3.0", "port-version": 0 }, "libressl": { @@ -4765,8 +4913,8 @@ "port-version": 1 }, "libsass": { - "baseline": "3.6.5", - "port-version": 1 + "baseline": "3.6.6", + "port-version": 0 }, "libsbml": { "baseline": "5.20.2", @@ -4777,12 +4925,12 @@ "port-version": 0 }, "libsecret": { - "baseline": "0.20.4", - "port-version": 2 + "baseline": "0.21.4", + "port-version": 0 }, "libsercomm": { "baseline": "1.3.2", - "port-version": 0 + "port-version": 1 }, "libsigcpp": { "baseline": "3.6.0", @@ -4817,8 +4965,8 @@ "port-version": 2 }, "libsodium": { - "baseline": "1.0.18", - "port-version": 9 + "baseline": "1.0.19", + "port-version": 2 }, "libsonic": { "baseline": "0.2.0", @@ -4828,13 +4976,17 @@ "baseline": "2.0.0", "port-version": 7 }, + "libsoup": { + "baseline": "3.4.4", + "port-version": 0 + }, "libspatialindex": { "baseline": "1.9.3", "port-version": 3 }, "libspatialite": { "baseline": "5.1.0", - "port-version": 0 + "port-version": 1 }, "libspnav": { "baseline": "0.2.3", @@ -4849,12 +5001,12 @@ "port-version": 13 }, "libsrt": { - "baseline": "1.5.0", - "port-version": 3 + "baseline": "1.5.3", + "port-version": 0 }, "libsrtp": { "baseline": "2.5.0", - "port-version": 0 + "port-version": 1 }, "libssh": { "baseline": "0.10.5", @@ -4877,8 +5029,8 @@ "port-version": 0 }, "libsystemd": { - "baseline": "254", - "port-version": 0 + "baseline": "255", + "port-version": 2 }, "libtar": { "baseline": "1.2.20", @@ -4913,23 +5065,23 @@ "port-version": 0 }, "libtorch": { - "baseline": "1.12.1", - "port-version": 3 + "baseline": "2.1.2", + "port-version": 2 }, "libtorrent": { - "baseline": "2.0.9", + "baseline": "2.0.10", "port-version": 0 }, "libtracepoint": { - "baseline": "1.2.1", + "baseline": "1.3.3", "port-version": 0 }, "libtracepoint-control": { - "baseline": "1.2.1", + "baseline": "1.3.3", "port-version": 0 }, "libtracepoint-decode": { - "baseline": "1.2.1", + "baseline": "1.3.3", "port-version": 0 }, "libu2f-server": { @@ -4949,28 +5101,28 @@ "port-version": 3 }, "libunibreak": { - "baseline": "5.1", - "port-version": 0 + "baseline": "6.1", + "port-version": 1 }, "libunifex": { - "baseline": "0.3.0", + "baseline": "0.4.0", "port-version": 0 }, "libunistring": { - "baseline": "1.1", - "port-version": 3 + "baseline": "1.2", + "port-version": 0 }, "libunwind": { - "baseline": "1.7.2", + "baseline": "1.8.1", "port-version": 0 }, "liburing": { - "baseline": "2.5", + "baseline": "2.6", "port-version": 0 }, "libusb": { - "baseline": "1.0.26.11791", - "port-version": 5 + "baseline": "1.0.27", + "port-version": 1 }, "libusb-win32": { "baseline": "1.2.6.0", @@ -4989,13 +5141,17 @@ "port-version": 1 }, "libuvc": { - "baseline": "2020-11-24", - "port-version": 4 + "baseline": "0.0.7", + "port-version": 0 }, "libvault": { "baseline": "0.56.0", "port-version": 0 }, + "libvhdi": { + "baseline": "20231127", + "port-version": 0 + }, "libvmdk": { "baseline": "20221124", "port-version": 0 @@ -5006,7 +5162,7 @@ }, "libvpx": { "baseline": "1.13.1", - "port-version": 0 + "port-version": 3 }, "libwandio": { "baseline": "4.2.1", @@ -5017,8 +5173,8 @@ "port-version": 1 }, "libwebp": { - "baseline": "1.3.2", - "port-version": 0 + "baseline": "1.4.0", + "port-version": 1 }, "libwebsockets": { "baseline": "4.3.2", @@ -5026,7 +5182,7 @@ }, "libx11": { "baseline": "1.8.1", - "port-version": 1 + "port-version": 2 }, "libxau": { "baseline": "1.0.9", @@ -5042,11 +5198,11 @@ }, "libxcrypt": { "baseline": "4.4.36", - "port-version": 0 + "port-version": 1 }, "libxcvt": { "baseline": "0.1.2", - "port-version": 0 + "port-version": 1 }, "libxdamage": { "baseline": "1.1.5", @@ -5058,7 +5214,7 @@ }, "libxdiff": { "baseline": "0.23", - "port-version": 3 + "port-version": 4 }, "libxdmcp": { "baseline": "1.1.3", @@ -5101,8 +5257,8 @@ "port-version": 2 }, "libxml2": { - "baseline": "2.11.6", - "port-version": 1 + "baseline": "2.11.7", + "port-version": 0 }, "libxmlmm": { "baseline": "0.6.0", @@ -5122,7 +5278,7 @@ }, "libxpm": { "baseline": "3.5.16", - "port-version": 0 + "port-version": 1 }, "libxpresent": { "baseline": "1.0.0", @@ -5146,11 +5302,11 @@ }, "libxslt": { "baseline": "1.1.37", - "port-version": 2 + "port-version": 3 }, "libxt": { - "baseline": "1.2.1", - "port-version": 1 + "baseline": "1.3.0", + "port-version": 0 }, "libxtst": { "baseline": "1.2.4", @@ -5177,15 +5333,15 @@ "port-version": 0 }, "libzim": { - "baseline": "8.2.0", - "port-version": 2 + "baseline": "9.0.0", + "port-version": 0 }, "libzip": { "baseline": "1.10.1", "port-version": 0 }, "libzippp": { - "baseline": "7.0-1.10.1", + "baseline": "7.1-1.10.1", "port-version": 0 }, "licensepp": { @@ -5204,10 +5360,6 @@ "baseline": "2.2", "port-version": 0 }, - "linenoise-ng": { - "baseline": "4754bee2d8eb3", - "port-version": 3 - }, "linmath": { "baseline": "2022-07-30", "port-version": 0 @@ -5217,19 +5369,19 @@ "port-version": 0 }, "litehtml": { - "baseline": "0.6.0", - "port-version": 2 + "baseline": "0.9.0", + "port-version": 0 }, "live555": { - "baseline": "2023-11-08", - "port-version": 0 + "baseline": "2023-11-30", + "port-version": 1 }, "llfio": { "baseline": "2023-11-06", "port-version": 0 }, "llgi": { - "baseline": "2023-11-04", + "baseline": "2023-12-19", "port-version": 0 }, "llgl": { @@ -5237,12 +5389,16 @@ "port-version": 0 }, "llhttp": { - "baseline": "9.1.3", + "baseline": "9.2.0", + "port-version": 0 + }, + "llnl-units": { + "baseline": "0.9.1", "port-version": 0 }, "llvm": { "baseline": "17.0.2", - "port-version": 2 + "port-version": 5 }, "lmdb": { "baseline": "0.9.31", @@ -5269,16 +5425,16 @@ "port-version": 0 }, "log4cxx": { - "baseline": "1.1.0", - "port-version": 1 + "baseline": "1.2.0", + "port-version": 0 }, "loguru": { "baseline": "2.1.0", "port-version": 3 }, "lpeg": { - "baseline": "1.0.2", - "port-version": 4 + "baseline": "1.1.0", + "port-version": 0 }, "ltla-aarand": { "baseline": "2023-03-19", @@ -5329,20 +5485,24 @@ "port-version": 5 }, "luasec": { - "baseline": "1.3.1", - "port-version": 0 + "baseline": "1.3.2", + "port-version": 2 }, "luasocket": { "baseline": "3.1.0", - "port-version": 0 + "port-version": 1 }, "luminoengine": { "baseline": "0.10.1", "port-version": 1 }, + "lunarg-vulkantools": { + "baseline": "1.3.280.0", + "port-version": 0 + }, "lunasvg": { - "baseline": "2.3.8", - "port-version": 1 + "baseline": "2.3.9", + "port-version": 0 }, "luv": { "baseline": "1.44.2", @@ -5356,6 +5516,10 @@ "baseline": "1.9.4", "port-version": 1 }, + "lzav": { + "baseline": "3.13", + "port-version": 0 + }, "lzfse": { "baseline": "1.0", "port-version": 5 @@ -5380,6 +5544,10 @@ "baseline": "2019-09-02", "port-version": 3 }, + "magma": { + "baseline": "2.7.2", + "port-version": 0 + }, "magnum": { "baseline": "2020.06", "port-version": 17 @@ -5433,12 +5601,12 @@ "port-version": 0 }, "mapnik": { - "baseline": "2023-06-12", - "port-version": 2 + "baseline": "2024-04-18", + "port-version": 0 }, "marble": { - "baseline": "22.04.0", - "port-version": 2 + "baseline": "24.02.0", + "port-version": 0 }, "marisa-trie": { "baseline": "0.2.6+20200926", @@ -5453,7 +5621,7 @@ "port-version": 0 }, "materialx": { - "baseline": "1.38.8", + "baseline": "1.38.9", "port-version": 0 }, "mathc": { @@ -5473,15 +5641,15 @@ "port-version": 2 }, "matplotplusplus": { - "baseline": "1.2.0", - "port-version": 1 + "baseline": "1.2.1", + "port-version": 0 }, "matroska": { "baseline": "1.7.1", "port-version": 2 }, "mbedtls": { - "baseline": "2.28.5", + "baseline": "2.28.7", "port-version": 0 }, "mchehab-zbar": { @@ -5494,7 +5662,7 @@ }, "mdl-sdk": { "baseline": "2021.1.2", - "port-version": 4 + "port-version": 5 }, "mdns": { "baseline": "1.4.3", @@ -5518,15 +5686,15 @@ }, "mesa": { "baseline": "23.2.1", - "port-version": 0 + "port-version": 1 }, "meschach": { "baseline": "1.2b", "port-version": 6 }, "meshoptimizer": { - "baseline": "0.19", - "port-version": 1 + "baseline": "0.20", + "port-version": 0 }, "metis": { "baseline": "2022-07-27", @@ -5566,7 +5734,7 @@ }, "mimalloc": { "baseline": "2.1.2", - "port-version": 0 + "port-version": 2 }, "minc": { "baseline": "2.4.03", @@ -5577,11 +5745,11 @@ "port-version": 4 }, "miniaudio": { - "baseline": "0.11.19", + "baseline": "0.11.21", "port-version": 0 }, "minifb": { - "baseline": "2023-02-03", + "baseline": "2023-09-21", "port-version": 0 }, "minimp3": { @@ -5589,8 +5757,8 @@ "port-version": 0 }, "minio-cpp": { - "baseline": "0.1.1", - "port-version": 1 + "baseline": "0.2.0", + "port-version": 0 }, "miniply": { "baseline": "2022-09-15", @@ -5605,7 +5773,7 @@ "port-version": 0 }, "miniupnpc": { - "baseline": "2.2.5", + "baseline": "2.2.6", "port-version": 0 }, "miniz": { @@ -5613,11 +5781,11 @@ "port-version": 0 }, "minizip": { - "baseline": "1.3", - "port-version": 1 + "baseline": "1.3.1", + "port-version": 0 }, "minizip-ng": { - "baseline": "4.0.2", + "baseline": "4.0.5", "port-version": 0 }, "mio": { @@ -5625,7 +5793,7 @@ "port-version": 0 }, "mlpack": { - "baseline": "4.2.0", + "baseline": "4.3.0", "port-version": 0 }, "mman": { @@ -5653,15 +5821,15 @@ "port-version": 2 }, "mongo-c-driver": { - "baseline": "1.25.1", - "port-version": 1 + "baseline": "1.27.1", + "port-version": 0 }, "mongo-cxx-driver": { - "baseline": "3.9.0", + "baseline": "3.10.1", "port-version": 0 }, "mongoose": { - "baseline": "7.12", + "baseline": "7.13", "port-version": 0 }, "monkeys-audio": { @@ -5693,12 +5861,12 @@ "port-version": 0 }, "mp-units": { - "baseline": "2.0.0", + "baseline": "2.1.0", "port-version": 0 }, "mp3lame": { "baseline": "3.100", - "port-version": 11 + "port-version": 13 }, "mpark-patterns": { "baseline": "2019-10-03", @@ -5718,7 +5886,7 @@ }, "mpg123": { "baseline": "1.31.3", - "port-version": 3 + "port-version": 4 }, "mpi": { "baseline": "1", @@ -5752,6 +5920,10 @@ "baseline": "4.0.0", "port-version": 1 }, + "ms-ifc-sdk": { + "baseline": "0.43.1", + "port-version": 0 + }, "ms-quic": { "baseline": "1.2.0", "port-version": 0 @@ -5788,13 +5960,17 @@ "baseline": "1.0.2", "port-version": 5 }, + "mtlt": { + "baseline": "1.0.0", + "port-version": 0 + }, "mujoco": { "baseline": "2.3.2", "port-version": 1 }, "mujs": { - "baseline": "1.3.2", - "port-version": 1 + "baseline": "1.3.4", + "port-version": 0 }, "munit": { "baseline": "2019-04-06", @@ -5813,19 +5989,19 @@ "port-version": 7 }, "mvfst": { - "baseline": "2023.10.02.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "mygui": { "baseline": "3.4.3", - "port-version": 0 + "port-version": 1 }, "mysql-connector-cpp": { "baseline": "8.0.32", "port-version": 1 }, "nameof": { - "baseline": "0.10.3", + "baseline": "0.10.4", "port-version": 0 }, "nana": { @@ -5840,6 +6016,10 @@ "baseline": "4.3.11", "port-version": 0 }, + "nanobind": { + "baseline": "1.9.2", + "port-version": 0 + }, "nanodbc": { "baseline": "2.13.0", "port-version": 8 @@ -5852,13 +6032,17 @@ "baseline": "2019-09-23", "port-version": 5 }, + "nanojsonc": { + "baseline": "1.0.0", + "port-version": 0 + }, "nanomsg": { - "baseline": "1.2.0", + "baseline": "1.2.1", "port-version": 1 }, "nanopb": { - "baseline": "0.4.7", - "port-version": 2 + "baseline": "0.4.8", + "port-version": 0 }, "nanoprintf": { "baseline": "0.3.4", @@ -5873,7 +6057,7 @@ "port-version": 3 }, "nanosvg": { - "baseline": "2022-12-04", + "baseline": "2023-12-29", "port-version": 0 }, "nanovg": { @@ -5893,20 +6077,20 @@ "port-version": 2 }, "ncnn": { - "baseline": "20231027", - "port-version": 0 + "baseline": "20240102", + "port-version": 1 }, "ncurses": { "baseline": "6.4", - "port-version": 1 + "port-version": 2 }, "ndis-driver-library": { "baseline": "1.2.0", "port-version": 0 }, "neargye-semver": { - "baseline": "0.3.0", - "port-version": 1 + "baseline": "0.3.1", + "port-version": 0 }, "ned14-internal-quickcpplib": { "baseline": "2023-11-22", @@ -5918,26 +6102,30 @@ }, "netcdf-c": { "baseline": "4.8.1", - "port-version": 4 + "port-version": 5 }, "netcdf-cxx4": { "baseline": "4.3.1", "port-version": 5 }, + "netgen": { + "baseline": "6.2.2401", + "port-version": 1 + }, "nethost": { - "baseline": "8.0.0", + "baseline": "8.0.3", "port-version": 0 }, "nettle": { - "baseline": "3.8.1", - "port-version": 1 + "baseline": "3.9.1", + "port-version": 0 }, "networkdirect-sdk": { "baseline": "2.0.1", "port-version": 4 }, "nghttp2": { - "baseline": "1.58.0", + "baseline": "1.61.0", "port-version": 0 }, "nghttp2-asio": { @@ -5953,7 +6141,7 @@ "port-version": 0 }, "ngtcp2": { - "baseline": "1.1.0", + "baseline": "1.2.0", "port-version": 0 }, "nifly": { @@ -5974,7 +6162,7 @@ }, "nlopt": { "baseline": "2.7.1", - "port-version": 0 + "port-version": 1 }, "nmap": { "baseline": "7.70", @@ -5985,8 +6173,8 @@ "port-version": 1 }, "nng": { - "baseline": "1.5.2", - "port-version": 1 + "baseline": "1.7.3", + "port-version": 0 }, "nngpp": { "baseline": "1.3.0", @@ -5997,12 +6185,12 @@ "port-version": 3 }, "node-addon-api": { - "baseline": "6.1.0", + "baseline": "7.0.0", "port-version": 0 }, "node-api-headers": { - "baseline": "1.0.0", - "port-version": 1 + "baseline": "1.1.0", + "port-version": 0 }, "nodesoup": { "baseline": "2023-06-12", @@ -6025,8 +6213,8 @@ "port-version": 4 }, "nss": { - "baseline": "3.87", - "port-version": 2 + "baseline": "3.99", + "port-version": 0 }, "nsync": { "baseline": "1.26.0", @@ -6041,7 +6229,7 @@ "port-version": 1 }, "nu-book-zxing-cpp": { - "baseline": "2.1.0", + "baseline": "2.2.1", "port-version": 0 }, "nuklear": { @@ -6049,12 +6237,12 @@ "port-version": 0 }, "numactl": { - "baseline": "2.0.16", + "baseline": "2.0.18", "port-version": 0 }, "numcpp": { "baseline": "2.12.1", - "port-version": 0 + "port-version": 1 }, "nuspell": { "baseline": "5.1.4", @@ -6133,8 +6321,8 @@ "port-version": 0 }, "octomap": { - "baseline": "1.9.8", - "port-version": 1 + "baseline": "1.10.0", + "port-version": 0 }, "ode": { "baseline": "0.16.4", @@ -6149,12 +6337,12 @@ "port-version": 0 }, "ogre": { - "baseline": "14.0.1", - "port-version": 2 + "baseline": "14.2.2", + "port-version": 0 }, "ogre-next": { "baseline": "2.3.3", - "port-version": 0 + "port-version": 3 }, "ois": { "baseline": "1.5.1", @@ -6165,15 +6353,15 @@ "port-version": 2 }, "ompl": { - "baseline": "1.5.1", - "port-version": 5 + "baseline": "1.6.0", + "port-version": 0 }, "omplapp": { "baseline": "1.5.1", "port-version": 5 }, "onednn": { - "baseline": "3.3", + "baseline": "3.4", "port-version": 0 }, "oniguruma": { @@ -6182,7 +6370,7 @@ }, "onnx": { "baseline": "1.15.0", - "port-version": 0 + "port-version": 1 }, "onnx-optimizer": { "baseline": "0.3.18", @@ -6201,20 +6389,24 @@ "port-version": 0 }, "open62541": { - "baseline": "1.3.8", - "port-version": 1 + "baseline": "1.3.9", + "port-version": 0 + }, + "open62541pp": { + "baseline": "0.12.0", + "port-version": 0 }, "openal-soft": { "baseline": "1.23.1", "port-version": 0 }, "openblas": { - "baseline": "0.3.25", + "baseline": "0.3.27", "port-version": 0 }, "opencascade": { - "baseline": "7.7.2", - "port-version": 2 + "baseline": "7.8.1", + "port-version": 0 }, "opencc": { "baseline": "1.1.6", @@ -6233,8 +6425,8 @@ "port-version": 1 }, "opencsg": { - "baseline": "1.4.2", - "port-version": 4 + "baseline": "1.6.0", + "port-version": 0 }, "openctm": { "baseline": "1.0.3", @@ -6242,79 +6434,83 @@ }, "opencv": { "baseline": "4.8.0", - "port-version": 0 + "port-version": 1 }, "opencv2": { "baseline": "2.4.13.7", - "port-version": 19 + "port-version": 20 }, "opencv3": { "baseline": "3.4.18", - "port-version": 12 + "port-version": 14 }, "opencv4": { "baseline": "4.8.0", - "port-version": 12 + "port-version": 19 }, "opendnp3": { "baseline": "3.1.1", "port-version": 1 }, "openexr": { - "baseline": "3.1.8", - "port-version": 0 + "baseline": "3.2.3", + "port-version": 1 }, "openfbx": { "baseline": "2022-07-18", "port-version": 0 }, - "opengl": { - "baseline": "2022-12-04", + "openfx": { + "baseline": "1.4", + "port-version": 0 + }, + "opengl": { + "baseline": "2022-12-04", "port-version": 3 }, "opengl-registry": { - "baseline": "2022-09-29", + "baseline": "2024-02-10", "port-version": 1 }, "openh264": { "baseline": "2021-03-16", - "port-version": 3 + "port-version": 4 }, "openigtlink": { "baseline": "3.0", "port-version": 4 }, "openimageio": { - "baseline": "2.4.14.0", + "baseline": "2.5.8.0", "port-version": 3 }, "openjpeg": { - "baseline": "2.5.0", + "baseline": "2.5.2", "port-version": 1 }, "openldap": { - "baseline": "2.5.13", - "port-version": 1 + "baseline": "2.5.17", + "port-version": 0 }, "openmama": { "baseline": "6.3.2", "port-version": 3 }, "openmesh": { - "baseline": "9.0", - "port-version": 1 + "baseline": "10.0", + "port-version": 0 }, "openmpi": { "baseline": "4.1.6", - "port-version": 0 + "port-version": 1 }, "openmvg": { "baseline": "2.0", - "port-version": 9 + "port-version": 10 }, "openmvs": { "baseline": "2.1.0", - "port-version": 2 + "port-version": 5 }, "openni2": { "baseline": "2.2.0.33", @@ -6326,11 +6522,11 @@ }, "openslide": { "baseline": "3.4.1", - "port-version": 3 + "port-version": 4 }, "openssl": { - "baseline": "3.1.4", - "port-version": 1 + "baseline": "3.3.0", + "port-version": 0 }, "openssl-unix": { "baseline": "deprecated", @@ -6346,14 +6542,10 @@ }, "opensubdiv": { "baseline": "3.5.0", - "port-version": 0 + "port-version": 2 }, "opentelemetry-cpp": { - "baseline": "1.12.0", - "port-version": 1 - }, - "opentelemetry-fluentd": { - "baseline": "2.0.0", + "baseline": "1.14.2", "port-version": 1 }, "opentracing": { @@ -6362,14 +6554,14 @@ }, "openturns": { "baseline": "1.20", - "port-version": 0 + "port-version": 2 }, "openvdb": { - "baseline": "10.0.0", - "port-version": 6 + "baseline": "11.0.0", + "port-version": 0 }, "openvino": { - "baseline": "2023.2.0", + "baseline": "2024.1.0", "port-version": 0 }, "openvpn3": { @@ -6377,7 +6569,7 @@ "port-version": 2 }, "openvr": { - "baseline": "1.23.7", + "baseline": "2.5.1", "port-version": 0 }, "openxr-loader": { @@ -6393,11 +6585,11 @@ "port-version": 3 }, "optional-lite": { - "baseline": "3.5.0", - "port-version": 1 + "baseline": "3.6.0", + "port-version": 0 }, "opus": { - "baseline": "1.4", + "baseline": "1.5.1", "port-version": 0 }, "opusfile": { @@ -6405,7 +6597,7 @@ "port-version": 1 }, "orc": { - "baseline": "1.9.1", + "baseline": "2.0.0", "port-version": 0 }, "orocos-kdl": { @@ -6414,7 +6606,7 @@ }, "osg": { "baseline": "3.6.5", - "port-version": 22 + "port-version": 23 }, "osg-qt": { "baseline": "Qt5", @@ -6433,7 +6625,7 @@ "port-version": 0 }, "outcome": { - "baseline": "2.2.7", + "baseline": "2.2.8", "port-version": 0 }, "p-ranav-csv": { @@ -6450,7 +6642,7 @@ }, "paho-mqtt": { "baseline": "1.3.13", - "port-version": 0 + "port-version": 1 }, "paho-mqttpp3": { "baseline": "1.3.2", @@ -6466,14 +6658,14 @@ }, "pangolin": { "baseline": "0.8", - "port-version": 2 + "port-version": 3 }, "pangomm": { "baseline": "2.50.1", "port-version": 3 }, "parallel-hashmap": { - "baseline": "1.3.11", + "baseline": "1.3.12", "port-version": 0 }, "parallelstl": { @@ -6481,8 +6673,8 @@ "port-version": 3 }, "paraview": { - "baseline": "5.11.0", - "port-version": 4 + "baseline": "5.12.0", + "port-version": 0 }, "parmetis": { "baseline": "2022-07-27", @@ -6513,16 +6705,16 @@ "port-version": 0 }, "pcl": { - "baseline": "1.13.1", - "port-version": 1 + "baseline": "1.14.1", + "port-version": 0 }, "pcre": { "baseline": "8.45", - "port-version": 5 + "port-version": 6 }, "pcre2": { - "baseline": "10.42", - "port-version": 1 + "baseline": "10.43", + "port-version": 0 }, "pdal": { "baseline": "2.5.3", @@ -6541,8 +6733,8 @@ "port-version": 2 }, "pe-parse": { - "baseline": "2.1.0", - "port-version": 1 + "baseline": "2.1.1", + "port-version": 0 }, "pegtl": { "baseline": "3.2.7", @@ -6552,6 +6744,10 @@ "baseline": "2.8.3", "port-version": 3 }, + "perfetto": { + "baseline": "45.0", + "port-version": 0 + }, "pffft": { "baseline": "2021-10-09", "port-version": 1 @@ -6593,7 +6789,7 @@ "port-version": 2 }, "pipewire": { - "baseline": "0.3.83", + "baseline": "1.0.4", "port-version": 0 }, "pistache": { @@ -6605,11 +6801,11 @@ "port-version": 1 }, "pixman": { - "baseline": "0.42.2", - "port-version": 2 + "baseline": "0.43.4", + "port-version": 0 }, "pkgconf": { - "baseline": "2.1.0", + "baseline": "2.2.0", "port-version": 0 }, "plasma-wayland-protocols": { @@ -6621,7 +6817,7 @@ "port-version": 1 }, "plf-colony": { - "baseline": "7.3.1", + "baseline": "7.41", "port-version": 0 }, "plf-hive": { @@ -6636,6 +6832,10 @@ "baseline": "2019-08-10", "port-version": 2 }, + "plf-queue": { + "baseline": "2.2", + "port-version": 0 + }, "plf-stack": { "baseline": "2019-08-10", "port-version": 2 @@ -6664,6 +6864,10 @@ "baseline": "1.12.0", "port-version": 2 }, + "pmp-library": { + "baseline": "3.0.0", + "port-version": 0 + }, "pngpp": { "baseline": "0.2.10", "port-version": 2 @@ -6676,28 +6880,28 @@ "baseline": "2023-09-25", "port-version": 0 }, + "pocketpy": { + "baseline": "1.4.5", + "port-version": 0 + }, "poco": { - "baseline": "1.12.5.1", + "baseline": "1.13.3", "port-version": 0 }, "podofo": { - "baseline": "0.10.2", + "baseline": "0.10.3", "port-version": 0 }, "poissonrecon": { "baseline": "2021-09-26", "port-version": 0 }, - "poly2tri": { - "baseline": "2020-07-21", - "port-version": 3 - }, "polyclipping": { "baseline": "6.4.2", "port-version": 12 }, "polyhook2": { - "baseline": "2023-08-11", + "baseline": "2024-02-08", "port-version": 0 }, "polymorphic-value": { @@ -6709,8 +6913,8 @@ "port-version": 5 }, "poppler": { - "baseline": "23.11.0", - "port-version": 0 + "baseline": "24.3.0", + "port-version": 1 }, "popsift": { "baseline": "0.9", @@ -6722,7 +6926,7 @@ }, "portable-snippets": { "baseline": "2019-09-20", - "port-version": 3 + "port-version": 4 }, "portaudio": { "baseline": "19.7", @@ -6730,7 +6934,7 @@ }, "portmidi": { "baseline": "2.0.4", - "port-version": 2 + "port-version": 3 }, "portsmf": { "baseline": "239", @@ -6756,24 +6960,28 @@ "baseline": "2023-10-16", "port-version": 0 }, + "pravila00-enumflag": { + "baseline": "2024-04-12", + "port-version": 0 + }, "pravila00-make-vector": { "baseline": "2023-04-10", "port-version": 0 }, "presentmon": { - "baseline": "1.7.0", - "port-version": 2 + "baseline": "1.10.0", + "port-version": 0 }, "proj": { - "baseline": "9.3.1", + "baseline": "9.4.0", "port-version": 0 }, - "proj4": { - "baseline": "8.9.9", - "port-version": 1 + "projectm-eval": { + "baseline": "1.0.0", + "port-version": 0 }, "prometheus-cpp": { - "baseline": "1.1.0", + "baseline": "1.2.4", "port-version": 0 }, "promise-cpp": { @@ -6782,7 +6990,7 @@ }, "protobuf": { "baseline": "3.21.12", - "port-version": 0 + "port-version": 2 }, "protobuf-c": { "baseline": "1.4.1", @@ -6797,15 +7005,15 @@ "port-version": 0 }, "proxsuite": { - "baseline": "0.5.0", + "baseline": "0.6.4", "port-version": 0 }, "proxy": { - "baseline": "1.1.1", + "baseline": "2.4.0", "port-version": 0 }, "proxygen": { - "baseline": "2023.10.02.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "psimd": { @@ -6817,8 +7025,8 @@ "port-version": 1 }, "ptex": { - "baseline": "2.3.2", - "port-version": 4 + "baseline": "2.4.2", + "port-version": 0 }, "pthread": { "baseline": "3.0.0", @@ -6844,13 +7052,21 @@ "baseline": "1.14", "port-version": 0 }, + "pulsar-client-cpp": { + "baseline": "3.4.2", + "port-version": 2 + }, + "pulseaudio": { + "baseline": "17.0", + "port-version": 0 + }, "pulzed-mini": { "baseline": "0.9.14", "port-version": 0 }, "pybind11": { - "baseline": "2.11.1", - "port-version": 0 + "baseline": "2.12.0", + "port-version": 1 }, "pystring": { "baseline": "1.1.4", @@ -6861,12 +7077,12 @@ "port-version": 7 }, "python3": { - "baseline": "3.11.5", + "baseline": "3.11.8", "port-version": 2 }, "qca": { "baseline": "2.3.7", - "port-version": 0 + "port-version": 1 }, "qcoro": { "baseline": "0.10.0", @@ -6882,7 +7098,7 @@ }, "qhull": { "baseline": "8.0.2", - "port-version": 4 + "port-version": 5 }, "qnnpack": { "baseline": "2021-02-26", @@ -6901,255 +7117,255 @@ "port-version": 1 }, "qscintilla": { - "baseline": "2.13.4", - "port-version": 2 + "baseline": "2.14.1", + "port-version": 1 }, "qt": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qt-advanced-docking-system": { - "baseline": "4.2.1", + "baseline": "4.3.0", "port-version": 0 }, "qt3d": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qt5": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 2 }, "qt5-3d": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-activeqt": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-androidextras": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-base": { - "baseline": "5.15.11", + "baseline": "5.15.13", "port-version": 1 }, "qt5-canvas3d": { "baseline": "0", - "port-version": 2 + "port-version": 3 }, "qt5-charts": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-connectivity": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-datavis3d": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-declarative": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-doc": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-gamepad": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-graphicaleffects": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-imageformats": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 2 }, "qt5-location": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-macextras": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-modularscripts": { "baseline": "deprecated", "port-version": 1 }, "qt5-mqtt": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-multimedia": { - "baseline": "5.15.11", + "baseline": "5.15.13", "port-version": 1 }, "qt5-networkauth": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-purchasing": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-quickcontrols": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-quickcontrols2": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-remoteobjects": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-script": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-scxml": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-sensors": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-serialbus": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-serialport": { - "baseline": "5.15.11", + "baseline": "5.15.13", "port-version": 0 }, "qt5-speech": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-svg": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-tools": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-translations": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-virtualkeyboard": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-wayland": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-webchannel": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-webengine": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 3 }, "qt5-webglplugin": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-websockets": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-webview": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-winextras": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 2 }, "qt5-x11extras": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5-xmlpatterns": { - "baseline": "5.15.11", - "port-version": 0 + "baseline": "5.15.13", + "port-version": 1 }, "qt5compat": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtactiveqt": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtapplicationmanager": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtbase": { - "baseline": "6.6.1", - "port-version": 1 + "baseline": "6.7.0", + "port-version": 0 }, "qtcharts": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtcoap": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtconnectivity": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtdatavis3d": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtdeclarative": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtdeviceutilities": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtdoc": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtgraphs": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtgrpc": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qthttpserver": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtimageformats": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtinterfaceframework": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtkeychain": { @@ -7158,122 +7374,122 @@ }, "qtkeychain-qt6": { "baseline": "0.14.1", - "port-version": 0 + "port-version": 1 }, "qtlanguageserver": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtlocation": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtlottie": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtmqtt": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtmultimedia": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtnetworkauth": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtopcua": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtpositioning": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtquick3d": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtquick3dphysics": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtquickcontrols2": { "baseline": "deprecated", - "port-version": 0 + "port-version": 1 }, "qtquickeffectmaker": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtquicktimeline": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtremoteobjects": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtscxml": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtsensors": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtserialbus": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtserialport": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtshadertools": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtspeech": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtsvg": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qttools": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qttranslations": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtvirtualkeyboard": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtwayland": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtwebchannel": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtwebengine": { - "baseline": "6.6.1", - "port-version": 1 + "baseline": "6.7.0", + "port-version": 0 }, "qtwebsockets": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "qtwebview": { - "baseline": "6.6.1", + "baseline": "6.7.0", "port-version": 0 }, "quadtree": { @@ -7281,7 +7497,7 @@ "port-version": 0 }, "quantlib": { - "baseline": "1.32", + "baseline": "1.34", "port-version": 0 }, "quaternions": { @@ -7294,23 +7510,23 @@ }, "quickfast": { "baseline": "1.5", - "port-version": 3 + "port-version": 4 }, "quickfix": { "baseline": "1.15.1", "port-version": 9 }, "quill": { - "baseline": "3.5.0", + "baseline": "3.8.0", "port-version": 0 }, "quirc": { - "baseline": "1.1", - "port-version": 3 + "baseline": "1.2", + "port-version": 0 }, "qwt": { - "baseline": "6.2.0+20220616", - "port-version": 1 + "baseline": "6.3.0", + "port-version": 0 }, "qwtw": { "baseline": "3.1.0", @@ -7338,27 +7554,27 @@ }, "range-v3": { "baseline": "0.12.0", - "port-version": 1 + "port-version": 2 }, "range-v3-vs2015": { "baseline": "20151130-vcpkg5", "port-version": 2 }, "rapidcheck": { - "baseline": "2023-01-13", + "baseline": "2023-12-14", "port-version": 0 }, "rapidcsv": { - "baseline": "8.64", + "baseline": "8.80", "port-version": 0 }, "rapidfuzz": { - "baseline": "2.0.0", + "baseline": "3.0.2", "port-version": 0 }, "rapidjson": { "baseline": "2023-07-17", - "port-version": 0 + "port-version": 1 }, "rapidxml": { "baseline": "1.13", @@ -7382,18 +7598,18 @@ }, "rbdl": { "baseline": "3.3.0", - "port-version": 5 + "port-version": 6 }, "rbdl-orb": { "baseline": "3.2.0", "port-version": 2 }, "re2": { - "baseline": "2023-07-01", - "port-version": 0 + "baseline": "2024-04-01", + "port-version": 2 }, "reactiveplusplus": { - "baseline": "0.2.3", + "baseline": "2.0.0", "port-version": 0 }, "readerwriterqueue": { @@ -7422,7 +7638,7 @@ }, "realsense2": { "baseline": "2.54.2", - "port-version": 1 + "port-version": 2 }, "recast": { "baseline": "deprecated", @@ -7430,14 +7646,14 @@ }, "recastnavigation": { "baseline": "1.6.0", - "port-version": 0 + "port-version": 1 }, "recycle": { "baseline": "6.0.0", "port-version": 0 }, "redis-plus-plus": { - "baseline": "1.3.10", + "baseline": "1.3.12", "port-version": 0 }, "refl-cpp": { @@ -7449,7 +7665,7 @@ "port-version": 0 }, "rendergraph": { - "baseline": "1.3.0", + "baseline": "1.4.1", "port-version": 0 }, "replxx": { @@ -7477,7 +7693,7 @@ "port-version": 0 }, "restinio": { - "baseline": "0.7.0", + "baseline": "0.7.2", "port-version": 0 }, "rexo": { @@ -7486,7 +7702,7 @@ }, "rhash": { "baseline": "1.4.4", - "port-version": 0 + "port-version": 1 }, "rhasheq": { "baseline": "2023-06-17", @@ -7514,14 +7730,14 @@ }, "rmlui": { "baseline": "5.1", - "port-version": 0 + "port-version": 1 }, "rmqcpp": { "baseline": "1.0.0", "port-version": 0 }, "roaring": { - "baseline": "0.9.6", + "baseline": "3.0.1", "port-version": 0 }, "robin-hood-hashing": { @@ -7529,11 +7745,19 @@ "port-version": 0 }, "robin-map": { - "baseline": "1.2.1", + "baseline": "1.2.2", + "port-version": 0 + }, + "robotraconteur": { + "baseline": "1.2.0", + "port-version": 1 + }, + "robotraconteur-companion": { + "baseline": "0.3.1", "port-version": 0 }, "rocksdb": { - "baseline": "8.5.3", + "baseline": "9.1.0", "port-version": 0 }, "rpclib": { @@ -7542,7 +7766,7 @@ }, "rply": { "baseline": "1.1.4", - "port-version": 3 + "port-version": 4 }, "rsasynccpp": { "baseline": "0.0.7", @@ -7566,22 +7790,26 @@ }, "rsocket": { "baseline": "2021.08.30.00", - "port-version": 2 + "port-version": 4 }, "rtabmap": { - "baseline": "0.21.0", - "port-version": 3 + "baseline": "0.21.4.1", + "port-version": 1 + }, + "rtabmap-res-tool": { + "baseline": "0.21.4.1", + "port-version": 0 }, "rtaudio": { "baseline": "6.0.1", - "port-version": 0 + "port-version": 1 }, "rtlsdr": { "baseline": "2020-04-16", "port-version": 4 }, "rtmfp-cpp": { - "baseline": "1.4.0-20230213.18168ec", + "baseline": "1.5.1", "port-version": 0 }, "rtmidi": { @@ -7590,11 +7818,11 @@ }, "rttr": { "baseline": "0.9.6+20210811", - "port-version": 0 + "port-version": 1 }, "rubberband": { "baseline": "3.3.0", - "port-version": 0 + "port-version": 1 }, "rxcpp": { "baseline": "4.1.1", @@ -7617,20 +7845,20 @@ "port-version": 9 }, "s2geometry": { - "baseline": "0.10.0", + "baseline": "0.11.1", "port-version": 0 }, "s2n": { - "baseline": "1.3.56", + "baseline": "1.4.8", "port-version": 0 }, "safeint": { - "baseline": "3.0.26", + "baseline": "3.0.28", "port-version": 0 }, "sail": { - "baseline": "0.9.0", - "port-version": 0 + "baseline": "0.9.4", + "port-version": 1 }, "sajson": { "baseline": "2018-09-21", @@ -7681,8 +7909,8 @@ "port-version": 0 }, "scnlib": { - "baseline": "1.1.2", - "port-version": 0 + "baseline": "2.0.2", + "port-version": 2 }, "scope-guard": { "baseline": "1.1.0", @@ -7701,28 +7929,28 @@ "port-version": 3 }, "sdbus-cpp": { - "baseline": "1.3.0", - "port-version": 1 + "baseline": "1.5.0", + "port-version": 0 }, "sdformat10": { "baseline": "10.0.0", - "port-version": 3 + "port-version": 4 }, "sdformat13": { - "baseline": "13.5.0", - "port-version": 1 + "baseline": "13.6.0", + "port-version": 0 }, "sdformat6": { "baseline": "6.2.0", - "port-version": 6 + "port-version": 7 }, "sdformat9": { "baseline": "9.8.0", - "port-version": 1 + "port-version": 2 }, "sdl1": { "baseline": "1.2.15", - "port-version": 19 + "port-version": 20 }, "sdl1-mixer": { "baseline": "2023-03-25", @@ -7733,20 +7961,20 @@ "port-version": 6 }, "sdl2": { - "baseline": "2.28.5", - "port-version": 1 + "baseline": "2.30.1", + "port-version": 0 }, "sdl2-gfx": { "baseline": "1.0.4", "port-version": 11 }, "sdl2-image": { - "baseline": "2.6.3", - "port-version": 1 + "baseline": "2.8.2", + "port-version": 2 }, "sdl2-mixer": { - "baseline": "2.6.3", - "port-version": 2 + "baseline": "2.8.0", + "port-version": 3 }, "sdl2-mixer-ext": { "baseline": "2.6.0", @@ -7757,7 +7985,7 @@ "port-version": 3 }, "sdl2-ttf": { - "baseline": "2.20.2", + "baseline": "2.22.0", "port-version": 1 }, "sdl2pp": { @@ -7770,7 +7998,7 @@ }, "seal": { "baseline": "4.1.1", - "port-version": 1 + "port-version": 2 }, "seasocks": { "baseline": "1.4.6", @@ -7782,14 +8010,14 @@ }, "selene": { "baseline": "0.3.1", - "port-version": 6 + "port-version": 7 }, "sentencepiece": { - "baseline": "0.1.99", - "port-version": 1 + "baseline": "0.2.0", + "port-version": 0 }, "sentry-native": { - "baseline": "0.6.7", + "baseline": "0.7.2", "port-version": 0 }, "septag-dmon": { @@ -7825,15 +8053,15 @@ "port-version": 0 }, "sfsexp": { - "baseline": "1.3.1", - "port-version": 1 + "baseline": "1.4.1", + "port-version": 0 }, "shader-slang": { - "baseline": "0.27.20", + "baseline": "2024.1.12", "port-version": 0 }, "shaderc": { - "baseline": "2023.7", + "baseline": "2023.8", "port-version": 0 }, "shaderwriter": { @@ -7841,11 +8069,11 @@ "port-version": 0 }, "shapelib": { - "baseline": "1.5.0", - "port-version": 4 + "baseline": "1.6.0", + "port-version": 0 }, "shiftmedia-libgcrypt": { - "baseline": "1.10.1-1", + "baseline": "1.10.3-1", "port-version": 0 }, "shiftmedia-libgnutls": { @@ -7854,7 +8082,7 @@ }, "shiftmedia-libgpg-error": { "baseline": "1.45", - "port-version": 0 + "port-version": 1 }, "shiva": { "baseline": "1.0", @@ -7862,7 +8090,7 @@ }, "shogun": { "baseline": "6.1.4", - "port-version": 9 + "port-version": 10 }, "si": { "baseline": "2.5.1", @@ -7881,8 +8109,8 @@ "port-version": 5 }, "simage": { - "baseline": "1.8.2", - "port-version": 2 + "baseline": "1.8.3", + "port-version": 0 }, "simbody": { "baseline": "2023-01-10", @@ -7890,18 +8118,22 @@ }, "simd": { "baseline": "5.3.128", - "port-version": 0 + "port-version": 1 }, "simde": { - "baseline": "0.7.6", + "baseline": "0.8.2", "port-version": 0 }, "simdjson": { - "baseline": "3.6.2", + "baseline": "3.8.0", "port-version": 0 }, "simdutf": { - "baseline": "3.2.16", + "baseline": "5.2.5", + "port-version": 0 + }, + "simonbrunel-qtpromise": { + "baseline": "0.7.0", "port-version": 0 }, "simple-fft": { @@ -7913,7 +8145,7 @@ "port-version": 0 }, "simpleini": { - "baseline": "4.19", + "baseline": "4.22", "port-version": 0 }, "simsimd": { @@ -7929,8 +8161,8 @@ "port-version": 0 }, "skia": { - "baseline": "0.38.2", - "port-version": 1 + "baseline": "124", + "port-version": 0 }, "skyr-url": { "baseline": "1.13.0", @@ -7972,6 +8204,10 @@ "baseline": "0", "port-version": 2 }, + "snitch": { + "baseline": "1.2.4", + "port-version": 0 + }, "snowhouse": { "baseline": "5.0.0", "port-version": 2 @@ -7981,7 +8217,7 @@ "port-version": 0 }, "sobjectizer": { - "baseline": "5.8.1.1", + "baseline": "5.8.2", "port-version": 0 }, "soci": { @@ -7989,16 +8225,16 @@ "port-version": 3 }, "socket-io-client": { - "baseline": "2023-02-14", + "baseline": "2023-11-11", "port-version": 0 }, "sockpp": { - "baseline": "0.8.1", + "baseline": "1.0.0", "port-version": 0 }, "soem": { "baseline": "2023-06-09", - "port-version": 1 + "port-version": 2 }, "soil": { "baseline": "2021-04-22", @@ -8033,19 +8269,19 @@ "port-version": 2 }, "soundtouch": { - "baseline": "2.3.2", - "port-version": 1 + "baseline": "2.3.3", + "port-version": 0 }, "soxr": { "baseline": "0.1.3", - "port-version": 7 + "port-version": 8 }, "spaceland": { "baseline": "7.8.2", "port-version": 8 }, "span-lite": { - "baseline": "0.10.3", + "baseline": "0.11.0", "port-version": 0 }, "sparsehash": { @@ -8061,8 +8297,8 @@ "port-version": 0 }, "spdk": { - "baseline": "19.01.1", - "port-version": 3 + "baseline": "24.01", + "port-version": 0 }, "spdk-dpdk": { "baseline": "2018-11-24", @@ -8077,7 +8313,7 @@ "port-version": 3 }, "spdlog": { - "baseline": "1.12.0", + "baseline": "1.14.1", "port-version": 0 }, "spectra": { @@ -8098,22 +8334,22 @@ }, "spirit-po": { "baseline": "1.1.2", - "port-version": 3 + "port-version": 4 }, "spirv-cross": { - "baseline": "2021-01-15", - "port-version": 2 + "baseline": "1.3.280.0", + "port-version": 0 }, "spirv-headers": { - "baseline": "1.3.246.1", + "baseline": "1.3.280.0", "port-version": 0 }, "spirv-reflect": { - "baseline": "1.3.236.0", - "port-version": 0 + "baseline": "1.3.280.0", + "port-version": 1 }, "spirv-tools": { - "baseline": "2023.2", + "baseline": "1.3.280.0", "port-version": 0 }, "spout2": { @@ -8129,19 +8365,19 @@ "port-version": 3 }, "sqlcipher": { - "baseline": "4.5.4", + "baseline": "4.5.6", "port-version": 0 }, "sqlite-modern-cpp": { - "baseline": "3.2-936cd0c8", - "port-version": 2 + "baseline": "2023-12-03", + "port-version": 0 }, "sqlite-orm": { "baseline": "1.8.2", "port-version": 1 }, "sqlite3": { - "baseline": "3.43.2", + "baseline": "3.45.3", "port-version": 0 }, "sqlitecpp": { @@ -8149,8 +8385,8 @@ "port-version": 0 }, "sqlpp11": { - "baseline": "0.61", - "port-version": 3 + "baseline": "0.64", + "port-version": 0 }, "sqlpp11-connector-mysql": { "baseline": "0.61", @@ -8165,8 +8401,8 @@ "port-version": 0 }, "sratom": { - "baseline": "0.6.4", - "port-version": 2 + "baseline": "0.6.16", + "port-version": 0 }, "srell": { "baseline": "3.010", @@ -8177,7 +8413,7 @@ "port-version": 0 }, "sse2neon": { - "baseline": "1.6.0", + "baseline": "1.7.0", "port-version": 0 }, "stackwalker": { @@ -8229,15 +8465,19 @@ "port-version": 2 }, "string-theory": { - "baseline": "3.6", + "baseline": "3.8", "port-version": 0 }, "string-view-lite": { "baseline": "1.7.0", "port-version": 1 }, + "stringzilla": { + "baseline": "3.7.0", + "port-version": 0 + }, "strong-type": { - "baseline": "12", + "baseline": "14", "port-version": 0 }, "stronk": { @@ -8246,10 +8486,10 @@ }, "strtk": { "baseline": "2020-09-14", - "port-version": 3 + "port-version": 4 }, "stx": { - "baseline": "0.0.3", + "baseline": "1.0.5", "port-version": 0 }, "stxxl": { @@ -8265,7 +8505,7 @@ "port-version": 0 }, "superlu": { - "baseline": "6.0.0", + "baseline": "6.0.1", "port-version": 0 }, "swenson-sort": { @@ -8273,7 +8513,7 @@ "port-version": 0 }, "symengine": { - "baseline": "0.11.1", + "baseline": "0.11.2", "port-version": 0 }, "systemc": { @@ -8293,7 +8533,7 @@ "port-version": 6 }, "taglib": { - "baseline": "1.13.1", + "baseline": "2.0", "port-version": 1 }, "talib": { @@ -8361,7 +8601,7 @@ "port-version": 0 }, "tesseract": { - "baseline": "5.3.3", + "baseline": "5.3.4", "port-version": 0 }, "tfhe": { @@ -8369,7 +8609,7 @@ "port-version": 5 }, "tgbot-cpp": { - "baseline": "1.7.2", + "baseline": "1.7.3", "port-version": 0 }, "tgc": { @@ -8378,26 +8618,26 @@ }, "tgui": { "baseline": "1.1.0", - "port-version": 0 + "port-version": 1 }, "theia": { "baseline": "0.8", - "port-version": 9 + "port-version": 10 }, "think-cell-range": { "baseline": "2023.1", - "port-version": 0 + "port-version": 1 }, "thomasmonkman-filewatch": { "baseline": "2023-01-16", - "port-version": 1 + "port-version": 2 }, "thor": { "baseline": "2022-04-16", "port-version": 0 }, "thorvg": { - "baseline": "0.11.3", + "baseline": "0.13.2", "port-version": 0 }, "threadpool": { @@ -8405,16 +8645,16 @@ "port-version": 3 }, "thrift": { - "baseline": "0.19.0", + "baseline": "0.20.0", "port-version": 0 }, "tidy-html5": { "baseline": "5.8.0", - "port-version": 0 + "port-version": 1 }, "tiff": { "baseline": "4.6.0", - "port-version": 1 + "port-version": 4 }, "tinkerforge": { "baseline": "2.1.25", @@ -8449,7 +8689,7 @@ "port-version": 3 }, "tinydir": { - "baseline": "1.2.5", + "baseline": "1.2.6", "port-version": 0 }, "tinyexif": { @@ -8461,7 +8701,7 @@ "port-version": 2 }, "tinyexr": { - "baseline": "1.0.5", + "baseline": "1.0.8", "port-version": 0 }, "tinyfiledialogs": { @@ -8473,7 +8713,7 @@ "port-version": 0 }, "tinygltf": { - "baseline": "2.8.17", + "baseline": "2.8.21", "port-version": 0 }, "tinynpy": { @@ -8481,19 +8721,19 @@ "port-version": 6 }, "tinyobjloader": { - "baseline": "2.0.0-rc9", + "baseline": "2.0.0rc13", "port-version": 0 }, "tinyorm": { - "baseline": "0.36.5", - "port-version": 2 + "baseline": "0.37.3", + "port-version": 0 }, "tinyply": { "baseline": "2.3.4", "port-version": 0 }, "tinyspline": { - "baseline": "0.4.0", + "baseline": "0.6.0", "port-version": 0 }, "tinythread": { @@ -8506,7 +8746,7 @@ }, "tinyutf8": { "baseline": "4.4.3", - "port-version": 0 + "port-version": 1 }, "tinyxml": { "baseline": "2.6.2", @@ -8537,23 +8777,23 @@ "port-version": 1 }, "tlx": { - "baseline": "0.5.20191212", - "port-version": 4 + "baseline": "0.6.1", + "port-version": 0 }, "tmx": { - "baseline": "1.2.0", - "port-version": 2 + "baseline": "1.4.0", + "port-version": 0 }, "tmxlite": { - "baseline": "1.3.0", - "port-version": 1 + "baseline": "1.4.4", + "port-version": 0 }, "tmxparser": { "baseline": "2019-10-14", "port-version": 0 }, "toml11": { - "baseline": "3.7.1", + "baseline": "3.8.1", "port-version": 0 }, "tomlplusplus": { @@ -8566,14 +8806,14 @@ }, "tracy": { "baseline": "0.10.0", - "port-version": 1 + "port-version": 2 }, "transwarp": { - "baseline": "2.2.2", + "baseline": "2.2.3", "port-version": 0 }, "trantor": { - "baseline": "1.5.15", + "baseline": "1.5.18", "port-version": 0 }, "tre": { @@ -8594,7 +8834,7 @@ }, "treehopper": { "baseline": "1.11.3", - "port-version": 8 + "port-version": 9 }, "triangle": { "baseline": "1.6", @@ -8605,16 +8845,20 @@ "port-version": 0 }, "trompeloeil": { - "baseline": "45", + "baseline": "47", + "port-version": 0 + }, + "try-catcher": { + "baseline": "1.0.1", "port-version": 0 }, "tsl-hopscotch-map": { - "baseline": "2.3.0", - "port-version": 3 + "baseline": "2.3.1", + "port-version": 0 }, "tsl-ordered-map": { - "baseline": "1.0.0", - "port-version": 3 + "baseline": "1.1.0", + "port-version": 0 }, "tsl-sparse-map": { "baseline": "0.6.2", @@ -8633,8 +8877,8 @@ "port-version": 3 }, "tvision": { - "baseline": "2021-08-10", - "port-version": 1 + "baseline": "2024-02-28", + "port-version": 0 }, "tweeny": { "baseline": "3.2.0", @@ -8645,8 +8889,8 @@ "port-version": 3 }, "type-safe": { - "baseline": "0.2.2", - "port-version": 1 + "baseline": "0.2.3", + "port-version": 0 }, "uchardet": { "baseline": "0.0.8", @@ -8661,7 +8905,7 @@ "port-version": 1 }, "uni-algo": { - "baseline": "1.0.0", + "baseline": "1.2.0", "port-version": 0 }, "unicorn": { @@ -8674,7 +8918,7 @@ }, "units": { "baseline": "2.3.3", - "port-version": 0 + "port-version": 1 }, "unittest-cpp": { "baseline": "2.0.0", @@ -8685,7 +8929,7 @@ "port-version": 2 }, "unordered-dense": { - "baseline": "4.1.2", + "baseline": "4.4.0", "port-version": 0 }, "unqlite": { @@ -8693,8 +8937,8 @@ "port-version": 2 }, "unrar": { - "baseline": "6.1.7", - "port-version": 3 + "baseline": "7.0.7", + "port-version": 0 }, "upb": { "baseline": "2022-06-21", @@ -8705,7 +8949,7 @@ "port-version": 0 }, "urdfdom-headers": { - "baseline": "1.1.0", + "baseline": "1.1.1", "port-version": 0 }, "urho3d": { @@ -8718,34 +8962,38 @@ }, "usbmuxd": { "baseline": "2023-07-21", - "port-version": 0 + "port-version": 1 }, "usd": { - "baseline": "23.5", - "port-version": 3 + "baseline": "24.5", + "port-version": 0 }, "usearch": { "baseline": "2.3.2", "port-version": 0 }, "usockets": { - "baseline": "0.8.6", + "baseline": "0.8.8", "port-version": 1 }, "usrsctp": { "baseline": "0.9.5.0", - "port-version": 2 + "port-version": 3 + }, + "utf8-range": { + "baseline": "2023-11-09", + "port-version": 0 }, "utf8h": { "baseline": "2021-11-18", "port-version": 1 }, "utf8proc": { - "baseline": "2.7.0", - "port-version": 1 + "baseline": "2.9.0", + "port-version": 0 }, "utfcpp": { - "baseline": "4.0.2", + "baseline": "4.0.5", "port-version": 0 }, "utfz": { @@ -8757,11 +9005,11 @@ "port-version": 0 }, "uthenticode": { - "baseline": "1.0.6", - "port-version": 2 + "baseline": "2.0.1", + "port-version": 0 }, "uvatlas": { - "baseline": "2023-10-31", + "baseline": "2024-02-21", "port-version": 0 }, "uvw": { @@ -8769,7 +9017,7 @@ "port-version": 0 }, "uwebsockets": { - "baseline": "20.47.0", + "baseline": "20.62.0", "port-version": 0 }, "v-hacd": { @@ -8778,10 +9026,10 @@ }, "v8": { "baseline": "9.1.269.39", - "port-version": 6 + "port-version": 7 }, "valijson": { - "baseline": "1.0.1", + "baseline": "1.0.2", "port-version": 0 }, "value-ptr-lite": { @@ -8790,7 +9038,7 @@ }, "vamp-sdk": { "baseline": "2.10", - "port-version": 4 + "port-version": 5 }, "variant-lite": { "baseline": "2.0.0", @@ -8804,8 +9052,12 @@ "baseline": "2022.02", "port-version": 0 }, + "vcpkg-boost": { + "baseline": "2024-04-25", + "port-version": 0 + }, "vcpkg-cmake": { - "baseline": "2023-05-04", + "baseline": "2024-04-18", "port-version": 0 }, "vcpkg-cmake-config": { @@ -8813,11 +9065,11 @@ "port-version": 1 }, "vcpkg-cmake-get-vars": { - "baseline": "2023-03-02", + "baseline": "2023-12-31", "port-version": 0 }, "vcpkg-get-python-packages": { - "baseline": "2023-07-28", + "baseline": "2024-01-24", "port-version": 0 }, "vcpkg-gfortran": { @@ -8825,28 +9077,28 @@ "port-version": 3 }, "vcpkg-gn": { - "baseline": "2021-11-16", - "port-version": 3 + "baseline": "2024-02-22", + "port-version": 0 }, "vcpkg-msbuild": { "baseline": "2023-08-08", "port-version": 0 }, "vcpkg-pkgconfig-get-modules": { - "baseline": "2023-09-06", + "baseline": "2024-04-03", "port-version": 0 }, "vcpkg-qmake": { "baseline": "2023-03-22", - "port-version": 0 + "port-version": 1 }, "vcpkg-tool-bazel": { "baseline": "5.2.0", "port-version": 0 }, "vcpkg-tool-gn": { - "baseline": "2022-04-16", - "port-version": 1 + "baseline": "2024-02-22", + "port-version": 0 }, "vcpkg-tool-gyp-next": { "baseline": "2022-10-15", @@ -8857,8 +9109,8 @@ "port-version": 1 }, "vcpkg-tool-meson": { - "baseline": "0.63", - "port-version": 0 + "baseline": "1.3.2", + "port-version": 2 }, "vcpkg-tool-mozbuild": { "baseline": "4.0.2", @@ -8880,6 +9132,14 @@ "baseline": "2.02.00", "port-version": 0 }, + "veigar": { + "baseline": "1.0", + "port-version": 0 + }, + "velodyne-decoder": { + "baseline": "3.0.0", + "port-version": 1 + }, "verdict": { "baseline": "1.4.0", "port-version": 0 @@ -8901,13 +9161,17 @@ "port-version": 0 }, "vk-bootstrap": { - "baseline": "0.7", + "baseline": "1.3.279", "port-version": 1 }, "vkfft": { "baseline": "1.2.31", "port-version": 0 }, + "vladimirshaleev-ipaddress": { + "baseline": "1.0.1", + "port-version": 0 + }, "vlfeat": { "baseline": "2020-07-10", "port-version": 3 @@ -8917,7 +9181,7 @@ "port-version": 1 }, "volk": { - "baseline": "1.3.250", + "baseline": "1.3.280.0", "port-version": 0 }, "vowpal-wabbit": { @@ -8929,43 +9193,67 @@ "port-version": 2 }, "vsg": { - "baseline": "1.0.9", + "baseline": "1.1.2", + "port-version": 0 + }, + "vsgimgui": { + "baseline": "0.1.0", "port-version": 0 }, "vsgxchange": { "baseline": "1.0.5", - "port-version": 0 + "port-version": 1 }, "vtk": { - "baseline": "9.2.0-pv5.11.0", - "port-version": 10 + "baseline": "9.3.0-pv5.12.0", + "port-version": 3 }, "vtk-dicom": { "baseline": "0.8.14", "port-version": 2 }, "vtk-m": { - "baseline": "1.9.0", - "port-version": 2 + "baseline": "2.1.0", + "port-version": 0 }, "vulkan": { - "baseline": "1.1.82.1", - "port-version": 6 + "baseline": "2023-12-17", + "port-version": 0 }, "vulkan-headers": { - "baseline": "1.3.260", + "baseline": "1.3.280.0", "port-version": 0 }, "vulkan-hpp": { "baseline": "deprecated", "port-version": 0 }, + "vulkan-loader": { + "baseline": "1.3.280.0", + "port-version": 0 + }, "vulkan-memory-allocator": { "baseline": "3.0.1", - "port-version": 3 + "port-version": 4 }, "vulkan-memory-allocator-hpp": { "baseline": "3.0.1.1", + "port-version": 1 + }, + "vulkan-sdk-components": { + "baseline": "1.3.280.0", + "port-version": 0 + }, + "vulkan-tools": { + "baseline": "1.3.280.0", + "port-version": 0 + }, + "vulkan-utility-libraries": { + "baseline": "1.3.280.0", + "port-version": 0 + }, + "vulkan-validationlayers": { + "baseline": "1.3.280.0", "port-version": 0 }, "vvenc": { @@ -8974,18 +9262,18 @@ }, "vxl": { "baseline": "2.0.2", - "port-version": 4 + "port-version": 6 }, "wampcc": { "baseline": "2019-09-04", "port-version": 5 }, "wangle": { - "baseline": "2023.10.02.00", + "baseline": "2024.05.06.00", "port-version": 0 }, "wasmedge": { - "baseline": "0.12.1", + "baseline": "0.13.5", "port-version": 1 }, "wavelib": { @@ -8994,7 +9282,7 @@ }, "wavpack": { "baseline": "5.6.0", - "port-version": 0 + "port-version": 1 }, "wayland": { "baseline": "1.21.0", @@ -9013,7 +9301,7 @@ "port-version": 3 }, "webview2": { - "baseline": "1.0.2088.41", + "baseline": "1.0.2277.86", "port-version": 0 }, "wepoll": { @@ -9029,7 +9317,7 @@ "port-version": 2 }, "wil": { - "baseline": "2023-10-28", + "baseline": "2024-01-22", "port-version": 0 }, "wildmidi": { @@ -9053,7 +9341,7 @@ "port-version": 0 }, "winreg": { - "baseline": "6.1.0", + "baseline": "6.2.0", "port-version": 0 }, "winsock2": { @@ -9081,8 +9369,8 @@ "port-version": 0 }, "wolfssl": { - "baseline": "5.6.4", - "port-version": 1 + "baseline": "5.7.0", + "port-version": 0 }, "wolftpm": { "baseline": "2.7.0", @@ -9105,8 +9393,8 @@ "port-version": 0 }, "wt": { - "baseline": "4.9.1", - "port-version": 2 + "baseline": "4.10.4", + "port-version": 1 }, "wtl": { "baseline": "10.0.10320", @@ -9121,16 +9409,16 @@ "port-version": 0 }, "wxwidgets": { - "baseline": "3.2.3", - "port-version": 0 + "baseline": "3.2.4", + "port-version": 2 }, "wyhash": { - "baseline": "2023-01-25", + "baseline": "2023-12-03", "port-version": 0 }, "x-plane": { - "baseline": "3.0.3", - "port-version": 2 + "baseline": "4.0.1", + "port-version": 0 }, "x264": { "baseline": "0.164.3107", @@ -9141,7 +9429,7 @@ "port-version": 0 }, "x86-simd-sort": { - "baseline": "3.0", + "baseline": "4.0", "port-version": 0 }, "xapian": { @@ -9150,7 +9438,7 @@ }, "xaudio2redist": { "baseline": "1.2.11", - "port-version": 1 + "port-version": 2 }, "xbitmaps": { "baseline": "1.1.2", @@ -9174,7 +9462,7 @@ }, "xcb-proto": { "baseline": "1.14.1", - "port-version": 1 + "port-version": 2 }, "xcb-render-util": { "baseline": "0.3.10", @@ -9186,7 +9474,7 @@ }, "xcb-util-errors": { "baseline": "1.0.1", - "port-version": 0 + "port-version": 1 }, "xcb-util-m4": { "baseline": "2022-01-24", @@ -9197,8 +9485,8 @@ "port-version": 1 }, "xerces-c": { - "baseline": "3.2.4", - "port-version": 3 + "baseline": "3.2.5", + "port-version": 0 }, "xeus": { "baseline": "0.24.3", @@ -9217,11 +9505,11 @@ "port-version": 0 }, "xmlsec": { - "baseline": "1.3.1", - "port-version": 2 + "baseline": "1.3.3", + "port-version": 0 }, "xnnpack": { - "baseline": "2022-02-17", + "baseline": "2022-12-22", "port-version": 0 }, "xorg-macros": { @@ -9249,11 +9537,11 @@ "port-version": 2 }, "xsimd": { - "baseline": "12.0.0", + "baseline": "12.1.1", "port-version": 0 }, "xtensor": { - "baseline": "0.24.7", + "baseline": "0.25.0", "port-version": 0 }, "xtensor-blas": { @@ -9269,7 +9557,7 @@ "port-version": 1 }, "xtl": { - "baseline": "0.7.5", + "baseline": "0.7.7", "port-version": 0 }, "xtrans": { @@ -9289,8 +9577,8 @@ "port-version": 1 }, "yara": { - "baseline": "4.3.2", - "port-version": 1 + "baseline": "4.5.0", + "port-version": 0 }, "yas": { "baseline": "7.1.0", @@ -9313,19 +9601,19 @@ "port-version": 0 }, "yoga": { - "baseline": "2.0.0", + "baseline": "3.0.2", "port-version": 0 }, "yomm2": { - "baseline": "1.4.0", - "port-version": 1 + "baseline": "1.5.1", + "port-version": 0 }, "yyjson": { "baseline": "0.8.0", "port-version": 0 }, "z3": { - "baseline": "4.12.2", + "baseline": "4.13.0", "port-version": 0 }, "z4kn4fein-semver": { @@ -9341,7 +9629,7 @@ "port-version": 4 }, "zeromq": { - "baseline": "2023-06-20", + "baseline": "4.3.5", "port-version": 1 }, "zfp": { @@ -9361,7 +9649,7 @@ "port-version": 3 }, "zlib": { - "baseline": "1.3", + "baseline": "1.3.1", "port-version": 0 }, "zlib-ng": { @@ -9369,8 +9657,8 @@ "port-version": 0 }, "zlmediakit": { - "baseline": "2023-08-12", - "port-version": 0 + "baseline": "2024-03-30", + "port-version": 1 }, "zoe": { "baseline": "3.0", @@ -9393,8 +9681,8 @@ "port-version": 0 }, "zstd": { - "baseline": "1.5.5", - "port-version": 2 + "baseline": "1.5.6", + "port-version": 0 }, "zstr": { "baseline": "1.0.7", @@ -9434,15 +9722,15 @@ }, "zydis": { "baseline": "4.0.0", - "port-version": 1 + "port-version": 2 }, "zyre": { "baseline": "2019-07-07", "port-version": 5 }, "zziplib": { - "baseline": "0.13.72", - "port-version": 3 + "baseline": "0.13.73", + "port-version": 0 } } } diff --git a/vcpkg/versions/d-/dpp.json b/vcpkg/versions/d-/dpp.json index 57360900c7..d5b64f737f 100644 --- a/vcpkg/versions/d-/dpp.json +++ b/vcpkg/versions/d-/dpp.json @@ -1,5 +1,10 @@ { "versions": [ + { + "git-tree": "2224384b8c94dc8993bee072c9f506ef17e6eef4", + "version": "10.0.30", + "port-version": 0 + }, { "git-tree": "57e513b7c5b9b43418e0be4bdbb739359878baaa", "version": "10.0.29", From 6782d472d47080b08bfb8c64721bac1b8586a862 Mon Sep 17 00:00:00 2001 From: Henonicks <130137602+Henonicks@users.noreply.github.com> Date: Mon, 13 May 2024 17:24:06 +0300 Subject: [PATCH 85/89] docs: Added an example on how to edit an embed (#1128) --- ...ing_messages.cpp => editing_messages1.cpp} | 34 +--------- docpages/example_code/editing_messages2.cpp | 45 +++++++++++++ docpages/example_code/editing_messages3.cpp | 59 +++++++++++++++++ .../editing-channels-and-messages.md | 61 +++++++++++++----- docpages/images/stuff_edit1.png | Bin 40603 -> 16679 bytes docpages/images/stuff_edit2.png | Bin 72514 -> 37706 bytes docpages/images/stuff_edit3.png | Bin 0 -> 5466 bytes docpages/images/stuff_edit4.png | Bin 0 -> 24684 bytes docpages/images/stuff_edit5.png | Bin 0 -> 25588 bytes docpages/images/stuff_edit6.png | Bin 0 -> 41226 bytes 10 files changed, 153 insertions(+), 46 deletions(-) rename docpages/example_code/{editing_messages.cpp => editing_messages1.cpp} (57%) create mode 100644 docpages/example_code/editing_messages2.cpp create mode 100644 docpages/example_code/editing_messages3.cpp create mode 100644 docpages/images/stuff_edit3.png create mode 100644 docpages/images/stuff_edit4.png create mode 100644 docpages/images/stuff_edit5.png create mode 100644 docpages/images/stuff_edit6.png diff --git a/docpages/example_code/editing_messages.cpp b/docpages/example_code/editing_messages1.cpp similarity index 57% rename from docpages/example_code/editing_messages.cpp rename to docpages/example_code/editing_messages1.cpp index b1c5bd9e50..04e7640ba7 100644 --- a/docpages/example_code/editing_messages.cpp +++ b/docpages/example_code/editing_messages1.cpp @@ -1,8 +1,8 @@ #include int main() { - dpp::cluster bot("token", dpp::i_default_intents | dpp::i_message_content); /* the second argument is a bitmask of intents - i_message_content is needed to get messages */ + dpp::cluster bot("Token", dpp::i_default_intents | dpp::i_message_content); bot.on_log(dpp::utility::cout_logger()); @@ -13,9 +13,8 @@ int main() { } else if (event.command.get_command_name() == "msg-edit") { const auto content = std::get(event.get_parameter("content")); - /* get message to edit it after */ + /* get the message to edit it after. here string will automatically be converted to snowflake */ const dpp::snowflake msg_id = std::get(event.get_parameter("msg-id")); - /* here string will automatically be converted to snowflake */ bot.message_get(msg_id, event.command.channel_id, [&bot, content, event](const dpp::confirmation_callback_t& callback) { if (callback.is_error()) { @@ -27,51 +26,24 @@ int main() { /* change the message content and edit the message itself */ message.set_content(content); bot.message_edit(message); - event.reply("Message content is now `" + content + "`."); }); - } else if (event.command.get_command_name() == "channel-edit") { - const auto name = std::get(event.get_parameter("name")); - - /* get the channel to edit it after */ - const auto channel_id = std::get(event.get_parameter("channel")); - - bot.channel_get(channel_id, [&bot, name, event](const dpp::confirmation_callback_t& callback) { - if (callback.is_error()) { - event.reply("error"); - return; - } - auto channel = callback.get(); - - /* change the channel name and edit the channel itself */ - channel.set_name(name); - bot.channel_edit(channel); - - event.reply("Channel name is now `" + name + "`."); - }); } }); bot.on_ready([&bot](const dpp::ready_t& event) { - if (dpp::run_once ()) { dpp::slashcommand msg_edit("msg-edit", "Edit a message sent by the bot", bot.me.id); msg_edit.add_option(dpp::command_option(dpp::co_string, "msg-id", "ID of the message to edit", true)); /* true for required option */ msg_edit.add_option(dpp::command_option(dpp::co_string, "content", "New content for the message", true)); /* same here */ - dpp::slashcommand channel_edit("channel-edit", "Edit the name of channel specified", bot.me.id); - - channel_edit.add_option(dpp::command_option(dpp::co_channel, "channel", "Channel to edit", true)); - channel_edit.add_option(dpp::command_option(dpp::co_string, "name", "New name for the channel", true)); - dpp::slashcommand msg_send("msg-send", "Send my message", bot.me.id); - bot.global_bulk_command_create({ msg_edit, channel_edit, msg_send }); + bot.global_bulk_command_create({ msg_edit, msg_send }); } }); bot.start(dpp::st_wait); - return 0; } diff --git a/docpages/example_code/editing_messages2.cpp b/docpages/example_code/editing_messages2.cpp new file mode 100644 index 0000000000..a3595d8e81 --- /dev/null +++ b/docpages/example_code/editing_messages2.cpp @@ -0,0 +1,45 @@ +#include + +int main() { + /* the second argument is a bitmask of intents - i_message_content is needed to get messages */ + dpp::cluster bot("Token", dpp::i_default_intents | dpp::i_message_content); + + bot.on_log(dpp::utility::cout_logger()); + + /* The event is fired when someone issues your commands */ + bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) { + if (event.command.get_command_name() == "channel-edit") { + const auto name = std::get(event.get_parameter("name")); + + /* get the channel to edit it after */ + const auto channel_id = std::get(event.get_parameter("channel")); + bot.channel_get(channel_id, [&bot, name, event](const dpp::confirmation_callback_t& callback) { + if (callback.is_error()) { + event.reply("error"); + return; + } + auto channel = callback.get(); + + /* change the channel name and edit the channel itself */ + channel.set_name(name); + bot.channel_edit(channel); + event.reply("Channel name is now `" + name + "`."); + }); + } + }); + + bot.on_ready([&bot](const dpp::ready_t& event) { + + if (dpp::run_once ()) { + dpp::slashcommand channel_edit("channel-edit", "Edit the name of channel specified", bot.me.id); + + channel_edit.add_option(dpp::command_option(dpp::co_channel, "channel", "Channel to edit", true)); + channel_edit.add_option(dpp::command_option(dpp::co_string, "name", "New name for the channel", true)); + + bot.global_command_create(channel_edit); + } + }); + + bot.start(dpp::st_wait); + return 0; +} diff --git a/docpages/example_code/editing_messages3.cpp b/docpages/example_code/editing_messages3.cpp new file mode 100644 index 0000000000..5d598dfbe8 --- /dev/null +++ b/docpages/example_code/editing_messages3.cpp @@ -0,0 +1,59 @@ +#include + +int main() { + /* the second argument is a bitmask of intents - i_message_content is needed to get messages */ + dpp::cluster bot("Token", dpp::i_default_intents | dpp::i_message_content); + + bot.on_log(dpp::utility::cout_logger()); + + /* The event is fired when someone issues your commands */ + bot.on_slashcommand([&bot](const dpp::slashcommand_t& event) { + if (event.command.get_command_name() == "embed-send") { + dpp::embed embed = dpp::embed() + .set_color(dpp::colors::sti_blue) + .set_title("like and subscribe") + .set_url("https://dpp.dev/") + .set_author("Some author", "https://dpp.dev/", "https://dpp.dev/DPP-Logo.png") + .set_description("Creator is "); + event.reply(embed); + } else if (event.command.get_command_name() == "embed-edit") { + const auto description = std::get(event.get_parameter("desc")); + + /* get the message to edit its embed after. here string will automatically be converted to snowflake */ + const dpp::snowflake msg_id = std::get(event.get_parameter("msg-id")); + + bot.message_get(msg_id, event.command.channel_id, [&bot, description, event](const dpp::confirmation_callback_t& callback) { + if (callback.is_error()) { + event.reply("error"); + return; + } + auto message = callback.get(); + auto& embeds = message.embeds; + + /* change the embed description and edit the message itself. + * since we're using a reference, what changes in embeds changes in message.embeds + */ + embeds[0].set_description(description); + + bot.message_edit(message); + event.reply("Embed description is now `" + description + "`."); + }); + } + }); + + bot.on_ready([&bot](const dpp::ready_t& event) { + if (dpp::run_once ()) { + dpp::slashcommand embed_send("embed-send", "Send my embed", bot.me.id); + + dpp::slashcommand embed_edit("embed-edit", "Edit an embed sent by the bot", bot.me.id); + + embed_edit.add_option(dpp::command_option(dpp::co_string, "msg-id", "ID of the embed to edit", true)); /* true for required option */ + embed_edit.add_option(dpp::command_option(dpp::co_string, "desc", "New description for the embed", true)); /* same here */ + + bot.global_bulk_command_create({ embed_send, embed_edit }); + } + }); + + bot.start(dpp::st_wait); + return 0; +} diff --git a/docpages/example_programs/the_basics/editing-channels-and-messages.md b/docpages/example_programs/the_basics/editing-channels-and-messages.md index a94ab7ccd8..af4b733d1e 100644 --- a/docpages/example_programs/the_basics/editing-channels-and-messages.md +++ b/docpages/example_programs/the_basics/editing-channels-and-messages.md @@ -1,15 +1,46 @@ -\page editing-channels-and-messages Editing Channels and Messages - -Sometimes we need to update an object, such as message or channel. At first, it might seem confusing, but it's actually really simple! You just need to use an object with identical properties you don't need to update. NOTE: your bot can't edit messages sent by others. - -\note This example uses callback functions. To see more information about them, visit \ref callback-functions. - -\include{cpp} editing_messages.cpp - -Before editing: - -\image html stuff_edit1.png - -After editing: - -\image html stuff_edit2.png \ No newline at end of file +\page editing-channels-and-messages Editing Channels and Messages + +Sometimes we need to update an object, such as a message (whether it's plain text or an embed) or a channel. At first, it might seem confusing, but it's actually really simple! You need an object with all the properties being identical to the existing one. Say you're editing a message. You need to have an object with its ID the same as the one in Discord. Then you replace what you need, such as its content. + +\note This example uses callback functions and embeds. To see more information about them, visit \ref callback-functions and + +## Editing messages +Here we send a message and edit it after. To do so, we first reply to the command `msg-send` with some text, "This is a message" in our case. As described above, on the next step the message object is taken and the text is replaced with whatever the user desires. + +\include{cpp} editing_messages1.cpp + +\note Your bot can't edit messages sent by others!\ref embed-message. + +Before editing the message: + +\image html stuff_edit1.png + +After editing the message: + +\image html stuff_edit2.png + +## Editing channels +Now we'll want to edit an existing channel - its name in this case. This works similarly to how messages are edited. + +\include{cpp} editing_messages2.cpp + +Before editing the channel: + +\image html stuff_edit3.png + +After editing the channel: + +\image html stuff_edit4.png + +## Editing embeds +Now let's send an embed and edit it. If a message has one `content` field, it can have a few `embed` fields, up to 10 to be precise. So we first get the embed we want and edit and change its description. + +\include{cpp} editing_messages3.cpp + +Before editing the embed: + +\image html stuff_edit5.png + +Finally, after editing the embed: + +\image html stuff_edit6.png diff --git a/docpages/images/stuff_edit1.png b/docpages/images/stuff_edit1.png index bf6487861040ead032270162fd1aebf3a7eb9261..745891a0370882383e51beebfc52d256f4188469 100644 GIT binary patch literal 16679 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 O5J^!vks2X`!2bi%eU=~q literal 40603 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 diff --git a/docpages/images/stuff_edit2.png b/docpages/images/stuff_edit2.png index cf77dd5fd8801c7e871588878b4b7569494c58f7..4571433f58e2ae6eea81ab522feee92d02722ae8 100644 GIT binary patch literal 37706 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 F)ISw%ks$y8 literal 72514 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 diff --git a/docpages/images/stuff_edit3.png b/docpages/images/stuff_edit3.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce5dd68eb91ead3513e2b84b8ea7d0dd32afe66 GIT binary patch literal 5466 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 RkN;4B5?EcnLe?z!e*l=fIIsW! literal 0 HcmV?d00001 diff --git a/docpages/images/stuff_edit4.png b/docpages/images/stuff_edit4.png new file mode 100644 index 0000000000000000000000000000000000000000..a4166a18ad80b66d03faf0a4c75b37f69dd400f5 GIT binary patch literal 24684 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%0A|^HM|L4 zb?0PBPAnt4b_N)7oW7joCGK{<$0`ks)`4-wbM8|3goi!HT{6i96z6K<3qXlUf2q#r zo}Kse?p1;_xQh@#3wzBxs}?v2-OD_pUAfS-TtVH~F+EwG9m`}xg)_gK0C$eR>n7cP z+Lfap8q+};?S*%NZ}&GfFcS7p*!2DeCt*2gcO?R=C}Wx1RBgJc-b* z^DR2O*OtD2@K6|$EW?)RRetNEimL3k{Q)_F4B($8V0nX+rAuXBtPAgX?Sn9KZT*HT~gvaoC(L7tQi`CilR|sk{=l}bt z_8UnZE~Dta2A618_cANqBaW5=e`|17@(VnhPeZ{qHfp>SfnC$`I}n#RxI5-M-OiDR zcE^)rf1JY)QLNp>i8hu+)4Jf|o`V`>(Yt&yv F{~ysVwE+MC literal 0 HcmV?d00001 diff --git a/docpages/images/stuff_edit5.png b/docpages/images/stuff_edit5.png new file mode 100644 index 0000000000000000000000000000000000000000..48579eed9daab8758d2d3ed46183d45058f0cab6 GIT binary patch literal 25588 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 literal 0 HcmV?d00001 diff --git a/docpages/images/stuff_edit6.png b/docpages/images/stuff_edit6.png new file mode 100644 index 0000000000000000000000000000000000000000..a61be95c254a0aa019d295a51ac03bb5f7da07f8 GIT binary patch literal 41226 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 cfJ_cU##FI4cmKLS{%2VUsQ$KE?tSQg0J*kyeE Date: Wed, 15 May 2024 16:14:58 -0700 Subject: [PATCH 86/89] Updated autocomplete tutorial (#1151) --- docpages/example_code/autocomplete.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docpages/example_code/autocomplete.cpp b/docpages/example_code/autocomplete.cpp index da29127e30..380cb45785 100644 --- a/docpages/example_code/autocomplete.cpp +++ b/docpages/example_code/autocomplete.cpp @@ -50,10 +50,10 @@ int main() */ std::string uservalue = std::get(opt.value); bot.interaction_response_create(event.command.id, event.command.token, dpp::interaction_response(dpp::ir_autocomplete_reply) - .add_autocomplete_choice(dpp::command_option_choice("squids", "lots of squids")) - .add_autocomplete_choice(dpp::command_option_choice("cats", "a few cats")) - .add_autocomplete_choice(dpp::command_option_choice("dogs", "bucket of dogs")) - .add_autocomplete_choice(dpp::command_option_choice("elephants", "bottle of elephants")) + .add_autocomplete_choice(dpp::command_option_choice("squids", std::string("lots of squids"))) + .add_autocomplete_choice(dpp::command_option_choice("cats", std::string("a few cats"))) + .add_autocomplete_choice(dpp::command_option_choice("dogs", std::string("bucket of dogs"))) + .add_autocomplete_choice(dpp::command_option_choice("elephants", std::string("bottle of elephants"))) ); bot.log(dpp::ll_debug, "Autocomplete " + opt.name + " with value '" + uservalue + "' in field " + event.name); break; From 5356fde59a26d96e61950f48d3bf7d03ffc6c4fc Mon Sep 17 00:00:00 2001 From: "Craig Edwards (Brain)" Date: Thu, 16 May 2024 06:35:14 +0100 Subject: [PATCH 87/89] FIX: poll conflicting with dpp::poll (#1152) --- src/dpp/sslclient.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dpp/sslclient.cpp b/src/dpp/sslclient.cpp index f9aa2df1ac..ee7f4d7af0 100644 --- a/src/dpp/sslclient.cpp +++ b/src/dpp/sslclient.cpp @@ -208,7 +208,7 @@ int connect_with_timeout(dpp::socket sockfd, const struct sockaddr *addr, sockle pollfd pfd = {}; pfd.fd = sockfd; pfd.events = POLLOUT; - int r = poll(&pfd, 1, 10); + int r = ::poll(&pfd, 1, 10); if (r > 0 && pfd.revents & POLLOUT) { rc = 0; } else if (r != 0 || pfd.revents & POLLERR) { @@ -269,7 +269,7 @@ ssl_client::ssl_client(const std::string &_hostname, const std::string &_port, b pollfd pfd = {}; pfd.fd = iter->second.sfd; pfd.events = POLLOUT; - int r = poll(&pfd, 1, 1); + int r = ::poll(&pfd, 1, 1); if (time(nullptr) > (iter->second.created + 60) || r < 0 || pfd.revents & POLLERR) { make_new = true; /* This connection is dead, free its resources and make a new one */ @@ -480,7 +480,7 @@ void ssl_client::read_loop() const int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); int poll_time = 1000 - (now % 1000); poll_time = poll_time > 400 ? 1000 : poll_time + poll_time / 3 + 1; - r = poll(pfd, sockets, now / 1000 == (int64_t)last_tick ? poll_time : 0); + r = ::poll(pfd, sockets, now / 1000 == (int64_t)last_tick ? poll_time : 0); if (r == 0) { continue; From 0f6ce7dce6edfa442d4d66582ff8b23632767108 Mon Sep 17 00:00:00 2001 From: Craig Edwards Date: Sun, 19 May 2024 20:17:49 +0000 Subject: [PATCH 88/89] version bump --- include/dpp/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/dpp/version.h b/include/dpp/version.h index e3131506b6..92941b5eee 100644 --- a/include/dpp/version.h +++ b/include/dpp/version.h @@ -22,9 +22,9 @@ #pragma once #if !defined(DPP_VERSION_LONG) -#define DPP_VERSION_LONG 0x00100030 -#define DPP_VERSION_SHORT 100030 -#define DPP_VERSION_TEXT "D++ 10.0.30 (11-Dec-2023)" +#define DPP_VERSION_LONG 0x00100031 +#define DPP_VERSION_SHORT 100031 +#define DPP_VERSION_TEXT "D++ 10.0.31 (19-May-2024)" #define DPP_VERSION_MAJOR ((DPP_VERSION_LONG & 0x00ff0000) >> 16) #define DPP_VERSION_MINOR ((DPP_VERSION_LONG & 0x0000ff00) >> 8) From fd643d71e2b7dc6b2f97bef58d1b6d0d36b95cec Mon Sep 17 00:00:00 2001 From: Craig Edwards Date: Mon, 20 May 2024 04:06:11 +0000 Subject: [PATCH 89/89] fix: default gateway reference --- include/dpp/cluster.h | 2 +- src/dpp/cluster.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index b27d068e9d..ec4044964b 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -325,7 +325,7 @@ class DPP_EXPORT cluster { * * @return cluster& Reference to self for chaining. */ - cluster& set_default_gateway(std::string& default_gateway); + cluster& set_default_gateway(const std::string& default_gateway); /** * @brief Log a message to whatever log the user is using. diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index 96b9d56421..db8ce14c31 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -411,7 +411,7 @@ cluster& cluster::clear_audit_reason() { return *this; } -cluster& cluster::set_default_gateway(std::string &default_gateway_new) { +cluster& cluster::set_default_gateway(const std::string &default_gateway_new) { default_gateway = default_gateway_new; return *this; }