From d2322315aa661c175bbbed152d0ccac8f29e33b3 Mon Sep 17 00:00:00 2001 From: Miuna <809711+Mishura4@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:10:27 -0400 Subject: [PATCH] refactor: fix json_interface (#937) --- include/dpp/appcommand.h | 231 ++++++++++++++------------ include/dpp/application.h | 17 +- include/dpp/auditlog.h | 33 ++-- include/dpp/automod.h | 80 +++++---- include/dpp/ban.h | 25 ++- include/dpp/channel.h | 128 ++++++++------- include/dpp/dtemplate.h | 36 +++-- include/dpp/emoji.h | 37 +++-- include/dpp/guild.h | 270 +++++++++++++++++-------------- include/dpp/integration.h | 45 +++--- include/dpp/invite.h | 28 ++-- include/dpp/json_interface.h | 56 ++++--- include/dpp/message.h | 117 +++++++++----- include/dpp/presence.h | 48 ++++-- include/dpp/prune.h | 30 ++-- include/dpp/restresults.h | 22 +-- include/dpp/role.h | 89 +++++----- include/dpp/scheduled_event.h | 34 ++-- include/dpp/stage_instance.h | 36 +++-- include/dpp/user.h | 64 ++++---- include/dpp/voiceregion.h | 35 ++-- include/dpp/voicestate.h | 27 ++-- include/dpp/webhook.h | 37 +++-- src/dpp/application.cpp | 2 +- src/dpp/auditlog.cpp | 4 +- src/dpp/automod.cpp | 22 +-- src/dpp/ban.cpp | 7 +- src/dpp/channel.cpp | 29 ++-- src/dpp/cluster.cpp | 4 +- src/dpp/cluster/appcommand.cpp | 4 +- src/dpp/cluster/guild.cpp | 2 +- src/dpp/cluster/guild_member.cpp | 2 +- src/dpp/cluster/role.cpp | 2 +- src/dpp/cluster/thread.cpp | 2 +- src/dpp/cluster/webhook.cpp | 4 +- src/dpp/dtemplate.cpp | 9 +- src/dpp/emoji.cpp | 6 +- src/dpp/guild.cpp | 55 ++++--- src/dpp/integration.cpp | 6 +- src/dpp/invite.cpp | 6 +- src/dpp/message.cpp | 20 +-- src/dpp/presence.cpp | 10 +- src/dpp/prune.cpp | 10 +- src/dpp/role.cpp | 18 +-- src/dpp/scheduled_event.cpp | 10 +- src/dpp/slashcommand.cpp | 32 ++-- src/dpp/stage_instance.cpp | 7 +- src/dpp/user.cpp | 12 +- src/dpp/voiceregion.cpp | 10 +- src/dpp/voicestate.cpp | 7 +- src/dpp/webhook.cpp | 6 +- src/unittest/test.cpp | 78 +++++++++ src/unittest/test.h | 1 + 53 files changed, 1094 insertions(+), 818 deletions(-) diff --git a/include/dpp/appcommand.h b/include/dpp/appcommand.h index 7cae5d28ad..068a58f740 100644 --- a/include/dpp/appcommand.h +++ b/include/dpp/appcommand.h @@ -90,7 +90,19 @@ typedef std::variant { +struct DPP_EXPORT command_option_choice : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return command_option_choice& Reference to self + */ + command_option_choice& fill_from_json_impl(nlohmann::json* j); + +public: std::string name; //!< Option name (1-32 chars) command_value value; //!< Option value std::map name_localizations; //!< Localisations of command option name @@ -118,14 +130,6 @@ struct DPP_EXPORT command_option_choice : public json_interface command_option_range; * Adding options acts like sub-commands and can contain more * options. */ -struct DPP_EXPORT command_option : public json_interface { +struct DPP_EXPORT command_option : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON. Fills options recursively. + * + * @param j JSON to fill from + * @return command_option& Reference to self + */ + command_option& fill_from_json_impl(nlohmann::json* j); + +public: command_option_type type; //!< Option type (what type of value is accepted) std::string name; //!< Option name (1-32 chars) std::string description; //!< Option description (1-100 chars) @@ -265,14 +281,6 @@ struct DPP_EXPORT command_option : public json_interface { * @throw dpp::logic_exception You attempted to enable auto complete on a command_option that has choices added to it */ command_option& set_auto_complete(bool autocomp); - - /** - * @brief Fill object properties from JSON. Fills options recursively. - * - * @param j JSON to fill from - * @return command_option& Reference to self - */ - command_option& fill_from_json(nlohmann::json* j); }; /** @@ -308,8 +316,26 @@ enum interaction_response_type { * * `mymessage.flags |= dpp::m_ephemeral;` */ -struct DPP_EXPORT interaction_response : public json_interface { +struct DPP_EXPORT interaction_response : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return interaction_response& Reference to self + */ + interaction_response& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build json for this object + * + * @return json JSON object + */ + json to_json_impl(bool with_id = false) const; +public: /** * @brief Response type from dpp::interaction_response_type. * Should be one of ir_pong, ir_channel_message_with_source, @@ -355,21 +381,6 @@ struct DPP_EXPORT interaction_response : public json_interface { -private: +protected: + friend struct json_interface; + size_t current_row; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return interaction_response& Reference to self + */ + interaction_modal_response& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build a json for this object + * @param with_id include id in json output + * + * @return json JSON object + */ + json to_json_impl(bool with_id = false) const; + public: /** * @brief Custom ID for the modal form @@ -458,22 +488,6 @@ struct DPP_EXPORT interaction_modal_response : public interaction_response, publ */ interaction_modal_response& add_row(); - /** - * @brief Fill object properties from JSON - * - * @param j JSON to fill from - * @return interaction_response& Reference to self - */ - interaction_modal_response& fill_from_json(nlohmann::json* j); - - /** - * @brief Build a json string for this object - * @param with_id include id in json output - * - * @return std::string JSON string - */ - std::string build_json(bool with_id = false) const; - /** * @brief Destroy the interaction modal response object */ @@ -675,7 +689,9 @@ void from_json(const nlohmann::json& j, autocomplete_interaction& ai); * into the events on_form_submit, on_slashcommand, on_user_context_menu, * on_button_click, on_select_menu, etc. */ -class DPP_EXPORT interaction : public managed, public json_interface { +class DPP_EXPORT interaction : public managed, public json_interface { +protected: + friend struct json_interface; /** * @brief Get a resolved object from the resolved set @@ -695,6 +711,22 @@ class DPP_EXPORT interaction : public managed, public json_interfacesecond; } + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return interaction& Reference to self + */ + interaction& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build a json for this object + * + * @param with_id True if to include the ID in the JSON + * @return json JSON object + */ + virtual json to_json_impl(bool with_id = false) const; + public: snowflake application_id; //!< id of the application this interaction is for uint8_t type; //!< the type of interaction (dpp::interaction_type) @@ -866,22 +898,6 @@ class DPP_EXPORT interaction : public managed, public json_interface { +class DPP_EXPORT command_permission : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return command_permission& Reference to self + */ + command_permission &fill_from_json_impl(nlohmann::json *j); + public: snowflake id; //!< the ID of the role or user command_permission_type type; //!< the type of permission @@ -935,14 +962,6 @@ class DPP_EXPORT command_permission : public json_interface * @param permission True to allow, false, to disallow */ command_permission(snowflake id, const command_permission_type t, bool permission); - - /** - * @brief Fill object properties from JSON - * - * @param j JSON to fill from - * @return command_permission& Reference to self - */ - command_permission &fill_from_json(nlohmann::json *j); }; /** @@ -958,7 +977,18 @@ void to_json(nlohmann::json& j, const command_permission& cp); /** * @brief Returned when fetching the permissions for a command in a guild. */ -class DPP_EXPORT guild_command_permissions : public json_interface { +class DPP_EXPORT guild_command_permissions : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return guild_command_permissions& Reference to self + */ + guild_command_permissions &fill_from_json_impl(nlohmann::json *j); + public: snowflake id; //!< the id of the command snowflake application_id; //!< the id of the application the command belongs to @@ -972,14 +1002,6 @@ class DPP_EXPORT guild_command_permissions : public json_interface { +class DPP_EXPORT slashcommand : public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return slashcommand& Reference to self + */ + slashcommand& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build a json for this object + * + * @param with_id True if to include the ID in the JSON + * @return json JSON object + */ + json to_json_impl(bool with_id = false) const; + public: /** * @brief Application id (usually matches your bots id) @@ -1207,22 +1248,6 @@ class DPP_EXPORT slashcommand : public managed, public json_interface { +class DPP_EXPORT application : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + application& fill_from_json_impl(nlohmann::json* j); + public: std::string name; //!< the name of the app utility::iconhash icon; //!< the icon hash of the app (may be empty) @@ -146,12 +155,6 @@ class DPP_EXPORT application : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + audit_entry& fill_from_json_impl(nlohmann::json* j); + +public: snowflake id; //!< id of the entry /** * ID of the affected entity (webhook, user, role, etc.) (may be empty) @@ -200,32 +210,29 @@ struct DPP_EXPORT audit_entry : public json_interface { /** Destructor */ virtual ~audit_entry() = default; +}; + +/** + * @brief The auditlog class represents the audit log entries of a guild. + */ +class DPP_EXPORT auditlog : public json_interface { +protected: + friend struct json_interface; /** Read class values from json object * @param j A json object to read from * @return A reference to self */ - audit_entry& fill_from_json(nlohmann::json* j); -}; + auditlog& fill_from_json_impl(nlohmann::json* j); -/** - * @brief The auditlog class represents the audit log entries of a guild. - */ -class DPP_EXPORT auditlog : public json_interface { public: std::vector entries; //!< Audit log entries - + /** Constructor */ auditlog() = default; /** Destructor */ virtual ~auditlog() = default; - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - auditlog& fill_from_json(nlohmann::json* j); }; } // namespace dpp diff --git a/include/dpp/automod.h b/include/dpp/automod.h index bd0d067921..fd33586815 100644 --- a/include/dpp/automod.h +++ b/include/dpp/automod.h @@ -109,6 +109,25 @@ enum automod_trigger_type : uint8_t { * @brief Metadata associated with an automod action. Different fields are relevant based on the value of dpp::automod_rule::trigger_type. */ struct DPP_EXPORT automod_metadata : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return automod_metadata& Reference to self + */ + automod_metadata& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build a json for this object + * + * @return json JSON object + */ + virtual json to_json_impl(bool with_id = false) const; + +public: /** * @brief @brief Substrings which will be searched for in content (Maximum of 1000). * @@ -224,28 +243,31 @@ struct DPP_EXPORT automod_metadata : public json_interface { * @brief Destroy the automod metadata object */ virtual ~automod_metadata(); +}; + +/** + * @brief Represents an automod action + */ +struct DPP_EXPORT automod_action : public json_interface { +protected: + friend struct json_interface; /** * @brief Fill object properties from JSON * * @param j JSON to fill from - * @return automod_metadata& Reference to self + * @return automod_action& Reference to self */ - automod_metadata& fill_from_json(nlohmann::json* j); + automod_action& fill_from_json_impl(nlohmann::json* j); /** - * @brief Build a json string for this object + * @brief Build a json for this object * - * @return std::string JSON string + * @return json JSON object */ - virtual std::string build_json(bool with_id = false) const; - -}; + virtual json to_json_impl(bool with_id = false) const; -/** - * @brief Represents an automod action - */ -struct DPP_EXPORT automod_action : public json_interface { +public: /** * @brief Type of action to take */ @@ -275,27 +297,30 @@ struct DPP_EXPORT automod_action : public json_interface { * @brief Destroy the automod action object */ virtual ~automod_action(); +}; + +/** + * @brief Represents an automod rule + */ +class DPP_EXPORT automod_rule : public managed, public json_interface { +protected: + friend struct json_interface; /** * @brief Fill object properties from JSON * * @param j JSON to fill from - * @return automod_action& Reference to self + * @return automod_rule& Reference to self */ - automod_action& fill_from_json(nlohmann::json* j); + automod_rule& fill_from_json_impl(nlohmann::json* j); /** * @brief Build a json string for this object * - * @return std::string JSON string + * @return json JSON object */ - virtual std::string build_json(bool with_id = false) const; -}; + virtual json to_json_impl(bool with_id = false) const; -/** - * @brief Represents an automod rule - */ -class DPP_EXPORT automod_rule : public managed, public json_interface { public: /** * @brief the id of this rule @@ -351,21 +376,6 @@ class DPP_EXPORT automod_rule : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + ban& fill_from_json_impl(nlohmann::json* j); + public: /** The ban reason */ std::string reason; /** User ID the ban applies to */ snowflake user_id; - + /** Constructor */ ban(); /** Destructor */ virtual ~ban() = default; - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - ban& fill_from_json(nlohmann::json* j); - - /** - * @brief Build json representation of a ban - * @param with_id Include ID in json - * - * @return std::string stringified json - */ - std::string build_json(bool with_id = false) const; }; /** diff --git a/include/dpp/channel.h b/include/dpp/channel.h index afa09823d9..14c1d92396 100644 --- a/include/dpp/channel.h +++ b/include/dpp/channel.h @@ -175,8 +175,18 @@ enum auto_archive_duration_t : uint8_t { /** * @brief represents membership of a user with a thread */ -struct DPP_EXPORT thread_member -{ +struct DPP_EXPORT thread_member : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read struct values from a json object + * @param j json to read values from + * @return A reference to self + */ + thread_member& fill_from_json_impl(nlohmann::json* j); + +public: /// ID of the thread member is part of snowflake thread_id; /// ID of the member @@ -185,19 +195,31 @@ struct DPP_EXPORT thread_member time_t joined; /// Any user-thread settings, currently only used for notifications uint32_t flags; - - /** - * @brief Read struct values from a json object - * @param j json to read values from - * @return A reference to self - */ - thread_member& fill_from_json(nlohmann::json* j); }; /** * @brief Represents a tag that is able to be applied to a thread in a forum or media channel */ struct DPP_EXPORT forum_tag : public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read struct values from a json object + * @param j json to read values from + * @return A reference to self + */ + forum_tag& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build json for this forum_tag object + * + * @param with_id include the ID in the json + * @return json JSON object + */ + json to_json_impl(bool with_id = false) const; + +public: /** The name of the tag (0-20 characters) */ std::string name; /** The emoji of the tag. Contains either nothing, the id of a guild's custom emoji or the unicode character of the emoji */ @@ -218,21 +240,6 @@ struct DPP_EXPORT forum_tag : public managed, public json_interface { /** Destructor */ virtual ~forum_tag() = default; - /** - * @brief Read struct values from a json object - * @param j json to read values from - * @return A reference to self - */ - forum_tag& fill_from_json(nlohmann::json* j); - - /** - * @brief Build json for this forum_tag object - * - * @param with_id include the ID in the json - * @return std::string JSON string - */ - std::string build_json(bool with_id = false) const; - /** * @brief Set name of this forum_tag object * @@ -254,7 +261,24 @@ typedef std::unordered_map thread_member_map; * There are one of these for every channel type except threads. Threads are * special snowflakes. Get it? A Discord pun. Hahaha. .... I'll get my coat. */ -class DPP_EXPORT channel : public managed, public json_interface { +class DPP_EXPORT channel : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + channel& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build json for this channel object + * + * @param with_id include the ID in the json + * @return json JSON object + */ + virtual json to_json_impl(bool with_id = false) const; + public: /** Channel name (1-100 characters) */ std::string name; @@ -333,7 +357,7 @@ class DPP_EXPORT channel : public managed, public json_interface { /** Flags bitmap (dpp::channel_flags) */ uint16_t flags; - + /** Maximum user limit for voice channels (0-99) */ uint8_t user_limit; @@ -350,20 +374,6 @@ class DPP_EXPORT channel : public managed, public json_interface { */ static std::string get_mention(const snowflake& id); - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - channel& fill_from_json(nlohmann::json* j); - - /** - * @brief Build json for this channel object - * - * @param with_id include the ID in the json - * @return std::string JSON string - */ - virtual std::string build_json(bool with_id = false) const; - /** * @brief Set name of this channel object * @@ -742,8 +752,29 @@ class DPP_EXPORT channel : public managed, public json_interface { /** @brief A definition of a discord thread. * A thread is a superset of a channel. Not to be confused with `std::thread`! */ -class DPP_EXPORT thread : public channel { +class DPP_EXPORT thread : public channel, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + thread& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build json for this thread object + * + * @param with_id include the ID in the json + * @return std::string JSON string + */ + json to_json_impl(bool with_id = false) const override; + public: + using json_interface::fill_from_json; + using json_interface::build_json; + using json_interface::to_json; + /** * @brief Thread member of current user if joined to the thread. * Note this is only set by certain api calls otherwise contains default data @@ -802,25 +833,10 @@ class DPP_EXPORT thread : public channel { */ bool is_private_thread() const; - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - thread& fill_from_json(nlohmann::json* j); - /** * @brief Destroy the thread object */ virtual ~thread() = default; - - /** - * @brief Build json for this thread object - * - * @param with_id include the ID in the json - * @return std::string JSON string - */ - std::string build_json(bool with_id = false) const; - }; diff --git a/include/dpp/dtemplate.h b/include/dpp/dtemplate.h index f0618f408d..3c1bbb724a 100644 --- a/include/dpp/dtemplate.h +++ b/include/dpp/dtemplate.h @@ -31,8 +31,25 @@ namespace dpp { /** * @brief Represents a guild template */ -class DPP_EXPORT dtemplate : public json_interface { -public: +class DPP_EXPORT dtemplate : public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + dtemplate& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build the JSON for this object + * + * @param with_id Add ID to output + * @return json JSON content + */ + json to_json_impl(bool with_id = false) const; + +public: /** * @brief Template code */ @@ -80,21 +97,6 @@ class DPP_EXPORT dtemplate : public json_interface { * @brief Destroy the dtemplate object */ virtual ~dtemplate() = default; - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - dtemplate& fill_from_json(nlohmann::json* j); - - /** - * @brief Build the JSON for this object - * - * @param with_id Add ID to output - * @return std::string JSON content - */ - std::string build_json(bool with_id = false) const; - }; /** A container of invites */ diff --git a/include/dpp/emoji.h b/include/dpp/emoji.h index ab95736595..69f8a7b3b5 100644 --- a/include/dpp/emoji.h +++ b/include/dpp/emoji.h @@ -50,7 +50,26 @@ enum emoji_flags : uint8_t { /** * @brief Represents an emoji for a dpp::guild */ -class DPP_EXPORT emoji : public managed, public json_interface { +class DPP_EXPORT emoji : public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read class values from json object + * + * @param j A json object to read from + * @return A reference to self + */ + emoji& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build the json for this object + * + * @param with_id include the id in the JSON + * @return std::string json data + */ + json to_json_impl(bool with_id = false) const; + public: /** * @brief Emoji name @@ -125,22 +144,6 @@ class DPP_EXPORT emoji : public managed, public json_interface { */ static std::string get_mention(std::string_view name, snowflake id, bool is_animated = false); - /** - * @brief Read class values from json object - * - * @param j A json object to read from - * @return A reference to self - */ - emoji& fill_from_json(nlohmann::json* j); - - /** - * @brief Build the json for this object - * - * @param with_id include the id in the JSON - * @return std::string json data - */ - std::string build_json(bool with_id = false) const override; - /** * @brief Emoji requires colons * diff --git a/include/dpp/guild.h b/include/dpp/guild.h index 15c76d6989..b68d1181dc 100644 --- a/include/dpp/guild.h +++ b/include/dpp/guild.h @@ -188,7 +188,18 @@ enum guild_member_flags : uint16_t { * @brief Represents dpp::user membership upon a dpp::guild. * This contains the user's nickname, guild roles, and any other guild-specific flags. */ -class DPP_EXPORT guild_member { +class DPP_EXPORT guild_member : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Build json for the member object + * + * @param with_id Add ID to output + * @return json JSON object + */ + json to_json_impl(bool with_id = false) const; + protected: /** Nickname, or empty string if they don't have a nickname on this guild */ std::string nickname; @@ -198,6 +209,7 @@ class DPP_EXPORT guild_member { uint16_t flags; friend void from_json(const nlohmann::json& j, guild_member& gm); + public: /** Guild id */ snowflake guild_id; @@ -223,14 +235,6 @@ class DPP_EXPORT guild_member { */ guild_member& fill_from_json(nlohmann::json* j, snowflake g_id, snowflake u_id); - /** - * @brief Build json string for the member object - * - * @param with_id Add ID to output - * @return std::string json string - */ - std::string build_json(bool with_id = false) const; - /** * @brief Returns true if the user is in time-out (communication disabled) * @@ -437,6 +441,26 @@ class DPP_EXPORT guild_member { * @brief Defines a channel on a server's welcome screen */ struct DPP_EXPORT welcome_channel: public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read class values from json object + * + * @param j A json object to read from + * @return A reference to self + */ + welcome_channel& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build the json for this object + * + * @param with_id include the id in the JSON + * @return json JSON data + */ + json to_json_impl(bool with_id = false) const; + +public: /// The description shown for the channel std::string description; /// The emoji name if custom, the unicode character if standard, or null if no emoji is set @@ -456,22 +480,6 @@ struct DPP_EXPORT welcome_channel: public json_interface { */ virtual ~welcome_channel() = default; - /** - * @brief Read class values from json object - * - * @param j A json object to read from - * @return A reference to self - */ - welcome_channel& fill_from_json(nlohmann::json* j); - - /** - * @brief Build the json for this object - * - * @param with_id include the id in the JSON - * @return std::string json data - */ - std::string build_json(bool with_id = false) const; - /** * @brief Set the channel ID of this welcome channel object * @@ -494,20 +502,8 @@ struct DPP_EXPORT welcome_channel: public json_interface { * @brief Defines a server's welcome screen */ struct DPP_EXPORT welcome_screen: public json_interface { - /// The server description shown in the welcome screen - std::string description; - /// The channels shown in the welcome screen (max 5) - std::vector welcome_channels; - - /** - * @brief Construct a new welcome screen object - */ - welcome_screen() = default; - - /** - * @brief Destroy the welcome screen object - */ - virtual ~welcome_screen() = default; +protected: + friend struct json_interface; /** * @brief Read class values from json object @@ -515,7 +511,7 @@ struct DPP_EXPORT welcome_screen: public json_interface { * @param j A json object to read from * @return A reference to self */ - welcome_screen& fill_from_json(nlohmann::json* j); + welcome_screen& fill_from_json_impl(nlohmann::json* j); /** * @brief Build the json for this object @@ -523,7 +519,23 @@ struct DPP_EXPORT welcome_screen: public json_interface { * @param with_id include the id in the JSON * @return std::string json data */ - std::string build_json(bool with_id = false) const; + json to_json_impl(bool with_id = false) const; + +public: + /// The server description shown in the welcome screen + std::string description; + /// The channels shown in the welcome screen (max 5) + std::vector welcome_channels; + + /** + * @brief Construct a new welcome screen object + */ + welcome_screen() = default; + + /** + * @brief Destroy the welcome screen object + */ + virtual ~welcome_screen() = default; /** * @brief Set the server description for this welcome screen object shown in the welcome screen @@ -640,8 +652,25 @@ typedef std::unordered_map members_container; /** * @brief Represents a guild on Discord (AKA a server) */ -class DPP_EXPORT guild : public managed, public json_interface { +class DPP_EXPORT guild : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + guild& fill_from_json_impl(nlohmann::json* j); + + /** Build a JSON from this object. + * @param with_id True if an ID is to be included in the JSON + * @return JSON + */ + json to_json_impl(bool with_id = false) const; + public: + using json_interface::fill_from_json; + /** Guild name */ std::string name; @@ -782,12 +811,6 @@ class DPP_EXPORT guild : public managed, public json_interface { */ virtual ~guild() = default; - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - guild& fill_from_json(nlohmann::json* j); - /** Read class values from json object * @param shard originating shard * @param j A json object to read from @@ -795,12 +818,6 @@ class DPP_EXPORT guild : public managed, public json_interface { */ guild& fill_from_json(class discord_client* shard, nlohmann::json* j); - /** Build a JSON string from this object. - * @param with_id True if an ID is to be included in the JSON - * @return JSON string - */ - std::string build_json(bool with_id = false) const; - /** * @brief Compute the base permissions for a member on this guild, * before channel overwrites are applied. @@ -1149,7 +1166,26 @@ typedef std::unordered_map guild_map; /** * @brief Represents a guild widget, simple web widget of member list */ -class DPP_EXPORT guild_widget { +class DPP_EXPORT guild_widget : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Build a guild widget from json + * + * @param j json to build from + * @return guild_widget& reference to self + */ + guild_widget& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build json for a guild widget + * + * @param with_id Add ID to output + * @return std::string guild widget stringified json + */ + json to_json_impl(bool with_id = false) const; + public: /** * @brief Channel widget points to @@ -1165,22 +1201,6 @@ class DPP_EXPORT guild_widget { * @brief Construct a new guild widget object */ guild_widget(); - - /** - * @brief Build a guild widget from json - * - * @param j json to build from - * @return guild_widget& reference to self - */ - guild_widget& fill_from_json(nlohmann::json* j); - - /** - * @brief Build json for a guild widget - * - * @param with_id Add ID to output - * @return std::string guild widget stringified json - */ - std::string build_json(bool with_id = false) const; }; /** @@ -1212,6 +1232,26 @@ enum onboarding_prompt_flags: uint8_t { * @brief Represents an onboarding prompt option */ struct DPP_EXPORT onboarding_prompt_option: public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read class values from json object + * + * @param j A json object to read from + * @return A reference to self + */ + onboarding_prompt_option& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build the json for this object + * + * @param with_id include the id in the JSON + * @return json data + */ + json to_json_impl(bool with_id = false) const; + +public: std::vector channel_ids; //!< IDs for channels a member is added to when the option is selected std::vector role_ids; //!< IDs for roles assigned to a member when the option is selected dpp::emoji emoji; //!< Emoji of the option @@ -1228,22 +1268,6 @@ struct DPP_EXPORT onboarding_prompt_option: public managed, public json_interfac */ virtual ~onboarding_prompt_option() = default; - /** - * @brief Read class values from json object - * - * @param j A json object to read from - * @return A reference to self - */ - onboarding_prompt_option& fill_from_json(nlohmann::json* j); - - /** - * @brief Build the json for this object - * - * @param with_id include the id in the JSON - * @return std::string json data - */ - std::string build_json(bool with_id = false) const; - /** * @brief Set the emoji of this onboarding prompt option object * @@ -1273,6 +1297,26 @@ struct DPP_EXPORT onboarding_prompt_option: public managed, public json_interfac * @brief Represents an onboarding prompt */ struct DPP_EXPORT onboarding_prompt: public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read class values from json object + * + * @param j A json object to read from + * @return A reference to self + */ + onboarding_prompt& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build the json for this object + * + * @param with_id include the id in the JSON + * @return json data + */ + json to_json_impl(bool with_id = false) const; + +public: onboarding_prompt_type type; //!< Type of prompt (defaults to dpp::opt_multiple_choice) std::vector options; //!< Options available within the prompt std::string title; //!< Title of the prompt @@ -1288,22 +1332,6 @@ struct DPP_EXPORT onboarding_prompt: public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Read class values from json object + * + * @param j A json object to read from + * @return A reference to self + */ + onboarding& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build the json for this object + * + * @param with_id include the id in the JSON + * @return json data + */ + json to_json_impl(bool with_id = false) const; + +public: snowflake guild_id; //!< ID of the guild this onboarding is part of std::vector prompts; //!< Prompts shown during onboarding and in customize community std::vector default_channel_ids; //!< Channel IDs that members get opted into automatically @@ -1359,22 +1407,6 @@ struct DPP_EXPORT onboarding: public json_interface { */ virtual ~onboarding() = default; - /** - * @brief Read class values from json object - * - * @param j A json object to read from - * @return A reference to self - */ - onboarding& fill_from_json(nlohmann::json* j); - - /** - * @brief Build the json for this object - * - * @param with_id include the id in the JSON - * @return std::string json data - */ - std::string build_json(bool with_id = false) const; - /** * @brief Set guild_id of this onboarding object * diff --git a/include/dpp/integration.h b/include/dpp/integration.h index b26d40f630..6310c78bdb 100644 --- a/include/dpp/integration.h +++ b/include/dpp/integration.h @@ -81,6 +81,21 @@ struct DPP_EXPORT integration_app { * @brief Represents an integration on a guild, e.g. a connection to twitch. */ class DPP_EXPORT integration : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + integration& fill_from_json_impl(nlohmann::json* j); + + /** Build a json from this object. + * @param with_id Add ID to output + * @return JSON of the object + */ + virtual json to_json_impl(bool with_id = false) const; + public: /** Integration name */ std::string name; @@ -111,18 +126,6 @@ class DPP_EXPORT integration : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + connection& fill_from_json_impl(nlohmann::json* j); + public: std::string id; //!< id of the connection account std::string name; //!< the username of the connection account @@ -155,13 +167,6 @@ class DPP_EXPORT connection { * @brief Construct a new connection object */ connection(); - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - connection& fill_from_json(nlohmann::json* j); - }; /** A group of integrations */ diff --git a/include/dpp/invite.h b/include/dpp/invite.h index de780bc556..37798ec410 100644 --- a/include/dpp/invite.h +++ b/include/dpp/invite.h @@ -45,6 +45,21 @@ enum invite_target_t : uint8_t { * @brief Represents an invite to a discord guild or channel */ class DPP_EXPORT invite : public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + invite& fill_from_json_impl(nlohmann::json* j); + + /** Build JSON from this object. + * @param with_id Include ID in JSON + * @return The JSON of the invite + */ + virtual json to_json_impl(bool with_id = false) const; + public: /** Invite code */ @@ -164,19 +179,6 @@ class DPP_EXPORT invite : public json_interface { * @return invite& reference to self for chaining of calls */ invite& set_unique(const bool is_unique); - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - invite& fill_from_json(nlohmann::json* j); - - /** Build JSON from this object. - * @param with_id Include ID in JSON - * @return The JSON text of the invite - */ - virtual std::string build_json(bool with_id = false) const; - }; /** A container of invites */ diff --git a/include/dpp/json_interface.h b/include/dpp/json_interface.h index 430a1522a4..a5c5fbd3e5 100644 --- a/include/dpp/json_interface.h +++ b/include/dpp/json_interface.h @@ -21,41 +21,51 @@ #pragma once #include -#include #include namespace dpp { /** * @brief Represents an interface for an object that can optionally implement functions - * for converting to and from nlohmann::json. In the event either parse_from_json() or - * build_json() are not implemented and are called, they will throw at runtime. - * + * for converting to and from nlohmann::json. The methods are only present if the actual object + * also has those methods. + * * @tparam T Type of class that implements the interface */ - template struct DPP_EXPORT json_interface { - protected: - /* Must not destruct through pointer to json_interface. */ - ~json_interface() = default; + template + struct DPP_EXPORT json_interface { + /** + * @brief Convert object from nlohmann::json + * + * @param j nlohmann::json object + * @return T& Reference to self for fluent calling + */ + template ().fill_from_json_impl(std::declval()))> + T& fill_from_json(nlohmann::json* j) { + return static_cast(this)->fill_from_json_impl(j); + } - public: /** - * @brief Convert object from nlohmann::json - * - * @param j nlohmann::json object - * @return T& Reference to self for fluent calling - */ - T& fill_from_json([[maybe_unused]] nlohmann::json* j) { - throw dpp::logic_exception("JSON interface doesn't implement parse_from_json"); + * @brief Convert object to nlohmann::json + * + * @param with_id Whether to include the ID or not + * @note Some fields are conditionally filled, do not rely on all fields being present + * @return json Json built from the structure + */ + template ().to_json_impl(bool{}))> + auto to_json(bool with_id = false) const { + return static_cast(this)->to_json_impl(with_id); } /** - * @brief Build JSON string from the object - * - * @param with_id Include the ID in the JSON - * @return std::string JSON string version of object - */ - virtual std::string build_json([[maybe_unused]] bool with_id = false) const { - throw dpp::logic_exception("JSON interface doesn't implement build_json"); + * @brief Convert object to json string + * + * @param with_id Whether to include the ID or not + * @note Some fields are conditionally filled, do not rely on all fields being present + * @return std::string Json built from the structure + */ + template ().to_json_impl(bool{}))> + std::string build_json(bool with_id = false) const { + return to_json(with_id).dump(); } }; } // namespace dpp diff --git a/include/dpp/message.h b/include/dpp/message.h index ea38829b2c..6f05a701f5 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -84,6 +84,16 @@ enum component_style : uint8_t { * @brief An option for a select component */ struct DPP_EXPORT select_option : public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + select_option& fill_from_json_impl(nlohmann::json* j); + +public: /** * @brief User-facing name of the option */ @@ -198,12 +208,6 @@ struct DPP_EXPORT select_option : public json_interface { * @return select_option& reference to self for chaining */ select_option& set_animated(bool anim); - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - select_option& fill_from_json(nlohmann::json* j); }; /** @@ -219,6 +223,15 @@ struct DPP_EXPORT select_option : public json_interface { * object is an action row and the child objects are buttons. */ class DPP_EXPORT component : public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + component& fill_from_json_impl(nlohmann::json* j); + public: /** Component type, either a button or action row */ @@ -508,13 +521,6 @@ class DPP_EXPORT component : public json_interface { * @return component& Reference to self */ component& set_emoji(const std::string& name, dpp::snowflake id = 0, bool animated = false); - - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - component& fill_from_json(nlohmann::json* j); - }; /** @@ -875,6 +881,22 @@ enum sticker_format : uint8_t { * @brief Represents stickers received in messages */ struct DPP_EXPORT sticker : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + sticker& fill_from_json_impl(nlohmann::json* j); + + /** Build JSON from this object. + * @param with_id True if the ID is to be set in the JSON structure + * @return The JSON of the invite + */ + virtual json to_json_impl(bool with_id = true) const; + +public: /** Optional: for standard stickers, id of the pack the sticker is from */ snowflake pack_id; @@ -917,18 +939,6 @@ struct DPP_EXPORT sticker : public managed, public json_interface { virtual ~sticker() = default; - /** Read class values from json object - * @param j A json object to read from - * @return A reference to self - */ - sticker& fill_from_json(nlohmann::json* j); - - /** Build JSON from this object. - * @param with_id True if the ID is to be set in the JSON structure - * @return The JSON text of the invite - */ - virtual std::string build_json(bool with_id = true) const; - /** * @brief Get the sticker url. * @@ -958,6 +968,22 @@ struct DPP_EXPORT sticker : public managed, public json_interface { * @brief Represents a sticker pack (the built in groups of stickers that all nitro users get to use) */ struct DPP_EXPORT sticker_pack : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + sticker_pack& fill_from_json_impl(nlohmann::json* j); + + /** Build JSON from this object. + * @param with_id True if the ID is to be set in the JSON structure + * @return The JSON of the invite + */ + virtual json to_json_impl(bool with_id = true) const; + +public: /// the stickers in the pack std::map stickers; /// name of the sticker pack @@ -977,19 +1003,6 @@ struct DPP_EXPORT sticker_pack : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Read class values from json object + * @param j A json object to read from + * @return A reference to self + */ + inline message& fill_from_json_impl(nlohmann::json *j) { + return fill_from_json(j, {cp_aggressive, cp_aggressive, cp_aggressive}); + } + + /** Build a JSON from this object. + * @param with_id True if an ID is to be included in the JSON + * @return JSON + */ + inline json to_json_impl(bool with_id = false) const { + return to_json(with_id, false); + } +public: /** id of the channel the message was sent in */ snowflake channel_id; /** Optional: id of the guild the message was sent in */ @@ -1398,12 +1430,15 @@ struct DPP_EXPORT message : public managed { */ message& set_allowed_mentions(bool _parse_users, bool _parse_roles, bool _parse_everyone, bool _replied_user, const std::vector &users, const std::vector &roles); + using json_interface::fill_from_json; + using json_interface::to_json; + /** Fill this object from json. * @param j JSON object to fill from * @param cp Cache policy for user records, whether or not we cache users when a message is received * @return A reference to self */ - message& fill_from_json(nlohmann::json* j, cache_policy_t cp = {cp_aggressive, cp_aggressive, cp_aggressive}); + message& fill_from_json(nlohmann::json* j, cache_policy_t cp); /** Build JSON from this object. * @param with_id True if the ID is to be included in the built JSON @@ -1411,7 +1446,7 @@ struct DPP_EXPORT message : public managed { * This will exclude some fields that are not valid in interactions at this time. * @return The JSON text of the message */ - virtual std::string build_json(bool with_id = false, bool is_interaction_response = false) const; + virtual json to_json(bool with_id, bool is_interaction_response) const; /** * @brief Returns true if the message was crossposted to other servers diff --git a/include/dpp/presence.h b/include/dpp/presence.h index eafbfdcc03..1dbc09cbf7 100644 --- a/include/dpp/presence.h +++ b/include/dpp/presence.h @@ -315,6 +315,26 @@ class DPP_EXPORT activity { * @brief Represents user presence, e.g. what game they are playing and if they are online */ class DPP_EXPORT presence : public json_interface { +protected: + friend struct json_interface; + + /** Fill this object from json. + * @param j JSON object to fill from + * @return A reference to self + */ + presence& fill_from_json_impl(nlohmann::json* j); + + /** Build JSON from this object. + * + * @note This excludes any part of the presence object that are not valid for websockets and bots, + * and includes websocket opcode 3. You will not get what you expect if you call this on a user's + * presence received from on_presence_update or on_guild_create! + * + * @param with_id Add ID to output + * @return The JSON text of the presence + */ + virtual json to_json_impl(bool with_id = false) const; + public: /** The user the presence applies to */ snowflake user_id; @@ -351,23 +371,6 @@ class DPP_EXPORT presence : public json_interface { /** Destructor */ ~presence(); - /** Fill this object from json. - * @param j JSON object to fill from - * @return A reference to self - */ - presence& fill_from_json(nlohmann::json* j); - - /** Build JSON from this object. - * - * Note: This excludes any part of the presence object that are not valid for websockets and bots, - * and includes websocket opcode 3. You will not get what you expect if you call this on a user's - * presence received from on_presence_update or on_guild_create! - * - * @param with_id Add ID to output - * @return The JSON text of the presence - */ - virtual std::string build_json(bool with_id = false) const; - /** The users status on desktop * @return The user's status on desktop */ @@ -387,6 +390,17 @@ class DPP_EXPORT presence : public json_interface { * @return The user's status as shown to other users */ presence_status status() const; + + /** Build JSON from this object. + * + * @note This excludes any part of the presence object that are not valid for websockets and bots, + * and includes websocket opcode 3. You will not get what you expect if you call this on a user's + * presence received from on_presence_update or on_guild_create! + * + * @param with_id Add ID to output + * @return The JSON of the presence + */ + json to_json(bool with_id = false) const; // Intentional shadow of json_interface, mostly present for documentation }; /** A container of presences */ diff --git a/include/dpp/prune.h b/include/dpp/prune.h index be7b228a3f..3dc15169af 100644 --- a/include/dpp/prune.h +++ b/include/dpp/prune.h @@ -31,6 +31,22 @@ namespace dpp { * @brief Defines a request to count prunable users, or start a prune operation */ struct DPP_EXPORT prune : public json_interface { +protected: + friend struct json_interface; + + /** Fill this object from json. + * @param j JSON object to fill from + * @return A reference to self + */ + prune& fill_from_json_impl(nlohmann::json* j); + + /** Build JSON from this object. + * @param with_prune_count True if the prune count boolean is to be set in the built JSON + * @return The JSON of the prune object + */ + virtual json to_json_impl(bool with_prune_count = false) const; + +public: /** * Destroy this prune object */ @@ -47,18 +63,12 @@ struct DPP_EXPORT prune : public json_interface { */ bool compute_prune_count; - /** Fill this object from json. - * @param j JSON object to fill from - * @return A reference to self - */ - prune& fill_from_json(nlohmann::json* j); - - /** Build JSON from this object. + /** + * Build JSON from this object. * @param with_prune_count True if the prune count boolean is to be set in the built JSON - * @return The JSON text of the prune object + * @return The JSON of the prune object */ - virtual std::string build_json(bool with_prune_count = false) const; - + json to_json(bool with_id = false) const; // Intentional shadow of json_interface, mostly present for documentation }; } // namespace dpp diff --git a/include/dpp/restresults.h b/include/dpp/restresults.h index 77ca392057..55170c24a4 100644 --- a/include/dpp/restresults.h +++ b/include/dpp/restresults.h @@ -77,7 +77,19 @@ typedef std::map shard_list; /** * @brief Represents the various information from the 'get gateway bot' api call */ -struct DPP_EXPORT gateway { +struct DPP_EXPORT gateway : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill this object from json + * + * @param j json to fill from + * @return gateway& reference to self + */ + gateway& fill_from_json_impl(nlohmann::json* j); + +public: /// Gateway websocket url std::string url; @@ -107,14 +119,6 @@ struct DPP_EXPORT gateway { * @brief Construct a new gateway object */ gateway(); - - /** - * @brief Fill this object from json - * - * @param j json to fill from - * @return gateway& reference to self - */ - gateway& fill_from_json(nlohmann::json* j); }; /** diff --git a/include/dpp/role.h b/include/dpp/role.h index 01351b8eb7..6a9b7d093e 100644 --- a/include/dpp/role.h +++ b/include/dpp/role.h @@ -49,7 +49,26 @@ enum role_flags : uint8_t { * ID as the guild's ID. This is the base permission set applied to all users where no other role or override * applies, and is the starting value of the bit mask looped through to calculate channel permissions. */ -class DPP_EXPORT role : public managed, public json_interface { +class DPP_EXPORT role : public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill this role from json. + * + * @param j The json data + * @return A reference to self + */ + role& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build a json from this object. + * + * @param with_id true if the ID is to be included in the json + * @return The json of the role + */ + virtual json to_json_impl(bool with_id = false) const; + public: /** * @brief Role name @@ -162,13 +181,7 @@ class DPP_EXPORT role : public managed, public json_interface { */ role& set_guild_id(snowflake gid); - /** - * @brief Fill this role from json. - * - * @param j The json data - * @return A reference to self - */ - role& fill_from_json(nlohmann::json* j); + using json_interface::fill_from_json; /** * @brief Fill this role from json. @@ -179,14 +192,6 @@ class DPP_EXPORT role : public managed, public json_interface { */ role& fill_from_json(snowflake guild_id, nlohmann::json* j); - /** - * @brief Build a json string from this object. - * - * @param with_id true if the ID is to be included in the json text - * @return The json of the role - */ - virtual std::string build_json(bool with_id = false) const; - /** * @brief Get the mention/ping for the role * @@ -640,6 +645,23 @@ enum application_role_connection_metadata_type : uint8_t { * @brief Application Role Connection Metadata. Represents a role connection metadata for an dpp::application */ class DPP_EXPORT application_role_connection_metadata : public json_interface { +protected: + friend struct json_interface; + + /** Fill this record from json. + * @param j The json to fill this record from + * @return Reference to self + */ + application_role_connection_metadata& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Convert to JSON + * + * @param with_id include ID in output + * @return json JSON output + */ + virtual json to_json_impl(bool with_id = false) const; + public: application_role_connection_metadata_type type; //!< Type of metadata value std::string key; //!< Dictionary key for the metadata field (must be `a-z`, `0-9`, or `_` characters; 1-50 characters) @@ -654,26 +676,29 @@ class DPP_EXPORT application_role_connection_metadata : public json_interface { +protected: + friend struct json_interface; /** Fill this record from json. * @param j The json to fill this record from * @return Reference to self */ - application_role_connection_metadata& fill_from_json(nlohmann::json* j); + application_role_connection& fill_from_json_impl(nlohmann::json* j); /** - * @brief Convert to JSON string + * @brief Convert to JSON * * @param with_id include ID in output - * @return std::string JSON output + * @return json JSON output */ - virtual std::string build_json(bool with_id = false) const; -}; + virtual json to_json_impl(bool with_id = false) const; -/** - * @brief The application role connection that an application has attached to a user. - */ -class DPP_EXPORT application_role_connection : public json_interface { public: std::string platform_name; //!< Optional: The vanity name of the platform a bot has connected (max 50 characters) std::string platform_username; //!< Optional: The username on the platform a bot has connected (max 100 characters) @@ -685,20 +710,6 @@ class DPP_EXPORT application_role_connection : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Serialise a scheduled_event object from json + * + * @return scheduled_event& a reference to self + */ + scheduled_event& fill_from_json_impl(const nlohmann::json* j); + + /** + * @brief Build json for this object + * @param with_id Include id field in json + * + * @return std::string Json of this object + */ + virtual json to_json_impl(bool with_id = false) const; + +public: snowflake guild_id; //!< the guild id which the scheduled event belongs to snowflake channel_id; //!< the channel id in which the scheduled event will be hosted, or null if scheduled entity type is EXTERNAL (may be empty) snowflake creator_id; //!< Optional: the id of the user that created the scheduled event @@ -194,21 +213,6 @@ struct DPP_EXPORT scheduled_event : public managed, public json_interface { +struct DPP_EXPORT stage_instance : public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Serialise a stage_instance object rom json + * + * @return stage_instance& a reference to self + */ + stage_instance& fill_from_json_impl(const nlohmann::json* j); + + /** + * @brief Build json for this object + * + * @param with_id include ID + * @return json Json of this object + */ + virtual json to_json_impl(bool with_id = false) const; + +public: /// The guild id of the associated Stage channel snowflake guild_id; /// The id of the associated Stage channel @@ -64,21 +83,6 @@ struct DPP_EXPORT stage_instance : public managed, public json_interface { +class DPP_EXPORT user : public managed, public json_interface { +protected: + friend struct json_interface; + + /** Fill this record from json. + * @param j The json to fill this record from + * @return Reference to self + */ + user& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Convert to JSON + * + * @param with_id include ID in output + * @return json JSON output + */ + virtual json to_json_impl(bool with_id = true) const; + public: /** Discord username */ std::string username; @@ -123,20 +140,6 @@ class DPP_EXPORT user : public managed, public json_interface { */ static std::string get_mention(const snowflake& id); - /** Fill this record from json. - * @param j The json to fill this record from - * @return Reference to self - */ - user& fill_from_json(nlohmann::json* j); - - /** - * @brief Convert to JSON string - * - * @param with_id include ID in output - * @return std::string JSON output - */ - virtual std::string build_json(bool with_id = true) const; - /** * @brief Get the avatar url of the user * @@ -341,26 +344,29 @@ class DPP_EXPORT user : public managed, public json_interface { * which bots do not normally have. */ class DPP_EXPORT user_identified : public user, public json_interface { -public: - std::string locale; //!< Optional: the user's chosen language option identify - std::string email; //!< Optional: the user's email email (may be empty) - utility::iconhash banner; //!< Optional: the user's banner hash identify (may be empty) - uint32_t accent_color; //!< Optional: the user's banner color encoded as an integer representation of hexadecimal color code identify (may be empty) - bool verified; //!< Optional: whether the email on this account has been verified email - +protected: + friend struct json_interface; + /** Fill this record from json. * @param j The json to fill this record from * @return Reference to self */ - user_identified& fill_from_json(nlohmann::json* j); + user_identified& fill_from_json_impl(nlohmann::json* j); /** - * @brief Convert to JSON string - * + * @brief Convert to JSON + * * @param with_id include ID in output - * @return std::string JSON output + * @return json JSON output */ - virtual std::string build_json(bool with_id = true) const; + virtual json to_json_impl(bool with_id = true) const; + +public: + std::string locale; //!< Optional: the user's chosen language option identify + std::string email; //!< Optional: the user's email email (may be empty) + utility::iconhash banner; //!< Optional: the user's banner hash identify (may be empty) + uint32_t accent_color; //!< Optional: the user's banner color encoded as an integer representation of hexadecimal color code identify (may be empty) + bool verified; //!< Optional: whether the email on this account has been verified email /** * @brief Construct a new user identified object @@ -379,6 +385,10 @@ class DPP_EXPORT user_identified : public user, public json_interface::fill_from_json; + using json_interface::build_json; + using json_interface::to_json; + /** * @brief Return true if user has an animated banner * diff --git a/include/dpp/voiceregion.h b/include/dpp/voiceregion.h index dc86aab16f..5bec303671 100644 --- a/include/dpp/voiceregion.h +++ b/include/dpp/voiceregion.h @@ -41,6 +41,25 @@ enum voiceregion_flags { * @brief Represents a voice region on discord */ class DPP_EXPORT voiceregion : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill object properties from JSON + * + * @param j JSON to fill from + * @return voiceregion& Reference to self + */ + voiceregion& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build a json for this object + * + * @param with_id Add ID to output + * @return json JSON string + */ + virtual json to_json_impl(bool with_id = false) const; + public: /** * @brief Voice server ID @@ -67,22 +86,6 @@ class DPP_EXPORT voiceregion : public json_interface { */ virtual ~voiceregion() = default; - /** - * @brief Fill object properties from JSON - * - * @param j JSON to fill from - * @return voiceregion& Reference to self - */ - voiceregion& fill_from_json(nlohmann::json* j); - - /** - * @brief Build a json string for this object - * - * @param with_id Add ID to output - * @return std::string JSON string - */ - virtual std::string build_json(bool with_id = false) const; - /** * @brief True if is the optimal voice server * diff --git a/include/dpp/voicestate.h b/include/dpp/voicestate.h index 4ece887833..29fb61d570 100644 --- a/include/dpp/voicestate.h +++ b/include/dpp/voicestate.h @@ -47,6 +47,17 @@ enum voicestate_flags { * or via dpp::channel::get_voice_members */ class DPP_EXPORT voicestate : public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill voicestate object from json data + * + * @param j JSON data to fill from + * @return voicestate& Reference to self + */ + voicestate& fill_from_json_impl(nlohmann::json* j); + public: class discord_client* shard; //!< Owning shard snowflake guild_id; //!< Optional: the guild id this voice state is for @@ -66,22 +77,6 @@ class DPP_EXPORT voicestate : public json_interface { */ virtual ~voicestate() = default; - /** - * @brief Fill voicestate object from json data - * - * @param j JSON data to fill from - * @return voicestate& Reference to self - */ - voicestate& fill_from_json(nlohmann::json* j); - - /** - * @brief Build json representation of the object - * - * @param with_id Add ID to output - * @return std::string JSON string - */ - virtual std::string build_json(bool with_id = false) const; - /// Return true if the user is deafened by the server bool is_deaf() const; diff --git a/include/dpp/webhook.h b/include/dpp/webhook.h index bb046570cf..808eb45227 100644 --- a/include/dpp/webhook.h +++ b/include/dpp/webhook.h @@ -41,7 +41,26 @@ enum webhook_type { /** * @brief Represents a discord webhook */ -class DPP_EXPORT webhook : public managed, public json_interface { +class DPP_EXPORT webhook : public managed, public json_interface { +protected: + friend struct json_interface; + + /** + * @brief Fill in object from json data + * + * @param j JSON data + * @return webhook& Reference to self + */ + webhook& fill_from_json_impl(nlohmann::json* j); + + /** + * @brief Build JSON string from object + * + * @param with_id Include the ID of the webhook in the json + * @return std::string JSON encoded object + */ + virtual json to_json_impl(bool with_id = false) const; + public: uint8_t type; //!< the type of the webhook snowflake guild_id; //!< Optional: the guild id this webhook is for @@ -79,22 +98,6 @@ class DPP_EXPORT webhook : public managed, public json_interface { */ ~webhook(); - /** - * @brief Fill in object from json data - * - * @param j JSON data - * @return webhook& Reference to self - */ - webhook& fill_from_json(nlohmann::json* j); - - /** - * @brief Build JSON string from object - * - * @param with_id Include the ID of the webhook in the json - * @return std::string JSON encoded object - */ - virtual std::string build_json(bool with_id = false) const; - /** * @brief Base64 encode image data and allocate it to image_data * diff --git a/src/dpp/application.cpp b/src/dpp/application.cpp index 928e80294a..033a570b92 100644 --- a/src/dpp/application.cpp +++ b/src/dpp/application.cpp @@ -35,7 +35,7 @@ application::application() : managed(0), bot_public(false), bot_require_code_gra application::~application() = default; -application& application::fill_from_json(nlohmann::json* j) { +application& application::fill_from_json_impl(nlohmann::json* j) { set_snowflake_not_null(j, "id", id); set_string_not_null(j, "name", name); std::string ic = string_not_null(j, "icon"); diff --git a/src/dpp/auditlog.cpp b/src/dpp/auditlog.cpp index a821ad5bb8..c1480938f1 100644 --- a/src/dpp/auditlog.cpp +++ b/src/dpp/auditlog.cpp @@ -30,7 +30,7 @@ using json = nlohmann::json; audit_entry::audit_entry(): type(aut_guild_update) { } -audit_entry &audit_entry::fill_from_json(nlohmann::json *j) { +audit_entry &audit_entry::fill_from_json_impl(nlohmann::json *j) { this->id = snowflake_not_null(j, "id"); this->type = (audit_type)int8_not_null(j, "action_type"); this->user_id = snowflake_not_null(j, "user_id"); @@ -69,7 +69,7 @@ audit_entry &audit_entry::fill_from_json(nlohmann::json *j) { return *this; } -auditlog& auditlog::fill_from_json(nlohmann::json* j) { +auditlog& auditlog::fill_from_json_impl(nlohmann::json* j) { set_object_array_not_null(j, "audit_log_entries", this->entries); return *this; } diff --git a/src/dpp/automod.cpp b/src/dpp/automod.cpp index 0ee9e1eb3a..219d347859 100644 --- a/src/dpp/automod.cpp +++ b/src/dpp/automod.cpp @@ -33,7 +33,7 @@ automod_action::automod_action() : channel_id(0), duration_seconds(0) automod_action::~automod_action() = default; -automod_action& automod_action::fill_from_json(nlohmann::json* j) { +automod_action& automod_action::fill_from_json_impl(nlohmann::json* j) { type = (automod_action_type)int8_not_null(j, "type"); switch (type) { case amod_action_block_message: @@ -51,7 +51,7 @@ automod_action& automod_action::fill_from_json(nlohmann::json* j) { return *this; } -std::string automod_action::build_json(bool with_id) const { +json automod_action::to_json_impl(bool with_id) const { json j({ { "type", type } }); @@ -77,14 +77,14 @@ std::string automod_action::build_json(bool with_id) const { default: break; }; - return j.dump(); + return j; } automod_metadata::automod_metadata() : mention_total_limit(0) {} automod_metadata::~automod_metadata() = default; -automod_metadata& automod_metadata::fill_from_json(nlohmann::json* j) { +automod_metadata& automod_metadata::fill_from_json_impl(nlohmann::json* j) { for (auto k : (*j)["keyword_filter"]) { keywords.push_back(k); } @@ -102,7 +102,7 @@ automod_metadata& automod_metadata::fill_from_json(nlohmann::json* j) { return *this; } -std::string automod_metadata::build_json(bool with_id) const { +json automod_metadata::to_json_impl(bool with_id) const { json j; j["keyword_filter"] = json::array(); j["regex_patterns"] = json::array(); @@ -122,7 +122,7 @@ std::string automod_metadata::build_json(bool with_id) const { } j["mention_total_limit"] = mention_total_limit; j["mention_raid_protection_enabled"] = mention_raid_protection_enabled; - return j.dump(); + return j; } @@ -132,7 +132,7 @@ automod_rule::automod_rule() : managed(), guild_id(0), creator_id(0), event_type automod_rule::~automod_rule() = default; -automod_rule& automod_rule::fill_from_json(nlohmann::json* j) { +automod_rule& automod_rule::fill_from_json_impl(nlohmann::json* j) { id = snowflake_not_null(j, "id"); guild_id = snowflake_not_null(j, "guild_id"); name = string_not_null(j, "name"); @@ -149,7 +149,7 @@ automod_rule& automod_rule::fill_from_json(nlohmann::json* j) { return *this; } -std::string automod_rule::build_json(bool with_id) const { +json automod_rule::to_json_impl(bool with_id) const { json j; if (with_id && id) { j["id"] = std::to_string(id); @@ -161,12 +161,12 @@ std::string automod_rule::build_json(bool with_id) const { j["enabled"] = enabled; j["event_type"] = event_type; j["trigger_type"] = trigger_type; - j["trigger_metadata"] = json::parse(trigger_metadata.build_json()); + j["trigger_metadata"] = trigger_metadata.to_json(); if (actions.size()) { j["actions"] = json::array(); json& act = j["actions"]; for (auto v : actions) { - act.push_back(json::parse(v.build_json())); + act.push_back(v.to_json()); } } if (exempt_roles.size()) { @@ -183,7 +183,7 @@ std::string automod_rule::build_json(bool with_id) const { channels.push_back(std::to_string(v)); } } - return j.dump(); + return j; } } // namespace dpp diff --git a/src/dpp/ban.cpp b/src/dpp/ban.cpp index e2a0bf127e..aee056b68e 100644 --- a/src/dpp/ban.cpp +++ b/src/dpp/ban.cpp @@ -31,7 +31,7 @@ ban::ban() : user_id(0) { } -ban& ban::fill_from_json(nlohmann::json* j) { +ban& ban::fill_from_json_impl(nlohmann::json* j) { reason = string_not_null(j, "reason"); if (j->contains("user")) { json & user = (*j)["user"]; @@ -40,10 +40,5 @@ ban& ban::fill_from_json(nlohmann::json* j) { return *this; } -std::string ban::build_json(bool with_id) const { - /* This is an unused stub, because sending a ban is simple as a user id and a reason */ - return "{}"; -} - } // namespace dpp diff --git a/src/dpp/channel.cpp b/src/dpp/channel.cpp index 7f90c7eaa2..e5d77acd71 100644 --- a/src/dpp/channel.cpp +++ b/src/dpp/channel.cpp @@ -51,7 +51,7 @@ forum_tag::forum_tag(const std::string& name) : forum_tag() { this->set_name(name); } -forum_tag& forum_tag::fill_from_json(nlohmann::json *j) { +forum_tag& forum_tag::fill_from_json_impl(nlohmann::json *j) { set_snowflake_not_null(j, "id", this->id); set_string_not_null(j, "name", this->name); set_bool_not_null(j, "moderated", this->moderated); @@ -65,7 +65,7 @@ forum_tag& forum_tag::fill_from_json(nlohmann::json *j) { return *this; } -std::string forum_tag::build_json(bool with_id) const { +json forum_tag::to_json_impl(bool with_id) const { json j; if (with_id && id) { j["id"] = std::to_string(id); @@ -77,7 +77,7 @@ std::string forum_tag::build_json(bool with_id) const { } else if (std::holds_alternative(emoji)) { j["emoji_name"] = std::get(emoji); } - return j.dump(); + return j; } forum_tag &forum_tag::set_name(const std::string &name) { @@ -88,7 +88,7 @@ forum_tag &forum_tag::set_name(const std::string &name) { const uint16_t CHANNEL_TYPE_MASK = 0b0000000000001111; const uint16_t DEFAULT_FORUM_LAYOUT_MASK = 0b0000011000000000; -thread_member& thread_member::fill_from_json(nlohmann::json* j) { +thread_member& thread_member::fill_from_json_impl(nlohmann::json* j) { set_snowflake_not_null(j, "id", this->thread_id); set_snowflake_not_null(j, "user_id", this->user_id); set_ts_not_null(j, "join_timestamp", this->joined); @@ -344,7 +344,7 @@ bool thread::is_private_thread() const { return (flags & CHANNEL_TYPE_MASK) == CHANNEL_PRIVATE_THREAD; } -thread& thread::fill_from_json(json* j) { +thread& thread::fill_from_json_impl(json* j) { channel::fill_from_json(j); uint8_t type = int8_not_null(j, "type"); @@ -366,14 +366,13 @@ thread& thread::fill_from_json(json* j) { if (j->contains("member")) { member.fill_from_json(&((*j)["member"])); } - return *this; } thread::thread() : channel(), total_messages_sent(0), message_count(0), member_count(0) { } -channel& channel::fill_from_json(json* j) { +channel& channel::fill_from_json_impl(json* j) { this->id = snowflake_not_null(j, "id"); set_snowflake_not_null(j, "guild_id", this->guild_id); set_int16_not_null(j, "position", this->position); @@ -477,13 +476,13 @@ channel& channel::fill_from_json(json* j) { return *this; } -std::string thread::build_json(bool with_id) const { - json j = json::parse(channel::build_json(with_id)); +json thread::to_json_impl(bool with_id) const { + json j = channel::to_json_impl(with_id); j["type"] = (flags & CHANNEL_TYPE_MASK); j["archived"] = this->metadata.archived; j["auto_archive_duration"] = this->metadata.auto_archive_duration; j["locked"] = this->metadata.locked; - + if(this->get_type() == dpp::channel_type::CHANNEL_PRIVATE_THREAD) { j["invitable"] = this->metadata.invitable; } @@ -496,10 +495,10 @@ std::string thread::build_json(bool with_id) const { } } } - return j.dump(); + return j; } -std::string channel::build_json(bool with_id) const { +json channel::to_json_impl(bool with_id) const { json j; if (with_id && id) { j["id"] = std::to_string(id); @@ -569,7 +568,7 @@ std::string channel::build_json(bool with_id) const { if (!available_tags.empty()) { j["available_tags"] = json::array(); for (const auto &available_tag : this->available_tags) { - j["available_tags"].push_back(json::parse(available_tag.build_json())); + j["available_tags"].push_back(available_tag.to_json()); } } if (std::holds_alternative(this->default_reaction)) { @@ -583,8 +582,8 @@ std::string channel::build_json(bool with_id) const { if (flags & c_lock_permissions) { j["lock_permissions"] = true; } - - return j.dump(); + + return j; } permission channel::get_user_permissions(const user* user) const { diff --git a/src/dpp/cluster.cpp b/src/dpp/cluster.cpp index 89bb07f964..16d3a777f3 100644 --- a/src/dpp/cluster.cpp +++ b/src/dpp/cluster.cpp @@ -344,7 +344,7 @@ void cluster::request(const std::string &url, http_method method, http_completio gateway::gateway() : shards(0), session_start_total(0), session_start_remaining(0), session_start_reset_after(0), session_start_max_concurrency(0) { } -gateway& gateway::fill_from_json(nlohmann::json* j) { +gateway& gateway::fill_from_json_impl(nlohmann::json* j) { url = string_not_null(j, "url"); shards = int32_not_null(j, "shards"); session_start_total = int32_not_null(&((*j)["session_start_limit"]), "total"); @@ -359,7 +359,7 @@ gateway::gateway(nlohmann::json* j) { } void cluster::set_presence(const dpp::presence &p) { - json pres = json::parse(p.build_json()); + json pres = p.to_json(); for (auto& s : shards) { if (s.second->is_connected()) { s.second->queue_message(s.second->jsonobj_to_string(pres)); diff --git a/src/dpp/cluster/appcommand.cpp b/src/dpp/cluster/appcommand.cpp index 4ca0c3d1f6..eb1f056d5c 100644 --- a/src/dpp/cluster/appcommand.cpp +++ b/src/dpp/cluster/appcommand.cpp @@ -26,7 +26,7 @@ namespace dpp { void cluster::global_bulk_command_create(const std::vector &commands, command_completion_event_t callback) { json j = json::array(); for (auto & s : commands) { - j.push_back(json::parse(s.build_json(false))); + 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); } @@ -58,7 +58,7 @@ void cluster::global_commands_get(command_completion_event_t callback) { void cluster::guild_bulk_command_create(const std::vector &commands, snowflake guild_id, command_completion_event_t callback) { json j = json::array(); for (auto & s : commands) { - j.push_back(json::parse(s.build_json(false))); + 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); } diff --git a/src/dpp/cluster/guild.cpp b/src/dpp/cluster/guild.cpp index 8806fe0531..87f73371c4 100644 --- a/src/dpp/cluster/guild.cpp +++ b/src/dpp/cluster/guild.cpp @@ -163,7 +163,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 = json::parse(welcome_screen.build_json()); + 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); } diff --git a/src/dpp/cluster/guild_member.cpp b/src/dpp/cluster/guild_member.cpp index cbfe7d5cd5..e851e9c7ad 100644 --- a/src/dpp/cluster/guild_member.cpp +++ b/src/dpp/cluster/guild_member.cpp @@ -23,7 +23,7 @@ namespace dpp { void cluster::guild_add_member(const guild_member& gm, const std::string &access_token, command_completion_event_t callback) { - json j = json::parse(gm.build_json()); + 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); } diff --git a/src/dpp/cluster/role.cpp b/src/dpp/cluster/role.cpp index 58f700f191..1ff58bbf1d 100644 --- a/src/dpp/cluster/role.cpp +++ b/src/dpp/cluster/role.cpp @@ -57,7 +57,7 @@ void cluster::application_role_connection_get(snowflake application_id, command_ void cluster::application_role_connection_update(snowflake application_id, const std::vector &connection_metadata, command_completion_event_t callback) { json j = json::array(); for (const auto &conn_metadata : connection_metadata) { - j.push_back(json::parse(conn_metadata.build_json())); + 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); } diff --git a/src/dpp/cluster/thread.cpp b/src/dpp/cluster/thread.cpp index 8c0dab0fce..be58b82b41 100644 --- a/src/dpp/cluster/thread.cpp +++ b/src/dpp/cluster/thread.cpp @@ -94,7 +94,7 @@ void cluster::thread_create_in_forum(const std::string& thread_name, snowflake c json j({ {"name", thread_name}, {"rate_limit_per_user", rate_limit_per_user}, - {"message", json::parse(msg.build_json())}, + {"message", msg.to_json()}, {"applied_tags", applied_tags}, }); switch (auto_archive_duration) { diff --git a/src/dpp/cluster/webhook.cpp b/src/dpp/cluster/webhook.cpp index 1d87825bfe..f182012ec2 100644 --- a/src/dpp/cluster/webhook.cpp +++ b/src/dpp/cluster/webhook.cpp @@ -64,7 +64,7 @@ void cluster::edit_webhook_message(const class webhook &wh, const struct message void cluster::edit_webhook_with_token(const class webhook& wh, command_completion_event_t callback) { - json jwh = json::parse(wh.build_json(true)); + json jwh = wh.to_json(true); if (jwh.find("channel_id") != jwh.end()) { jwh.erase(jwh.find("channel_id")); } @@ -79,7 +79,7 @@ void cluster::execute_webhook(const class webhook &wh, const struct message& m, }); std::string body; if (!thread_name.empty() || !wh.avatar.empty() || !wh.name.empty()) { // only use json::parse if thread_name is set - json j = json::parse(m.build_json(false)); + json j = m.to_json(false); if (!thread_name.empty()) { j["thread_name"] = thread_name; } diff --git a/src/dpp/dtemplate.cpp b/src/dpp/dtemplate.cpp index ebbb3eb7b5..8f67e0efd6 100644 --- a/src/dpp/dtemplate.cpp +++ b/src/dpp/dtemplate.cpp @@ -31,7 +31,7 @@ dtemplate::dtemplate() : code(""), name(""), description(""), usage_count(0), cr { } -dtemplate& dtemplate::fill_from_json(nlohmann::json* j) { +dtemplate& dtemplate::fill_from_json_impl(nlohmann::json* j) { code = string_not_null(j, "code"); name = string_not_null(j, "name"); description = string_not_null(j, "description"); @@ -44,8 +44,8 @@ dtemplate& dtemplate::fill_from_json(nlohmann::json* j) { return *this; } -std::string dtemplate::build_json(bool with_id) const { - json j({ +json dtemplate::to_json_impl(bool with_id) const { + return { {"code", code}, {"name", name}, {"description", description}, @@ -54,8 +54,7 @@ std::string dtemplate::build_json(bool with_id) const { {"updated_at", updated_at}, {"source_guild_id", source_guild_id, "is_dirty", is_dirty} - }); - return j.dump(); + }; } } // namespace dpp diff --git a/src/dpp/emoji.cpp b/src/dpp/emoji.cpp index f33a636ad2..b033366e32 100644 --- a/src/dpp/emoji.cpp +++ b/src/dpp/emoji.cpp @@ -34,7 +34,7 @@ std::string emoji::get_mention(std::string_view name, snowflake id, bool is_anim return utility::emoji_mention(name,id,is_animated); } -emoji& emoji::fill_from_json(nlohmann::json* j) { +emoji& emoji::fill_from_json_impl(nlohmann::json* j) { id = snowflake_not_null(j, "id"); name = string_not_null(j, "name"); if (j->contains("user")) { @@ -56,7 +56,7 @@ emoji& emoji::fill_from_json(nlohmann::json* j) { return *this; } -std::string emoji::build_json(bool with_id) const { +json emoji::to_json_impl(bool with_id) const { json j; if (with_id) { j["id"] = std::to_string(id); @@ -65,7 +65,7 @@ std::string emoji::build_json(bool with_id) const { if (!image_data.empty()) { j["image"] = image_data; } - return j.dump(); + return j; } bool emoji::requires_colons() const { diff --git a/src/dpp/guild.cpp b/src/dpp/guild.cpp index 1a4864e6ec..d919618fe3 100644 --- a/src/dpp/guild.cpp +++ b/src/dpp/guild.cpp @@ -229,7 +229,7 @@ bool guild_member::has_animated_guild_avatar() const { return this->flags & gm_animated_avatar; } -std::string guild_member::build_json(bool with_id) const { +json guild_member::to_json_impl(bool with_id) const { json j; if (this->communication_disabled_until > 0) { if (this->communication_disabled_until > std::time(nullptr)) { @@ -238,7 +238,7 @@ std::string guild_member::build_json(bool with_id) const { j["communication_disabled_until"] = json::value_t::null; } } - + if (this->flags & gm_nickname_action) { if (!this->nickname.empty()) { j["nick"] = this->nickname; @@ -259,7 +259,7 @@ std::string guild_member::build_json(bool with_id) const { j["deaf"] = is_deaf(); } - return j.dump(); + return j; } guild& guild::set_name(const std::string& n) { @@ -303,7 +303,7 @@ bool guild_member::has_bypasses_verification() const { welcome_channel::welcome_channel(): channel_id(0), emoji_id(0) { } -welcome_channel &welcome_channel::fill_from_json(nlohmann::json *j) { +welcome_channel &welcome_channel::fill_from_json_impl(nlohmann::json *j) { channel_id = snowflake_not_null(j, "channel_id"); description = string_not_null(j, "channel_id"); emoji_id = snowflake_not_null(j, "emoji_id"); @@ -311,7 +311,7 @@ welcome_channel &welcome_channel::fill_from_json(nlohmann::json *j) { return *this; } -std::string welcome_channel::build_json(bool with_id) const { +json welcome_channel::to_json_impl(bool with_id) const { json j; j["channel_id"] = std::to_string(channel_id); j["description"] = description; @@ -321,7 +321,7 @@ std::string welcome_channel::build_json(bool with_id) const { if (!emoji_name.empty()) { j["emoji_name"] = emoji_name; } - return j.dump(); + return j; } welcome_channel &welcome_channel::set_channel_id(const snowflake _channel_id) { @@ -334,14 +334,14 @@ welcome_channel &welcome_channel::set_description(const std::string &_descriptio return *this; } -welcome_screen &welcome_screen::fill_from_json(nlohmann::json *j) { +welcome_screen &welcome_screen::fill_from_json_impl(nlohmann::json *j) { description = string_not_null(j, "description"); set_object_array_not_null(j, "welcome_channels", welcome_channels); return *this; } -std::string welcome_screen::build_json(bool with_id) const { +json welcome_screen::to_json_impl(bool with_id) const { json j; if (!description.empty()) { j["description"] = description; @@ -350,11 +350,11 @@ std::string welcome_screen::build_json(bool with_id) const { if (!welcome_channels.empty()) { j["welcome_channels"] = json::array(); for (const auto &welcome_channel : welcome_channels) { - j["welcome_channels"].push_back(json::parse(welcome_channel.build_json())); + j["welcome_channels"].push_back(welcome_channel.to_json()); } } - return j.dump(); + return j; } welcome_screen &welcome_screen::set_description(const std::string &s){ @@ -502,7 +502,7 @@ bool guild::has_ticketed_events() const { return this->flags & g_ticketed_events; } -std::string guild::build_json(bool with_id) const { +json guild::to_json_impl(bool with_id) const { json j; if (with_id) { j["id"] = std::to_string(id); @@ -549,7 +549,7 @@ std::string guild::build_json(bool with_id) const { if (!safety_alerts_channel_id.empty()) { j["safety_alerts_channel_id"] = safety_alerts_channel_id; } - return j.dump(); + return j; } void guild::rehash_members() { @@ -561,7 +561,7 @@ void guild::rehash_members() { members = n; } -guild& guild::fill_from_json(nlohmann::json* d) { +guild& guild::fill_from_json_impl(nlohmann::json* d) { return fill_from_json(nullptr, d); } @@ -687,7 +687,6 @@ guild& guild::fill_from_json(discord_client* shard, nlohmann::json* d) { } set_snowflake_not_null(d, "safety_alerts_channel_id", this->safety_alerts_channel_id); - } else { this->flags |= dpp::g_unavailable; } @@ -698,13 +697,13 @@ guild_widget::guild_widget() : channel_id(0), enabled(false) { } -guild_widget& guild_widget::fill_from_json(nlohmann::json* j) { +guild_widget& guild_widget::fill_from_json_impl(nlohmann::json* j) { enabled = bool_not_null(j, "enabled"); channel_id = snowflake_not_null(j, "channel_id"); return *this; } -std::string guild_widget::build_json(bool with_id) const { +json guild_widget::to_json_impl(bool with_id) const { return json({{"channel_id", channel_id}, {"enabled", enabled}}).dump(); } @@ -954,7 +953,7 @@ onboarding_prompt::onboarding_prompt(): managed(0), type(opt_multiple_choice), f onboarding::onboarding(): guild_id(0), mode(gom_default), enabled(false) { } -onboarding_prompt_option &onboarding_prompt_option::fill_from_json(nlohmann::json *j) { +onboarding_prompt_option &onboarding_prompt_option::fill_from_json_impl(nlohmann::json *j) { this->id = snowflake_not_null(j, "id"); if (j->contains("emoji")) { this->emoji = dpp::emoji().fill_from_json(&j->at("emoji")); @@ -967,9 +966,9 @@ onboarding_prompt_option &onboarding_prompt_option::fill_from_json(nlohmann::jso return *this; } -std::string onboarding_prompt_option::build_json(bool with_id) const { +json onboarding_prompt_option::to_json_impl(bool with_id) const { json j; - j["emoji"] = json::parse(emoji.build_json()); + j["emoji"] = emoji.to_json(); j["title"] = title; if (!description.empty()) { j["description"] = description; @@ -989,7 +988,7 @@ std::string onboarding_prompt_option::build_json(bool with_id) const { } } - return j.dump(); + return j; } onboarding_prompt_option &onboarding_prompt_option::set_emoji(const dpp::emoji &_emoji) { @@ -1007,7 +1006,7 @@ onboarding_prompt_option &onboarding_prompt_option::set_description(const std::s return *this; } -onboarding_prompt &onboarding_prompt::fill_from_json(nlohmann::json *j) { +onboarding_prompt &onboarding_prompt::fill_from_json_impl(nlohmann::json *j) { id = snowflake_not_null(j, "id"); type = static_cast(int8_not_null(j, "type")); title = string_not_null(j, "title"); @@ -1020,7 +1019,7 @@ onboarding_prompt &onboarding_prompt::fill_from_json(nlohmann::json *j) { return *this; } -std::string onboarding_prompt::build_json(bool with_id) const { +json onboarding_prompt::to_json_impl(bool with_id) const { json j; j["type"] = type; j["title"] = title; @@ -1028,14 +1027,14 @@ std::string onboarding_prompt::build_json(bool with_id) const { if (!options.empty()) { j["options"] = json::array(); for (auto const &option : options) { - j["options"].push_back(json::parse(option.build_json())); + j["options"].push_back(option.to_json()); } } j["single_select"] = is_single_select(); j["required"] = is_required(); j["in_onboarding"] = is_in_onboarding(); - return j.dump(); + return j; } bool onboarding_prompt::is_single_select() const { @@ -1060,7 +1059,7 @@ onboarding_prompt &onboarding_prompt::set_title(const std::string& _title) { return *this; } -onboarding& onboarding::fill_from_json(nlohmann::json* j) { +onboarding& onboarding::fill_from_json_impl(nlohmann::json* j) { guild_id = snowflake_not_null(j, "guild_id"); enabled = bool_not_null(j, "enabled"); mode = static_cast(int8_not_null(j, "mode")); @@ -1071,13 +1070,13 @@ onboarding& onboarding::fill_from_json(nlohmann::json* j) { return *this; } -std::string onboarding::build_json(bool with_id) const { +json onboarding::to_json_impl(bool with_id) const { json j; if (!prompts.empty()) { j["prompts"] = json::array(); for (auto const &prompt : prompts) { - j["prompts"].push_back(json::parse(prompt.build_json())); + j["prompts"].push_back(prompt.to_json()); } } @@ -1090,7 +1089,7 @@ std::string onboarding::build_json(bool with_id) const { j["enabled"] = enabled; j["mode"] = mode; - return j.dump(); + return j; } onboarding &onboarding::set_guild_id(const snowflake id) { diff --git a/src/dpp/integration.cpp b/src/dpp/integration.cpp index 15da5f3305..7f0570e8a7 100644 --- a/src/dpp/integration.cpp +++ b/src/dpp/integration.cpp @@ -45,7 +45,7 @@ integration::integration() : app.bot = nullptr; } -integration& integration::fill_from_json(nlohmann::json* j) +integration& integration::fill_from_json_impl(nlohmann::json* j) { std::map type_map = { { "", i_discord }, @@ -93,7 +93,7 @@ integration& integration::fill_from_json(nlohmann::json* j) return *this; } -std::string integration::build_json(bool with_id) const { +json integration::to_json_impl(bool with_id) const { return json({ { "expire_behavior", (flags & if_expire_kick) ? 1 : 0 }, { "expire_grace_period", expire_grace_period }, @@ -124,7 +124,7 @@ bool integration::expiry_kicks_user() const { connection::connection() : id({}), revoked(false), verified(false), friend_sync(false), show_activity(false), visible(false) { } -connection& connection::fill_from_json(nlohmann::json* j) { +connection& connection::fill_from_json_impl(nlohmann::json* j) { this->id = string_not_null(j, "id"); this->name = string_not_null(j, "name"); this->type = string_not_null(j, "type"); diff --git a/src/dpp/invite.cpp b/src/dpp/invite.cpp index a11f2e2417..c063ac4aed 100644 --- a/src/dpp/invite.cpp +++ b/src/dpp/invite.cpp @@ -33,7 +33,7 @@ invite::invite() : expires_at(0), guild_id(0), channel_id(0), inviter_id(0), tar { } -invite& invite::fill_from_json(nlohmann::json* j) { +invite& invite::fill_from_json_impl(nlohmann::json* j) { code = string_not_null(j, "code"); expires_at = (j->contains("expires_at")) ? ts_not_null(j, "expires_at") : 0; created_at = (j->contains("created_at")) ? ts_not_null(j, "created_at") : 0; @@ -68,7 +68,7 @@ invite& invite::fill_from_json(nlohmann::json* j) { return *this; } -std::string invite::build_json(bool with_id) const { +json invite::to_json_impl(bool with_id) const { json j; j["max_age"] = max_age; j["max_uses"] = max_uses; @@ -84,7 +84,7 @@ std::string invite::build_json(bool with_id) const { if (unique) { j["unique"] = unique; } - return j.dump(); + return j; } invite &invite::set_max_age(const uint32_t max_age_) { diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index b753c88696..fba25b7ae4 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -46,7 +46,7 @@ component::component() : } -component& component::fill_from_json(nlohmann::json* j) { +component& component::fill_from_json_impl(nlohmann::json* j) { type = static_cast(int8_not_null(j, "type")); label = string_not_null(j, "label"); custom_id = string_not_null(j, "custom_id"); @@ -397,7 +397,7 @@ select_option& select_option::set_animated(bool anim) { return *this; } -select_option& select_option::fill_from_json(nlohmann::json* j) { +select_option& select_option::fill_from_json_impl(nlohmann::json* j) { label = string_not_null(j, "label"); value = string_not_null(j, "value"); description = string_not_null(j, "description"); @@ -819,7 +819,7 @@ bool attachment::is_remix() const { return flags & a_is_remix; } -std::string message::build_json(bool with_id, bool is_interaction_response) const { +json message::to_json(bool with_id, bool is_interaction_response) const { /* This is the basics. once it works, expand on it. */ json j({ {"channel_id", channel_id}, @@ -946,7 +946,7 @@ std::string message::build_json(bool with_id, bool is_interaction_response) cons j["embeds"].push_back(e); } - return j.dump(); + return j; } bool message::is_crossposted() const { @@ -1136,7 +1136,7 @@ std::string message::get_url() const { sticker::sticker() : managed(0), pack_id(0), type(st_standard), format_type(sf_png), available(true), guild_id(0), sort_value(0) { } -sticker& sticker::fill_from_json(nlohmann::json* j) { +sticker& sticker::fill_from_json_impl(nlohmann::json* j) { this->id = snowflake_not_null(j, "id"); this->pack_id = snowflake_not_null(j, "pack_id"); this->name = string_not_null(j, "name"); @@ -1155,7 +1155,7 @@ sticker& sticker::fill_from_json(nlohmann::json* j) { return *this; } -std::string sticker::build_json(bool with_id) const { +json sticker::to_json_impl(bool with_id) const { json j; if (with_id) { @@ -1178,13 +1178,13 @@ std::string sticker::build_json(bool with_id) const { j["available"] = this->available; j["sort_value"] = this->sort_value; - return j.dump(); + 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(nlohmann::json* j) { +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"); this->cover_sticker_id = snowflake_not_null(j, "cover_sticker_id"); @@ -1200,7 +1200,7 @@ sticker_pack& sticker_pack::fill_from_json(nlohmann::json* j) { return *this; } -std::string sticker_pack::build_json(bool with_id) const { +json sticker_pack::to_json_impl(bool with_id) const { json j; if (with_id) { j["id"] = std::to_string(this->id); @@ -1220,7 +1220,7 @@ std::string sticker_pack::build_json(bool with_id) const { for (auto& s : stickers) { j["stickers"].push_back(json::parse(s.second.build_json(with_id))); } - return j.dump(); + return j; } std::string sticker::get_url() const { diff --git a/src/dpp/presence.cpp b/src/dpp/presence.cpp index a2229687ce..34809b1c4c 100644 --- a/src/dpp/presence.cpp +++ b/src/dpp/presence.cpp @@ -110,7 +110,7 @@ presence::presence(presence_status status, const activity &a) { presence::~presence() = default; -presence& presence::fill_from_json(nlohmann::json* j) { +presence& presence::fill_from_json_impl(nlohmann::json* j) { guild_id = snowflake_not_null(j, "guild_id"); user_id = snowflake_not_null(&((*j)["user"]), "id"); @@ -244,7 +244,7 @@ presence& presence::fill_from_json(nlohmann::json* j) { return *this; } -std::string presence::build_json(bool with_id) const { +json presence::to_json_impl(bool with_id) const { std::map status_name_mapping = { {ps_online, "online"}, {ps_offline, "offline"}, @@ -285,7 +285,11 @@ std::string presence::build_json(bool with_id) const { });*/ } - return j.dump(); + return j; +} + +json presence::to_json(bool with_id) const { + return to_json_impl(with_id); } presence_status presence::desktop_status() const { diff --git a/src/dpp/prune.cpp b/src/dpp/prune.cpp index d9e8771142..afd7f9ae52 100644 --- a/src/dpp/prune.cpp +++ b/src/dpp/prune.cpp @@ -28,14 +28,14 @@ namespace dpp { using json = nlohmann::json; -prune& prune::fill_from_json(nlohmann::json* j) { +prune& prune::fill_from_json_impl(nlohmann::json* j) { days = int32_not_null(j, "days"); compute_prune_count = bool_not_null(j, "compute_prune_count"); set_snowflake_array_not_null(j, "include_roles", include_roles); return *this; } -std::string prune::build_json(bool with_prune_count) const { +json prune::to_json_impl(bool with_prune_count) const { json j; for (auto & r : include_roles) { j["include_roles"].push_back(std::to_string(r)); @@ -44,7 +44,11 @@ std::string prune::build_json(bool with_prune_count) const { j["compute_prune_count"] = compute_prune_count; } j["days"] = days; - return j.dump(); + return j; +} + +json prune::to_json(bool with_id) const { + return to_json_impl(with_id); } } // namespace dpp diff --git a/src/dpp/role.cpp b/src/dpp/role.cpp index 24147055d4..501288675b 100644 --- a/src/dpp/role.cpp +++ b/src/dpp/role.cpp @@ -61,7 +61,7 @@ std::string role::get_mention(const snowflake& id){ return utility::role_mention(id); } -role& role::fill_from_json(nlohmann::json* j) +role& role::fill_from_json_impl(nlohmann::json* j) { return fill_from_json(0, j); } @@ -110,7 +110,7 @@ role& role::fill_from_json(snowflake _guild_id, nlohmann::json* j) return *this; } -std::string role::build_json(bool with_id) const { +json role::to_json_impl(bool with_id) const { json j; if (with_id) { @@ -133,7 +133,7 @@ std::string role::build_json(bool with_id) const { j["unicode_emoji"] = unicode_emoji; } - return j.dump(); + return j; } std::string role::get_mention() const { @@ -436,7 +436,7 @@ std::string role::get_icon_url(uint16_t size, const image_type format) const { application_role_connection_metadata::application_role_connection_metadata() : key(""), name(""), description("") { } -application_role_connection_metadata &application_role_connection_metadata::fill_from_json(nlohmann::json *j) { +application_role_connection_metadata &application_role_connection_metadata::fill_from_json_impl(nlohmann::json *j) { type = (application_role_connection_metadata_type)int8_not_null(j, "type"); key = string_not_null(j, "key"); name = string_not_null(j, "name"); @@ -454,7 +454,7 @@ application_role_connection_metadata &application_role_connection_metadata::fill return *this; } -std::string application_role_connection_metadata::build_json(bool with_id) const { +json application_role_connection_metadata::to_json_impl(bool with_id) const { json j; j["type"] = type; j["key"] = key; @@ -472,21 +472,21 @@ std::string application_role_connection_metadata::build_json(bool with_id) const j["description_localizations"][loc.first] = loc.second; } } - return j.dump(); + return j; } application_role_connection::application_role_connection() : platform_name(""), platform_username("") { } -application_role_connection &application_role_connection::fill_from_json(nlohmann::json *j) { +application_role_connection &application_role_connection::fill_from_json_impl(nlohmann::json *j) { platform_name = string_not_null(j, "platform_name"); platform_username = string_not_null(j, "platform_username"); metadata = application_role_connection_metadata().fill_from_json(&((*j)["metadata"])); return *this; } -std::string application_role_connection::build_json(bool with_id) const { +json application_role_connection::to_json_impl(bool with_id) const { json j; if (!platform_name.empty()) { j["platform_name"] = platform_name; @@ -497,7 +497,7 @@ std::string application_role_connection::build_json(bool with_id) const { if (std::holds_alternative(metadata)) { j["metadata"] = json::parse(std::get(metadata).build_json()); } - return j.dump(); + return j; } diff --git a/src/dpp/scheduled_event.cpp b/src/dpp/scheduled_event.cpp index 5954058eea..6793d3547c 100644 --- a/src/dpp/scheduled_event.cpp +++ b/src/dpp/scheduled_event.cpp @@ -31,8 +31,8 @@ using json = nlohmann::json; scheduled_event::scheduled_event() : managed(0), guild_id(0), - channel_id(0), - creator_id(0), + channel_id(0), + creator_id(0), scheduled_start_time(0), scheduled_end_time(0), privacy_level(ep_guild_only), @@ -109,7 +109,7 @@ scheduled_event& scheduled_event::set_end_time(time_t t) { return *this; } -scheduled_event& scheduled_event::fill_from_json(const json* j) { +scheduled_event& scheduled_event::fill_from_json_impl(const json* j) { set_snowflake_not_null(j, "id", this->id); set_snowflake_not_null(j, "guild_id", this->guild_id); set_snowflake_not_null(j, "channel_id", this->channel_id); @@ -135,7 +135,7 @@ scheduled_event& scheduled_event::fill_from_json(const json* j) { return *this; } -std::string scheduled_event::build_json(bool with_id) const { +json scheduled_event::to_json_impl(bool with_id) const { json j; if (this->id && with_id) { j["id"] = std::to_string(id); @@ -179,7 +179,7 @@ std::string scheduled_event::build_json(bool with_id) const { j["entity_metadata"]["location"] = json::value_t::null; } - return j.dump(); + return j; } } // namespace dpp diff --git a/src/dpp/slashcommand.cpp b/src/dpp/slashcommand.cpp index 9832eb28f4..77dde316fb 100644 --- a/src/dpp/slashcommand.cpp +++ b/src/dpp/slashcommand.cpp @@ -60,7 +60,7 @@ slashcommand& slashcommand::set_default_permissions(uint64_t defaults) { return *this; } -slashcommand& slashcommand::fill_from_json(nlohmann::json* j) { +slashcommand& slashcommand::fill_from_json_impl(nlohmann::json* j) { id = snowflake_not_null(j, "id"); name = string_not_null(j, "name"); description = string_not_null(j, "description"); @@ -257,14 +257,14 @@ void to_json(json& j, const slashcommand& p) { j["application_id"] = std::to_string(p.application_id); } -std::string slashcommand::build_json(bool with_id) const { +json slashcommand::to_json_impl(bool with_id) const { json j = *this; if (with_id) { j["id"] = std::to_string(id); } - return j.dump(); + return j; } slashcommand& slashcommand::set_type(slashcommand_contextmenu_type t) { @@ -308,7 +308,7 @@ command_option_choice::command_option_choice(const std::string &n, command_value { } -command_option_choice &command_option_choice::fill_from_json(nlohmann::json *j) { +command_option_choice &command_option_choice::fill_from_json_impl(nlohmann::json *j) { name = string_not_null(j, "name"); if ((*j)["value"].is_boolean()) { // is bool value.emplace((*j)["value"].get()); @@ -368,7 +368,7 @@ command_option& command_option::set_auto_complete(bool autocomp) return *this; } -command_option &command_option::fill_from_json(nlohmann::json *j) { +command_option &command_option::fill_from_json_impl(nlohmann::json *j) { /* * Command options contains command options. Therefor the object is filled with recursion. */ @@ -474,12 +474,12 @@ std::string interaction::get_command_name() const { } } -interaction& interaction::fill_from_json(nlohmann::json* j) { +interaction& interaction::fill_from_json_impl(nlohmann::json* j) { j->get_to(*this); return *this; } -std::string interaction::build_json(bool with_id) const { +json interaction::to_json_impl(bool with_id) const { /* There is no facility to build the json of an interaction as bots don't send them, only the API sends them as an event payload */ return ""; } @@ -737,7 +737,7 @@ interaction_response::interaction_response(interaction_response_type t) : intera type = t; } -interaction_response& interaction_response::fill_from_json(nlohmann::json* j) { +interaction_response& interaction_response::fill_from_json_impl(nlohmann::json* j) { type = (interaction_response_type)int8_not_null(j, "type"); if (j->contains("data")) { msg.fill_from_json(&((*j)["data"])); @@ -745,7 +745,7 @@ interaction_response& interaction_response::fill_from_json(nlohmann::json* j) { return *this; } -interaction_modal_response& interaction_modal_response::fill_from_json(nlohmann::json* j) { +interaction_modal_response& interaction_modal_response::fill_from_json_impl(nlohmann::json* j) { type = (interaction_response_type)int8_not_null(j, "type"); json& d = (*j)["data"]; custom_id = string_not_null(&d, "custom_id"); @@ -762,11 +762,11 @@ interaction_modal_response& interaction_modal_response::fill_from_json(nlohmann: return *this; } -std::string interaction_response::build_json(bool with_id) const { +json interaction_response::to_json_impl(bool with_id) const { json j; j["type"] = this->type; if (this->autocomplete_choices.empty()) { - json msg_json = json::parse(msg.build_json(false, true)); + json msg_json = msg.to_json(false, true); auto cid = msg_json.find("channel_id"); if (cid != msg_json.end()) { msg_json.erase(cid); @@ -780,7 +780,7 @@ std::string interaction_response::build_json(bool with_id) const { j["data"]["choices"].push_back(opt); } } - return j.dump(); + return j; } /* NOTE: Forward declaration for internal function actually defined in message.cpp */ @@ -799,7 +799,7 @@ interaction_modal_response::interaction_modal_response(const std::string& _custo components.push_back(_components); } -std::string interaction_modal_response::build_json(bool with_id) const { +json interaction_modal_response::to_json_impl(bool with_id) const { json j; j["type"] = this->type; j["data"] = json::object(); @@ -816,7 +816,7 @@ std::string interaction_modal_response::build_json(bool with_id) const { } j["data"]["components"].push_back(n); } - return j.dump(); + return j; } interaction_modal_response& interaction_modal_response::add_component(const component& c) { @@ -848,7 +848,7 @@ command_permission::command_permission(snowflake id, const command_permission_ty id(id), type(t), permission(permission) { } -command_permission& command_permission::fill_from_json(nlohmann::json* j) { +command_permission& command_permission::fill_from_json_impl(nlohmann::json* j) { id = snowflake_not_null(j, "id"); type = (command_permission_type)int8_not_null(j, "type"); permission = bool_not_null(j, "permission"); @@ -859,7 +859,7 @@ guild_command_permissions::guild_command_permissions() : id(0), application_id(0 { } -guild_command_permissions &guild_command_permissions::fill_from_json(nlohmann::json *j) { +guild_command_permissions &guild_command_permissions::fill_from_json_impl(nlohmann::json *j) { id = snowflake_not_null(j, "id"); application_id = snowflake_not_null(j, "application_id"); guild_id = snowflake_not_null(j, "guild_id"); diff --git a/src/dpp/stage_instance.cpp b/src/dpp/stage_instance.cpp index 544ae37f38..4fde6c9dd3 100644 --- a/src/dpp/stage_instance.cpp +++ b/src/dpp/stage_instance.cpp @@ -36,24 +36,23 @@ stage_instance::stage_instance() : { } -stage_instance& stage_instance::fill_from_json(const json* j) { +stage_instance& stage_instance::fill_from_json_impl(const json* j) { set_snowflake_not_null(j, "id", this->id); set_snowflake_not_null(j, "guild_id", this->guild_id); set_snowflake_not_null(j, "channel_id", this->channel_id); set_string_not_null(j, "topic", this->topic) ; this->privacy_level = static_cast(int8_not_null(j, "privacy_level")); set_bool_not_null(j, "discoverable_disabled", this->discoverable_disabled); - return *this; } -std::string stage_instance::build_json(bool with_id) const { +json stage_instance::to_json_impl(bool with_id) const { json j; j["topic"] = this->topic; j["privacy_level"] = this->privacy_level; j["channel_id"] = std::to_string(this->channel_id); - return j.dump(); + return j; } } // namespace dpp diff --git a/src/dpp/user.cpp b/src/dpp/user.cpp index d2dc7e0143..64f21ae898 100644 --- a/src/dpp/user.cpp +++ b/src/dpp/user.cpp @@ -58,7 +58,7 @@ std::string user::get_mention(const snowflake& id) { return utility::user_mention(id); } -std::string user::build_json(bool with_id) const { +json user::to_json_impl(bool with_id) const { json j; j["id"] = id; @@ -79,11 +79,11 @@ std::string user::build_json(bool with_id) const { } j["flags"] = out_flags; - return j.dump(); + return j; } -std::string user_identified::build_json(bool with_id) const { - return ""; +json user_identified::to_json_impl(bool with_id) const { + return {}; } user_identified::user_identified() : user(), accent_color(0), verified(false) { @@ -236,12 +236,12 @@ bool user::has_animated_icon() const { return this->flags & u_animated_icon; } -user& user::fill_from_json(json* j) { +user& user::fill_from_json_impl(json* j) { j->get_to(*this); return *this; } -user_identified& user_identified::fill_from_json(json* j) { +user_identified& user_identified::fill_from_json_impl(json* j) { j->get_to(*this); return *this; } diff --git a/src/dpp/voiceregion.cpp b/src/dpp/voiceregion.cpp index b377fa4f83..c2abf5b8d8 100644 --- a/src/dpp/voiceregion.cpp +++ b/src/dpp/voiceregion.cpp @@ -27,11 +27,11 @@ namespace dpp { using json = nlohmann::json; -voiceregion::voiceregion() : flags(0) +voiceregion::voiceregion() : flags(0) { } -voiceregion& voiceregion::fill_from_json(nlohmann::json* j) { +voiceregion& voiceregion::fill_from_json_impl(nlohmann::json* j) { id = string_not_null(j, "id"); name = string_not_null(j, "id"); if (bool_not_null(j, "optimal")) { @@ -49,15 +49,15 @@ voiceregion& voiceregion::fill_from_json(nlohmann::json* j) { return *this; } -std::string voiceregion::build_json(bool with_id) const { - return json({ +json voiceregion::to_json_impl(bool with_id) const { + return json{ { "id", id }, { "name", name }, { "optimal", is_optimal() }, { "deprecated", is_deprecated() }, { "custom", is_custom() }, { "vip", is_vip() } - }).dump(); + }; } bool voiceregion::is_optimal() const { diff --git a/src/dpp/voicestate.cpp b/src/dpp/voicestate.cpp index f58d1f2968..e69211dba8 100644 --- a/src/dpp/voicestate.cpp +++ b/src/dpp/voicestate.cpp @@ -31,7 +31,7 @@ voicestate::voicestate() : shard(nullptr), guild_id(0), channel_id(0), user_id(0 { } -voicestate& voicestate::fill_from_json(nlohmann::json* j) { +voicestate& voicestate::fill_from_json_impl(nlohmann::json* j) { guild_id = snowflake_not_null(j, "guild_id"); channel_id = snowflake_not_null(j, "channel_id"); user_id = snowflake_not_null(j, "user_id"); @@ -90,9 +90,4 @@ bool voicestate::is_suppressed() const { return flags & vs_suppress; } -std::string voicestate::build_json(bool with_id) const { - /* Voicestates are never sent from a bot */ - return json({}).dump(); -} - } // namespace dpp diff --git a/src/dpp/webhook.cpp b/src/dpp/webhook.cpp index f8cd64325c..9ef46d2df6 100644 --- a/src/dpp/webhook.cpp +++ b/src/dpp/webhook.cpp @@ -60,7 +60,7 @@ webhook::~webhook() { delete image_data; } -webhook& webhook::fill_from_json(nlohmann::json* j) { +webhook& webhook::fill_from_json_impl(nlohmann::json* j) { id = snowflake_not_null(j, "id"); type = int8_not_null(j, "type"); channel_id = snowflake_not_null(j, "channel_id"); @@ -77,7 +77,7 @@ webhook& webhook::fill_from_json(nlohmann::json* j) { return *this; } -std::string webhook::build_json(bool with_id) const { +json webhook::to_json_impl(bool with_id) const { json j; if (with_id) { j["id"] = std::to_string(id); @@ -99,7 +99,7 @@ std::string webhook::build_json(bool with_id) const { if (application_id) { j["application_id"] = application_id; } - return j.dump(); + return j; } webhook& webhook::load_image(const std::string &image_blob, const image_type type, bool is_base64_encoded) { diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp index c703ff3c69..086e0336f9 100644 --- a/src/unittest/test.cpp +++ b/src/unittest/test.cpp @@ -20,11 +20,50 @@ * ************************************************************************************/ #include "test.h" + #include #include #include #include +/** + * @brief Type trait to check if a certain type has a build_json method + * + * @tparam T type to check for + */ +template > +struct has_build_json : std::false_type {}; + +template +struct has_build_json().build_json())>> : std::true_type {}; + +/** + * @brief Type trait to check if a certain type has a build_json method + * + * @tparam T type to check for + */ +template +constexpr bool has_build_json_v = has_build_json::value; + +/** + * @brief Type trait to check if a certain type has a fill_from_json method + * + * @tparam T type to check for + */ +template +struct has_fill_from_json : std::false_type {}; + +template +struct has_fill_from_json().fill_from_json(std::declval()))>> : std::true_type {}; + +/** + * @brief Type trait to check if a certain type has a fill_from_json method + * + * @tparam T type to check for + */ +template +constexpr bool has_fill_from_json_v = has_fill_from_json::value; + /* Unit tests go here */ int main(int argc, char *argv[]) { @@ -308,6 +347,45 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b set_test(SNOWFLAKE, success); } + { // test dpp::json_interface + start_test(JSON_INTERFACE); + struct fillable : dpp::json_interface { + fillable &fill_from_json_impl(dpp::json *) { + return *this; + } + }; + struct buildable : dpp::json_interface { + json to_json_impl(bool = false) const { + return {}; + } + }; + struct fillable_and_buildable : dpp::json_interface { + fillable_and_buildable &fill_from_json_impl(dpp::json *) { + return *this; + } + + json to_json_impl(bool = false) const { + return {}; + } + }; + bool success = true; + + DPP_CHECK(JSON_INTERFACE, has_build_json_v>, success); + DPP_CHECK(JSON_INTERFACE, !has_fill_from_json_v>, success); + DPP_CHECK(JSON_INTERFACE, has_build_json_v, success); + DPP_CHECK(JSON_INTERFACE, !has_fill_from_json_v, success); + + DPP_CHECK(JSON_INTERFACE, !has_build_json_v>, success); + DPP_CHECK(JSON_INTERFACE, has_fill_from_json_v>, success); + DPP_CHECK(JSON_INTERFACE, !has_build_json_v, success); + DPP_CHECK(JSON_INTERFACE, has_fill_from_json_v, success); + + DPP_CHECK(JSON_INTERFACE, has_build_json_v>, success); + DPP_CHECK(JSON_INTERFACE, has_fill_from_json_v>, success); + DPP_CHECK(JSON_INTERFACE, has_build_json_v, success); + DPP_CHECK(JSON_INTERFACE, has_fill_from_json_v, success); + set_test(JSON_INTERFACE, success); + } { // test interaction_create_t::get_parameter // create a fake interaction diff --git a/src/unittest/test.h b/src/unittest/test.h index ab7ea54445..7b2ee53e8b 100644 --- a/src/unittest/test.h +++ b/src/unittest/test.h @@ -81,6 +81,7 @@ struct test_t { /* Current list of unit tests */ DPP_TEST(SNOWFLAKE, "dpp::snowflake class", tf_offline); +DPP_TEST(JSON_INTERFACE, "dpp::json_interface class", tf_offline); DPP_TEST(CLUSTER, "Instantiate DPP cluster", tf_offline); DPP_TEST(BOTSTART, "cluster::start method", tf_online); DPP_TEST(CONNECTION, "Connection to client websocket", tf_online);