Skip to content

Commit

Permalink
refactor: use new abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
didinele committed Sep 23, 2024
1 parent 358b925 commit efee37d
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 202 deletions.
1 change: 0 additions & 1 deletion packages/builders/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export * from './interactions/commands/chatInput/mixins/ApplicationCommandOption
export * from './interactions/commands/chatInput/mixins/ApplicationCommandOptionWithChoicesMixin.js';
export * from './interactions/commands/chatInput/mixins/SharedChatInputCommandOptions.js';
export * from './interactions/commands/chatInput/mixins/SharedSubcommands.js';
export * from './interactions/commands/chatInput/mixins/SharedChatInputCommand.js';

export * from './interactions/commands/chatInput/options/boolean.js';
export * from './interactions/commands/chatInput/options/channel.js';
Expand Down
70 changes: 69 additions & 1 deletion packages/builders/src/interactions/commands/Command.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,77 @@
import type { JSONEncodable } from '@discordjs/util';
import type { RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v10';
import type {
ApplicationIntegrationType,
InteractionContextType,
Permissions,
RESTPostAPIApplicationCommandsJSONBody,
} from 'discord-api-types/v10';
import type { RestOrArray } from '../../util/normalizeArray.js';
import { normalizeArray } from '../../util/normalizeArray.js';

export interface CommandData
extends Partial<
Pick<
RESTPostAPIApplicationCommandsJSONBody,
'contexts' | 'default_member_permissions' | 'integration_types' | 'nsfw'
>
> {}

export abstract class CommandBuilder<Command extends RESTPostAPIApplicationCommandsJSONBody>
implements JSONEncodable<Command>
{
protected declare readonly data: CommandData;

/**
* Sets the contexts of this command.
*
* @param contexts - The contexts
*/
public setContexts(...contexts: RestOrArray<InteractionContextType>) {
this.data.contexts = normalizeArray(contexts);
return this;
}

/**
* Sets the integration types of this command.
*
* @param integrationTypes - The integration types
*/
public setIntegrationTypes(...integrationTypes: RestOrArray<ApplicationIntegrationType>) {
this.data.integration_types = normalizeArray(integrationTypes);
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) {
this.data.default_member_permissions = typeof permissions === 'string' ? permissions : permissions.toString();
return this;
}

/**
* Clears the default permissions a member should have in order to run the command.
*/
public clearDefaultMemberPermissions() {
this.data.default_member_permissions = undefined;
return this;
}

/**
* Sets whether this command is NSFW.
*
* @param nsfw - Whether this command is NSFW
*/
public setNSFW(nsfw = true) {
this.data.nsfw = nsfw;
return this;
}

/**
* Serializes this builder to API-compatible JSON data.
*
Expand Down
5 changes: 3 additions & 2 deletions packages/builders/src/interactions/commands/SharedName.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { APIApplicationCommand, LocaleString } from 'discord-api-types/v10';
import type { LocaleString, RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v10';

export interface SharedNameData extends Partial<Pick<APIApplicationCommand, 'name_localizations' | 'name'>> {}
export interface SharedNameData
extends Partial<Pick<RESTPostAPIApplicationCommandsJSONBody, 'name_localizations' | 'name'>> {}

/**
* This mixin holds name and description symbols for chat input commands.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import { ApplicationCommandType, type RESTPostAPIChatInputApplicationCommandsJSO
import { Mixin } from 'ts-mixer';
import { isValidationEnabled } from '../../../util/validation.js';
import { CommandBuilder } from '../Command.js';
import { SharedNameAndDescription } from '../SharedNameAndDescription.js';
import { chatInputCommandPredicate } from './Assertions.js';
import { SharedChatInputCommand } from './mixins/SharedChatInputCommand.js';
import { SharedChatInputCommandOptions } from './mixins/SharedChatInputCommandOptions.js';
import { SharedNameAndDescription } from '../SharedNameAndDescription.js';
import { SharedChatInputCommandSubcommands } from './mixins/SharedSubcommands.js';

/**
Expand All @@ -16,7 +15,6 @@ export class ChatInputCommandBuilder extends Mixin(
SharedChatInputCommandOptions,
SharedNameAndDescription,
SharedChatInputCommandSubcommands,
SharedChatInputCommand,
) {
/**
* {@inheritDoc CommandBuilder.toJSON}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import type {
ApplicationCommandType,
ApplicationIntegrationType,
InteractionContextType,
LocaleString,
Permissions,
RESTPostAPIContextMenuApplicationCommandsJSONBody,
} from 'discord-api-types/v10';
import type { RestOrArray } from '../../../util/normalizeArray.js';
import { normalizeArray } from '../../../util/normalizeArray.js';
import type { ApplicationCommandType, RESTPostAPIContextMenuApplicationCommandsJSONBody } from 'discord-api-types/v10';
import { Mixin } from 'ts-mixer';
import { CommandBuilder } from '../Command.js';
import { SharedName } from '../SharedName.js';

/**
* The type a context menu command can be.
Expand All @@ -18,123 +11,17 @@ export type ContextMenuCommandType = ApplicationCommandType.Message | Applicatio
/**
* A builder that creates API-compatible JSON data for context menu commands.
*/
export abstract class ContextMenuCommandBuilder extends CommandBuilder<RESTPostAPIContextMenuApplicationCommandsJSONBody> {
protected readonly data: Partial<RESTPostAPIContextMenuApplicationCommandsJSONBody>;
export abstract class ContextMenuCommandBuilder extends Mixin(
CommandBuilder<RESTPostAPIContextMenuApplicationCommandsJSONBody>,
SharedName,
) {
protected override readonly data: Partial<RESTPostAPIContextMenuApplicationCommandsJSONBody>;

public constructor(data: Partial<RESTPostAPIContextMenuApplicationCommandsJSONBody> = {}) {
super();
this.data = structuredClone(data);
}

/**
* Sets the contexts of this command.
*
* @param contexts - The contexts
*/
public setContexts(...contexts: RestOrArray<InteractionContextType>) {
this.data.contexts = normalizeArray(contexts);
return this;
}

/**
* Sets integration types of this command.
*
* @param integrationTypes - The integration types
*/
public setIntegrationTypes(...integrationTypes: RestOrArray<ApplicationIntegrationType>) {
this.data.integration_types = normalizeArray(integrationTypes);
return this;
}

/**
* Sets the name of this command.
*
* @param name - The name to use
*/
public setName(name: string) {
this.data.name = name;
return this;
}

/**
* Sets the default permissions a member should have in order to run this 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) {
this.data.default_member_permissions = typeof permissions === 'string' ? permissions : permissions.toString();
return this;
}

/**
* Clears the default permissions for this command.
*/
public clearDefaultMemberPermissions() {
this.data.default_member_permissions = undefined;
return this;
}

/**
* Sets a name localization for this command.
*
* @param locale - The locale to set
* @param localizedName - The localized name for the given `locale`
*/
public setNameLocalization(locale: LocaleString, localizedName: string) {
this.data.name_localizations ??= {};
this.data.name_localizations[locale] = localizedName;

return this;
}

/**
* Clears a name localization for this command.
*
* @param locale - The locale to clear
*/
public clearNameLocalization(locale: LocaleString) {
this.data.name_localizations ??= {};
this.data.name_localizations[locale] = undefined;

return this;
}

/**
* Sets the name localizations for this command.
*
* @param localizedNames - The object of localized names to set
*/
public setNameLocalizations(localizedNames: Partial<Record<LocaleString, string>>) {
this.data.name_localizations = {};

for (const args of Object.entries(localizedNames)) {
this.setNameLocalization(...(args as [LocaleString, string]));
}

return this;
}

/**
* Clears the name localizations for this command.
*/
public clearNameLocalizations() {
this.data.name_localizations = undefined;
return this;
}

/**
* Sets whether this command is NSFW.
*
* @param nsfw - Whether this command is NSFW
*/
public setNSFW(nsfw = true) {
this.data.nsfw = nsfw;
return this;
}

/**
* {@inheritDoc CommandBuilder.toJSON}
*/
Expand Down

0 comments on commit efee37d

Please sign in to comment.