From 361352d7737aab8a44f4d82634f7e1acb2512ebc Mon Sep 17 00:00:00 2001 From: March 7th <71698422+aiko-chan-ai@users.noreply.github.com> Date: Thu, 26 Jan 2023 14:10:27 +0700 Subject: [PATCH] feat(ClientApplication): v13 add role connections #9072 djs --- package.json | 16 +++--- src/index.js | 2 + .../ApplicationRoleConnectionMetadata.js | 45 +++++++++++++++ src/structures/ClientApplication.js | 44 +++++++++++++++ src/structures/DeveloperPortalApplication.js | 55 ++++++++++++++++++- src/structures/interfaces/Application.js | 10 ++++ src/util/Constants.js | 30 ++++++++++ typings/enums.d.ts | 11 ++++ typings/index.d.ts | 31 +++++++++++ typings/rawDataTypes.d.ts | 11 ++++ 10 files changed, 246 insertions(+), 9 deletions(-) create mode 100644 src/structures/ApplicationRoleConnectionMetadata.js diff --git a/package.json b/package.json index 09f1480..7f7e5d6 100644 --- a/package.json +++ b/package.json @@ -56,19 +56,19 @@ "@discordjs/collection": "^1.3.0", "@discordjs/voice": "^0.14.0", "@sapphire/async-queue": "^1.5.0", - "@sapphire/shapeshift": "^3.8.0", + "@sapphire/shapeshift": "^3.8.1", "@types/node-fetch": "^2.6.2", - "@types/ws": "^8.5.3", + "@types/ws": "^8.5.4", "axios": "1.1", "chalk": "^4.1.2", - "discord-api-types": "^0.37.22", + "discord-api-types": "^0.37.29", "form-data": "^4.0.0", "json-bigint": "^1.0.0", "node-fetch": "^2.6.1", "safe-base64": "^2.0.1-0", "string_decoder": "^1.3.0", "string-similarity": "^4.0.4", - "ws": "^8.11.0" + "ws": "^8.12.0" }, "engines": { "node": ">=16.6.0", @@ -82,15 +82,15 @@ "@types/node": "^16.11.12", "conventional-changelog-cli": "^2.2.2", "dtslint": "^4.2.1", - "eslint": "^8.29.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.25.3", + "eslint": "^8.32.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^4.2.1", "husky": "^7.0.4", "is-ci": "^3.0.1", "jest": "^28.1.3", "lint-staged": "^12.1.4", - "prettier": "^2.8.1", + "prettier": "^2.8.3", "tsd": "^0.25.0", "tslint": "^6.1.3", "typescript": "^4.9.4" diff --git a/src/index.js b/src/index.js index c311926..446766f 100644 --- a/src/index.js +++ b/src/index.js @@ -76,6 +76,8 @@ exports.Activity = require('./structures/Presence').Activity; exports.AnonymousGuild = require('./structures/AnonymousGuild'); exports.Application = require('./structures/interfaces/Application'); exports.ApplicationCommand = require('./structures/ApplicationCommand'); +exports.ApplicationRoleConnectionMetadata = + require('./structures/ApplicationRoleConnectionMetadata').ApplicationRoleConnectionMetadata; exports.AutocompleteInteraction = require('./structures/AutocompleteInteraction'); exports.AutoModerationActionExecution = require('./structures/AutoModerationActionExecution'); exports.AutoModerationRule = require('./structures/AutoModerationRule'); diff --git a/src/structures/ApplicationRoleConnectionMetadata.js b/src/structures/ApplicationRoleConnectionMetadata.js new file mode 100644 index 00000000..037c190 --- /dev/null +++ b/src/structures/ApplicationRoleConnectionMetadata.js @@ -0,0 +1,45 @@ +'use strict'; + +const { ApplicationRoleConnectionMetadataTypes } = require('../util/Constants'); + +class ApplicationRoleConnectionMetadata { + constructor(data) { + /** + * The name of this metadata field + * @type {string} + */ + this.name = data.name; + + /** + * The name localizations for this metadata field + * @type {?Object} + */ + this.nameLocalizations = data.name_localizations ?? null; + + /** + * The description of this metadata field + * @type {string} + */ + this.description = data.description; + + /** + * The description localizations for this metadata field + * @type {?Object} + */ + this.descriptionLocalizations = data.description_localizations ?? null; + + /** + * The dictionary key for this metadata field + * @type {string} + */ + this.key = data.key; + + /** + * The type of this metadata field + * @type {ApplicationRoleConnectionMetadataType} + */ + this.type = typeof data.type === 'number' ? ApplicationRoleConnectionMetadataTypes[data.type] : data.type; + } +} + +exports.ApplicationRoleConnectionMetadata = ApplicationRoleConnectionMetadata; diff --git a/src/structures/ClientApplication.js b/src/structures/ClientApplication.js index 0d63011..0f03361 100644 --- a/src/structures/ClientApplication.js +++ b/src/structures/ClientApplication.js @@ -1,10 +1,12 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); +const { ApplicationRoleConnectionMetadata } = require('./ApplicationRoleConnectionMetadata'); const Team = require('./Team'); const Application = require('./interfaces/Application'); const ApplicationCommandManager = require('../managers/ApplicationCommandManager'); const ApplicationFlags = require('../util/ApplicationFlags'); +const { ApplicationRoleConnectionMetadataTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); /** @@ -155,6 +157,48 @@ class ClientApplication extends Application { this._patch(app.application); return this; } + + /** + * Gets this application's role connection metadata records + * @returns {Promise} + */ + async fetchRoleConnectionMetadataRecords() { + const metadata = await this.client.api.applications(this.id)('role-connections').metadata.get(); + return metadata.map(data => new ApplicationRoleConnectionMetadata(data)); + } + + /** + * Data for creating or editing an application role connection metadata. + * @typedef {Object} ApplicationRoleConnectionMetadataEditOptions + * @property {string} name The name of the metadata field + * @property {?Object} [nameLocalizations] The name localizations for the metadata field + * @property {string} description The description of the metadata field + * @property {?Object} [descriptionLocalizations] The description localizations for the metadata field + * @property {string} key The dictionary key of the metadata field + * @property {ApplicationRoleConnectionMetadataType} type The type of the metadata field + */ + + /** + * Updates this application's role connection metadata records + * @param {ApplicationRoleConnectionMetadataEditOptions[]} records The new role connection metadata records + * @returns {Promise} + */ + async editRoleConnectionMetadataRecords(records) { + const newRecords = await this.client.api + .applications(this.client.user.id)('role-connections') + .metadata.put({ + data: records.map(record => ({ + type: typeof record.type === 'string' ? ApplicationRoleConnectionMetadataTypes[record.type] : record.type, + key: record.key, + name: record.name, + name_localizations: record.nameLocalizations, + description: record.description, + description_localizations: record.descriptionLocalizations, + })), + }); + + return newRecords.map(data => new ApplicationRoleConnectionMetadata(data)); + } } module.exports = ClientApplication; diff --git a/src/structures/DeveloperPortalApplication.js b/src/structures/DeveloperPortalApplication.js index 593afa6..7834d7c 100644 --- a/src/structures/DeveloperPortalApplication.js +++ b/src/structures/DeveloperPortalApplication.js @@ -1,8 +1,9 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); +const { ApplicationRoleConnectionMetadata } = require('./ApplicationRoleConnectionMetadata'); const Base = require('./Base'); const ApplicationFlags = require('../util/ApplicationFlags'); -const { ClientApplicationAssetTypes, Endpoints } = require('../util/Constants'); +const { ClientApplicationAssetTypes, Endpoints, ApplicationRoleConnectionMetadataTypes } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); const Permissions = require('../util/Permissions'); const SnowflakeUtil = require('../util/SnowflakeUtil'); @@ -192,6 +193,16 @@ class DeveloperPortalApplication extends Base { * @type {?string} */ this.PrivacyPolicy = data.privacy_policy_url ?? null; + + if ('role_connections_verification_url' in data) { + /** + * This application's role connection verification entry point URL + * @type {?string} + */ + this.roleConnectionsVerificationURL = data.role_connections_verification_url; + } else { + this.roleConnectionsVerificationURL ??= null; + } } /** * The timestamp the application was created at @@ -447,6 +458,48 @@ class DeveloperPortalApplication extends Base { return undefined; } + /** + * Gets this application's role connection metadata records + * @returns {Promise} + */ + async fetchRoleConnectionMetadataRecords() { + const metadata = await this.client.api.applications(this.id)('role-connections').metadata.get(); + return metadata.map(data => new ApplicationRoleConnectionMetadata(data)); + } + + /** + * Data for creating or editing an application role connection metadata. + * @typedef {Object} ApplicationRoleConnectionMetadataEditOptions + * @property {string} name The name of the metadata field + * @property {?Object} [nameLocalizations] The name localizations for the metadata field + * @property {string} description The description of the metadata field + * @property {?Object} [descriptionLocalizations] The description localizations for the metadata field + * @property {string} key The dictionary key of the metadata field + * @property {ApplicationRoleConnectionMetadataType} type The type of the metadata field + */ + + /** + * Updates this application's role connection metadata records + * @param {ApplicationRoleConnectionMetadataEditOptions[]} records The new role connection metadata records + * @returns {Promise} + */ + async editRoleConnectionMetadataRecords(records) { + const newRecords = await this.client.api + .applications(this.client.user.id)('role-connections') + .metadata.put({ + data: records.map(record => ({ + type: typeof record.type === 'string' ? ApplicationRoleConnectionMetadataTypes[record.type] : record.type, + key: record.key, + name: record.name, + name_localizations: record.nameLocalizations, + description: record.description, + description_localizations: record.descriptionLocalizations, + })), + }); + + return newRecords.map(data => new ApplicationRoleConnectionMetadata(data)); + } + /** * When concatenated with a string, this automatically returns the application's name instead of the * Application object. diff --git a/src/structures/interfaces/Application.js b/src/structures/interfaces/Application.js index 155630f..05d5ab2 100644 --- a/src/structures/interfaces/Application.js +++ b/src/structures/interfaces/Application.js @@ -57,6 +57,16 @@ class Application extends Base { } else { this.icon ??= null; } + + if ('role_connections_verification_url' in data) { + /** + * This application's role connection verification entry point URL + * @type {?string} + */ + this.roleConnectionsVerificationURL = data.role_connections_verification_url; + } else { + this.roleConnectionsVerificationURL ??= null; + } } /** diff --git a/src/util/Constants.js b/src/util/Constants.js index 896c8a1..fb50bb6 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -1483,6 +1483,35 @@ exports.ApplicationCommandOptionTypes = createEnum([ */ exports.ApplicationCommandPermissionTypes = createEnum([null, 'ROLE', 'USER']); +/** + * Each metadata type offers a comparison operation that allows + * guilds to configure role requirements based on metadata values stored by the bot. + * Bots specify a metadata value for each user and guilds specify + * the required guild's configured value within the guild role settings. + * All available channel types: + * * INTEGER_LESS_THAN_OR_EQUAL + * * INTEGER_GREATER_THAN_OR_EQUAL + * * INTEGER_EQUAL + * * INTEGER_NOT_EQUAL + * * DATATIME_LESS_THAN_OR_EQUAL + * * DATATIME_GREATER_THAN_OR_EQUAL + * * BOOLEAN_EQUAL + * * BOOLEAN_NOT_EQUAL + * @typedef {string} ApplicationRoleConnectionMetadataType + * @see{@link https://discord.com/developers/docs/resources/application-role-connection-metadata#application-role-connection-metadata-object-application-role-connection-metadata-type} + */ +exports.ApplicationRoleConnectionMetadataTypes = createEnum( + null, + 'INTEGER_LESS_THAN_OR_EQUAL', + 'INTEGER_GREATER_THAN_OR_EQUAL', + 'INTEGER_EQUAL', + 'INTEGER_NOT_EQUAL', + 'DATATIME_LESS_THAN_OR_EQUAL', + 'DATATIME_GREATER_THAN_OR_EQUAL', + 'BOOLEAN_EQUAL', + 'BOOLEAN_NOT_EQUAL', +); + /** * The type of an {@link AutoModerationRuleTriggerTypes} object: * * KEYWORD @@ -1780,6 +1809,7 @@ function createEnum(keys) { * The type of an {@link ApplicationCommandPermissions} object. * @property {Object} ApplicationCommandTypes * The type of an {@link ApplicationCommand} object. + * @property {Object{ApplicationRoleConnectionMetadataType, number}} ApplicationRoleConnectionMetadataTypes * @property {Object} AutoModerationRuleTriggerTypes Characterizes the type * of content which can trigger the rule. * @property {Object} AutoModerationActionTypes diff --git a/typings/enums.d.ts b/typings/enums.d.ts index f4077cb..39b3300 100644 --- a/typings/enums.d.ts +++ b/typings/enums.d.ts @@ -333,3 +333,14 @@ export const enum WebhookTypes { 'Channel Follower' = 2, Application = 3, } + +export enum ApplicationRoleConnectionMetadataTypes { + INTEGER_LESS_THAN_OR_EQUAL = 1, + INTEGER_GREATER_THAN_OR_EQUAL, + INTEGER_EQUAL, + INTEGER_NOT_EQUAL, + DATATIME_LESS_THAN_OR_EQUAL, + DATATIME_GREATER_THAN_OR_EQUAL, + BOOLEAN_EQUAL, + BOOLEAN_NOT_EQUAL, +} diff --git a/typings/index.d.ts b/typings/index.d.ts index bf11ff4..760f1a6 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -106,8 +106,10 @@ import { SortOrderType, SelectMenuComponentTypes, ForumLayoutType, + ApplicationRoleConnectionMetadataTypes, } from './enums'; import { + APIApplicationRoleConnectionMetadata, APIAutoModerationRule, GatewayAutoModerationActionExecutionDispatchData, RawActivityData, @@ -411,6 +413,7 @@ export abstract class Application extends Base { public icon: string | null; public id: Snowflake; public name: string | null; + public roleConnectionsVerificationURL: string | null; public coverURL(options?: StaticImageURLOptions): string | null; /** @deprecated This method is deprecated as it is unsupported and will be removed in the next major version. */ public fetchAssets(): Promise; @@ -463,6 +466,7 @@ export class DeveloperPortalApplication extends Base { public testers: Collection; public TermsOfService: string | null; public PrivacyPolicy: string | null; + public roleConnectionsVerificationURL: string | null; public fetch(): Promise; public coverURL(options?: StaticImageURLOptions): string | null; /** @deprecated This method is deprecated as it is unsupported and will be removed in the next major version. */ @@ -480,6 +484,10 @@ export class DeveloperPortalApplication extends Base { public delete(MFACode?: number): Promise; public addAsset(image: BufferResolvable | Base64Resolvable, name: string): Promise; public deleteAsset(id: string): Promise; + public fetchRoleConnectionMetadataRecords(): Promise; + public editRoleConnectionMetadataRecords( + records: ApplicationRoleConnectionMetadataEditOptions[], + ): Promise; } export class DeveloperPortalManager extends BaseManager { @@ -560,6 +568,16 @@ export class ApplicationCommand extends Base { public static sendContextMenu(message: Message): Promise; } +export class ApplicationRoleConnectionMetadata { + private constructor(data: APIApplicationRoleConnectionMetadata); + public name: string; + public nameLocalizations: LocalizationMap | null; + public description: string; + public descriptionLocalizations: LocalizationMap | null; + public key: string; + public type: ApplicationRoleConnectionMetadataTypes; +} + export type ApplicationResolvable = Application | Activity | Snowflake; export type AutoModerationRuleResolvable = AutoModerationRule | Snowflake; @@ -968,6 +986,10 @@ export class ClientApplication extends Application { public readonly partial: boolean; public rpcOrigins: string[]; public fetch(): Promise; + public fetchRoleConnectionMetadataRecords(): Promise; + public editRoleConnectionMetadataRecords( + records: ApplicationRoleConnectionMetadataEditOptions[], + ): Promise; } export class ClientPresence extends Presence { @@ -5178,6 +5200,15 @@ export type ApplicationFlagsString = | 'EMBEDDED_FIRST_PARTY' | 'APPLICATION_COMMAND_BADGE'; +export interface ApplicationRoleConnectionMetadataEditOptions { + name: string; + nameLocalizations?: LocalizationMap | null; + description: string; + descriptionLocalizations?: LocalizationMap | null; + key: string; + type: ApplicationRoleConnectionMetadataTypes; +} + export interface AutoModerationAction { type: AutoModerationActionType | AutoModerationActionTypes; metadata: AutoModerationActionMetadata; diff --git a/typings/rawDataTypes.d.ts b/typings/rawDataTypes.d.ts index 615f9b0..8ccb3ae 100644 --- a/typings/rawDataTypes.d.ts +++ b/typings/rawDataTypes.d.ts @@ -80,6 +80,7 @@ import { APITextInputComponent, APIModalActionRowComponent, APIModalSubmitInteraction, + LocalizationMap, } from 'discord-api-types/v9'; import { GuildChannel, Guild, PermissionOverwrites, InteractionType } from '.'; @@ -90,6 +91,7 @@ import type { AutoModerationRuleTriggerTypes, InteractionTypes, MessageComponentTypes, + ApplicationRoleConnectionMetadataTypes, } from './enums'; export type RawActivityData = GatewayActivity; @@ -269,3 +271,12 @@ export interface APIAutoModerationRuleTriggerMetadata { regex_patterns?: string[]; mention_total_limit?: number; } + +export interface APIApplicationRoleConnectionMetadata { + type: ApplicationRoleConnectionMetadataTypes; + key: string; + name: string; + name_localizations?: LocalizationMap; + description: string; + description_localizations?: LocalizationMap; +} \ No newline at end of file