From 1fe72475286775cdfc68dad251ed662db7375ad1 Mon Sep 17 00:00:00 2001 From: Jiralite <33201955+Jiralite@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:25:26 +0200 Subject: [PATCH] feat: Support new application properties and patch endpoint (#9709) * feat: support new application endpoints * chore: edit comment * fix(ClientApplication): handle flags properly * types: `readonly` * chore: update route * feat: add to core * refactor(ClientApplication): add to user manager * chore: remove comments --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- packages/core/src/api/applications.ts | 21 +++++- .../src/structures/ClientApplication.js | 70 +++++++++++++++++++ .../src/util/ApplicationFlagsBitField.js | 15 ++++ packages/discord.js/typings/index.d.ts | 17 +++++ 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/packages/core/src/api/applications.ts b/packages/core/src/api/applications.ts index 4c288c74e4e1..97445935d231 100644 --- a/packages/core/src/api/applications.ts +++ b/packages/core/src/api/applications.ts @@ -1,7 +1,12 @@ /* eslint-disable jsdoc/check-param-names */ import type { RequestData, REST } from '@discordjs/rest'; -import { type RESTGetCurrentApplicationResult, Routes } from 'discord-api-types/v10'; +import { + type RESTGetCurrentApplicationResult, + type RESTPatchCurrentApplicationJSONBody, + type RESTPatchCurrentApplicationResult, + Routes, +} from 'discord-api-types/v10'; export class ApplicationsAPI { public constructor(private readonly rest: REST) {} @@ -15,4 +20,18 @@ export class ApplicationsAPI { public async getCurrent({ signal }: Pick = {}) { return this.rest.get(Routes.currentApplication(), { signal }) as Promise; } + + /** + * Edits properties of the application associated with the requesting bot user. + * + * @see {@link https://discord.com/developers/docs/resources/application#edit-current-application} + * @param body - The new application data + * @param options - The options for editing the application + */ + public async editCurrent(body: RESTPatchCurrentApplicationJSONBody, { signal }: Pick = {}) { + return this.rest.patch(Routes.currentApplication(), { + body, + signal, + }) as Promise; + } } diff --git a/packages/discord.js/src/structures/ClientApplication.js b/packages/discord.js/src/structures/ClientApplication.js index 69f51340bb5d..065b1fa1bbf9 100644 --- a/packages/discord.js/src/structures/ClientApplication.js +++ b/packages/discord.js/src/structures/ClientApplication.js @@ -6,6 +6,7 @@ const Team = require('./Team'); const Application = require('./interfaces/Application'); const ApplicationCommandManager = require('../managers/ApplicationCommandManager'); const ApplicationFlagsBitField = require('../util/ApplicationFlagsBitField'); +const DataResolver = require('../util/DataResolver'); const PermissionsBitField = require('../util/PermissionsBitField'); /** @@ -119,6 +120,16 @@ class ClientApplication extends Application { this.botRequireCodeGrant ??= null; } + if ('bot' in data) { + /** + * The bot associated with this application. + * @type {?User} + */ + this.bot = this.client.users._add(data.bot); + } else { + this.bot ??= null; + } + if ('bot_public' in data) { /** * If this application's bot is public @@ -129,6 +140,16 @@ class ClientApplication extends Application { this.botPublic ??= null; } + if ('interactions_endpoint_url' in data) { + /** + * This application's interaction endpoint URL. + * @type {?string} + */ + this.interactionsEndpointURL = data.interactions_endpoint_url; + } else { + this.interactionsEndpointURL ??= null; + } + if ('role_connections_verification_url' in data) { /** * This application's role connection verification entry point URL @@ -168,6 +189,55 @@ class ClientApplication extends Application { return !this.name; } + /** + * Options used for editing an application. + * @typedef {Object} ClientApplicationEditOptions + * @property {string} [customInstallURL] The application's custom installation URL + * @property {string} [description] The application's description + * @property {string} [roleConnectionsVerificationURL] The application's role connection verification URL + * @property {ClientApplicationInstallParams} [installParams] + * Settings for the application's default in-app authorization + * @property {ApplicationFlagsResolvable} [flags] The flags for the application + * @property {?(BufferResolvable|Base64Resolvable)} [icon] The application's icon + * @property {?(BufferResolvable|Base64Resolvable)} [coverImage] The application's cover image + * @property {string} [interactionsEndpointURL] The application's interaction endpoint URL + * @property {string[]} [tags] The application's tags + */ + + /** + * Edits this application. + * @param {ClientApplicationEditOptions} [options] The options for editing this application + * @returns {Promise} + */ + async edit({ + customInstallURL, + description, + roleConnectionsVerificationURL, + installParams, + flags, + icon, + coverImage, + interactionsEndpointURL, + tags, + } = {}) { + const data = await this.client.rest.patch(Routes.currentApplication(), { + body: { + custom_install_url: customInstallURL, + description, + role_connections_verification_url: roleConnectionsVerificationURL, + install_params: installParams, + flags: flags === undefined ? undefined : ApplicationFlagsBitField.resolve(flags), + icon: icon && (await DataResolver.resolveImage(icon)), + cover_image: coverImage && (await DataResolver.resolveImage(coverImage)), + interactions_endpoint_url: interactionsEndpointURL, + tags, + }, + }); + + this._patch(data); + return this; + } + /** * Obtains this application from Discord. * @returns {Promise} diff --git a/packages/discord.js/src/util/ApplicationFlagsBitField.js b/packages/discord.js/src/util/ApplicationFlagsBitField.js index 6a5a9fe9fec1..f9ad6abacfd7 100644 --- a/packages/discord.js/src/util/ApplicationFlagsBitField.js +++ b/packages/discord.js/src/util/ApplicationFlagsBitField.js @@ -23,4 +23,19 @@ class ApplicationFlagsBitField extends BitField { * @param {BitFieldResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name ApplicationFlagsBitField#bitfield + */ + +/** + * Data that can be resolved to give an application flag bit field. This can be: + * * A string (see {@link ApplicationFlagsBitField.Flags}) + * * An application flag + * * An instance of ApplicationFlagsBitField + * * An Array of ApplicationFlagsResolvable + * @typedef {string|number|ApplicationFlagsBitField|ApplicationFlagsResolvable[]} ApplicationFlagsResolvable + */ + module.exports = ApplicationFlagsBitField; diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 818d62afe0a8..0e23ba39e8e1 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -496,6 +496,8 @@ export class ApplicationFlagsBitField extends BitField { public static resolve(bit?: BitFieldResolvable): number; } +export type ApplicationFlagsResolvable = BitFieldResolvable; + export type AutoModerationRuleResolvable = AutoModerationRule | Snowflake; export abstract class Base { @@ -1019,6 +1021,7 @@ export class ClientApplication extends Application { private constructor(client: Client, data: RawClientApplicationData); public botPublic: boolean | null; public botRequireCodeGrant: boolean | null; + public bot: User | null; public commands: ApplicationCommandManager; public guildId: Snowflake | null; public get guild(): Guild | null; @@ -1030,8 +1033,10 @@ export class ClientApplication extends Application { public customInstallURL: string | null; public owner: User | Team | null; public get partial(): boolean; + public interactionsEndpointURL: string | null; public roleConnectionsVerificationURL: string | null; public rpcOrigins: string[]; + public edit(optins: ClientApplicationEditOptions): Promise; public fetch(): Promise; public fetchRoleConnectionMetadataRecords(): Promise; public editRoleConnectionMetadataRecords( @@ -6518,6 +6523,18 @@ export interface WelcomeScreenEditOptions { welcomeChannels?: WelcomeChannelData[]; } +export interface ClientApplicationEditOptions { + customInstallURL?: string; + description?: string; + roleConnectionsVerificationURL?: string; + installParams?: ClientApplicationInstallParams; + flags?: ApplicationFlagsResolvable; + icon?: BufferResolvable | Base64Resolvable | null; + coverImage?: BufferResolvable | Base64Resolvable | null; + interactionsEndpointURL?: string; + tags?: readonly string[]; +} + export interface ClientApplicationInstallParams { scopes: OAuth2Scopes[]; permissions: Readonly;