Skip to content

Commit

Permalink
feat: initial support for user-installable apps
Browse files Browse the repository at this point in the history
  • Loading branch information
TTtie committed Mar 19, 2024
1 parent bbf3a8b commit 6f87bb8
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 3 deletions.
11 changes: 9 additions & 2 deletions lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ class Client extends EventEmitter {
command.dm_permission = command.dmPermission;
command.description_localizations = command.descriptionLocalizations;
command.name_localizations = command.nameLocalizations;
command.integration_types = command.integrationTypes;
}
return this.requestHandler.request("PUT", Endpoints.COMMANDS(this.application.id), true, commands).then((applicationCommands) => applicationCommands.map((applicationCommand) => new ApplicationCommand(applicationCommand, this)));
}
Expand Down Expand Up @@ -563,7 +564,9 @@ class Client extends EventEmitter {
* @arg {Boolean} [command.nsfw] Whether this command is age-restricted or not
* @arg {Array<Object>} [command.options] An array of [command options](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure)
* @arg {BigInt | Number | String | Permission} [command.defaultMemberPermissions] The default member [permissions](https://discord.com/developers/docs/topics/permissions) represented as a bit set
* @arg {Boolean} [command.dmPermission=true] If this command can be used in direct messages
* @arg {Boolean} [command.dmPermission=true] [DEPRECATED] If this command can be used in direct messages
* @arg {Array<Number>} [command.integrationTypes] Specifies for which installation contexts the new command will be available
* @arg {Array<Number>} [command.contexts] Specifies in which interaction contexts can the command be run
* @returns {Promise<ApplicationCommand>}
*/
createCommand(command) {
Expand All @@ -577,6 +580,7 @@ class Client extends EventEmitter {
command.dm_permission = command.dmPermission;
command.description_localizations = command.descriptionLocalizations;
command.name_localizations = command.nameLocalizations;
command.integration_types = command.integrationTypes;
return this.requestHandler.request("POST", Endpoints.COMMANDS(this.application.id), true, command).then((applicationCommand) => new ApplicationCommand(applicationCommand, this));
}

Expand Down Expand Up @@ -1415,7 +1419,9 @@ class Client extends EventEmitter {
* @arg {Array<Object>} [command.options] An array of [command options](https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure)
* @arg {bigint | number | string | Permission} [command.defaultMemberPermissions] The default member [permissions](https://discord.com/developers/docs/topics/permissions) represented as a bit set
* @arg {String} [command.defaultMemberPermissions] The [permissions](https://discord.com/developers/docs/topics/permissions) required by default for this command to be usable
* @arg {Boolean} [command.dmPermission] If this command can be used in direct messages
* @arg {Boolean} [command.dmPermission] [DEPRECATED] If this command can be used in direct messages
* @arg {Array<Number>} [command.integrationTypes] Specifies for which installation contexts the new command will be available
* @arg {Array<Number>} [command.contexts] Specifies in which interaction contexts can the command be run
* @returns {Promise<ApplicationCommand>}
*/
editCommand(commandID, command) {
Expand All @@ -1429,6 +1435,7 @@ class Client extends EventEmitter {
command.dm_permission = command.dmPermission;
command.description_localizations = command.descriptionLocalizations;
command.name_localizations = command.nameLocalizations;
command.integration_types = command.integrationTypes;
return this.requestHandler.request("PATCH", Endpoints.COMMAND(this.application.id, commandID), true, command).then((applicationCommand) => new ApplicationCommand(applicationCommand, this));
}

Expand Down
11 changes: 11 additions & 0 deletions lib/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ module.exports.ApplicationCommandTypes = {
MESSAGE: 3
};

module.exports.ApplicationIntegrationTypes = {
GUILD_INSTALL: 0,
USER_INSTALL: 1
};

module.exports.ApplicationFlags = {
APPLICATION_AUTO_MODERATION_RULE_CREATE_BADGE: 1 << 6,
GATEWAY_PRESENCE: 1 << 12,
Expand Down Expand Up @@ -355,6 +360,12 @@ Intents.allPrivileged = Intents.guildMembers
Intents.all = Intents.allNonPrivileged | Intents.allPrivileged;
module.exports.Intents = Intents;

module.exports.InteractionContextTypes = {
GUILD: 0,
BOT_DM: 1,
PRIVATE_CHANNEL: 2
};

module.exports.InteractionResponseTypes = {
PONG: 1,
CHANNEL_MESSAGE_WITH_SOURCE: 4,
Expand Down
17 changes: 17 additions & 0 deletions lib/structures/ApplicationCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class ApplicationCommand extends Base {
if(data.dm_permission !== undefined) {
/**
* If this command can be used in direct messages (global commands only)
* @deprecated Use {@link ApplicationCommand#contexts} instead
* @type {Boolean?}
*/
this.dmPermission = data.dm_permission;
Expand All @@ -98,6 +99,22 @@ class ApplicationCommand extends Base {
*/
this.nsfw = data.nsfw;
}

if(data.integration_types !== undefined) {
/**
* A list of installation contexts where the command is available
* @type {Array<Number>}
*/
this.integrationTypes = data.integration_types;
}

if(data.contexts !== undefined) {
/**
* A list of interaction contexts where the command can be run
* @type {Array<Number>}
*/
this.contexts = data.contexts;
}
}

/**
Expand Down
18 changes: 17 additions & 1 deletion lib/structures/Interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,27 @@ class Interaction extends Base {

if(data.app_permissions !== undefined) {
/**
* The permissions the app or bot has within the channel the interaction was sent from
* The permissions the app has in the source context of the interaction.
* @type {Permission?}
*/
this.appPermissions = new Permission(data.app_permissions);
}

if(data.context !== undefined) {
/**
* The context from which this interaction was triggered
* @type {Number?}
*/
this.context = data.context;
}

if(data.authorizing_integration_owners !== undefined) {
/**
* A mapping of installation contexts that the app was authorized for to respective guild/user IDs
* @type {Object<number, string>}
*/
this.authorizingIntegrationOwners = data.authorizing_integration_owners;
}
}

update() {
Expand Down
19 changes: 19 additions & 0 deletions lib/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class Message extends Base {
if(data.interaction) {
/**
* An object containing info about the interaction the message is responding to, if applicable
* @deprecated Use {@link Message#interactionMetadata} instead
* @type {Message.InteractionData}
*/
this.interaction = data.interaction;
Expand All @@ -142,6 +143,24 @@ class Message extends Base {
this.interaction = null;
}

if(data.interaction_metadata) {
/**
* An object containing metadata about the interaction the message is responding to, if applicable
* Typings TBD
* @type {Object}
*/
this.interactionMetadata = {
id: data.interaction_metadata.id,
type: data.interaction_metadata.type,
userID: data.interaction_metadata.user_id,
authorizingIntegrationOwners: data.interaction_metadata.authorizing_integration_owners,
originalResponseMessageID: data.interaction_metadata.original_response_message_id,
interactedMessageID: data.interaction_metadata.interacted_message_id,
// TODO: Do I transform the object into camel case as well?
triggeringInteractionMetadata: data.interaction_metadata.triggering_interaction_metadata
};
}

if(this.channel.guild) {
if(data.member) {
data.member.id = this.author.id;
Expand Down

0 comments on commit 6f87bb8

Please sign in to comment.