all repos — kitten @ f80d8c5364cf8ed06845366587938faec60d32db

pkgs/core/src/commands.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
import type { ChatInputCommandInteraction } from "discord.js";
import type { Option, InferOptions } from "./options";

export class Subcommand {
  constructor(
    public name: string,
    public config: {
      description: string;
      options?: Record<string, Option<any, any>>;
      run: Function;
    },
  ) {}
}

export class SubcommandGroup<Ctx = {}> {
  public subcommands: Record<string, Subcommand> = {};

  constructor(
    public name: string,
    public description: string,
  ) {}

  subcommand<O extends Record<string, Option<any, any>>>(
    name: string,
    config: {
      description: string;
      options?: O;
      run: (
        interaction: ChatInputCommandInteraction,
        args: InferOptions<O>,
        ctx: Ctx,
      ) => Promise<void> | void;
    },
  ): this {
    this.subcommands[name] = new Subcommand(name, config);
    return this;
  }
}

export class SubcommandGroupBuilder<Ctx = {}> {
  public subcommands: Record<string, Subcommand> = {};
  public groups: Record<string, SubcommandGroup<Ctx>> = {};

  constructor(
    public name: string,
    public description: string,
    public middlewares: Function[] = [],
  ) {}

  subcommand<O extends Record<string, Option<any, any>>>(
    name: string,
    config: {
      description: string;
      options?: O;
      run: (
        interaction: ChatInputCommandInteraction,
        args: InferOptions<O>,
        ctx: Ctx,
      ) => Promise<void> | void;
    },
  ): this {
    this.subcommands[name] = new Subcommand(name, config);
    return this;
  }

  group(
    name: string,
    config: { description: string },
    setup: (group: SubcommandGroup<Ctx>) => void,
  ): this {
    const group = new SubcommandGroup<Ctx>(name, config.description);
    setup(group);
    this.groups[name] = group;
    return this;
  }
}

export class Command {
  constructor(
    public name: string,
    public config: {
      description: string;
      options?: Record<string, Option<any, any>>;
      run: Function;
    },
    public middlewares: Function[] = [],
  ) {}
}

export class CommandBuilder<Ctx = {}> {
  constructor(private middlewares: Function[] = []) {}

  use<NewCtx extends Record<string, any>>(
    mw: (
      interaction: ChatInputCommandInteraction,
      ctx: Ctx,
    ) => Promise<NewCtx | void> | NewCtx | void,
  ): CommandBuilder<Ctx & NewCtx> {
    return new CommandBuilder<Ctx & NewCtx>([...this.middlewares, mw]);
  }

  command<O extends Record<string, Option<any, any>>>(
    name: string,
    config: {
      description: string;
      options?: O;
      run: (
        interaction: ChatInputCommandInteraction,
        args: InferOptions<O>,
        ctx: Ctx,
      ) => Promise<void> | void;
    },
  ): Command;

  command(name: string, config: { description: string }): SubcommandGroupBuilder<Ctx>;

  command(name: string, config: any): any {
    if (config.run) {
      return new Command(name, config, this.middlewares);
    }
    return new SubcommandGroupBuilder<Ctx>(name, config.description, this.middlewares);
  }
}