From 5903abd30d0c96ac1f120f427b2509e164a9605b Mon Sep 17 00:00:00 2001 From: Archie Date: Sat, 13 Jul 2024 17:59:37 +0100 Subject: [PATCH 1/3] feat: banners can now be uploaded to bots --- include/dpp/cluster.h | 8 +++++--- src/dpp/cluster/user.cpp | 29 +++++++++++++++++++---------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index 48d5203492..15629e718d 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -3259,13 +3259,15 @@ class DPP_EXPORT cluster { * Fires a `Guild Member Update` Gateway event. * @see https://discord.com/developers/docs/resources/user#modify-current-user * @param nickname Nickname to set - * @param image_blob Avatar data to upload (NOTE: Very heavily rate limited!) - * @param type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. + * @param avatar_blob Avatar data to upload (NOTE: Very heavily rate limited!) + * @param avatar_type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. + * @param banner_blob Banner data to upload (NOTE: Very heavily rate limited!) + * @param banner_type Type of image for Banner. It can be one of `i_gif`, `i_jpg` or `i_png`. * @param callback Function to call when the API call completes. * On success the callback will contain a dpp::user 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(). * @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes */ - void current_user_edit(const std::string &nickname, const std::string& image_blob = "", const image_type type = i_png, command_completion_event_t callback = utility::log_error()); + void current_user_edit(const std::string &nickname, const std::string& avatar_blob = "", const image_type avatar_type = i_png, const std::string& banner_blob = "", const image_type banner_type = i_png, command_completion_event_t callback = utility::log_error()); /** * @brief Get current user DM channels diff --git a/src/dpp/cluster/user.cpp b/src/dpp/cluster/user.cpp index b3cf763bb8..6498be6cda 100644 --- a/src/dpp/cluster/user.cpp +++ b/src/dpp/cluster/user.cpp @@ -24,23 +24,32 @@ namespace dpp { -void cluster::current_user_edit(const std::string &nickname, const std::string& image_blob, const image_type type, command_completion_event_t callback) { +void cluster::current_user_edit(const std::string &nickname, const std::string& avatar_blob, const image_type avatar_type, const std::string& banner_blob, const image_type banner_type, command_completion_event_t callback) { json j = json::parse("{\"nickname\": null}"); if (!nickname.empty()) { j["nickname"] = nickname; } - if (!image_blob.empty()) { - static const std::map mimetypes = { - { i_gif, "image/gif" }, - { i_jpg, "image/jpeg" }, - { i_png, "image/png" }, - { i_webp, "image/webp" }, - }; - if (image_blob.size() > MAX_EMOJI_SIZE) { + + static const std::map mimetypes = { + { i_gif, "image/gif" }, + { i_jpg, "image/jpeg" }, + { i_png, "image/png" }, + }; + + if (!avatar_blob.empty()) { + if (avatar_blob.size() > MAX_EMOJI_SIZE) { throw dpp::length_exception(err_icon_size, "User icon file exceeds discord limit of 256 kilobytes"); } - j["avatar"] = "data:" + mimetypes.find(type)->second + ";base64," + base64_encode((unsigned char const*)image_blob.data(), (unsigned int)image_blob.length()); + j["avatar"] = "data:" + mimetypes.find(avatar_type)->second + ";base64," + base64_encode((unsigned char const*)avatar_blob.data(), static_cast(avatar_blob.length())); + } + + if (!banner_blob.empty()) { + if (avatar_blob.size() > MAX_EMOJI_SIZE) { + throw dpp::length_exception(err_icon_size, "User banner file exceeds discord limit of 256 kilobytes"); + } + j["banner"] = "data:" + mimetypes.find(banner_type)->second + ";base64," + base64_encode((unsigned char const*)banner_blob.data(), static_cast(banner_blob.length())); } + rest_request(this, API_PATH "/users", "@me", "", m_patch, j.dump(-1, ' ', false, json::error_handler_t::replace), callback); } From 7e7bd2d6ae3b36012d2d8e1f8f8151f435099fdf Mon Sep 17 00:00:00 2001 From: Archie Date: Sat, 13 Jul 2024 18:16:37 +0100 Subject: [PATCH 2/3] fix: banner blob now correctly throws for banner blob size. coro and sync calls updated --- include/dpp/cluster_coro_calls.h | 8 +++++--- include/dpp/cluster_sync_calls.h | 8 +++++--- src/dpp/cluster/user.cpp | 3 ++- src/dpp/cluster_coro_calls.cpp | 4 ++-- src/dpp/cluster_sync_calls.cpp | 4 ++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index 831537f9f4..777e67d1f8 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -2253,13 +2253,15 @@ * @see dpp::cluster::current_user_edit * @see https://discord.com/developers/docs/resources/user#modify-current-user * @param nickname Nickname to set - * @param image_blob Avatar data to upload (NOTE: Very heavily rate limited!) - * @param type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. + * @param avatar_blob Avatar data to upload (NOTE: Very heavily rate limited!) + * @param avatar_type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. + * @param banner_blob Banner data to upload (NOTE: Very heavily rate limited!) + * @param banner_type Type of image for Banner. It can be one of `i_gif`, `i_jpg` or `i_png`. * @return user returned object on completion * @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes * \memberof dpp::cluster */ -[[nodiscard]] async co_current_user_edit(const std::string &nickname, const std::string& image_blob = "", const image_type type = i_png); +[[nodiscard]] async co_current_user_edit(const std::string &nickname, const std::string& avatar_blob = "", const image_type avatar_type = i_png, const std::string& banner_blob = "", const image_type banner_type = i_png); /** * @brief Get current (bot) application diff --git a/include/dpp/cluster_sync_calls.h b/include/dpp/cluster_sync_calls.h index e288318e69..46d38ae429 100644 --- a/include/dpp/cluster_sync_calls.h +++ b/include/dpp/cluster_sync_calls.h @@ -2772,8 +2772,10 @@ thread thread_get_sync(snowflake thread_id); * @see dpp::cluster::current_user_edit * @see https://discord.com/developers/docs/resources/user#modify-current-user * @param nickname Nickname to set - * @param image_blob Avatar data to upload (NOTE: Very heavily rate limited!) - * @param type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. + * @param avatar_blob Avatar data to upload (NOTE: Very heavily rate limited!) + * @param avatar_type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. + * @param banner_blob Banner data to upload (NOTE: Very heavily rate limited!) + * @param banner_type Type of image for Banner. It can be one of `i_gif`, `i_jpg` or `i_png`. * @return user returned object on completion * @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes * \memberof dpp::cluster @@ -2781,7 +2783,7 @@ thread thread_get_sync(snowflake thread_id); * @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 current_user_edit_sync(const std::string &nickname, const std::string& image_blob = "", const image_type type = i_png); +user current_user_edit_sync(const std::string &nickname, const std::string& avatar_blob = "", const image_type avatar_type = i_png, const std::string& banner_blob = "", const image_type banner_type = i_png); /** * @brief Get current (bot) application diff --git a/src/dpp/cluster/user.cpp b/src/dpp/cluster/user.cpp index 6498be6cda..71d1415a98 100644 --- a/src/dpp/cluster/user.cpp +++ b/src/dpp/cluster/user.cpp @@ -34,6 +34,7 @@ void cluster::current_user_edit(const std::string &nickname, const std::string& { i_gif, "image/gif" }, { i_jpg, "image/jpeg" }, { i_png, "image/png" }, + { i_webp, "image/webp" }, /* Whilst webp isn't supported (as of 13/07/24, UK date), best to keep this here for when Discord support webp */ }; if (!avatar_blob.empty()) { @@ -44,7 +45,7 @@ void cluster::current_user_edit(const std::string &nickname, const std::string& } if (!banner_blob.empty()) { - if (avatar_blob.size() > MAX_EMOJI_SIZE) { + if (banner_blob.size() > MAX_EMOJI_SIZE) { throw dpp::length_exception(err_icon_size, "User banner file exceeds discord limit of 256 kilobytes"); } j["banner"] = "data:" + mimetypes.find(banner_type)->second + ";base64," + base64_encode((unsigned char const*)banner_blob.data(), static_cast(banner_blob.length())); diff --git a/src/dpp/cluster_coro_calls.cpp b/src/dpp/cluster_coro_calls.cpp index 52bf1e814e..ad48ee1497 100644 --- a/src/dpp/cluster_coro_calls.cpp +++ b/src/dpp/cluster_coro_calls.cpp @@ -747,8 +747,8 @@ async cluster::co_thread_get(snowflake thread_id) { return async{ this, static_cast(&cluster::thread_get), thread_id }; } -async cluster::co_current_user_edit(const std::string &nickname, const std::string& image_blob, const image_type type) { - return async{ this, static_cast(&cluster::current_user_edit), nickname, image_blob, type }; +async cluster::co_current_user_edit(const std::string &nickname, const std::string& avatar_blob, const image_type avatar_type, const std::string& banner_blob, const image_type banner_type) { + return async{ this, static_cast(&cluster::current_user_edit), nickname, avatar_blob, avatar_type, banner_blob, banner_type }; } async cluster::co_current_application_get() { diff --git a/src/dpp/cluster_sync_calls.cpp b/src/dpp/cluster_sync_calls.cpp index 8372da2a93..70f3618f02 100644 --- a/src/dpp/cluster_sync_calls.cpp +++ b/src/dpp/cluster_sync_calls.cpp @@ -745,8 +745,8 @@ thread cluster::thread_get_sync(snowflake thread_id) { return dpp::sync(this, static_cast(&cluster::thread_get), thread_id); } -user cluster::current_user_edit_sync(const std::string &nickname, const std::string& image_blob, const image_type type) { - return dpp::sync(this, static_cast(&cluster::current_user_edit), nickname, image_blob, type); +user cluster::current_user_edit_sync(const std::string &nickname, const std::string& avatar_blob, const image_type avatar_type, const std::string& banner_blob, const image_type banner_type) { + return dpp::sync(this, static_cast(&cluster::current_user_edit), nickname, avatar_blob, avatar_type, banner_blob, banner_type); } application cluster::current_application_get_sync() { From fa749ce1520c0ab21843a439148f27d3eb0b3b26 Mon Sep 17 00:00:00 2001 From: Archie Date: Sun, 14 Jul 2024 11:53:11 +0100 Subject: [PATCH 3/3] fix: removed max limit for avatars and banners --- include/dpp/cluster.h | 13 ++++++++----- include/dpp/cluster_coro_calls.h | 13 ++++++++----- include/dpp/cluster_sync_calls.h | 13 ++++++++----- include/dpp/misc-enum.h | 2 +- src/dpp/cluster/user.cpp | 6 ------ 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/include/dpp/cluster.h b/include/dpp/cluster.h index 15629e718d..ab361dd5db 100644 --- a/include/dpp/cluster.h +++ b/include/dpp/cluster.h @@ -3253,15 +3253,18 @@ class DPP_EXPORT cluster { void current_user_get_guilds(command_completion_event_t callback); /** - * @brief Edit current (bot) user + * @brief Edit current (bot) user. + * + * Modify the requester's user account settings. Returns a dpp::user object on success. + * Fires a User Update Gateway event. + * + * @note There appears to be no limit to the image size, however, if your image cannot be processed/uploaded in time, you will receive a malformed http request. * - * Modifies the current member in a guild. Returns the updated guild_member object on success. - * Fires a `Guild Member Update` Gateway event. * @see https://discord.com/developers/docs/resources/user#modify-current-user * @param nickname Nickname to set - * @param avatar_blob Avatar data to upload (NOTE: Very heavily rate limited!) + * @param avatar_blob Avatar data to upload * @param avatar_type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. - * @param banner_blob Banner data to upload (NOTE: Very heavily rate limited!) + * @param banner_blob Banner data to upload * @param banner_type Type of image for Banner. It can be one of `i_gif`, `i_jpg` or `i_png`. * @param callback Function to call when the API call completes. * On success the callback will contain a dpp::user 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(). diff --git a/include/dpp/cluster_coro_calls.h b/include/dpp/cluster_coro_calls.h index 777e67d1f8..bc460605c6 100644 --- a/include/dpp/cluster_coro_calls.h +++ b/include/dpp/cluster_coro_calls.h @@ -2246,16 +2246,19 @@ [[nodiscard]] async co_thread_get(snowflake thread_id); /** - * @brief Edit current (bot) user + * @brief Edit current (bot) user. + * + * Modify the requester's user account settings. Returns a dpp::user object on success. + * Fires a User Update Gateway event. + * + * @note There appears to be no limit to the image size, however, if your image cannot be processed/uploaded in time, you will receive a malformed http request. * - * Modifies the current member in a guild. Returns the updated guild_member object on success. - * Fires a `Guild Member Update` Gateway event. * @see dpp::cluster::current_user_edit * @see https://discord.com/developers/docs/resources/user#modify-current-user * @param nickname Nickname to set - * @param avatar_blob Avatar data to upload (NOTE: Very heavily rate limited!) + * @param avatar_blob Avatar data to upload * @param avatar_type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. - * @param banner_blob Banner data to upload (NOTE: Very heavily rate limited!) + * @param banner_blob Banner data to upload * @param banner_type Type of image for Banner. It can be one of `i_gif`, `i_jpg` or `i_png`. * @return user returned object on completion * @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes diff --git a/include/dpp/cluster_sync_calls.h b/include/dpp/cluster_sync_calls.h index 46d38ae429..1086c4926d 100644 --- a/include/dpp/cluster_sync_calls.h +++ b/include/dpp/cluster_sync_calls.h @@ -2765,16 +2765,19 @@ confirmation thread_member_remove_sync(snowflake thread_id, snowflake user_id); thread thread_get_sync(snowflake thread_id); /** - * @brief Edit current (bot) user + * @brief Edit current (bot) user. + * + * Modify the requester's user account settings. Returns a dpp::user object on success. + * Fires a User Update Gateway event. + * + * @note There appears to be no limit to the image size, however, if your image cannot be processed/uploaded in time, you will receive a malformed http request. * - * Modifies the current member in a guild. Returns the updated guild_member object on success. - * Fires a `Guild Member Update` Gateway event. * @see dpp::cluster::current_user_edit * @see https://discord.com/developers/docs/resources/user#modify-current-user * @param nickname Nickname to set - * @param avatar_blob Avatar data to upload (NOTE: Very heavily rate limited!) + * @param avatar_blob Avatar data to upload * @param avatar_type Type of image for avatar. It can be one of `i_gif`, `i_jpg` or `i_png`. - * @param banner_blob Banner data to upload (NOTE: Very heavily rate limited!) + * @param banner_blob Banner data to upload * @param banner_type Type of image for Banner. It can be one of `i_gif`, `i_jpg` or `i_png`. * @return user returned object on completion * @throw dpp::length_exception Image data is larger than the maximum size of 256 kilobytes diff --git a/include/dpp/misc-enum.h b/include/dpp/misc-enum.h index 1a65371dec..8f4f160f5a 100644 --- a/include/dpp/misc-enum.h +++ b/include/dpp/misc-enum.h @@ -28,7 +28,7 @@ namespace dpp { /** * @brief Supported image types for profile pictures and CDN endpoints */ -enum image_type { +enum image_type : uint8_t { /** * @brief image/png */ diff --git a/src/dpp/cluster/user.cpp b/src/dpp/cluster/user.cpp index 71d1415a98..f50732ee57 100644 --- a/src/dpp/cluster/user.cpp +++ b/src/dpp/cluster/user.cpp @@ -38,16 +38,10 @@ void cluster::current_user_edit(const std::string &nickname, const std::string& }; if (!avatar_blob.empty()) { - if (avatar_blob.size() > MAX_EMOJI_SIZE) { - throw dpp::length_exception(err_icon_size, "User icon file exceeds discord limit of 256 kilobytes"); - } j["avatar"] = "data:" + mimetypes.find(avatar_type)->second + ";base64," + base64_encode((unsigned char const*)avatar_blob.data(), static_cast(avatar_blob.length())); } if (!banner_blob.empty()) { - if (banner_blob.size() > MAX_EMOJI_SIZE) { - throw dpp::length_exception(err_icon_size, "User banner file exceeds discord limit of 256 kilobytes"); - } j["banner"] = "data:" + mimetypes.find(banner_type)->second + ";base64," + base64_encode((unsigned char const*)banner_blob.data(), static_cast(banner_blob.length())); }