import { ApplicationCommand, ApplicationCommandDataResolvable, ApplicationCommandOptionType, ApplicationCommandType, AutocompleteInteraction, ChatInputCommandInteraction, Collection, } from "discord.js" import {CharacterCommand} from "./character/index" import {autocompleteNotImplementedError, CommandData} from "./types" import {BotCommand} from "./bot/index" import {UserTable} from "../database/users.js" export const invalidCommandError = "No command by that name exists." export class Commands { readonly all: CommandData[] readonly character: CharacterCommand readonly bot: BotCommand readonly definitions: ApplicationCommandDataResolvable[] private readonly _nameCache: Record constructor({users, cleanUp}: { users: UserTable, cleanUp: () => Promise }) { this.character = new CharacterCommand({users}) this.bot = new BotCommand({users, cleanUp}) this.all = [ this.character, this.bot, ] this.definitions = this.all.map((c) => c.definition) this._nameCache = Object.fromEntries( this.all.map((c) => [c.definition.name, c]), ) } setCache(data: Collection) { for (const command of data.values()) { if (this._nameCache.hasOwnProperty(command.name)) { this._nameCache[command.name].setCached(command) } else { console.log("No such command when caching commands: " + command.name) } } } async execute(ev: ChatInputCommandInteraction) { const name = ev.commandName if (!this._nameCache.hasOwnProperty(name)) { throw invalidCommandError } await this._nameCache[name].execute(ev) } async autocomplete(ev: AutocompleteInteraction) { const name = ev.commandName if (this._nameCache.hasOwnProperty(name)) { const command = this._nameCache[name] if (command.autocomplete) { await command.autocomplete(ev) return } } throw autocompleteNotImplementedError } } const otherCommands: ApplicationCommandDataResolvable[] = [ { name: "playstyle", type: ApplicationCommandType.ChatInput, description: "Updates your play style.", options: [ { name: "difficulty", type: ApplicationCommandOptionType.Subcommand, description: "Alters or displays the reformation difficulty of your currently selected character.", }, { name: "preference", type: ApplicationCommandOptionType.Subcommand, description: "Alters or displays the pred/prey preference of your currently selected character.", }, ], }, { name: "team", type: ApplicationCommandType.ChatInput, description: "Affects teams in battle.", options: [ { name: "join", type: ApplicationCommandOptionType.Subcommand, description: "Leaves the current team, if any, and requests to join the same team (and battle) as another player.", }, { name: "leave", type: ApplicationCommandOptionType.Subcommand, description: "Leaves the current team, if any, and strikes it out alone.", }, ], }, { name: "battle", type: ApplicationCommandType.ChatInput, description: "Takes actions in battle.", options: [ { name: "challenge", type: ApplicationCommandOptionType.Subcommand, description: "Challenges another character to a battle.", options: [ { name: "target", type: ApplicationCommandOptionType.String, description: "The character you want to challenge.", autocomplete: true, }, ], }, { name: "menu", type: ApplicationCommandOptionType.Subcommand, description: "Opens the battle menu to select an action for this turn.", }, { name: "skill", type: ApplicationCommandOptionType.Subcommand, description: "Uses a skill.", options: [ { name: "name", type: ApplicationCommandOptionType.String, description: "The name of the skill to use. Omit to see a list.", autocomplete: true, required: false, }, { name: "target", type: ApplicationCommandOptionType.String, description: "The target to use the skill on, if there are multiple options. Omit to see a list.", autocomplete: true, required: false, }, ], }, { name: "item", type: ApplicationCommandOptionType.Subcommand, description: "Uses an item.", options: [ { name: "name", type: ApplicationCommandOptionType.String, description: "The name of the item to use. Omit to see a list.", autocomplete: true, required: false, }, { name: "target", type: ApplicationCommandOptionType.String, description: "The target to use the item on, if there are multiple options. Omit to see a list.", autocomplete: true, required: false, }, ], }, { name: "vore", type: ApplicationCommandOptionType.Subcommand, description: "Devours your opponent. Requires your opponent to be at low Confidence.", options: [ { name: "style", type: ApplicationCommandOptionType.String, description: "The style of devouring to use. Omit to see a list.", autocomplete: true, required: false, }, ], }, { name: "rest", type: ApplicationCommandOptionType.Subcommand, description: "Takes a breather, recovering your Confidence and Energy at a faster-than-normal rate for this turn.", }, { name: "escape", type: ApplicationCommandOptionType.Subcommand, description: "Tries to escape from a battle or stomach. Requires your opponent to be at low Confidence.", }, { name: "surrender", type: ApplicationCommandOptionType.Subcommand, description: "Lets your opponent do as they will with you by reducing your Confidence or Health to 0.", }, { name: "prey", type: ApplicationCommandOptionType.SubcommandGroup, description: "Commands for when you have a full belly.", options: [ { name: "release", type: ApplicationCommandOptionType.Subcommand, description: "Releases your prey from your stomach.", }, { name: "squish", type: ApplicationCommandOptionType.Subcommand, description: "Squishes your prey, ending the combat. Can only be performed when the prey is at or below 0% Health.", }, ], }, ], }, { name: "safety", type: ApplicationCommandType.ChatInput, description: "Safety commands for protecting consent and user data.", options: [ { name: "exit", type: ApplicationCommandOptionType.SubcommandGroup, description: "Exits battle(s) and reverts its/their effects on you. To flee in-character, use /battle escape.", }, { name: "block", type: ApplicationCommandOptionType.SubcommandGroup, description: "Manages your block list.", options: [ { name: "add", type: ApplicationCommandOptionType.Subcommand, description: "Prevents a user or character from challenging you or joining battles you're in.", options: [ { name: "user", type: ApplicationCommandOptionType.User, description: "The user to block from challenging you or joining battles you're in.", required: false, }, { name: "character", type: ApplicationCommandOptionType.String, description: "The character to block from challenging you or joining battles you're in.", required: false, autocomplete: true, }, ], }, { name: "remove", type: ApplicationCommandOptionType.Subcommand, description: "Allows a user or character to challenge you and join battles you're in once more.", options: [ { name: "user", type: ApplicationCommandOptionType.User, description: "The user to allow to challenge you and join battles you're in once more.", required: false, }, { name: "character", type: ApplicationCommandOptionType.String, description: "The character to allow to challenge you and join battles you're in once more.", required: false, autocomplete: true, }, ], }, { name: "list", type: ApplicationCommandOptionType.Subcommand, description: "Displays your current block list.", }, ], }, { name: "kick", type: ApplicationCommandOptionType.SubcommandGroup, description: "Manages the list of users kicked from the current battle.", options: [ { name: "add", type: ApplicationCommandOptionType.Subcommand, description: "Removes a user or character from the current battle and prevents them from rejoining.", options: [ { name: "user", type: ApplicationCommandOptionType.User, description: "The user to remove from the current battle and prevent from rejoining.", required: false, }, { name: "character", type: ApplicationCommandOptionType.String, description: "The character to remove from the current battle and prevent from rejoining.", required: false, autocomplete: true, }, ], }, { name: "remove", type: ApplicationCommandOptionType.Subcommand, description: "Allows a user or character to rejoin the current battle.", options: [ { name: "user", type: ApplicationCommandOptionType.User, description: "The user to allow to rejoin the current battle.", required: false, }, { name: "character", type: ApplicationCommandOptionType.String, description: "The user to allow to rejoin the current battle.", required: false, autocomplete: true, }, ], }, { name: "list", type: ApplicationCommandOptionType.Subcommand, description: "Displays the list of users forbidden from rejoining the current battle.", }, ], }, { name: "ban", type: ApplicationCommandOptionType.SubcommandGroup, description: "Manages the ban list of the current server.", options: [ { name: "add", type: ApplicationCommandOptionType.Subcommand, description: "Bans a user from participating in battles in the current server and kicks them from any they're in.", options: [ { name: "user", type: ApplicationCommandOptionType.User, description: "The user to ban from participating in battles in the current server.", required: true, }, ], }, { name: "remove", type: ApplicationCommandOptionType.Subcommand, description: "Allows a user to resume participating in battles in the current server.", options: [ { name: "user", type: ApplicationCommandOptionType.User, description: "The user to allow to participate in battles in the current server once more.", required: true, }, ], }, { name: "list", type: ApplicationCommandOptionType.Subcommand, description: "Displays this server's current ban list.", }, ], }, { name: "delete", type: ApplicationCommandOptionType.Subcommand, description: "PERMANENTLY deletes a character, exiting any battles they were part of. See also /character archive.", }, { name: "wipe", type: ApplicationCommandOptionType.Subcommand, description: "PERMANENTLY deletes ALL data about you in the system, erasing you from the system's knowledge.", }, ], }, ]