From 3f092b06b7fa3f6b30ee99047f71b91819b5643b Mon Sep 17 00:00:00 2001 From: Raghav Narang Date: Tue, 13 Aug 2024 03:24:24 +0530 Subject: [PATCH 1/5] feat: add interaction_context_type support --- include/dpp/appcommand.h | 37 +++++++++++++++++++++++++++++++++++++ src/dpp/slashcommand.cpp | 20 +++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/dpp/appcommand.h b/include/dpp/appcommand.h index e628bd97f8..f98c70f497 100644 --- a/include/dpp/appcommand.h +++ b/include/dpp/appcommand.h @@ -773,6 +773,26 @@ enum interaction_type { it_modal_submit = 5, }; +/* +* @brief Context type where the interaction can be used or triggered from, e.g. guild, user etc +*/ +enum interaction_context_type { + /** + * @brief Interaction can be used within servers + */ + itc_guild = 0, + + /** + * @brief Interaction can be used within DMs with the app's bot user + */ + itc_bot_dm = 1, + + /** + * @brief Interaction can be used within Group DMs and DMs other than the app's bot user + */ + itc_private_channel = 2, +}; + /** * @brief Right-click context menu types */ @@ -952,6 +972,10 @@ class DPP_EXPORT interaction : public managed, public json_interface context; /** * @brief ID of the application this interaction is for. */ @@ -1420,6 +1444,11 @@ class DPP_EXPORT slashcommand : public managed, public json_interface contexts; + /** * @brief True if this command should be allowed in a DM * D++ defaults this to false. Cannot be set to true in a guild @@ -1543,6 +1572,14 @@ class DPP_EXPORT slashcommand : public managed, public json_interface contexts); + /** * @brief Adds a permission to the command * diff --git a/src/dpp/slashcommand.cpp b/src/dpp/slashcommand.cpp index 77dd4bfebe..a86f722da5 100644 --- a/src/dpp/slashcommand.cpp +++ b/src/dpp/slashcommand.cpp @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include namespace dpp { @@ -74,6 +75,9 @@ slashcommand& slashcommand::fill_from_json_impl(nlohmann::json* j) { type = (slashcommand_contextmenu_type)int8_not_null(j, "type"); set_object_array_not_null(j, "options", options); // command_option fills recursive + if (auto it = j->find("contexts"); it != j->end()) { + it->get_to(this->contexts); + } return *this; } @@ -252,6 +256,11 @@ void to_json(json& j, const slashcommand& p) { } } + // TODO: Maybe a std::optional is better to differentiate + if (p.contexts.size()) { + j["contexts"] = p.contexts; + } + // DEPRECATED // j["default_permission"] = p.default_permission; j["application_id"] = std::to_string(p.application_id); @@ -294,6 +303,11 @@ slashcommand& slashcommand::set_application_id(snowflake i) { return *this; } +slashcommand& slashcommand::set_interaction_contexts(std::vector contexts) { + this->contexts = std::move(contexts); + return *this; +} + slashcommand& slashcommand::add_permission(const command_permission& p) { this->permissions.emplace_back(p); return *this; @@ -728,6 +742,10 @@ void from_json(const nlohmann::json& j, interaction& i) { } } + if (auto it = j.find("context"); it != j.end()) { + i.context = static_cast(*it); + } + if(j.contains("entitlements")) { for (auto& entitle : j["entitlements"]) { i.entitlements.emplace_back(entitlement().fill_from_json(const_cast(&entitle))); From 0cf24070aab67af23aa8bcf6cdf7ae3c5ae3b44c Mon Sep 17 00:00:00 2001 From: Raghav Narang Date: Tue, 13 Aug 2024 04:18:01 +0530 Subject: [PATCH 2/5] fix: deprecate old fields --- include/dpp/appcommand.h | 2 +- include/dpp/message.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/dpp/appcommand.h b/include/dpp/appcommand.h index f98c70f497..68ae42c283 100644 --- a/include/dpp/appcommand.h +++ b/include/dpp/appcommand.h @@ -1454,7 +1454,7 @@ class DPP_EXPORT slashcommand : public managed, public json_interface { /** * @brief Reference to an interaction */ - struct message_interaction_struct{ + [[deprecated("Use interaction_metadata instead.")]] struct message_interaction_struct{ /** * @brief ID of the interaction. */ From 3fc8ac00e102e7a00fe676cd586b5fc683968576 Mon Sep 17 00:00:00 2001 From: Raghav Narang Date: Tue, 13 Aug 2024 16:22:29 +0530 Subject: [PATCH 3/5] feat: add support for application_integration_types --- include/dpp/appcommand.h | 5 +++++ include/dpp/application.h | 15 +++++++++++++++ include/dpp/integration.h | 14 ++++++++++++++ src/dpp/application.cpp | 20 ++++++++++++++++++++ src/dpp/slashcommand.cpp | 9 +++++++++ 5 files changed, 63 insertions(+) diff --git a/include/dpp/appcommand.h b/include/dpp/appcommand.h index 68ae42c283..b5979241fc 100644 --- a/include/dpp/appcommand.h +++ b/include/dpp/appcommand.h @@ -1444,6 +1444,11 @@ class DPP_EXPORT slashcommand : public managed, public json_interface integration_types; + /** * @brief Interaction context(s) where the command can be used, only for globally-scoped commands. By default, all interaction context types included for new commands. */ diff --git a/include/dpp/application.h b/include/dpp/application.h index eb7e8b32df..a68c6c5c9b 100644 --- a/include/dpp/application.h +++ b/include/dpp/application.h @@ -21,6 +21,7 @@ ************************************************************************************/ #pragma once +#include #include #include #include @@ -30,6 +31,8 @@ #include #include #include +#include +#include namespace dpp { @@ -209,6 +212,13 @@ class DPP_EXPORT app_team { snowflake owner_user_id; }; +/** + * * @brief Configuration object for an app installation + * */ +struct integration_configuration { + std::optional oauth2_install_params; +}; + /** * @brief The application class represents details of a bot application */ @@ -352,6 +362,11 @@ class DPP_EXPORT application : public managed, public json_interface integration_types_config; + /** * @brief The application's default custom authorization link, if enabled. */ diff --git a/include/dpp/integration.h b/include/dpp/integration.h index 1e48c7be65..acde8addb3 100644 --- a/include/dpp/integration.h +++ b/include/dpp/integration.h @@ -30,6 +30,20 @@ namespace dpp { +/** + * @brief Where an app can be installed, also called its supported installation contexts. + */ +enum application_integration_types { + /** + * @brief Installable to servers + */ + ait_guild_install = 0, + /** + * @brief Installable to users + */ + ait_user_install = 1, +}; + /** * @brief Integration types */ diff --git a/src/dpp/application.cpp b/src/dpp/application.cpp index 78908a03fe..fc78a08842 100644 --- a/src/dpp/application.cpp +++ b/src/dpp/application.cpp @@ -21,6 +21,7 @@ ************************************************************************************/ #include #include +#include #include #include #include @@ -30,6 +31,21 @@ namespace dpp { using json = nlohmann::json; +void from_json(const json &j, application_integration_types& out) { + out = static_cast(j.get()); +} + +void from_json(const json &j, application_install_params& out) { + out.permissions = j.at("permissions").get(); + j.at("scopes").get_to(out.scopes); +} + +void from_json(const json &j, integration_configuration& out) { + if (auto it = j.find("oauth2_install_params"); it != j.end()) { + it->get_to(out.oauth2_install_params.value()); + } +} + application::application() : managed(0), bot_public(false), bot_require_code_grant(false), guild_id(0), primary_sku_id(0), flags(0) { } @@ -118,6 +134,10 @@ application& application::fill_from_json_impl(nlohmann::json* j) { } } + if (auto it = j->find("integration_types_config"); it != j->end()) { + it->get_to(this->integration_types_config); + } + set_string_not_null(j, "custom_install_url", custom_install_url); // TODO: Investigate https://discord.com/developers/docs/resources/application#application-resource when v11 releases. See if the variables below are documented. diff --git a/src/dpp/slashcommand.cpp b/src/dpp/slashcommand.cpp index a86f722da5..ee1d88f5c4 100644 --- a/src/dpp/slashcommand.cpp +++ b/src/dpp/slashcommand.cpp @@ -75,6 +75,11 @@ slashcommand& slashcommand::fill_from_json_impl(nlohmann::json* j) { type = (slashcommand_contextmenu_type)int8_not_null(j, "type"); set_object_array_not_null(j, "options", options); // command_option fills recursive + + if (auto it = j->find("integration_types"); it != j->end()) { + it->get_to(this->integration_types); + } + if (auto it = j->find("contexts"); it != j->end()) { it->get_to(this->contexts); } @@ -256,6 +261,10 @@ void to_json(json& j, const slashcommand& p) { } } + if (p.integration_types.size()) { + j["integration_types"] = p.integration_types; + } + // TODO: Maybe a std::optional is better to differentiate if (p.contexts.size()) { j["contexts"] = p.contexts; From af6361f57e33604bfafea7238cfcdcb1f0c72df8 Mon Sep 17 00:00:00 2001 From: Raghav Narang Date: Tue, 13 Aug 2024 16:29:24 +0530 Subject: [PATCH 4/5] feat: add authorizing_integration_owners --- include/dpp/appcommand.h | 7 +++++++ src/dpp/slashcommand.cpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/include/dpp/appcommand.h b/include/dpp/appcommand.h index b5979241fc..184978954e 100644 --- a/include/dpp/appcommand.h +++ b/include/dpp/appcommand.h @@ -19,6 +19,7 @@ * ************************************************************************************/ #pragma once +#include #include #include #include @@ -972,10 +973,16 @@ class DPP_EXPORT interaction : public managed, public json_interface authorizing_integration_owners; + /** * @brief Context where the interaction was triggered from */ std::optional context; + /** * @brief ID of the application this interaction is for. */ diff --git a/src/dpp/slashcommand.cpp b/src/dpp/slashcommand.cpp index ee1d88f5c4..86a97fbbc5 100644 --- a/src/dpp/slashcommand.cpp +++ b/src/dpp/slashcommand.cpp @@ -755,6 +755,10 @@ void from_json(const nlohmann::json& j, interaction& i) { i.context = static_cast(*it); } + if (auto it = j.find("authorizing_integration_owners"); it != j.end()) { + it->get_to(i.authorizing_integration_owners); + } + if(j.contains("entitlements")) { for (auto& entitle : j["entitlements"]) { i.entitlements.emplace_back(entitlement().fill_from_json(const_cast(&entitle))); From 00de234fb7f6336630b3c3f5996a3dbaa6fd7be3 Mon Sep 17 00:00:00 2001 From: Raghav Narang Date: Tue, 13 Aug 2024 16:54:48 +0530 Subject: [PATCH 5/5] feat: add interaction_metadata for messages --- include/dpp/message.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/dpp/message.cpp | 15 +++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/dpp/message.h b/include/dpp/message.h index 78d43eb67b..f63dc5e056 100644 --- a/include/dpp/message.h +++ b/include/dpp/message.h @@ -2010,6 +2010,43 @@ namespace cache_policy { }; +/** + * @brief Metadata about the interaction, including the source of the interaction and relevant server and user IDs. + */ +struct DPP_EXPORT interaction_metadata_type { + + /** + * @brief ID of the interaction + */ + snowflake id; + + /** + * @brief User who triggered the interaction + */ + uint8_t type; + + /** + * @brief User who triggered the interaction + */ + user usr; + + /** + * @brief ID of the original response message, present only on follow-up messages + */ + snowflake original_response_message_id; + + /** + * @brief ID of the message that contained interactive component, present only on messages created from component interactions + */ + snowflake interacted_message_id; + + // FIXME: Add this field sometime + /** + * @brief Metadata for the interaction that was used to open the modal, present only on modal submit interactions + */ + // interaction_metadata_type triggering_interaction_metadata; +}; + /** * @brief Represents messages sent and received on Discord */ @@ -2187,6 +2224,11 @@ struct DPP_EXPORT message : public managed, json_interface { user usr; } interaction; + /** + * @brief Sent if the message is sent as a result of an interaction + */ + interaction_metadata_type interaction_metadata; + /** * @brief Allowed mentions details */ diff --git a/src/dpp/message.cpp b/src/dpp/message.cpp index 6d416f0abb..c92ed7426d 100644 --- a/src/dpp/message.cpp +++ b/src/dpp/message.cpp @@ -649,14 +649,20 @@ std::optional poll::get_vote_count(uint32_t answer_id) const noexcept return 0; } - +void from_json(const json& j, interaction_metadata_type& i) { + i.id = snowflake_not_null(&j, "id"); + i.interacted_message_id = snowflake_not_null(&j, "interacted_message_id"); + i.original_response_message_id = snowflake_not_null(&j, "original_response_message_id"); + i.type = j["type"]; + i.usr = j["usr"]; +} embed::~embed() = default; embed::embed() : timestamp(0) { } -message::message() : managed(0), channel_id(0), guild_id(0), sent(0), edited(0), webhook_id(0), +message::message() : managed(0), channel_id(0), guild_id(0), sent(0), edited(0), webhook_id(0), interaction_metadata{}, owner(nullptr), type(mt_default), flags(0), pinned(false), tts(false), mention_everyone(false) { message_reference.channel_id = 0; @@ -1328,6 +1334,11 @@ message& message::fill_from_json(json* d, cache_policy_t cp) { this->author = *authoruser; } } + + if (auto it = d->find("interaction_medata"); it != d->end()) { + it->get_to(this->interaction_metadata); + } + if (d->find("interaction") != d->end()) { json& inter = (*d)["interaction"]; interaction.id = snowflake_not_null(&inter, "id");