mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
feat(bot,rest,types,utils): Support User-Installed apps, Interaction contexts and install types (#3502)
* Support integrationTypesConfig in Application * Add support for commands with integrationTypes and contexts And deprecate the dmPermission boolean, it is being replaced by contexts * Update contexts comment to make it more clear * User-Installed apps * Add integrationType oauth parameter fixes #3517 * Add null to contexts closes #3523 * Mark oauth2 install params as nullable closes #3525 * Fix typescript errors * Add preview notices --------- Co-authored-by: Matt Hatcher <3768988+MatthewSH@users.noreply.github.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import type {
|
||||
DiscordInviteStageInstance,
|
||||
DiscordMember,
|
||||
DiscordMessage,
|
||||
DiscordMessageInteractionMetadata,
|
||||
DiscordPoll,
|
||||
DiscordPollMedia,
|
||||
DiscordPresenceUpdate,
|
||||
@@ -85,7 +86,7 @@ import { transformIntegration, type Integration } from './transformers/integrati
|
||||
import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js'
|
||||
import { transformInvite, type Invite } from './transformers/invite.js'
|
||||
import { transformMember, type Member } from './transformers/member.js'
|
||||
import { transformMessage, type Message } from './transformers/message.js'
|
||||
import { transformMessage, type Message, type MessageInteractionMetadata, transformMessageInteractionMetadata } from './transformers/message.js'
|
||||
import { transformGuildOnboarding, type GuildOnboarding } from './transformers/onboarding.js'
|
||||
import { transformPoll, transformPollMedia, type Poll, type PollMedia } from './transformers/poll.js'
|
||||
import { transformPresence, type PresenceUpdate } from './transformers/presence.js'
|
||||
@@ -120,6 +121,7 @@ export interface Transformers {
|
||||
channel: (bot: Bot, payload: DiscordChannel, channel: Channel) => any
|
||||
interaction: (bot: Bot, payload: DiscordInteraction, interaction: Interaction) => any
|
||||
message: (bot: Bot, payload: DiscordMessage, message: Message) => any
|
||||
messageInteractionMetadata: (bot: Bot, payload: DiscordMessageInteractionMetadata, metadata: MessageInteractionMetadata) => any
|
||||
user: (bot: Bot, payload: DiscordUser, user: User) => any
|
||||
member: (bot: Bot, payload: DiscordMember, member: Member) => any
|
||||
role: (bot: Bot, payload: DiscordRole, role: Role) => any
|
||||
@@ -297,6 +299,8 @@ export interface Transformers {
|
||||
locale: boolean
|
||||
guildLocale: boolean
|
||||
appPermissions: boolean
|
||||
authorizingIntegrationOwners: boolean
|
||||
context: boolean
|
||||
}
|
||||
invite: {
|
||||
channelId: boolean
|
||||
@@ -345,6 +349,15 @@ export interface Transformers {
|
||||
embeds: boolean
|
||||
guildId: boolean
|
||||
id: boolean
|
||||
interactionMetadata: {
|
||||
id: boolean
|
||||
type: boolean
|
||||
userId: boolean
|
||||
authorizingIntegrationOwners: boolean
|
||||
originalResponseMessageId: boolean
|
||||
interactedMessageId: boolean
|
||||
triggeringInteractionMetadata: boolean
|
||||
}
|
||||
interaction: {
|
||||
id: boolean
|
||||
member: boolean
|
||||
@@ -560,6 +573,7 @@ export interface Transformers {
|
||||
user: (bot: Bot, payload: DiscordUser) => User
|
||||
member: (bot: Bot, payload: DiscordMember, guildId: BigString, userId: BigString) => Member
|
||||
message: (bot: Bot, payload: DiscordMessage) => Message
|
||||
messageInteractionMetadata: (bot: Bot, payload: DiscordMessageInteractionMetadata) => MessageInteractionMetadata
|
||||
role: (bot: Bot, payload: { role: DiscordRole } & { guildId: BigString }) => Role
|
||||
voiceState: (bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }) => VoiceState
|
||||
interaction: (bot: Bot, payload: DiscordInteraction) => Interaction
|
||||
@@ -631,6 +645,9 @@ export function createTransformers(options: Partial<Transformers>, opts?: Create
|
||||
message(bot, payload, message) {
|
||||
return message
|
||||
},
|
||||
messageInteractionMetadata(bot, payload, metadata) {
|
||||
return metadata
|
||||
},
|
||||
role(bot, payload, role) {
|
||||
return role
|
||||
},
|
||||
@@ -881,6 +898,8 @@ export function createTransformers(options: Partial<Transformers>, opts?: Create
|
||||
locale: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
guildLocale: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
appPermissions: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
authorizingIntegrationOwners: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
context: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
},
|
||||
invite: {
|
||||
channelId: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
@@ -929,6 +948,15 @@ export function createTransformers(options: Partial<Transformers>, opts?: Create
|
||||
embeds: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
guildId: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
id: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
interactionMetadata: {
|
||||
id: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
type: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
userId: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
authorizingIntegrationOwners: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
originalResponseMessageId: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
interactedMessageId: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
triggeringInteractionMetadata: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
},
|
||||
interaction: {
|
||||
id: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
member: opts?.defaultDesiredPropertiesValue ?? false,
|
||||
@@ -1152,6 +1180,7 @@ export function createTransformers(options: Partial<Transformers>, opts?: Create
|
||||
invite: options.invite ?? transformInvite,
|
||||
member: options.member ?? transformMember,
|
||||
message: options.message ?? transformMessage,
|
||||
messageInteractionMetadata: options.messageInteractionMetadata ?? transformMessageInteractionMetadata,
|
||||
presence: options.presence ?? transformPresence,
|
||||
role: options.role ?? transformRole,
|
||||
user: options.user ?? transformUser,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import {
|
||||
DiscordApplicationIntegrationType,
|
||||
iconHashToBigInt,
|
||||
type ApplicationFlags,
|
||||
type Bot,
|
||||
type DiscordApplication,
|
||||
type DiscordUser,
|
||||
type Guild,
|
||||
type OAuth2Scope,
|
||||
type Team,
|
||||
type User,
|
||||
} from '../index.js'
|
||||
@@ -38,6 +40,26 @@ export function transformApplication(bot: Bot, payload: { application: DiscordAp
|
||||
bot: payload.application.bot ? bot.transformers.user(bot, payload.application.bot as DiscordUser) : undefined,
|
||||
interactionsEndpointUrl: payload.application.interactions_endpoint_url,
|
||||
redirectUris: payload.application.redirect_uris,
|
||||
integrationTypesConfig: payload.application.integration_types_config
|
||||
? {
|
||||
[DiscordApplicationIntegrationType.GuildInstall]: payload.application.integration_types_config['0']?.oauth2_install_params
|
||||
? {
|
||||
oauth2InstallParams: {
|
||||
scopes: payload.application.integration_types_config['0'].oauth2_install_params.scopes,
|
||||
permissions: bot.transformers.snowflake(payload.application.integration_types_config['0'].oauth2_install_params.permissions),
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
[DiscordApplicationIntegrationType.UserInstall]: payload.application.integration_types_config['1']?.oauth2_install_params
|
||||
? {
|
||||
oauth2InstallParams: {
|
||||
scopes: payload.application.integration_types_config['1'].oauth2_install_params.scopes,
|
||||
permissions: bot.transformers.snowflake(payload.application.integration_types_config['1'].oauth2_install_params.permissions),
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
: undefined,
|
||||
} as Application
|
||||
|
||||
return bot.transformers.customizers.application(bot, payload.application, application)
|
||||
@@ -66,4 +88,15 @@ export interface Application {
|
||||
bot?: User
|
||||
redirectUris?: string[]
|
||||
interactionsEndpointUrl?: string
|
||||
integrationTypesConfig?: Partial<Record<DiscordApplicationIntegrationType, ApplicationIntegrationTypeConfiguration>>
|
||||
}
|
||||
|
||||
export interface ApplicationIntegrationTypeConfiguration {
|
||||
/** Install params for each installation context's default in-app authorization link */
|
||||
oauth2InstallParams?: {
|
||||
/** Scopes to add the application to the server with */
|
||||
scopes: OAuth2Scope[]
|
||||
/** Permissions to request for the bot role */
|
||||
permissions: bigint
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,14 @@ import {
|
||||
type MessageComponentTypes,
|
||||
} from '@discordeno/types'
|
||||
import { Collection } from '@discordeno/utils'
|
||||
import type { Bot, Channel, Component, DiscordChannel } from '../index.js'
|
||||
import {
|
||||
type Bot,
|
||||
type Channel,
|
||||
type Component,
|
||||
DiscordApplicationIntegrationType,
|
||||
type DiscordChannel,
|
||||
type DiscordInteractionContextType,
|
||||
} from '../index.js'
|
||||
import { MessageFlags, type DiscordInteractionDataResolved } from '../typings.js'
|
||||
import type { Attachment } from './attachment.js'
|
||||
import type { Member } from './member.js'
|
||||
@@ -71,6 +78,10 @@ export interface Interaction extends BaseInteraction {
|
||||
guildLocale?: string
|
||||
/** The computed permissions for a bot or app in the context of a specific interaction (including channel overwrites) */
|
||||
appPermissions: bigint
|
||||
/** Mapping of installation contexts that the interaction was authorized for to related user or guild IDs. */
|
||||
authorizingIntegrationOwners: Partial<Record<DiscordApplicationIntegrationType, bigint>>
|
||||
/** Context where the interaction was triggered from */
|
||||
context?: DiscordInteractionContextType
|
||||
}
|
||||
|
||||
export interface BaseInteraction {
|
||||
@@ -232,6 +243,19 @@ export function transformInteraction(bot: Bot, payload: DiscordInteraction): Int
|
||||
if (props.channel && payload.channel) interaction.channel = bot.transformers.channel(bot, { channel: payload.channel as DiscordChannel, guildId })
|
||||
if (props.channelId && payload.channel_id) interaction.channelId = bot.transformers.snowflake(payload.channel_id)
|
||||
if (props.member && guildId && payload.member) interaction.member = bot.transformers.member(bot, payload.member, guildId, user.id)
|
||||
if (props.authorizingIntegrationOwners && payload.authorizing_integration_owners) {
|
||||
interaction.authorizingIntegrationOwners = {}
|
||||
|
||||
if (payload.authorizing_integration_owners['0'])
|
||||
interaction.authorizingIntegrationOwners[DiscordApplicationIntegrationType.GuildInstall] = bot.transformers.snowflake(
|
||||
payload.authorizing_integration_owners['0'],
|
||||
)
|
||||
if (payload.authorizing_integration_owners['1'])
|
||||
interaction.authorizingIntegrationOwners[DiscordApplicationIntegrationType.UserInstall] = bot.transformers.snowflake(
|
||||
payload.authorizing_integration_owners['1'],
|
||||
)
|
||||
}
|
||||
if (props.context && payload.context) interaction.context = payload.context
|
||||
if (props.data && payload.data) {
|
||||
interaction.data = {
|
||||
type: payload.data.type,
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import type { DiscordMessage, InteractionTypes, MessageActivityTypes, MessageTypes, StickerFormatTypes } from '@discordeno/types'
|
||||
import {
|
||||
DiscordApplicationIntegrationType,
|
||||
type DiscordMessage,
|
||||
type DiscordMessageInteractionMetadata,
|
||||
type InteractionTypes,
|
||||
type MessageActivityTypes,
|
||||
type MessageTypes,
|
||||
type StickerFormatTypes,
|
||||
} from '@discordeno/types'
|
||||
import { CHANNEL_MENTION_REGEX } from '../constants.js'
|
||||
import { snowflakeToTimestamp, type Bot } from '../index.js'
|
||||
import { MessageFlags } from '../typings.js'
|
||||
@@ -189,7 +197,13 @@ export interface Message extends MessageBase {
|
||||
guildId?: bigint
|
||||
/** id of the message */
|
||||
id: bigint
|
||||
/** Sent if the message is a response to an Interaction */
|
||||
/** sent if the message is sent as a result of an interaction */
|
||||
interactionMetadata?: MessageInteractionMetadata
|
||||
/**
|
||||
* Sent if the message is a response to an Interaction
|
||||
*
|
||||
* @deprecated Deprecated in favor of {@link interactionMetadata}
|
||||
*/
|
||||
interaction?: {
|
||||
/** Id of the interaction */
|
||||
id: bigint
|
||||
@@ -281,6 +295,7 @@ export function transformMessage(bot: Bot, payload: DiscordMessage): Message {
|
||||
if (props.embeds && payload.embeds?.length) message.embeds = payload.embeds.map((embed) => bot.transformers.embed(bot, embed))
|
||||
if (props.guildId && guildId) message.guildId = guildId
|
||||
if (props.id && payload.id) message.id = bot.transformers.snowflake(payload.id)
|
||||
if (payload.interaction_metadata) message.interactionMetadata = transformMessageInteractionMetadata(bot, payload.interaction_metadata)
|
||||
if (payload.interaction) {
|
||||
const interaction = {} as NonNullable<Message['interaction']>
|
||||
let edited = false
|
||||
@@ -371,3 +386,48 @@ export function transformMessage(bot: Bot, payload: DiscordMessage): Message {
|
||||
|
||||
return bot.transformers.customizers.message(bot, payload, message)
|
||||
}
|
||||
|
||||
export function transformMessageInteractionMetadata(bot: Bot, payload: DiscordMessageInteractionMetadata): MessageInteractionMetadata {
|
||||
const props = bot.transformers.desiredProperties.message.interactionMetadata
|
||||
const metadata = {} as MessageInteractionMetadata
|
||||
|
||||
if (props.id) metadata.id = bot.transformers.snowflake(payload.id)
|
||||
if (props.authorizingIntegrationOwners) {
|
||||
metadata.authorizingIntegrationOwners = {}
|
||||
if (payload.authorizing_integration_owners['0'])
|
||||
metadata.authorizingIntegrationOwners[DiscordApplicationIntegrationType.GuildInstall] = bot.transformers.snowflake(
|
||||
payload.authorizing_integration_owners['0'],
|
||||
)
|
||||
if (payload.authorizing_integration_owners['1'])
|
||||
metadata.authorizingIntegrationOwners[DiscordApplicationIntegrationType.UserInstall] = bot.transformers.snowflake(
|
||||
payload.authorizing_integration_owners['1'],
|
||||
)
|
||||
}
|
||||
if (props.interactedMessageId && payload.interacted_message_id)
|
||||
metadata.interactedMessageId = bot.transformers.snowflake(payload.interacted_message_id)
|
||||
if (props.originalResponseMessageId && payload.original_response_message_id)
|
||||
metadata.originalResponseMessageId = bot.transformers.snowflake(payload.original_response_message_id)
|
||||
if (props.triggeringInteractionMetadata && payload.triggering_interaction_metadata)
|
||||
metadata.triggeringInteractionMetadata = transformMessageInteractionMetadata(bot, payload.triggering_interaction_metadata)
|
||||
if (props.type) metadata.type = payload.type
|
||||
if (props.userId) metadata.userId = bot.transformers.snowflake(payload.user_id)
|
||||
|
||||
return bot.transformers.customizers.messageInteractionMetadata(bot, payload, metadata)
|
||||
}
|
||||
|
||||
export interface MessageInteractionMetadata {
|
||||
/** Id of the interaction */
|
||||
id: bigint
|
||||
/** The type of interaction */
|
||||
type: InteractionTypes
|
||||
/** ID of the user who triggered the interaction */
|
||||
userId: bigint
|
||||
/** IDs for installation context(s) related to an interaction */
|
||||
authorizingIntegrationOwners: Partial<Record<DiscordApplicationIntegrationType, bigint>>
|
||||
/** ID of the original response message, present only on follow-up messages */
|
||||
originalResponseMessageId?: bigint
|
||||
/** ID of the message that contained interactive component, present only on messages created from component interactions */
|
||||
interactedMessageId?: bigint
|
||||
/** Metadata for the interaction that was used to open the modal, present only on modal submit interactions */
|
||||
triggeringInteractionMetadata?: MessageInteractionMetadata
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user