Skip to content
This repository has been archived by the owner on Oct 17, 2024. It is now read-only.

Commit

Permalink
CompoundCommandクラスを作成
Browse files Browse the repository at this point in the history
  • Loading branch information
takejohn committed Apr 26, 2024
1 parent e20aea9 commit a46ee56
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 15 deletions.
103 changes: 103 additions & 0 deletions common/CompoundCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
CacheType,
ChatInputCommandInteraction,
Client,
SlashCommandBuilder,
SlashCommandSubcommandBuilder,
} from 'discord.js';
import {
Option,
OptionValueMap,
SimpleCommand,
SimpleSlashCommandBuilder,
} from './SimpleCommand';
import { Command } from '../util/types';

export class CompoundCommandBuilder {
readonly #handle: SlashCommandBuilder;

readonly #subcommands = new Map<
string,
SimpleCommand<Option<unknown, boolean>[]>
>();

constructor(name: string, description: string) {
this.#handle = new SlashCommandBuilder()
.setName(name)
.setDescription(description);
}

subcommand(name: string, description: string): SimpleSubcommandBuilder {
const handle = new SlashCommandSubcommandBuilder();
this.#handle.addSubcommand(handle);
return new SimpleSubcommandBuilder(
name,
description,
handle,
[],
(name, subcommand) => this.#subcommands.set(name, subcommand),
);
}

build(): CompoundCommand {
return new CompoundCommand(this.#subcommands, this.#handle);
}
}

export class SimpleSubcommandBuilder<
Options extends Option<unknown, boolean>[] = [],
> extends SimpleSlashCommandBuilder<Options> {
readonly #onBuild: (name: string, subcommand: SimpleCommand<Options>) => void;

constructor(
name: string,
description: string,
handle: SlashCommandSubcommandBuilder,
options: Options,
onBuild: (name: string, subcommand: SimpleCommand<Options>) => void,
) {
super(name, description, handle, options);
this.#onBuild = onBuild;
}

build(
action: (
interaction: ChatInputCommandInteraction<CacheType>,
...options: OptionValueMap<Options>
) => Promise<void>,
): SimpleCommand<Options> {
const subcommand = super.build(action);
this.#onBuild(this.name, subcommand);
return subcommand;
}
}

export class CompoundCommand implements Command {
readonly #subcommands: Map<string, SimpleCommand<Option<unknown, boolean>[]>>;

data: SlashCommandBuilder;

constructor(
subcommands: Map<string, SimpleCommand<Option<unknown, boolean>[]>>,
data: SlashCommandBuilder,
) {
this.#subcommands = subcommands;
this.data = data;
}

async execute(
interaction: ChatInputCommandInteraction<CacheType>,
client: Client<true>,
): Promise<void> {
const subcommandName = interaction.options.getSubcommand(true);
const subcommand = this.#subcommands.get(subcommandName);
if (subcommand == null) {
await interaction.reply({
ephemeral: true,
content: 'Invalid subcommand: ' + subcommandName,
});
return;
}
subcommand.execute(interaction);
}
}
18 changes: 9 additions & 9 deletions common/SimpleCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
ApplicationCommandOptionWithChoicesAndAutocompleteMixin,
CacheType,
SharedSlashCommandOptions,
SlashCommandBuilder,
SlashCommandSubcommandBuilder,
} from 'discord.js';
import { ChatInputCommandInteraction } from 'discord.js';
import { Command } from '../util/types';
Expand All @@ -12,7 +12,7 @@ type Value<T, Required extends boolean = boolean> = Required extends true
? T
: T | undefined;

type OptionValueMap<O extends Option<unknown>[]> = {
export type OptionValueMap<O extends Option<unknown>[]> = {
[I in keyof O]: O[I] extends Option<infer T, infer Required>
? Value<T, Required>
: never;
Expand Down Expand Up @@ -50,7 +50,7 @@ interface SimpleStringOptionData<
min_length?: number;
}

interface Option<T = unknown, Required extends boolean = boolean> {
export interface Option<T = unknown, Required extends boolean = boolean> {
/** オプションの名前 */
name: string;

Expand Down Expand Up @@ -163,23 +163,23 @@ class StringOption<
export class SimpleSlashCommandBuilder<
Options extends Option<unknown, boolean>[] = [],
> {
#name: string;
public readonly name: string;

#description: string;

handle: SlashCommandBuilder;
handle: SlashCommandSubcommandBuilder;

options: Options;

constructor(
name: string,
description: string,
handle: SlashCommandBuilder,
handle: SlashCommandSubcommandBuilder,
options: Options,
) {
handle.setName(name);
handle.setDescription(description);
this.#name = name;
this.name = name;
this.#description = description;
this.handle = handle;
this.options = options;
Expand All @@ -196,7 +196,7 @@ export class SimpleSlashCommandBuilder<
return new SimpleSlashCommandBuilder(
name,
description,
new SlashCommandBuilder(),
new SlashCommandSubcommandBuilder(),
[],
);
}
Expand All @@ -208,7 +208,7 @@ export class SimpleSlashCommandBuilder<
option,
];
return new SimpleSlashCommandBuilder(
this.#name,
this.name,
this.#description,
this.handle,
options,
Expand Down
14 changes: 8 additions & 6 deletions packages/misc/commands/date.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { SimpleSlashCommandBuilder } from '../../../common/SimpleCommand';
import { CompoundCommandBuilder } from '../../../common/CompoundCommand';

export default SimpleSlashCommandBuilder.create('date', '時刻を表示').build(
async (i) => {
await i.reply(new Date().toString());
},
);
const builder = new CompoundCommandBuilder('date', '時刻の計算と表示');

builder.subcommand('now', '現在時刻を表示').build(async (i) => {
await i.reply(new Date().toString());
});

export default builder.build();

0 comments on commit a46ee56

Please sign in to comment.