Skip to content

Commit 37e50a0

Browse files
feat: add support for user apps (#1304)
2 parents de593a4 + c7928b0 commit 37e50a0

9 files changed

+294
-4
lines changed

include/dpp/appcommand.h

+74
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*
2020
************************************************************************************/
2121
#pragma once
22+
#include <dpp/integration.h>
2223
#include <dpp/export.h>
2324
#include <dpp/snowflake.h>
2425
#include <dpp/managed.h>
@@ -773,6 +774,26 @@ enum interaction_type {
773774
it_modal_submit = 5,
774775
};
775776

777+
/*
778+
* @brief Context type where the interaction can be used or triggered from, e.g. guild, user etc
779+
*/
780+
enum interaction_context_type {
781+
/**
782+
* @brief Interaction can be used within servers
783+
*/
784+
itc_guild = 0,
785+
786+
/**
787+
* @brief Interaction can be used within DMs with the app's bot user
788+
*/
789+
itc_bot_dm = 1,
790+
791+
/**
792+
* @brief Interaction can be used within Group DMs and DMs other than the app's bot user
793+
*/
794+
itc_private_channel = 2,
795+
};
796+
776797
/**
777798
* @brief Right-click context menu types
778799
*/
@@ -952,6 +973,16 @@ class DPP_EXPORT interaction : public managed, public json_interface<interaction
952973
virtual json to_json_impl(bool with_id = false) const;
953974

954975
public:
976+
/**
977+
* @brief Context where the interaction was triggered from
978+
*/
979+
std::map<application_integration_types, snowflake> authorizing_integration_owners;
980+
981+
/**
982+
* @brief Context where the interaction was triggered from
983+
*/
984+
std::optional<interaction_context_type> context;
985+
955986
/**
956987
* @brief ID of the application this interaction is for.
957988
*/
@@ -1194,6 +1225,30 @@ class DPP_EXPORT interaction : public managed, public json_interface<interaction
11941225
* is not for a command.
11951226
*/
11961227
std::string get_command_name() const;
1228+
1229+
/**
1230+
* @brief Get the user who installed the application for a given type.
1231+
* @param type Type of installation for the command, e.g. dpp::ait_guild_install or
1232+
* dpp::ait_user_install.
1233+
* @return The snowflake of the user. In the event this type is not allowed for the
1234+
* given command, this will return a default-initialised snowflake with value 0.
1235+
*/
1236+
dpp::snowflake get_authorizing_integration_owner(application_integration_types type) const;
1237+
1238+
/**
1239+
* @brief Returns true if this interaction occurred as a user-app interaction, e.g.
1240+
* within a DM or group DM, added to the user not a guild.
1241+
* @return true if a user-app interaction
1242+
*/
1243+
bool is_user_app_interaction() const;
1244+
1245+
/**
1246+
* @brief Returns true if this interaction occurred as a guild-invited interaction, e.g.
1247+
* within a guild's channel, or a DM of a user in that guild.
1248+
* @return true if a guild interaction
1249+
*/
1250+
bool is_guild_interaction() const;
1251+
11971252
};
11981253

11991254
/**
@@ -1420,10 +1475,21 @@ class DPP_EXPORT slashcommand : public managed, public json_interface<slashcomma
14201475
*/
14211476
permission default_member_permissions;
14221477

1478+
/**
1479+
* @brief Installation contexts where the command is available, only for globally-scoped commands. Defaults to your app's configured contexts
1480+
*/
1481+
std::vector<application_integration_types> integration_types;
1482+
1483+
/**
1484+
* @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.
1485+
*/
1486+
std::vector<interaction_context_type> contexts;
1487+
14231488
/**
14241489
* @brief True if this command should be allowed in a DM
14251490
* D++ defaults this to false. Cannot be set to true in a guild
14261491
* command, only a global command.
1492+
* @deprecated Use dpp::slashcommand_t::set_interaction_contexts instead
14271493
*/
14281494
bool dm_permission;
14291495

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

1612+
/**
1613+
* @brief Set the interaction contexts for the command
1614+
*
1615+
* @param contexts the contexts to set
1616+
* @return slashcommand& reference to self for chaining of calls
1617+
*/
1618+
slashcommand& set_interaction_contexts(std::vector<interaction_context_type> contexts);
1619+
15461620
/**
15471621
* @brief Adds a permission to the command
15481622
*

include/dpp/application.h

+15
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
************************************************************************************/
2222

2323
#pragma once
24+
#include <dpp/integration.h>
2425
#include <dpp/export.h>
2526
#include <dpp/snowflake.h>
2627
#include <dpp/managed.h>
@@ -30,6 +31,8 @@
3031
#include <dpp/permissions.h>
3132
#include <dpp/json_fwd.h>
3233
#include <dpp/json_interface.h>
34+
#include <map>
35+
#include <optional>
3336

3437
namespace dpp {
3538

@@ -209,6 +212,13 @@ class DPP_EXPORT app_team {
209212
snowflake owner_user_id;
210213
};
211214

215+
/**
216+
* @brief Configuration object for an app installation
217+
*/
218+
struct DPP_EXPORT integration_configuration {
219+
std::optional<application_install_params> oauth2_install_params;
220+
};
221+
212222
/**
213223
* @brief The application class represents details of a bot application
214224
*/
@@ -357,6 +367,11 @@ class DPP_EXPORT application : public managed, public json_interface<application
357367
*/
358368
application_install_params install_params;
359369

370+
/**
371+
* @brief Default scopes and permissions for each supported installation context
372+
*/
373+
std::map<application_integration_types, integration_configuration> integration_types_config;
374+
360375
/**
361376
* @brief The application's default custom authorization link, if enabled.
362377
*/

include/dpp/integration.h

+14
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@
3030

3131
namespace dpp {
3232

33+
/**
34+
* @brief Where an app can be installed, also called its supported installation contexts.
35+
*/
36+
enum application_integration_types {
37+
/**
38+
* @brief Installable to servers
39+
*/
40+
ait_guild_install = 0,
41+
/**
42+
* @brief Installable to users
43+
*/
44+
ait_user_install = 1,
45+
};
46+
3347
/**
3448
* @brief Integration types
3549
*/

include/dpp/message.h

+42
Original file line numberDiff line numberDiff line change
@@ -2010,6 +2010,43 @@ namespace cache_policy {
20102010

20112011
};
20122012

2013+
/**
2014+
* @brief Metadata about the interaction, including the source of the interaction and relevant server and user IDs.
2015+
*/
2016+
struct DPP_EXPORT interaction_metadata_type {
2017+
2018+
/**
2019+
* @brief ID of the interaction
2020+
*/
2021+
snowflake id;
2022+
2023+
/**
2024+
* @brief User who triggered the interaction
2025+
*/
2026+
uint8_t type;
2027+
2028+
/**
2029+
* @brief User who triggered the interaction
2030+
*/
2031+
user usr;
2032+
2033+
/**
2034+
* @brief ID of the original response message, present only on follow-up messages
2035+
*/
2036+
snowflake original_response_message_id;
2037+
2038+
/**
2039+
* @brief ID of the message that contained interactive component, present only on messages created from component interactions
2040+
*/
2041+
snowflake interacted_message_id;
2042+
2043+
// FIXME: Add this field sometime
2044+
/**
2045+
* @brief Metadata for the interaction that was used to open the modal, present only on modal submit interactions
2046+
*/
2047+
// interaction_metadata_type triggering_interaction_metadata;
2048+
};
2049+
20132050
/**
20142051
* @brief Message Reference type
20152052
*/
@@ -2214,6 +2251,11 @@ struct DPP_EXPORT message : public managed, json_interface<message> {
22142251
user usr;
22152252
} interaction;
22162253

2254+
/**
2255+
* @brief Sent if the message is sent as a result of an interaction
2256+
*/
2257+
interaction_metadata_type interaction_metadata;
2258+
22172259
/**
22182260
* @brief Allowed mentions details
22192261
*/

src/dpp/application.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ namespace dpp {
2727

2828
using json = nlohmann::json;
2929

30+
void from_json(const json &j, application_integration_types& out) {
31+
out = static_cast<dpp::application_integration_types>(j.get<int>());
32+
}
33+
34+
void from_json(const json &j, application_install_params& out) {
35+
out.permissions = j.at("permissions").get<uint64_t>();
36+
j.at("scopes").get_to(out.scopes);
37+
}
38+
39+
void from_json(const json &j, integration_configuration& out) {
40+
if (auto it = j.find("oauth2_install_params"); it != j.end()) {
41+
it->get_to(out.oauth2_install_params.value());
42+
}
43+
}
44+
3045
application::application() : managed(0), bot_public(false), bot_require_code_grant(false), guild_id(0), primary_sku_id(0), flags(0)
3146
{
3247
}
@@ -116,6 +131,10 @@ application& application::fill_from_json_impl(nlohmann::json* j) {
116131
}
117132
}
118133

134+
if (auto it = j->find("integration_types_config"); it != j->end()) {
135+
it->get_to(this->integration_types_config);
136+
}
137+
119138
set_string_not_null(j, "custom_install_url", custom_install_url);
120139

121140
// TODO: Investigate https://discord.com/developers/docs/resources/application#application-resource when v11 releases. See if the variables below are documented.

src/dpp/message.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,20 @@ std::optional<uint32_t> poll::get_vote_count(uint32_t answer_id) const noexcept
649649
return 0;
650650
}
651651

652-
652+
void from_json(const json& j, interaction_metadata_type& i) {
653+
i.id = snowflake_not_null(&j, "id");
654+
i.interacted_message_id = snowflake_not_null(&j, "interacted_message_id");
655+
i.original_response_message_id = snowflake_not_null(&j, "original_response_message_id");
656+
i.type = j["type"];
657+
i.usr = j["usr"];
658+
}
653659

654660
embed::~embed() = default;
655661

656662
embed::embed() : timestamp(0) {
657663
}
658664

659-
message::message() : managed(0), channel_id(0), guild_id(0), sent(0), edited(0), webhook_id(0),
665+
message::message() : managed(0), channel_id(0), guild_id(0), sent(0), edited(0), webhook_id(0), interaction_metadata{},
660666
owner(nullptr), type(mt_default), flags(0), pinned(false), tts(false), mention_everyone(false)
661667
{
662668
message_reference.channel_id = 0;
@@ -1330,6 +1336,11 @@ message& message::fill_from_json(json* d, cache_policy_t cp) {
13301336
this->author = *authoruser;
13311337
}
13321338
}
1339+
1340+
if (auto it = d->find("interaction_medata"); it != d->end()) {
1341+
it->get_to(this->interaction_metadata);
1342+
}
1343+
13331344
if (d->find("interaction") != d->end()) {
13341345
json& inter = (*d)["interaction"];
13351346
interaction.id = snowflake_not_null(&inter, "id");

0 commit comments

Comments
 (0)