From c457b8d0596561fd1122e1d96bd168b322de368e Mon Sep 17 00:00:00 2001 From: Atora Date: Wed, 15 May 2024 08:41:08 -0400 Subject: [PATCH] feat: user-installable apps (#921) Co-authored-by: Vlad Frangu --- .../v10/_interactions/applicationCommands.ts | 46 +++++++++++++++++ deno/payloads/v10/_interactions/base.ts | 50 ++++++++++++++++++- deno/payloads/v10/application.ts | 15 ++++++ deno/payloads/v10/channel.ts | 10 +++- .../v9/_interactions/applicationCommands.ts | 46 +++++++++++++++++ deno/payloads/v9/_interactions/base.ts | 50 ++++++++++++++++++- deno/payloads/v9/application.ts | 15 ++++++ deno/payloads/v9/channel.ts | 8 ++- deno/rest/v10/application.ts | 1 + deno/rest/v10/interactions.ts | 13 ++++- deno/rest/v9/application.ts | 1 + deno/rest/v9/interactions.ts | 13 ++++- deno/utils/internals.ts | 4 ++ .../v10/_interactions/applicationCommands.ts | 46 +++++++++++++++++ payloads/v10/_interactions/base.ts | 50 ++++++++++++++++++- payloads/v10/application.ts | 15 ++++++ payloads/v10/channel.ts | 10 +++- .../v9/_interactions/applicationCommands.ts | 46 +++++++++++++++++ payloads/v9/_interactions/base.ts | 50 ++++++++++++++++++- payloads/v9/application.ts | 15 ++++++ payloads/v9/channel.ts | 8 ++- rest/v10/application.ts | 1 + rest/v10/interactions.ts | 13 ++++- rest/v9/application.ts | 1 + rest/v9/interactions.ts | 13 ++++- utils/internals.ts | 4 ++ 26 files changed, 524 insertions(+), 20 deletions(-) diff --git a/deno/payloads/v10/_interactions/applicationCommands.ts b/deno/payloads/v10/_interactions/applicationCommands.ts index 4e087fe5..940a93d5 100644 --- a/deno/payloads/v10/_interactions/applicationCommands.ts +++ b/deno/payloads/v10/_interactions/applicationCommands.ts @@ -74,6 +74,8 @@ export interface APIApplicationCommand { default_member_permissions: Permissions | null; /** * Indicates whether the command is available in DMs with the app, only for globally-scoped commands. By default, commands are visible + * + * @deprecated Use `contexts` instead */ dm_permission?: boolean; /** @@ -88,6 +90,18 @@ export interface APIApplicationCommand { * Indicates whether the command is age-restricted, defaults to `false` */ nsfw?: boolean; + /** + * Installation context(s) where the command is available, only for globally-scoped commands. Defaults to `GUILD_INSTALL ([0])` + * + * @unstable + */ + integration_types?: ApplicationIntegrationType[]; + /** + * Interaction context(s) where the command can be used, only for globally-scoped commands. By default, all interaction context types included for new commands `[0,1,2]`. + * + * @unstable + */ + contexts?: InteractionContextType[] | null; /** * Autoincrementing version identifier updated during substantial record changes */ @@ -103,6 +117,38 @@ export enum ApplicationCommandType { Message, } +/** + * https://discord.com/developers/docs/resources/application#application-object-application-integration-types + */ +export enum ApplicationIntegrationType { + /** + * App is installable to servers + */ + GuildInstall = 0, + /** + * App is installable to users + */ + UserInstall = 1, +} + +/** + * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types + */ +export enum InteractionContextType { + /** + * Interaction can be used within servers + */ + Guild = 0, + /** + * Interaction can be used within DMs with the app's bot user + */ + BotDM = 1, + /** + * Interaction can be used within Group DMs and DMs other than the app's bot user + */ + PrivateChannel = 2, +} + /** * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-data */ diff --git a/deno/payloads/v10/_interactions/base.ts b/deno/payloads/v10/_interactions/base.ts index 55f37b71..03a8f683 100644 --- a/deno/payloads/v10/_interactions/base.ts +++ b/deno/payloads/v10/_interactions/base.ts @@ -1,5 +1,5 @@ import type { Permissions, Snowflake } from '../../../globals.ts'; -import type { APIRole, LocaleString } from '../../../v10.ts'; +import type { APIRole, ApplicationIntegrationType, InteractionContextType, LocaleString } from '../../../v10.ts'; import type { APIAttachment, APIChannel, @@ -14,6 +14,40 @@ import type { APIEntitlement } from '../monetization.ts'; import type { APIUser } from '../user.ts'; import type { InteractionType } from './responses.ts'; +/** + * https://discord.com/developers/docs/resources/channel#message-interaction-metadata-object + */ +export interface APIMessageInteractionMetadata { + /** + * ID of the interaction + */ + id: Snowflake; + /** + * Type of interaction + */ + type: InteractionType; + /** + * User who triggered the interaction + */ + user: APIUser; + /** + * IDs for installation context(s) related to an interaction. Details in Authorizing Integration Owners Object + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * ID of the original response message, present only on follow-up messages + */ + original_response_message_id?: Snowflake; + /** + * ID of the message that contained interactive component, present only on messages created from component interactions + */ + interacted_message_id?: Snowflake; + /** + * Metadata for the interaction that was used to open the modal, present only on modal submit interactions + */ + triggering_interaction_metadata?: APIMessageInteractionMetadata; +} + export type PartialAPIMessageInteractionGuildMember = Pick< APIGuildMember, | 'avatar' @@ -122,7 +156,7 @@ export interface APIBaseInteraction { /** * Bitwise set of permissions the app or bot has within the channel the interaction was sent from */ - app_permissions?: Permissions; + app_permissions: Permissions; /** * The selected language of the invoking user */ @@ -135,8 +169,20 @@ export interface APIBaseInteraction { * For monetized apps, any entitlements for the invoking user, representing access to premium SKUs */ entitlements: APIEntitlement[]; + /** + * Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * Context where the interaction was triggered from + */ + context?: InteractionContextType; } +export type APIAuthorizingIntegrationOwnersMap = { + [key in ApplicationIntegrationType]?: Snowflake; +}; + export type APIDMInteractionWrapper> = Omit< Original, 'guild_id' | 'member' diff --git a/deno/payloads/v10/application.ts b/deno/payloads/v10/application.ts index e90bb8a3..1407b5c0 100644 --- a/deno/payloads/v10/application.ts +++ b/deno/payloads/v10/application.ts @@ -5,6 +5,7 @@ import type { Permissions, Snowflake } from '../../globals.ts'; import type { LocalizationMap } from '../common.ts'; import type { APIPartialGuild } from './guild.ts'; +import type { ApplicationIntegrationType } from './interactions.ts'; import type { OAuth2Scopes } from './oauth2.ts'; import type { APITeam } from './teams.ts'; import type { APIUser } from './user.ts'; @@ -128,6 +129,12 @@ export interface APIApplication { * Settings for the application's default in-app authorization link, if enabled */ install_params?: APIApplicationInstallParams; + /** + * Default scopes and permissions for each supported installation context. Value for each key is an integration type configuration object + * + * @unstable + */ + integration_types_config?: APIApplicationIntegrationTypesConfigMap; /** * The application's default custom authorization link, if enabled */ @@ -139,6 +146,14 @@ export interface APIApplicationInstallParams { permissions: Permissions; } +export interface APIApplicationIntegrationTypeConfiguration { + oauth2_install_params?: APIApplicationInstallParams; +} + +export type APIApplicationIntegrationTypesConfigMap = { + [key in ApplicationIntegrationType]?: APIApplicationIntegrationTypeConfiguration; +}; + /** * https://discord.com/developers/docs/resources/application#application-object-application-flags */ diff --git a/deno/payloads/v10/channel.ts b/deno/payloads/v10/channel.ts index 83d10d2b..72793908 100644 --- a/deno/payloads/v10/channel.ts +++ b/deno/payloads/v10/channel.ts @@ -6,7 +6,7 @@ import type { Permissions, Snowflake } from '../../globals.ts'; import type { APIApplication } from './application.ts'; import type { APIPartialEmoji } from './emoji.ts'; import type { APIGuildMember } from './guild.ts'; -import type { APIInteractionDataResolved, APIMessageInteraction } from './interactions.ts'; +import type { APIInteractionDataResolved, APIMessageInteraction, APIMessageInteractionMetadata } from './interactions.ts'; import type { APIRole } from './permissions.ts'; import type { APIPoll } from './poll.ts'; import type { APISticker, APIStickerItem } from './sticker.ts'; @@ -667,8 +667,16 @@ export interface APIMessage { * See https://discord.com/developers/docs/resources/channel#message-object */ referenced_message?: APIMessage | null; + /** + * Sent if the message is sent as a result of an interaction + * + * @unstable + */ + interaction_metadata?: APIMessageInteractionMetadata; /** * Sent if the message is a response to an Interaction + * + * @deprecated In favor of `interaction_metadata` */ interaction?: APIMessageInteraction; /** diff --git a/deno/payloads/v9/_interactions/applicationCommands.ts b/deno/payloads/v9/_interactions/applicationCommands.ts index 52c7b5a5..0dc27844 100644 --- a/deno/payloads/v9/_interactions/applicationCommands.ts +++ b/deno/payloads/v9/_interactions/applicationCommands.ts @@ -74,6 +74,8 @@ export interface APIApplicationCommand { default_member_permissions: Permissions | null; /** * Indicates whether the command is available in DMs with the app, only for globally-scoped commands. By default, commands are visible + * + * @deprecated Use `contexts` instead */ dm_permission?: boolean; /** @@ -88,6 +90,18 @@ export interface APIApplicationCommand { * Indicates whether the command is age-restricted, defaults to `false` */ nsfw?: boolean; + /** + * Installation context(s) where the command is available, only for globally-scoped commands. Defaults to `GUILD_INSTALL ([0])` + * + * @unstable + */ + integration_types?: ApplicationIntegrationType[]; + /** + * Interaction context(s) where the command can be used, only for globally-scoped commands. By default, all interaction context types included for new commands `[0,1,2]`. + * + * @unstable + */ + contexts?: InteractionContextType[] | null; /** * Autoincrementing version identifier updated during substantial record changes */ @@ -103,6 +117,38 @@ export enum ApplicationCommandType { Message, } +/** + * https://discord.com/developers/docs/resources/application#application-object-application-integration-types + */ +export enum ApplicationIntegrationType { + /** + * App is installable to servers + */ + GuildInstall = 0, + /** + * App is installable to users + */ + UserInstall = 1, +} + +/** + * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types + */ +export enum InteractionContextType { + /** + * Interaction can be used within servers + */ + Guild = 0, + /** + * Interaction can be used within DMs with the app's bot user + */ + BotDM = 1, + /** + * Interaction can be used within Group DMs and DMs other than the app's bot user + */ + PrivateChannel = 2, +} + /** * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-data */ diff --git a/deno/payloads/v9/_interactions/base.ts b/deno/payloads/v9/_interactions/base.ts index 897e3ab7..f20670ea 100644 --- a/deno/payloads/v9/_interactions/base.ts +++ b/deno/payloads/v9/_interactions/base.ts @@ -1,5 +1,5 @@ import type { Permissions, Snowflake } from '../../../globals.ts'; -import type { APIRole, LocaleString } from '../../../v9.ts'; +import type { APIRole, ApplicationIntegrationType, InteractionContextType, LocaleString } from '../../../v9.ts'; import type { APIAttachment, APIChannel, @@ -14,6 +14,40 @@ import type { APIEntitlement } from '../monetization.ts'; import type { APIUser } from '../user.ts'; import type { InteractionType } from './responses.ts'; +/** + * https://discord.com/developers/docs/resources/channel#message-interaction-metadata-object + */ +export interface APIMessageInteractionMetadata { + /** + * ID of the interaction + */ + id: Snowflake; + /** + * Type of interaction + */ + type: InteractionType; + /** + * User who triggered the interaction + */ + user: APIUser; + /** + * IDs for installation context(s) related to an interaction. Details in Authorizing Integration Owners Object + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * ID of the original response message, present only on follow-up messages + */ + original_response_message_id?: Snowflake; + /** + * ID of the message that contained interactive component, present only on messages created from component interactions + */ + interacted_message_id?: Snowflake; + /** + * Metadata for the interaction that was used to open the modal, present only on modal submit interactions + */ + triggering_interaction_metadata?: APIMessageInteractionMetadata; +} + export type PartialAPIMessageInteractionGuildMember = Pick< APIGuildMember, | 'avatar' @@ -122,7 +156,7 @@ export interface APIBaseInteraction { /** * Bitwise set of permissions the app or bot has within the channel the interaction was sent from */ - app_permissions?: Permissions; + app_permissions: Permissions; /** * The selected language of the invoking user */ @@ -135,8 +169,20 @@ export interface APIBaseInteraction { * For monetized apps, any entitlements for the invoking user, representing access to premium SKUs */ entitlements: APIEntitlement[]; + /** + * Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * Context where the interaction was triggered from + */ + context?: InteractionContextType; } +export type APIAuthorizingIntegrationOwnersMap = { + [key in ApplicationIntegrationType]?: Snowflake; +}; + export type APIDMInteractionWrapper> = Omit< Original, 'guild_id' | 'member' diff --git a/deno/payloads/v9/application.ts b/deno/payloads/v9/application.ts index e90bb8a3..1407b5c0 100644 --- a/deno/payloads/v9/application.ts +++ b/deno/payloads/v9/application.ts @@ -5,6 +5,7 @@ import type { Permissions, Snowflake } from '../../globals.ts'; import type { LocalizationMap } from '../common.ts'; import type { APIPartialGuild } from './guild.ts'; +import type { ApplicationIntegrationType } from './interactions.ts'; import type { OAuth2Scopes } from './oauth2.ts'; import type { APITeam } from './teams.ts'; import type { APIUser } from './user.ts'; @@ -128,6 +129,12 @@ export interface APIApplication { * Settings for the application's default in-app authorization link, if enabled */ install_params?: APIApplicationInstallParams; + /** + * Default scopes and permissions for each supported installation context. Value for each key is an integration type configuration object + * + * @unstable + */ + integration_types_config?: APIApplicationIntegrationTypesConfigMap; /** * The application's default custom authorization link, if enabled */ @@ -139,6 +146,14 @@ export interface APIApplicationInstallParams { permissions: Permissions; } +export interface APIApplicationIntegrationTypeConfiguration { + oauth2_install_params?: APIApplicationInstallParams; +} + +export type APIApplicationIntegrationTypesConfigMap = { + [key in ApplicationIntegrationType]?: APIApplicationIntegrationTypeConfiguration; +}; + /** * https://discord.com/developers/docs/resources/application#application-object-application-flags */ diff --git a/deno/payloads/v9/channel.ts b/deno/payloads/v9/channel.ts index d0efc933..27b8d7cb 100644 --- a/deno/payloads/v9/channel.ts +++ b/deno/payloads/v9/channel.ts @@ -6,7 +6,7 @@ import type { Permissions, Snowflake } from '../../globals.ts'; import type { APIApplication } from './application.ts'; import type { APIPartialEmoji } from './emoji.ts'; import type { APIGuildMember } from './guild.ts'; -import type { APIInteractionDataResolved, APIMessageInteraction } from './interactions.ts'; +import type { APIInteractionDataResolved, APIMessageInteraction, APIMessageInteractionMetadata } from './interactions.ts'; import type { APIRole } from './permissions.ts'; import type { APIPoll } from './poll.ts'; import type { APISticker, APIStickerItem } from './sticker.ts'; @@ -659,6 +659,12 @@ export interface APIMessage { * See https://discord.com/developers/docs/resources/channel#message-object */ referenced_message?: APIMessage | null; + /** + * Sent if the message is sent as a result of an interaction + * + * @unstable + */ + interaction_metadata?: APIMessageInteractionMetadata; /** * Sent if the message is a response to an Interaction */ diff --git a/deno/rest/v10/application.ts b/deno/rest/v10/application.ts index a5bb289b..0fe239e2 100644 --- a/deno/rest/v10/application.ts +++ b/deno/rest/v10/application.ts @@ -32,6 +32,7 @@ export type RESTPatchCurrentApplicationJSONBody = StrictPartial< | 'description' | 'flags' | 'install_params' + | 'integration_types_config' | 'interactions_endpoint_url' | 'role_connections_verification_url' | 'tags' diff --git a/deno/rest/v10/interactions.ts b/deno/rest/v10/interactions.ts index a6abe174..6a9e1466 100644 --- a/deno/rest/v10/interactions.ts +++ b/deno/rest/v10/interactions.ts @@ -6,7 +6,11 @@ import type { APIInteractionResponseCallbackData, ApplicationCommandType, } from '../../payloads/v10/mod.ts'; -import type { AddUndefinedToPossiblyUndefinedPropertiesOfInterface, StrictPartial } from '../../utils/internals.ts'; +import type { + AddUndefinedToPossiblyUndefinedPropertiesOfInterface, + NonNullableFields, + StrictPartial, +} from '../../utils/internals.ts'; import type { RESTDeleteAPIWebhookWithTokenMessageResult, RESTGetAPIWebhookWithTokenMessageResult, @@ -43,16 +47,21 @@ type RESTPostAPIBaseApplicationCommandsJSONBody = AddUndefinedToPossiblyUndefine Omit< APIApplicationCommand, | 'application_id' + | 'contexts' | 'default_member_permissions' | 'description_localized' | 'description' | 'guild_id' | 'id' + | 'integration_types' | 'name_localized' | 'type' | 'version' > & - Partial> + Partial< + NonNullableFields> & + Pick + > >; /** diff --git a/deno/rest/v9/application.ts b/deno/rest/v9/application.ts index f73095e3..d2878b5e 100644 --- a/deno/rest/v9/application.ts +++ b/deno/rest/v9/application.ts @@ -32,6 +32,7 @@ export type RESTPatchCurrentApplicationJSONBody = StrictPartial< | 'description' | 'flags' | 'install_params' + | 'integration_types_config' | 'interactions_endpoint_url' | 'role_connections_verification_url' | 'tags' diff --git a/deno/rest/v9/interactions.ts b/deno/rest/v9/interactions.ts index b6f2a985..1cd43f77 100644 --- a/deno/rest/v9/interactions.ts +++ b/deno/rest/v9/interactions.ts @@ -6,7 +6,11 @@ import type { APIInteractionResponseCallbackData, ApplicationCommandType, } from '../../payloads/v9/mod.ts'; -import type { AddUndefinedToPossiblyUndefinedPropertiesOfInterface, StrictPartial } from '../../utils/internals.ts'; +import type { + AddUndefinedToPossiblyUndefinedPropertiesOfInterface, + NonNullableFields, + StrictPartial, +} from '../../utils/internals.ts'; import type { RESTDeleteAPIWebhookWithTokenMessageResult, RESTGetAPIWebhookWithTokenMessageResult, @@ -43,16 +47,21 @@ type RESTPostAPIBaseApplicationCommandsJSONBody = AddUndefinedToPossiblyUndefine Omit< APIApplicationCommand, | 'application_id' + | 'contexts' | 'default_member_permissions' | 'description_localized' | 'description' | 'guild_id' | 'id' + | 'integration_types' | 'name_localized' | 'type' | 'version' > & - Partial> + Partial< + NonNullableFields> & + Pick + > >; /** diff --git a/deno/utils/internals.ts b/deno/utils/internals.ts index 9e78f8b9..369b60a3 100644 --- a/deno/utils/internals.ts +++ b/deno/utils/internals.ts @@ -2,6 +2,10 @@ export type Nullable = { [P in keyof T]: T[P] | null; }; +export type NonNullableFields = { + [P in keyof T]: NonNullable; +}; + export type AddUndefinedToPossiblyUndefinedPropertiesOfInterface = { [K in keyof Base]: Base[K] extends Exclude ? AddUndefinedToPossiblyUndefinedPropertiesOfInterface diff --git a/payloads/v10/_interactions/applicationCommands.ts b/payloads/v10/_interactions/applicationCommands.ts index f72421da..c8e03b40 100644 --- a/payloads/v10/_interactions/applicationCommands.ts +++ b/payloads/v10/_interactions/applicationCommands.ts @@ -74,6 +74,8 @@ export interface APIApplicationCommand { default_member_permissions: Permissions | null; /** * Indicates whether the command is available in DMs with the app, only for globally-scoped commands. By default, commands are visible + * + * @deprecated Use `contexts` instead */ dm_permission?: boolean; /** @@ -88,6 +90,18 @@ export interface APIApplicationCommand { * Indicates whether the command is age-restricted, defaults to `false` */ nsfw?: boolean; + /** + * Installation context(s) where the command is available, only for globally-scoped commands. Defaults to `GUILD_INSTALL ([0])` + * + * @unstable + */ + integration_types?: ApplicationIntegrationType[]; + /** + * Interaction context(s) where the command can be used, only for globally-scoped commands. By default, all interaction context types included for new commands `[0,1,2]`. + * + * @unstable + */ + contexts?: InteractionContextType[] | null; /** * Autoincrementing version identifier updated during substantial record changes */ @@ -103,6 +117,38 @@ export enum ApplicationCommandType { Message, } +/** + * https://discord.com/developers/docs/resources/application#application-object-application-integration-types + */ +export enum ApplicationIntegrationType { + /** + * App is installable to servers + */ + GuildInstall = 0, + /** + * App is installable to users + */ + UserInstall = 1, +} + +/** + * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types + */ +export enum InteractionContextType { + /** + * Interaction can be used within servers + */ + Guild = 0, + /** + * Interaction can be used within DMs with the app's bot user + */ + BotDM = 1, + /** + * Interaction can be used within Group DMs and DMs other than the app's bot user + */ + PrivateChannel = 2, +} + /** * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-data */ diff --git a/payloads/v10/_interactions/base.ts b/payloads/v10/_interactions/base.ts index 2fbd2d84..922fc968 100644 --- a/payloads/v10/_interactions/base.ts +++ b/payloads/v10/_interactions/base.ts @@ -1,5 +1,5 @@ import type { Permissions, Snowflake } from '../../../globals'; -import type { APIRole, LocaleString } from '../../../v10'; +import type { APIRole, ApplicationIntegrationType, InteractionContextType, LocaleString } from '../../../v10'; import type { APIAttachment, APIChannel, @@ -14,6 +14,40 @@ import type { APIEntitlement } from '../monetization'; import type { APIUser } from '../user'; import type { InteractionType } from './responses'; +/** + * https://discord.com/developers/docs/resources/channel#message-interaction-metadata-object + */ +export interface APIMessageInteractionMetadata { + /** + * ID of the interaction + */ + id: Snowflake; + /** + * Type of interaction + */ + type: InteractionType; + /** + * User who triggered the interaction + */ + user: APIUser; + /** + * IDs for installation context(s) related to an interaction. Details in Authorizing Integration Owners Object + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * ID of the original response message, present only on follow-up messages + */ + original_response_message_id?: Snowflake; + /** + * ID of the message that contained interactive component, present only on messages created from component interactions + */ + interacted_message_id?: Snowflake; + /** + * Metadata for the interaction that was used to open the modal, present only on modal submit interactions + */ + triggering_interaction_metadata?: APIMessageInteractionMetadata; +} + export type PartialAPIMessageInteractionGuildMember = Pick< APIGuildMember, | 'avatar' @@ -122,7 +156,7 @@ export interface APIBaseInteraction { /** * Bitwise set of permissions the app or bot has within the channel the interaction was sent from */ - app_permissions?: Permissions; + app_permissions: Permissions; /** * The selected language of the invoking user */ @@ -135,8 +169,20 @@ export interface APIBaseInteraction { * For monetized apps, any entitlements for the invoking user, representing access to premium SKUs */ entitlements: APIEntitlement[]; + /** + * Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * Context where the interaction was triggered from + */ + context?: InteractionContextType; } +export type APIAuthorizingIntegrationOwnersMap = { + [key in ApplicationIntegrationType]?: Snowflake; +}; + export type APIDMInteractionWrapper> = Omit< Original, 'guild_id' | 'member' diff --git a/payloads/v10/application.ts b/payloads/v10/application.ts index c5e510c9..c1fad902 100644 --- a/payloads/v10/application.ts +++ b/payloads/v10/application.ts @@ -5,6 +5,7 @@ import type { Permissions, Snowflake } from '../../globals'; import type { LocalizationMap } from '../common'; import type { APIPartialGuild } from './guild'; +import type { ApplicationIntegrationType } from './interactions'; import type { OAuth2Scopes } from './oauth2'; import type { APITeam } from './teams'; import type { APIUser } from './user'; @@ -128,6 +129,12 @@ export interface APIApplication { * Settings for the application's default in-app authorization link, if enabled */ install_params?: APIApplicationInstallParams; + /** + * Default scopes and permissions for each supported installation context. Value for each key is an integration type configuration object + * + * @unstable + */ + integration_types_config?: APIApplicationIntegrationTypesConfigMap; /** * The application's default custom authorization link, if enabled */ @@ -139,6 +146,14 @@ export interface APIApplicationInstallParams { permissions: Permissions; } +export interface APIApplicationIntegrationTypeConfiguration { + oauth2_install_params?: APIApplicationInstallParams; +} + +export type APIApplicationIntegrationTypesConfigMap = { + [key in ApplicationIntegrationType]?: APIApplicationIntegrationTypeConfiguration; +}; + /** * https://discord.com/developers/docs/resources/application#application-object-application-flags */ diff --git a/payloads/v10/channel.ts b/payloads/v10/channel.ts index 9dddd7b3..5d2b41b8 100644 --- a/payloads/v10/channel.ts +++ b/payloads/v10/channel.ts @@ -6,7 +6,7 @@ import type { Permissions, Snowflake } from '../../globals'; import type { APIApplication } from './application'; import type { APIPartialEmoji } from './emoji'; import type { APIGuildMember } from './guild'; -import type { APIInteractionDataResolved, APIMessageInteraction } from './interactions'; +import type { APIInteractionDataResolved, APIMessageInteraction, APIMessageInteractionMetadata } from './interactions'; import type { APIRole } from './permissions'; import type { APIPoll } from './poll'; import type { APISticker, APIStickerItem } from './sticker'; @@ -667,8 +667,16 @@ export interface APIMessage { * See https://discord.com/developers/docs/resources/channel#message-object */ referenced_message?: APIMessage | null; + /** + * Sent if the message is sent as a result of an interaction + * + * @unstable + */ + interaction_metadata?: APIMessageInteractionMetadata; /** * Sent if the message is a response to an Interaction + * + * @deprecated In favor of `interaction_metadata` */ interaction?: APIMessageInteraction; /** diff --git a/payloads/v9/_interactions/applicationCommands.ts b/payloads/v9/_interactions/applicationCommands.ts index 2ade8d3c..eee4b4d2 100644 --- a/payloads/v9/_interactions/applicationCommands.ts +++ b/payloads/v9/_interactions/applicationCommands.ts @@ -74,6 +74,8 @@ export interface APIApplicationCommand { default_member_permissions: Permissions | null; /** * Indicates whether the command is available in DMs with the app, only for globally-scoped commands. By default, commands are visible + * + * @deprecated Use `contexts` instead */ dm_permission?: boolean; /** @@ -88,6 +90,18 @@ export interface APIApplicationCommand { * Indicates whether the command is age-restricted, defaults to `false` */ nsfw?: boolean; + /** + * Installation context(s) where the command is available, only for globally-scoped commands. Defaults to `GUILD_INSTALL ([0])` + * + * @unstable + */ + integration_types?: ApplicationIntegrationType[]; + /** + * Interaction context(s) where the command can be used, only for globally-scoped commands. By default, all interaction context types included for new commands `[0,1,2]`. + * + * @unstable + */ + contexts?: InteractionContextType[] | null; /** * Autoincrementing version identifier updated during substantial record changes */ @@ -103,6 +117,38 @@ export enum ApplicationCommandType { Message, } +/** + * https://discord.com/developers/docs/resources/application#application-object-application-integration-types + */ +export enum ApplicationIntegrationType { + /** + * App is installable to servers + */ + GuildInstall = 0, + /** + * App is installable to users + */ + UserInstall = 1, +} + +/** + * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-context-types + */ +export enum InteractionContextType { + /** + * Interaction can be used within servers + */ + Guild = 0, + /** + * Interaction can be used within DMs with the app's bot user + */ + BotDM = 1, + /** + * Interaction can be used within Group DMs and DMs other than the app's bot user + */ + PrivateChannel = 2, +} + /** * https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-interaction-data */ diff --git a/payloads/v9/_interactions/base.ts b/payloads/v9/_interactions/base.ts index 230033cb..0bd8dd89 100644 --- a/payloads/v9/_interactions/base.ts +++ b/payloads/v9/_interactions/base.ts @@ -1,5 +1,5 @@ import type { Permissions, Snowflake } from '../../../globals'; -import type { APIRole, LocaleString } from '../../../v9'; +import type { APIRole, ApplicationIntegrationType, InteractionContextType, LocaleString } from '../../../v9'; import type { APIAttachment, APIChannel, @@ -14,6 +14,40 @@ import type { APIEntitlement } from '../monetization'; import type { APIUser } from '../user'; import type { InteractionType } from './responses'; +/** + * https://discord.com/developers/docs/resources/channel#message-interaction-metadata-object + */ +export interface APIMessageInteractionMetadata { + /** + * ID of the interaction + */ + id: Snowflake; + /** + * Type of interaction + */ + type: InteractionType; + /** + * User who triggered the interaction + */ + user: APIUser; + /** + * IDs for installation context(s) related to an interaction. Details in Authorizing Integration Owners Object + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * ID of the original response message, present only on follow-up messages + */ + original_response_message_id?: Snowflake; + /** + * ID of the message that contained interactive component, present only on messages created from component interactions + */ + interacted_message_id?: Snowflake; + /** + * Metadata for the interaction that was used to open the modal, present only on modal submit interactions + */ + triggering_interaction_metadata?: APIMessageInteractionMetadata; +} + export type PartialAPIMessageInteractionGuildMember = Pick< APIGuildMember, | 'avatar' @@ -122,7 +156,7 @@ export interface APIBaseInteraction { /** * Bitwise set of permissions the app or bot has within the channel the interaction was sent from */ - app_permissions?: Permissions; + app_permissions: Permissions; /** * The selected language of the invoking user */ @@ -135,8 +169,20 @@ export interface APIBaseInteraction { * For monetized apps, any entitlements for the invoking user, representing access to premium SKUs */ entitlements: APIEntitlement[]; + /** + * Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. + */ + authorizing_integration_owners: APIAuthorizingIntegrationOwnersMap; + /** + * Context where the interaction was triggered from + */ + context?: InteractionContextType; } +export type APIAuthorizingIntegrationOwnersMap = { + [key in ApplicationIntegrationType]?: Snowflake; +}; + export type APIDMInteractionWrapper> = Omit< Original, 'guild_id' | 'member' diff --git a/payloads/v9/application.ts b/payloads/v9/application.ts index c5e510c9..c1fad902 100644 --- a/payloads/v9/application.ts +++ b/payloads/v9/application.ts @@ -5,6 +5,7 @@ import type { Permissions, Snowflake } from '../../globals'; import type { LocalizationMap } from '../common'; import type { APIPartialGuild } from './guild'; +import type { ApplicationIntegrationType } from './interactions'; import type { OAuth2Scopes } from './oauth2'; import type { APITeam } from './teams'; import type { APIUser } from './user'; @@ -128,6 +129,12 @@ export interface APIApplication { * Settings for the application's default in-app authorization link, if enabled */ install_params?: APIApplicationInstallParams; + /** + * Default scopes and permissions for each supported installation context. Value for each key is an integration type configuration object + * + * @unstable + */ + integration_types_config?: APIApplicationIntegrationTypesConfigMap; /** * The application's default custom authorization link, if enabled */ @@ -139,6 +146,14 @@ export interface APIApplicationInstallParams { permissions: Permissions; } +export interface APIApplicationIntegrationTypeConfiguration { + oauth2_install_params?: APIApplicationInstallParams; +} + +export type APIApplicationIntegrationTypesConfigMap = { + [key in ApplicationIntegrationType]?: APIApplicationIntegrationTypeConfiguration; +}; + /** * https://discord.com/developers/docs/resources/application#application-object-application-flags */ diff --git a/payloads/v9/channel.ts b/payloads/v9/channel.ts index edf589b2..c879991c 100644 --- a/payloads/v9/channel.ts +++ b/payloads/v9/channel.ts @@ -6,7 +6,7 @@ import type { Permissions, Snowflake } from '../../globals'; import type { APIApplication } from './application'; import type { APIPartialEmoji } from './emoji'; import type { APIGuildMember } from './guild'; -import type { APIInteractionDataResolved, APIMessageInteraction } from './interactions'; +import type { APIInteractionDataResolved, APIMessageInteraction, APIMessageInteractionMetadata } from './interactions'; import type { APIRole } from './permissions'; import type { APIPoll } from './poll'; import type { APISticker, APIStickerItem } from './sticker'; @@ -659,6 +659,12 @@ export interface APIMessage { * See https://discord.com/developers/docs/resources/channel#message-object */ referenced_message?: APIMessage | null; + /** + * Sent if the message is sent as a result of an interaction + * + * @unstable + */ + interaction_metadata?: APIMessageInteractionMetadata; /** * Sent if the message is a response to an Interaction */ diff --git a/rest/v10/application.ts b/rest/v10/application.ts index f9145254..e952f6f7 100644 --- a/rest/v10/application.ts +++ b/rest/v10/application.ts @@ -32,6 +32,7 @@ export type RESTPatchCurrentApplicationJSONBody = StrictPartial< | 'description' | 'flags' | 'install_params' + | 'integration_types_config' | 'interactions_endpoint_url' | 'role_connections_verification_url' | 'tags' diff --git a/rest/v10/interactions.ts b/rest/v10/interactions.ts index 35925892..db791c46 100644 --- a/rest/v10/interactions.ts +++ b/rest/v10/interactions.ts @@ -6,7 +6,11 @@ import type { APIInteractionResponseCallbackData, ApplicationCommandType, } from '../../payloads/v10/index'; -import type { AddUndefinedToPossiblyUndefinedPropertiesOfInterface, StrictPartial } from '../../utils/internals'; +import type { + AddUndefinedToPossiblyUndefinedPropertiesOfInterface, + NonNullableFields, + StrictPartial, +} from '../../utils/internals'; import type { RESTDeleteAPIWebhookWithTokenMessageResult, RESTGetAPIWebhookWithTokenMessageResult, @@ -43,16 +47,21 @@ type RESTPostAPIBaseApplicationCommandsJSONBody = AddUndefinedToPossiblyUndefine Omit< APIApplicationCommand, | 'application_id' + | 'contexts' | 'default_member_permissions' | 'description_localized' | 'description' | 'guild_id' | 'id' + | 'integration_types' | 'name_localized' | 'type' | 'version' > & - Partial> + Partial< + NonNullableFields> & + Pick + > >; /** diff --git a/rest/v9/application.ts b/rest/v9/application.ts index 25dcb5f1..293aca37 100644 --- a/rest/v9/application.ts +++ b/rest/v9/application.ts @@ -32,6 +32,7 @@ export type RESTPatchCurrentApplicationJSONBody = StrictPartial< | 'description' | 'flags' | 'install_params' + | 'integration_types_config' | 'interactions_endpoint_url' | 'role_connections_verification_url' | 'tags' diff --git a/rest/v9/interactions.ts b/rest/v9/interactions.ts index 687e3c43..527cfe87 100644 --- a/rest/v9/interactions.ts +++ b/rest/v9/interactions.ts @@ -6,7 +6,11 @@ import type { APIInteractionResponseCallbackData, ApplicationCommandType, } from '../../payloads/v9/index'; -import type { AddUndefinedToPossiblyUndefinedPropertiesOfInterface, StrictPartial } from '../../utils/internals'; +import type { + AddUndefinedToPossiblyUndefinedPropertiesOfInterface, + NonNullableFields, + StrictPartial, +} from '../../utils/internals'; import type { RESTDeleteAPIWebhookWithTokenMessageResult, RESTGetAPIWebhookWithTokenMessageResult, @@ -43,16 +47,21 @@ type RESTPostAPIBaseApplicationCommandsJSONBody = AddUndefinedToPossiblyUndefine Omit< APIApplicationCommand, | 'application_id' + | 'contexts' | 'default_member_permissions' | 'description_localized' | 'description' | 'guild_id' | 'id' + | 'integration_types' | 'name_localized' | 'type' | 'version' > & - Partial> + Partial< + NonNullableFields> & + Pick + > >; /** diff --git a/utils/internals.ts b/utils/internals.ts index 9e78f8b9..369b60a3 100644 --- a/utils/internals.ts +++ b/utils/internals.ts @@ -2,6 +2,10 @@ export type Nullable = { [P in keyof T]: T[P] | null; }; +export type NonNullableFields = { + [P in keyof T]: NonNullable; +}; + export type AddUndefinedToPossiblyUndefinedPropertiesOfInterface = { [K in keyof Base]: Base[K] extends Exclude ? AddUndefinedToPossiblyUndefinedPropertiesOfInterface