mirror of
https://github.com/discordjs/discord.js.git
synced 2024-08-21 16:24:45 +12:00
fix: slashcommand builder type split (#10253)
This commit is contained in:
parent
30d79e85fb
commit
07c12101e5
6 changed files with 135 additions and 112 deletions
|
@ -357,6 +357,10 @@ describe('Slash Commands', () => {
|
||||||
getBuilder().addStringOption(getStringOption().setChoices({ name: 'owo', value: 'uwu' })),
|
getBuilder().addStringOption(getStringOption().setChoices({ name: 'owo', value: 'uwu' })),
|
||||||
).not.toThrowError();
|
).not.toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('GIVEN valid builder with NSFW, THEN does not throw error', () => {
|
||||||
|
expect(() => getBuilder().setName('foo').setDescription('foo').setNSFW(true)).not.toThrowError();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Builder with subcommand (group) options', () => {
|
describe('Builder with subcommand (group) options', () => {
|
||||||
|
@ -519,6 +523,14 @@ describe('Slash Commands', () => {
|
||||||
|
|
||||||
expect(() => getBuilder().setDefaultMemberPermissions(1.1)).toThrowError();
|
expect(() => getBuilder().setDefaultMemberPermissions(1.1)).toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('GIVEN valid permission with options THEN does not throw error', () => {
|
||||||
|
expect(() =>
|
||||||
|
getBuilder().addBooleanOption(getBooleanOption()).setDefaultMemberPermissions('1'),
|
||||||
|
).not.toThrowError();
|
||||||
|
|
||||||
|
expect(() => getBuilder().addChannelOption(getChannelOption()).setDMPermission(false)).not.toThrowError();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -140,7 +140,7 @@ export class TextInputBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc Equatable.equals}
|
* Whether this is equal to another structure.
|
||||||
*/
|
*/
|
||||||
public equals(other: APITextInputComponent | JSONEncodable<APITextInputComponent>): boolean {
|
public equals(other: APITextInputComponent | JSONEncodable<APITextInputComponent>): boolean {
|
||||||
if (isJSONEncodable(other)) {
|
if (isJSONEncodable(other)) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ export * from './interactions/slashCommands/mixins/ApplicationCommandOptionWithC
|
||||||
export * from './interactions/slashCommands/mixins/NameAndDescription.js';
|
export * from './interactions/slashCommands/mixins/NameAndDescription.js';
|
||||||
export * from './interactions/slashCommands/mixins/SharedSlashCommandOptions.js';
|
export * from './interactions/slashCommands/mixins/SharedSlashCommandOptions.js';
|
||||||
export * from './interactions/slashCommands/mixins/SharedSubcommands.js';
|
export * from './interactions/slashCommands/mixins/SharedSubcommands.js';
|
||||||
|
export * from './interactions/slashCommands/mixins/SharedSlashCommand.js';
|
||||||
|
|
||||||
export * as ContextMenuCommandAssertions from './interactions/contextMenuCommands/Assertions.js';
|
export * as ContextMenuCommandAssertions from './interactions/contextMenuCommands/Assertions.js';
|
||||||
export * from './interactions/contextMenuCommands/ContextMenuCommandBuilder.js';
|
export * from './interactions/contextMenuCommands/ContextMenuCommandBuilder.js';
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import type { APIApplicationCommandOption, LocalizationMap, Permissions } from 'discord-api-types/v10';
|
import type { APIApplicationCommandOption, LocalizationMap, Permissions } from 'discord-api-types/v10';
|
||||||
import { mix } from 'ts-mixer';
|
import { mix } from 'ts-mixer';
|
||||||
import { SharedNameAndDescription } from './mixins/NameAndDescription.js';
|
import { SharedNameAndDescription } from './mixins/NameAndDescription.js';
|
||||||
|
import { SharedSlashCommand } from './mixins/SharedSlashCommand.js';
|
||||||
import { SharedSlashCommandOptions } from './mixins/SharedSlashCommandOptions.js';
|
import { SharedSlashCommandOptions } from './mixins/SharedSlashCommandOptions.js';
|
||||||
import { SharedSlashCommandSubcommands } from './mixins/SharedSubcommands.js';
|
import { SharedSlashCommandSubcommands } from './mixins/SharedSubcommands.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder that creates API-compatible JSON data for slash commands.
|
* A builder that creates API-compatible JSON data for slash commands.
|
||||||
*/
|
*/
|
||||||
@mix(SharedSlashCommandOptions, SharedNameAndDescription, SharedSlashCommandSubcommands)
|
@mix(SharedSlashCommandOptions, SharedNameAndDescription, SharedSlashCommandSubcommands, SharedSlashCommand)
|
||||||
export class SlashCommandBuilder {
|
export class SlashCommandBuilder {
|
||||||
/**
|
/**
|
||||||
* The name of this command.
|
* The name of this command.
|
||||||
|
@ -37,7 +38,7 @@ export class SlashCommandBuilder {
|
||||||
/**
|
/**
|
||||||
* Whether this command is enabled by default when the application is added to a guild.
|
* Whether this command is enabled by default when the application is added to a guild.
|
||||||
*
|
*
|
||||||
* @deprecated Use {@link SharedSlashCommandSubcommands.setDefaultMemberPermissions} or {@link SharedSlashCommandSubcommands.setDMPermission} instead.
|
* @deprecated Use {@link SharedSlashCommand.setDefaultMemberPermissions} or {@link SharedSlashCommand.setDMPermission} instead.
|
||||||
*/
|
*/
|
||||||
public readonly default_permission: boolean | undefined = undefined;
|
public readonly default_permission: boolean | undefined = undefined;
|
||||||
|
|
||||||
|
@ -63,14 +64,16 @@ export class SlashCommandBuilder {
|
||||||
export interface SlashCommandBuilder
|
export interface SlashCommandBuilder
|
||||||
extends SharedNameAndDescription,
|
extends SharedNameAndDescription,
|
||||||
SharedSlashCommandOptions<SlashCommandOptionsOnlyBuilder>,
|
SharedSlashCommandOptions<SlashCommandOptionsOnlyBuilder>,
|
||||||
SharedSlashCommandSubcommands<SlashCommandSubcommandsOnlyBuilder> {}
|
SharedSlashCommandSubcommands<SlashCommandSubcommandsOnlyBuilder>,
|
||||||
|
SharedSlashCommand {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface specifically for slash command subcommands.
|
* An interface specifically for slash command subcommands.
|
||||||
*/
|
*/
|
||||||
export interface SlashCommandSubcommandsOnlyBuilder
|
export interface SlashCommandSubcommandsOnlyBuilder
|
||||||
extends SharedNameAndDescription,
|
extends SharedNameAndDescription,
|
||||||
SharedSlashCommandSubcommands<SlashCommandSubcommandsOnlyBuilder> {}
|
SharedSlashCommandSubcommands<SlashCommandSubcommandsOnlyBuilder>,
|
||||||
|
SharedSlashCommand {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface specifically for slash command options.
|
* An interface specifically for slash command options.
|
||||||
|
@ -78,7 +81,7 @@ export interface SlashCommandSubcommandsOnlyBuilder
|
||||||
export interface SlashCommandOptionsOnlyBuilder
|
export interface SlashCommandOptionsOnlyBuilder
|
||||||
extends SharedNameAndDescription,
|
extends SharedNameAndDescription,
|
||||||
SharedSlashCommandOptions<SlashCommandOptionsOnlyBuilder>,
|
SharedSlashCommandOptions<SlashCommandOptionsOnlyBuilder>,
|
||||||
ToAPIApplicationCommandOptions {}
|
SharedSlashCommand {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface that ensures the `toJSON()` call will return something
|
* An interface that ensures the `toJSON()` call will return something
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
import type {
|
||||||
|
LocalizationMap,
|
||||||
|
Permissions,
|
||||||
|
RESTPostAPIChatInputApplicationCommandsJSONBody,
|
||||||
|
} from 'discord-api-types/v10';
|
||||||
|
import {
|
||||||
|
validateDMPermission,
|
||||||
|
validateDefaultMemberPermissions,
|
||||||
|
validateDefaultPermission,
|
||||||
|
validateLocalizationMap,
|
||||||
|
validateNSFW,
|
||||||
|
validateRequiredParameters,
|
||||||
|
} from '../Assertions.js';
|
||||||
|
import type { ToAPIApplicationCommandOptions } from '../SlashCommandBuilder.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This mixin holds symbols that can be shared in slashcommands independent of options or subcommands.
|
||||||
|
*/
|
||||||
|
export class SharedSlashCommand {
|
||||||
|
public readonly name: string = undefined!;
|
||||||
|
|
||||||
|
public readonly name_localizations?: LocalizationMap;
|
||||||
|
|
||||||
|
public readonly description: string = undefined!;
|
||||||
|
|
||||||
|
public readonly description_localizations?: LocalizationMap;
|
||||||
|
|
||||||
|
public readonly options: ToAPIApplicationCommandOptions[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the command is enabled by default when the application is added to a guild.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* If set to `false`, you will have to later `PUT` the permissions for this command.
|
||||||
|
* @param value - Whether or not to enable this command by default
|
||||||
|
* @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
|
||||||
|
* @deprecated Use {@link SharedSlashCommand.setDefaultMemberPermissions} or {@link SharedSlashCommand.setDMPermission} instead.
|
||||||
|
*/
|
||||||
|
public setDefaultPermission(value: boolean) {
|
||||||
|
// Assert the value matches the conditions
|
||||||
|
validateDefaultPermission(value);
|
||||||
|
|
||||||
|
Reflect.set(this, 'default_permission', value);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the default permissions a member should have in order to run the command.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* You can set this to `'0'` to disable the command by default.
|
||||||
|
* @param permissions - The permissions bit field to set
|
||||||
|
* @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
|
||||||
|
*/
|
||||||
|
public setDefaultMemberPermissions(permissions: Permissions | bigint | number | null | undefined) {
|
||||||
|
// Assert the value and parse it
|
||||||
|
const permissionValue = validateDefaultMemberPermissions(permissions);
|
||||||
|
|
||||||
|
Reflect.set(this, 'default_member_permissions', permissionValue);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if the command is available in direct messages with the application.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* By default, commands are visible. This method is only for global commands.
|
||||||
|
* @param enabled - Whether the command should be enabled in direct messages
|
||||||
|
* @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
|
||||||
|
*/
|
||||||
|
public setDMPermission(enabled: boolean | null | undefined) {
|
||||||
|
// Assert the value matches the conditions
|
||||||
|
validateDMPermission(enabled);
|
||||||
|
|
||||||
|
Reflect.set(this, 'dm_permission', enabled);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this command is NSFW.
|
||||||
|
*
|
||||||
|
* @param nsfw - Whether this command is NSFW
|
||||||
|
*/
|
||||||
|
public setNSFW(nsfw = true) {
|
||||||
|
// Assert the value matches the conditions
|
||||||
|
validateNSFW(nsfw);
|
||||||
|
Reflect.set(this, 'nsfw', nsfw);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes this builder to API-compatible JSON data.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* This method runs validations on the data before serializing it.
|
||||||
|
* As such, it may throw an error if the data is invalid.
|
||||||
|
*/
|
||||||
|
public toJSON(): RESTPostAPIChatInputApplicationCommandsJSONBody {
|
||||||
|
validateRequiredParameters(this.name, this.description, this.options);
|
||||||
|
|
||||||
|
validateLocalizationMap(this.name_localizations);
|
||||||
|
validateLocalizationMap(this.description_localizations);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
options: this.options.map((option) => option.toJSON()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +1,4 @@
|
||||||
import type {
|
import { assertReturnOfBuilder, validateMaxOptionsLength } from '../Assertions.js';
|
||||||
LocalizationMap,
|
|
||||||
Permissions,
|
|
||||||
RESTPostAPIChatInputApplicationCommandsJSONBody,
|
|
||||||
} from 'discord-api-types/v10';
|
|
||||||
import {
|
|
||||||
assertReturnOfBuilder,
|
|
||||||
validateDMPermission,
|
|
||||||
validateDefaultMemberPermissions,
|
|
||||||
validateDefaultPermission,
|
|
||||||
validateLocalizationMap,
|
|
||||||
validateMaxOptionsLength,
|
|
||||||
validateNSFW,
|
|
||||||
validateRequiredParameters,
|
|
||||||
} from '../Assertions.js';
|
|
||||||
import type { ToAPIApplicationCommandOptions } from '../SlashCommandBuilder.js';
|
import type { ToAPIApplicationCommandOptions } from '../SlashCommandBuilder.js';
|
||||||
import { SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder } from '../SlashCommandSubcommands.js';
|
import { SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder } from '../SlashCommandSubcommands.js';
|
||||||
|
|
||||||
|
@ -24,80 +10,8 @@ import { SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder } fro
|
||||||
export class SharedSlashCommandSubcommands<
|
export class SharedSlashCommandSubcommands<
|
||||||
TypeAfterAddingSubcommands extends SharedSlashCommandSubcommands<TypeAfterAddingSubcommands>,
|
TypeAfterAddingSubcommands extends SharedSlashCommandSubcommands<TypeAfterAddingSubcommands>,
|
||||||
> {
|
> {
|
||||||
public readonly name: string = undefined!;
|
|
||||||
|
|
||||||
public readonly name_localizations?: LocalizationMap;
|
|
||||||
|
|
||||||
public readonly description: string = undefined!;
|
|
||||||
|
|
||||||
public readonly description_localizations?: LocalizationMap;
|
|
||||||
|
|
||||||
public readonly options: ToAPIApplicationCommandOptions[] = [];
|
public readonly options: ToAPIApplicationCommandOptions[] = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether the command is enabled by default when the application is added to a guild.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* If set to `false`, you will have to later `PUT` the permissions for this command.
|
|
||||||
* @param value - Whether or not to enable this command by default
|
|
||||||
* @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
|
|
||||||
* @deprecated Use {@link SharedSlashCommandSubcommands.setDefaultMemberPermissions} or {@link SharedSlashCommandSubcommands.setDMPermission} instead.
|
|
||||||
*/
|
|
||||||
public setDefaultPermission(value: boolean) {
|
|
||||||
// Assert the value matches the conditions
|
|
||||||
validateDefaultPermission(value);
|
|
||||||
|
|
||||||
Reflect.set(this, 'default_permission', value);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default permissions a member should have in order to run the command.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* You can set this to `'0'` to disable the command by default.
|
|
||||||
* @param permissions - The permissions bit field to set
|
|
||||||
* @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
|
|
||||||
*/
|
|
||||||
public setDefaultMemberPermissions(permissions: Permissions | bigint | number | null | undefined) {
|
|
||||||
// Assert the value and parse it
|
|
||||||
const permissionValue = validateDefaultMemberPermissions(permissions);
|
|
||||||
|
|
||||||
Reflect.set(this, 'default_member_permissions', permissionValue);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets if the command is available in direct messages with the application.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* By default, commands are visible. This method is only for global commands.
|
|
||||||
* @param enabled - Whether the command should be enabled in direct messages
|
|
||||||
* @see {@link https://discord.com/developers/docs/interactions/application-commands#permissions}
|
|
||||||
*/
|
|
||||||
public setDMPermission(enabled: boolean | null | undefined) {
|
|
||||||
// Assert the value matches the conditions
|
|
||||||
validateDMPermission(enabled);
|
|
||||||
|
|
||||||
Reflect.set(this, 'dm_permission', enabled);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether this command is NSFW.
|
|
||||||
*
|
|
||||||
* @param nsfw - Whether this command is NSFW
|
|
||||||
*/
|
|
||||||
public setNSFW(nsfw = true) {
|
|
||||||
// Assert the value matches the conditions
|
|
||||||
validateNSFW(nsfw);
|
|
||||||
Reflect.set(this, 'nsfw', nsfw);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new subcommand group to this command.
|
* Adds a new subcommand group to this command.
|
||||||
*
|
*
|
||||||
|
@ -149,23 +63,4 @@ export class SharedSlashCommandSubcommands<
|
||||||
|
|
||||||
return this as unknown as TypeAfterAddingSubcommands;
|
return this as unknown as TypeAfterAddingSubcommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes this builder to API-compatible JSON data.
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* This method runs validations on the data before serializing it.
|
|
||||||
* As such, it may throw an error if the data is invalid.
|
|
||||||
*/
|
|
||||||
public toJSON(): RESTPostAPIChatInputApplicationCommandsJSONBody {
|
|
||||||
validateRequiredParameters(this.name, this.description, this.options);
|
|
||||||
|
|
||||||
validateLocalizationMap(this.name_localizations);
|
|
||||||
validateLocalizationMap(this.description_localizations);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...this,
|
|
||||||
options: this.options.map((option) => option.toJSON()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue