Skip to content

Commit

Permalink
feat: add support for user apps (#1304)
Browse files Browse the repository at this point in the history
  • Loading branch information
braindigitalis authored Oct 21, 2024
2 parents de593a4 + c7928b0 commit 37e50a0
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 4 deletions.
2 changes: 1 addition & 1 deletion doxygen-awesome-css
74 changes: 74 additions & 0 deletions include/dpp/appcommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*
************************************************************************************/
#pragma once
#include <dpp/integration.h>
#include <dpp/export.h>
#include <dpp/snowflake.h>
#include <dpp/managed.h>
Expand Down Expand Up @@ -773,6 +774,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
*/
Expand Down Expand Up @@ -952,6 +973,16 @@ class DPP_EXPORT interaction : public managed, public json_interface<interaction
virtual json to_json_impl(bool with_id = false) const;

public:
/**
* @brief Context where the interaction was triggered from
*/
std::map<application_integration_types, snowflake> authorizing_integration_owners;

/**
* @brief Context where the interaction was triggered from
*/
std::optional<interaction_context_type> context;

/**
* @brief ID of the application this interaction is for.
*/
Expand Down Expand Up @@ -1194,6 +1225,30 @@ class DPP_EXPORT interaction : public managed, public json_interface<interaction
* is not for a command.
*/
std::string get_command_name() const;

/**
* @brief Get the user who installed the application for a given type.
* @param type Type of installation for the command, e.g. dpp::ait_guild_install or
* dpp::ait_user_install.
* @return The snowflake of the user. In the event this type is not allowed for the
* given command, this will return a default-initialised snowflake with value 0.
*/
dpp::snowflake get_authorizing_integration_owner(application_integration_types type) const;

/**
* @brief Returns true if this interaction occurred as a user-app interaction, e.g.
* within a DM or group DM, added to the user not a guild.
* @return true if a user-app interaction
*/
bool is_user_app_interaction() const;

/**
* @brief Returns true if this interaction occurred as a guild-invited interaction, e.g.
* within a guild's channel, or a DM of a user in that guild.
* @return true if a guild interaction
*/
bool is_guild_interaction() const;

};

/**
Expand Down Expand Up @@ -1420,10 +1475,21 @@ class DPP_EXPORT slashcommand : public managed, public json_interface<slashcomma
*/
permission default_member_permissions;

/**
* @brief Installation contexts where the command is available, only for globally-scoped commands. Defaults to your app's configured contexts
*/
std::vector<application_integration_types> 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.
*/
std::vector<interaction_context_type> 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
* command, only a global command.
* @deprecated Use dpp::slashcommand_t::set_interaction_contexts instead
*/
bool dm_permission;

Expand Down Expand Up @@ -1543,6 +1609,14 @@ class DPP_EXPORT slashcommand : public managed, public json_interface<slashcomma
*/
slashcommand& set_application_id(snowflake i);

/**
* @brief Set the interaction contexts for the command
*
* @param contexts the contexts to set
* @return slashcommand& reference to self for chaining of calls
*/
slashcommand& set_interaction_contexts(std::vector<interaction_context_type> contexts);

/**
* @brief Adds a permission to the command
*
Expand Down
15 changes: 15 additions & 0 deletions include/dpp/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
************************************************************************************/

#pragma once
#include <dpp/integration.h>
#include <dpp/export.h>
#include <dpp/snowflake.h>
#include <dpp/managed.h>
Expand All @@ -30,6 +31,8 @@
#include <dpp/permissions.h>
#include <dpp/json_fwd.h>
#include <dpp/json_interface.h>
#include <map>
#include <optional>

namespace dpp {

Expand Down Expand Up @@ -209,6 +212,13 @@ class DPP_EXPORT app_team {
snowflake owner_user_id;
};

/**
* @brief Configuration object for an app installation
*/
struct DPP_EXPORT integration_configuration {
std::optional<application_install_params> oauth2_install_params;
};

/**
* @brief The application class represents details of a bot application
*/
Expand Down Expand Up @@ -357,6 +367,11 @@ class DPP_EXPORT application : public managed, public json_interface<application
*/
application_install_params install_params;

/**
* @brief Default scopes and permissions for each supported installation context
*/
std::map<application_integration_types, integration_configuration> integration_types_config;

/**
* @brief The application's default custom authorization link, if enabled.
*/
Expand Down
14 changes: 14 additions & 0 deletions include/dpp/integration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
42 changes: 42 additions & 0 deletions include/dpp/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 Message Reference type
*/
Expand Down Expand Up @@ -2214,6 +2251,11 @@ struct DPP_EXPORT message : public managed, json_interface<message> {
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
*/
Expand Down
19 changes: 19 additions & 0 deletions src/dpp/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ namespace dpp {

using json = nlohmann::json;

void from_json(const json &j, application_integration_types& out) {
out = static_cast<dpp::application_integration_types>(j.get<int>());
}

void from_json(const json &j, application_install_params& out) {
out.permissions = j.at("permissions").get<uint64_t>();
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)
{
}
Expand Down Expand Up @@ -116,6 +131,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.
Expand Down
15 changes: 13 additions & 2 deletions src/dpp/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,14 +649,20 @@ std::optional<uint32_t> 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;
Expand Down Expand Up @@ -1330,6 +1336,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");
Expand Down
Loading

0 comments on commit 37e50a0

Please sign in to comment.