diff --git a/.env.example b/.env.example index 82f4578b..97b59089 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ DISCORD_TOKEN= MAIN_CHANNEL_ID= +APPLICATION_ID= GUILD_ID= PREFIX=! FEATURE=MESSAGE_CREATE,MESSAGE_UPDATE,COMMAND,VOICE_ROOM,ROLE,EMOJI diff --git a/README.md b/README.md index 5329a1dd..e5fcce75 100644 --- a/README.md +++ b/README.md @@ -66,13 +66,14 @@ OreOreBot2 の [Discussions](https://github.com/approvers/OreOreBot2/discussions 起動時にデフォルト値が存在する変数の値が指定されていない場合は、そのデフォルト値が使われます。 -| 変数名 | 説明 | 必須 | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | -| `DISCORD_TOKEN` | BOT のトークン | True | -| `MAIN_CHANNEL_ID` | VoiceDiff(VC 入退室ログ)を送信する **テキスト** チャンネルの ID | True | -| `GUILD_ID` | 限界開発鯖の ID | True | -| `PREFIX` | コマンドの接頭辞、デフォルト値は `"!"` | False | -| `FEATURE` | 有効にする機能のカンマ区切り文字列、デフォルト値は全ての機能。`"MESSAGE_CREATE"`, `"MESSAGE_UPDATE"`, `"COMMAND"`, `"VOICE_ROOM"`, `"ROLE"`, `"EMOJI"` を組み合わせ可能。 | False | +| 変数名 | 説明 | 必須 | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | +| `DISCORD_TOKEN` | BOT のトークン | True | +| `MAIN_CHANNEL_ID` | VoiceDiff(VC 入退室ログ)を送信する **テキスト** チャンネルの ID | True | +| `APPLICATION_ID` | BOT のアプリケーション ID | True | +| `GUILD_ID` | 限界開発鯖の ID | True | +| `PREFIX` | コマンドの接頭辞、デフォルト値は `"!"` | False | +| `FEATURE` | 有効にする機能のカンマ区切り文字列、デフォルト値は全ての機能。`"MESSAGE_CREATE"`, `"MESSAGE_UPDATE"`, `"COMMAND"`, `"VOICE_ROOM"`, `"ROLE"`, `"EMOJI"`, `"SLASH_COMMAND"` を組み合わせ可能。 | False | ### インストールと実行 diff --git a/package.json b/package.json index 3c5698f0..668995fe 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@discordjs/voice": "^0.16.0", "@js-temporal/polyfill": "^0.4.3", "date-fns": "^2.29.3", + "deep-equal": "^2.2.2", "discord.js": "^14.7.1", "dotenv": "^16.0.3", "fast-diff": "^1.2.0", @@ -44,6 +45,7 @@ "devDependencies": { "@codedependant/semantic-release-docker": "^4.1.0", "@trivago/prettier-plugin-sort-imports": "^4.1.1", + "@types/deep-equal": "^1.0.1", "@types/node": "^20.0.0", "@types/yargs": "^17.0.22", "@typescript-eslint/eslint-plugin": "^6.0.0", diff --git a/src/adaptor/command-schema.ts b/src/adaptor/command-schema.ts new file mode 100644 index 00000000..1912ab55 --- /dev/null +++ b/src/adaptor/command-schema.ts @@ -0,0 +1,125 @@ +import type { + Param, + Schema, + SubCommandEntries +} from '../model/command-schema.js'; + +const entriesToOptions = (entries: SubCommandEntries): unknown[] => + Object.keys(entries).map((key) => { + const entry = entries[key]; + if (entry.type === 'SUB_COMMAND') { + const options = entry.params?.map(paramToOption) ?? []; + return { + type: 1, // SUB_COMMAND + name: key, + description: entry.description, + options: options.length === 0 ? undefined : options + }; + } else { + const options = entriesToOptions(entry.subCommands); + return { + type: 2, // SUB_COMMAND_GROUP + name: key, + description: entry.description, + options: options.length === 0 ? undefined : options + }; + } + }); +const paramToOption = (param: Param): unknown => { + switch (param.type) { + case 'STRING': + return { + type: 3, // STRING + name: param.name, + description: param.description, + required: param.defaultValue === undefined, + min_length: param.minLength, + max_length: param.maxLength + }; + case 'INTEGER': + return { + type: 4, // INTEGER + name: param.name, + description: param.description, + required: param.defaultValue === undefined, + min_value: param.minValue, + max_value: param.maxValue + }; + case 'BOOLEAN': + return { + type: 5, // BOOLEAN + name: param.name, + description: param.description, + required: param.defaultValue === undefined + }; + case 'USER': + return { + type: 6, // USER + name: param.name, + description: param.description, + required: param.defaultValue === undefined + }; + case 'CHANNEL': + return { + type: 7, // CHANNEL + name: param.name, + description: param.description, + required: param.defaultValue === undefined + }; + case 'ROLE': + return { + type: 8, // ROLE + name: param.name, + description: param.description, + required: param.defaultValue === undefined + }; + case 'MESSAGE': + return { + type: 3, // STRING + name: param.name, + description: param.description, + required: param.defaultValue === undefined + }; + case 'FLOAT': + return { + type: 10, // NUMBER + name: param.name, + description: param.description, + required: param.defaultValue === undefined, + min_value: param.minValue, + max_value: param.maxValue + }; + case 'CHOICES': + return { + type: 3, // STRING + name: param.name, + description: param.description, + choices: param.choices.map((choice) => ({ + name: choice, + value: choice + })), + required: param.defaultValue === undefined, + autocomplete: true + }; + case 'VARIADIC': + return { + type: 3, // STRING + name: param.name, + description: param.description, + required: param.defaultValue === undefined + }; + default: + throw new Error('unreachable'); + } +}; +export const schemaToDiscordFormat = (schema: Schema): unknown[] => + schema.names.map((name) => { + const options = (schema.params?.map(paramToOption) ?? []).concat( + entriesToOptions(schema.subCommands) + ); + return { + name, + description: schema.description, + options: options.length === 0 ? undefined : options + }; + }); diff --git a/src/adaptor/proxy/command.ts b/src/adaptor/proxy/command.ts index 1002074c..4f0ddb5c 100644 --- a/src/adaptor/proxy/command.ts +++ b/src/adaptor/proxy/command.ts @@ -8,9 +8,9 @@ import { Message, type MessageActionRowComponentBuilder, type Interaction, - type MessageReplyOptions, + type InteractionReplyOptions, InteractionResponse, - type InteractionReplyOptions + type MessageReplyOptions } from 'discord.js'; import { type Schema, makeError } from '../../model/command-schema.js'; @@ -113,8 +113,6 @@ export class DiscordCommandProxy implements CommandProxy { return; } - await interaction.deferReply(); - const [schema, listener] = entry; const [tag, parsedArgs] = parseOptions( @@ -124,7 +122,7 @@ export class DiscordCommandProxy implements CommandProxy { ); if (tag === 'Err') { const error = makeError(parsedArgs); - await interaction.editReply(error.message); + await interaction.reply(error.message); return; } @@ -142,7 +140,7 @@ export class DiscordCommandProxy implements CommandProxy { senderName: interaction.user.username, args: parsedArgs, async reply(embed) { - const mes = await interaction.editReply({ + const mes = await interaction.reply({ embeds: [convertEmbed(embed)] }); return { diff --git a/src/adaptor/proxy/command/schema.test.ts b/src/adaptor/proxy/command/schema.test.ts index a845e210..40ced3eb 100644 --- a/src/adaptor/proxy/command/schema.test.ts +++ b/src/adaptor/proxy/command/schema.test.ts @@ -4,7 +4,8 @@ import { parseStrings } from './schema.js'; test('no args', () => { const SERVER_INFO_SCHEMA = { - names: ['serverinfo'], + names: ['guildinfo', 'serverinfo', 'guild', 'server'], + description: '限界開発鯖の情報を持ってくるよ', subCommands: {} } as const; @@ -20,42 +21,48 @@ test('no args', () => { }); test('single arg', () => { - const TIME_OPTION = [ + const TIME_OPTIONS = [ { name: 'at', description: '', type: 'STRING' } ] as const; const KAERE_SCHEMA = { names: ['kaere'], + description: 'VC内の人類に就寝を促すよ', subCommands: { - start: { - type: 'SUB_COMMAND' - }, bed: { type: 'SUB_COMMAND_GROUP', + description: '強制切断モードを取り扱うよ', subCommands: { enable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '強制切断モードを有効化するよ' }, disable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '強制切断モードを無効化するよ' }, status: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在の強制切断モードの設定を確認するよ' } } }, reserve: { type: 'SUB_COMMAND_GROUP', + description: '予約システムを取り扱うよ', subCommands: { add: { type: 'SUB_COMMAND', - params: TIME_OPTION + description: '指定の時刻で予約するよ', + params: TIME_OPTIONS }, cancel: { type: 'SUB_COMMAND', - params: TIME_OPTION + description: '指定時刻の予約をキャンセルするよ', + params: TIME_OPTIONS }, list: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在の予約を一覧するよ' } } } @@ -72,21 +79,6 @@ test('single arg', () => { } ]); - const oneParamRes = parseStrings(['kaere', 'start'], KAERE_SCHEMA); - - expect(oneParamRes).toStrictEqual([ - 'Ok', - { - name: 'kaere', - params: [], - subCommand: { - name: 'start', - type: 'PARAMS', - params: [] - } - } - ]); - const subCommandRes = parseStrings( ['kaere', 'reserve', 'add', '01:12'], KAERE_SCHEMA @@ -113,10 +105,20 @@ test('single arg', () => { test('multi args', () => { const ROLE_CREATE_SCHEMA = { names: ['rolecreate'], + description: 'ロールを作成するよ', subCommands: {}, params: [ - { type: 'USER', name: 'target', description: '' }, - { type: 'STRING', name: 'color', description: '', defaultValue: 'random' } + { + type: 'STRING', + name: 'name', + description: '作成するロールの名前を指定してね' + }, + { + type: 'STRING', + name: 'color', + description: + '作成するロールの色を[HEX](https://htmlcolorcodes.com/)で指定してね' + } ] } as const; @@ -125,7 +127,7 @@ test('multi args', () => { expect(noParamRes).toStrictEqual(['Err', ['NEED_MORE_ARGS']]); const oneParamRes = parseStrings( - ['rolecreate', '0123456789'], + ['rolecreate', '0123456789', '#bedead'], ROLE_CREATE_SCHEMA ); @@ -133,7 +135,7 @@ test('multi args', () => { 'Ok', { name: 'rolecreate', - params: ['0123456789', 'random'] + params: ['0123456789', '#bedead'] } ]); }); diff --git a/src/adaptor/proxy/command/slash.test.ts b/src/adaptor/proxy/command/slash.test.ts index 3783fc45..9b93a477 100644 --- a/src/adaptor/proxy/command/slash.test.ts +++ b/src/adaptor/proxy/command/slash.test.ts @@ -1,11 +1,12 @@ -import type { ChatInputCommandInteraction, User } from 'discord.js'; +import type { ChatInputCommandInteraction } from 'discord.js'; import { expect, test } from 'vitest'; import { parseOptions } from './slash.js'; test('no args', () => { const SERVER_INFO_SCHEMA = { - names: ['serverinfo'], + names: ['guildinfo', 'serverinfo', 'guild', 'server'], + description: '限界開発鯖の情報を持ってくるよ', subCommands: {} } as const; @@ -25,42 +26,48 @@ test('no args', () => { }); test('single arg', () => { - const TIME_OPTION = [ + const TIME_OPTIONS = [ { name: 'at', description: '', type: 'STRING' } ] as const; const KAERE_SCHEMA = { names: ['kaere'], + description: 'VC内の人類に就寝を促すよ', subCommands: { - start: { - type: 'SUB_COMMAND' - }, bed: { type: 'SUB_COMMAND_GROUP', + description: '強制切断モードを取り扱うよ', subCommands: { enable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '強制切断モードを有効化するよ' }, disable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '強制切断モードを無効化するよ' }, status: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在の強制切断モードの設定を確認するよ' } } }, reserve: { type: 'SUB_COMMAND_GROUP', + description: '予約システムを取り扱うよ', subCommands: { add: { type: 'SUB_COMMAND', - params: TIME_OPTION + description: '指定の時刻で予約するよ', + params: TIME_OPTIONS }, cancel: { type: 'SUB_COMMAND', - params: TIME_OPTION + description: '指定時刻の予約をキャンセルするよ', + params: TIME_OPTIONS }, list: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在の予約を一覧するよ' } } } @@ -85,29 +92,6 @@ test('single arg', () => { } ]); - const oneParamRes = parseOptions( - 'kaere', - { - data: [{}], - getSubcommand: () => 'start', - getSubcommandGroup: () => null - } as unknown as ChatInputCommandInteraction['options'], - KAERE_SCHEMA - ); - - expect(oneParamRes).toStrictEqual([ - 'Ok', - { - name: 'kaere', - params: [], - subCommand: { - name: 'start', - type: 'PARAMS', - params: [] - } - } - ]); - const subCommandRes = parseOptions( 'kaere', { @@ -140,28 +124,47 @@ test('single arg', () => { test('multi args', () => { const ROLE_CREATE_SCHEMA = { names: ['rolecreate'], + description: 'ロールを作成するよ', subCommands: {}, params: [ - { type: 'USER', name: 'target', description: '' }, - { type: 'STRING', name: 'color', description: '', defaultValue: 'random' } + { + type: 'STRING', + name: 'name', + description: '作成するロールの名前を指定してね' + }, + { + type: 'STRING', + name: 'color', + description: + '作成するロールの色を[HEX](https://htmlcolorcodes.com/)で指定してね' + } ] } as const; const noParamRes = parseOptions( 'rolecreate', { - getUser: () => null + getString: () => null } as unknown as ChatInputCommandInteraction['options'], ROLE_CREATE_SCHEMA ); expect(noParamRes).toStrictEqual(['Err', ['NEED_MORE_ARGS']]); + let count = 0; const oneParamRes = parseOptions( 'rolecreate', { - getUser: () => ({ id: '0123456789' }) as unknown as User, - getString: () => null + getString: () => { + ++count; + if (count === 1) { + return '0123456789'; + } + if (count === 2) { + return '#bedead'; + } + return null; + } } as unknown as ChatInputCommandInteraction['options'], ROLE_CREATE_SCHEMA ); @@ -170,7 +173,7 @@ test('multi args', () => { 'Ok', { name: 'rolecreate', - params: ['0123456789', 'random'] + params: ['0123456789', '#bedead'] } ]); }); diff --git a/src/adaptor/proxy/command/slash.ts b/src/adaptor/proxy/command/slash.ts index 6c104e37..ce1bdfb1 100644 --- a/src/adaptor/proxy/command/slash.ts +++ b/src/adaptor/proxy/command/slash.ts @@ -101,6 +101,15 @@ const parseParams = ( result.push(val); break; } + case 'CHANNEL': { + const val = + options.getChannel(param.name, false)?.id ?? param.defaultValue; + if (val === undefined) { + return ['Err', ['NEED_MORE_ARGS']]; + } + result.push(val); + break; + } case 'ROLE': { const val = options.getRole(param.name, false)?.id ?? param.defaultValue; diff --git a/src/model/command-schema.ts b/src/model/command-schema.ts index 7ad30455..da9b2ccd 100644 --- a/src/model/command-schema.ts +++ b/src/model/command-schema.ts @@ -107,6 +107,7 @@ export type ParamsValues = Equal extends true */ export interface SubCommand { type: 'SUB_COMMAND'; + description: string; params?: readonly Param[]; } @@ -145,6 +146,7 @@ export type SubCommandEntries = Record; */ export interface SubCommandGroup { type: 'SUB_COMMAND_GROUP'; + description: string; subCommands: SubCommandEntries; } @@ -155,6 +157,7 @@ export interface SubCommandGroup { */ export interface Schema { names: readonly string[]; + description: string; subCommands: SubCommandEntries; params?: readonly Param[]; } diff --git a/src/server/index.ts b/src/server/index.ts index e5174eb3..907606d8 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,8 +1,10 @@ import { generateDependencyReport } from '@discordjs/voice'; -import { Client, GatewayIntentBits, version } from 'discord.js'; +import equal from 'deep-equal'; +import { Client, GatewayIntentBits, REST, Routes, version } from 'discord.js'; import dotenv from 'dotenv'; import { join } from 'node:path'; +import { schemaToDiscordFormat } from '../adaptor/command-schema.js'; import { DiscordChannelRepository } from '../adaptor/discord/channel.js'; import { DiscordMemberStats } from '../adaptor/discord/member-stats.js'; import { DiscordMessageRepository } from '../adaptor/discord/message-repo.js'; @@ -63,9 +65,17 @@ const { MAIN_CHANNEL_ID: mainChannelId, GUILD_ID, PREFIX, - FEATURE + FEATURE, + APPLICATION_ID } = extractEnv( - ['DISCORD_TOKEN', 'MAIN_CHANNEL_ID', 'GUILD_ID', 'PREFIX', 'FEATURE'], + [ + 'DISCORD_TOKEN', + 'MAIN_CHANNEL_ID', + 'GUILD_ID', + 'PREFIX', + 'FEATURE', + 'APPLICATION_ID' + ], { PREFIX: '!', FEATURE: 'MESSAGE_CREATE,MESSAGE_UPDATE,COMMAND,VOICE_ROOM,ROLE,EMOJI' @@ -164,6 +174,96 @@ if (features.includes('COMMAND')) { }); } +const rest = new REST().setToken(token); +if (features.includes('SLASH_COMMAND')) { + const currentRegistered = (await rest.get( + Routes.applicationGuildCommands(APPLICATION_ID, GUILD_ID) + )) as unknown[]; + const currentRegisteredByName = new Map( + ( + currentRegistered as { + name: string; + id: string; + [key: string]: unknown; + }[] + ).map((obj) => [obj.name, obj]) + ); + const commands = commandRunner + .getResponders() + .flatMap((responder) => schemaToDiscordFormat(responder.schema)); + const commandNames = new Map( + (commands as { name: string }[]).map((obj) => [obj.name, obj]) + ); + + const idsNeedToDelete = [...currentRegisteredByName.keys()] + .filter((name) => !commandNames.has(name)) + .map((name) => currentRegisteredByName.get(name)?.id ?? 'unknown'); + const needToUpdate = [...currentRegisteredByName.values()].filter( + (registered) => equal(commandNames.get(registered.name) ?? {}, registered) + ); + const needToRegister = ( + commands as { name: string; [key: string]: unknown }[] + ).filter(({ name }) => !currentRegisteredByName.has(name)); + + try { + if (0 < idsNeedToDelete.length) { + console.log('コマンドの削除を開始…'); + for (let i = 0; i < idsNeedToDelete.length; ++i) { + console.log(`${i + 1}/${idsNeedToDelete.length}`); + await rest.delete( + Routes.applicationGuildCommand( + APPLICATION_ID, + GUILD_ID, + idsNeedToDelete[i] + ) + ); + } + } + + if (0 < needToUpdate.length) { + console.log('コマンドの更新を開始…'); + for (let i = 0; i < needToUpdate.length; ++i) { + console.log(`${i + 1}/${needToUpdate.length}`); + await rest.patch( + Routes.applicationGuildCommand( + APPLICATION_ID, + GUILD_ID, + needToUpdate[i].id + ), + { + body: needToUpdate[i] + } + ); + } + } + + if (0 < needToRegister.length) { + console.log('コマンドの追加を開始…'); + for (let i = 0; i < needToRegister.length; ++i) { + console.log(`${i + 1}/${needToRegister.length}`); + await rest.post( + Routes.applicationGuildCommands(APPLICATION_ID, GUILD_ID), + { + body: needToRegister[i] + } + ); + } + } + console.log('コマンドの登録に成功しました。'); + } catch (error) { + console.error(error); + } +} else { + try { + await rest.put(Routes.applicationGuildCommands(APPLICATION_ID, GUILD_ID), { + body: [] + }); + console.log('コマンドの削除に成功しました。'); + } catch (error) { + console.error(error); + } +} + const provider = new VoiceRoomProxy( client, (voiceState) => new DiscordParticipant(voiceState) diff --git a/src/service/command/channel-info.ts b/src/service/command/channel-info.ts index 24b9e28f..c9aa790b 100644 --- a/src/service/command/channel-info.ts +++ b/src/service/command/channel-info.ts @@ -12,11 +12,12 @@ export interface ChannelStatsRepository { const SCHEMA = { names: ['channel', 'chinfo', 'channelinfo'], + description: 'チャンネルの情報を調べてくるよ', subCommands: {}, params: [ { type: 'CHANNEL', - name: 'チャンネルID', + name: 'target', description: 'このIDのチャンネルを調べるよ。指定しない場合は実行したチャンネルを調べるよ', defaultValue: 'me' diff --git a/src/service/command/debug.ts b/src/service/command/debug.ts index 80f82598..5bcfd6bd 100644 --- a/src/service/command/debug.ts +++ b/src/service/command/debug.ts @@ -14,11 +14,12 @@ export interface MessageRepository { const SCHEMA = { names: ['debug'], + description: '同じチャンネル内のメッセージをコードブロックとして表示するよ', subCommands: {}, params: [ { type: 'MESSAGE', - name: 'メッセージID', + name: 'target', description: 'デバッグ表示したいメッセージのID' } ] diff --git a/src/service/command/dice.ts b/src/service/command/dice.ts index 8cd1de3c..384d0ae6 100644 --- a/src/service/command/dice.ts +++ b/src/service/command/dice.ts @@ -25,18 +25,19 @@ const choices = [...modes.map((elem) => elem[0]), ...modes] as const; const SCHEMA = { names: ['d', 'dice'], + description: 'ダイスが振れるよ', subCommands: {}, params: [ { type: 'STRING', - name: 'ダイスロール設定', + name: 'dice', description: 'どのダイスを何個振るかの指定。6面ダイス2個であれば `!dice 2d6`または`!d 2D6`のように入力してね。', defaultValue: '1d100' }, { type: 'CHOICES', - name: '詳細モード', + name: 'display_mode', description: '各ダイスの出目を表示させるかどうか。デフォルトは省略します。省略表示: `s`, `simple` 、詳細表示: `v`, `verbose`', defaultValue: 0, diff --git a/src/service/command/guild-info.ts b/src/service/command/guild-info.ts index ac5faeb6..00865512 100644 --- a/src/service/command/guild-info.ts +++ b/src/service/command/guild-info.ts @@ -70,6 +70,7 @@ export interface GuildStatsRepository { const SCHEMA = { names: ['guildinfo', 'serverinfo', 'guild', 'server'], + description: '限界開発鯖の情報を持ってくるよ', subCommands: {} } as const; diff --git a/src/service/command/gyokuon.ts b/src/service/command/gyokuon.ts index ae59d31e..86517194 100644 --- a/src/service/command/gyokuon.ts +++ b/src/service/command/gyokuon.ts @@ -12,6 +12,7 @@ export type GyokuonAssetKey = 'GYOKUON' | 'GYOKUON_SHORT'; const SCHEMA = { names: ['gyokuon'], + description: 'こるくの玉音放送を再生するよ', subCommands: {}, params: [ { diff --git a/src/service/command/help.ts b/src/service/command/help.ts index debb32f3..a5622e42 100644 --- a/src/service/command/help.ts +++ b/src/service/command/help.ts @@ -9,6 +9,7 @@ import type { const SCHEMA = { names: ['help', 'h'], + description: '搭載機能の説明を表示するよ', subCommands: {} } as const; diff --git a/src/service/command/judging.ts b/src/service/command/judging.ts index 4f459695..57d5ed14 100644 --- a/src/service/command/judging.ts +++ b/src/service/command/judging.ts @@ -35,6 +35,7 @@ const JUDGING_TITLE = '***†HARACHO ONLINE JUDGING SYSTEM†***'; const SCHEMA = { names: ['jd', 'judge'], + description: 'プログラムが適格かどうか判定してあげるよ', subCommands: {}, params: [ { diff --git a/src/service/command/kaere.ts b/src/service/command/kaere.ts index b0005ab8..486a618f 100644 --- a/src/service/command/kaere.ts +++ b/src/service/command/kaere.ts @@ -81,34 +81,43 @@ const TIME_OPTIONS = [ const SCHEMA = { names: ['kaere'], + description: 'VC内の人類に就寝を促すよ', subCommands: { bed: { type: 'SUB_COMMAND_GROUP', + description: '強制切断モードを取り扱うよ', subCommands: { enable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '強制切断モードを有効化するよ' }, disable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '強制切断モードを無効化するよ' }, status: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在の強制切断モードの設定を確認するよ' } } }, reserve: { type: 'SUB_COMMAND_GROUP', + description: '予約システムを取り扱うよ', subCommands: { add: { type: 'SUB_COMMAND', + description: '指定の時刻で予約するよ', params: TIME_OPTIONS }, cancel: { type: 'SUB_COMMAND', + description: '指定時刻の予約をキャンセルするよ', params: TIME_OPTIONS }, list: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在の予約を一覧するよ' } } } diff --git a/src/service/command/kokusei-chousa.ts b/src/service/command/kokusei-chousa.ts index 18ad2376..5288afb0 100644 --- a/src/service/command/kokusei-chousa.ts +++ b/src/service/command/kokusei-chousa.ts @@ -18,6 +18,7 @@ const SCHEMA = { 'zinnkou', 'zinkou' ], + description: '限界開発鯖の人類の数、Botの数とBot率を算出するよ', subCommands: {} } as const; diff --git a/src/service/command/meme.ts b/src/service/command/meme.ts index 0d125f09..cab117b7 100644 --- a/src/service/command/meme.ts +++ b/src/service/command/meme.ts @@ -17,6 +17,7 @@ const memesByCommandName: Record< const SCHEMA = { names: memes.flatMap((meme) => meme.commandNames), + description: '何これ……引数のテキストを構文にはめ込むみたいだよ', subCommands: {}, params: [ { diff --git a/src/service/command/party.ts b/src/service/command/party.ts index f0eb42b8..d53865fd 100644 --- a/src/service/command/party.ts +++ b/src/service/command/party.ts @@ -51,35 +51,41 @@ export interface RandomGenerator { const SCHEMA = { names: ['party'], + description: 'VC内の人類に押しかけてPartyを開くよ', subCommands: { enable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: 'ゲリラを有効化するよ' }, disable: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: 'ゲリラを無効化するよ' }, status: { - type: 'SUB_COMMAND' + type: 'SUB_COMMAND', + description: '現在のゲリラの設定を確認するよ' }, time: { type: 'SUB_COMMAND', + description: '次にゲリラを始める時間を設定するよ', params: [ { type: 'INTEGER', - name: '開始する分', + name: 'start_minutes', description: - '次にゲリラを始める分を指定できるよ。指定しなかったり負数を指定したらランダムになるよ。', + '分単位で指定できるよ。指定しなかったり負数を指定したらランダムになるよ。', defaultValue: -1 } ] }, set: { type: 'SUB_COMMAND', + description: '次の Party で再生する曲を設定するよ', params: [ { type: 'CHOICES', - name: '曲', - description: '次の Party で再生する曲を指定できるよ。', + name: 'music', + description: '再生する曲の ID だよ。', choices: assetKeys } ] diff --git a/src/service/command/ping.ts b/src/service/command/ping.ts index 15bc5e9b..2c13bb97 100644 --- a/src/service/command/ping.ts +++ b/src/service/command/ping.ts @@ -13,6 +13,7 @@ export interface Ping { const SCHEMA = { names: ['ping', 'latency'], + description: '現在のレイテンシを表示するよ', subCommands: {} } as const; diff --git a/src/service/command/role-create.ts b/src/service/command/role-create.ts index 001d079d..bb7186b6 100644 --- a/src/service/command/role-create.ts +++ b/src/service/command/role-create.ts @@ -16,16 +16,17 @@ const HEX_FORMAT = /^#?[0-9a-fA-F]{6}$/m; const SCHEMA = { names: ['rolecreate'], + description: 'ロールを作成するよ', subCommands: {}, params: [ { type: 'STRING', - name: 'ロール名', + name: 'name', description: '作成するロールの名前を指定してね' }, { type: 'STRING', - name: 'ロールの色', + name: 'color', description: '作成するロールの色を[HEX](https://htmlcolorcodes.com/)で指定してね' } diff --git a/src/service/command/role-info.ts b/src/service/command/role-info.ts index 642a3a9c..f124d61f 100644 --- a/src/service/command/role-info.ts +++ b/src/service/command/role-info.ts @@ -29,11 +29,12 @@ export interface RoleStatsRepository { const SCHEMA = { names: ['roleinfo', 'role'], + description: 'ロールの情報を調べてくるよ', subCommands: {}, params: [ { type: 'ROLE', - name: 'ロールID', + name: 'target', description: 'このIDのロールを調べるよ' } ] diff --git a/src/service/command/role-rank.ts b/src/service/command/role-rank.ts index 4f1d63f3..eae5cb4d 100644 --- a/src/service/command/role-rank.ts +++ b/src/service/command/role-rank.ts @@ -15,6 +15,7 @@ export interface MembersWithRoleRepository { const SCHEMA = { names: ['rolerank'], + description: 'メンバーごとのロール数をランキングにするよ', subCommands: {} } as const; diff --git a/src/service/command/stfu.ts b/src/service/command/stfu.ts index 43958acc..8d947b29 100644 --- a/src/service/command/stfu.ts +++ b/src/service/command/stfu.ts @@ -20,6 +20,7 @@ export interface Sheriff { const SCHEMA = { names: ['stfu'], + description: '私のうるさい発言をまとめて消すよ', subCommands: {}, params: [ { diff --git a/src/service/command/typo-record.ts b/src/service/command/typo-record.ts index bae080f9..04805fb8 100644 --- a/src/service/command/typo-record.ts +++ b/src/service/command/typo-record.ts @@ -95,15 +95,16 @@ const typoRecordResetTask = const SCHEMA = { names: ['typo'], + description: '今日の Typo「〜だカス」を表示するよ', subCommands: { by: { type: 'SUB_COMMAND', + description: 'そのユーザ ID の今日の Typo を表示するよ', params: [ { type: 'USER', - name: '表示するユーザID', - description: - 'この後にユーザ ID を入れると, そのユーザ ID の今日の Typo を表示するよ', + name: 'target', + description: '表示するユーザID', defaultValue: 'me' } ] diff --git a/src/service/command/user-info.ts b/src/service/command/user-info.ts index f7b76f0c..95c2638e 100644 --- a/src/service/command/user-info.ts +++ b/src/service/command/user-info.ts @@ -23,11 +23,12 @@ export interface UserStatsRepository { const SCHEMA = { names: ['userinfo', 'user'], + description: 'ユーザーの情報を調べてくるよ', subCommands: {}, params: [ { type: 'USER', - name: 'ユーザーID', + name: 'target', description: 'このIDのロールを調べるよ。何も入力しないと自分が対象になるよ。', defaultValue: 'me' diff --git a/src/service/command/version.ts b/src/service/command/version.ts index c0c9292a..67661933 100644 --- a/src/service/command/version.ts +++ b/src/service/command/version.ts @@ -10,6 +10,7 @@ export interface VersionFetcher { const SCHEMA = { names: ['version'], + description: '現在の私のバージョンを出力するよ', subCommands: {} } as const; diff --git a/yarn.lock b/yarn.lock index 101e265b..09f19745 100644 --- a/yarn.lock +++ b/yarn.lock @@ -984,6 +984,13 @@ __metadata: languageName: node linkType: hard +"@types/deep-equal@npm:^1.0.1": + version: 1.0.1 + resolution: "@types/deep-equal@npm:1.0.1" + checksum: 689b5737dd0a37d173d9e1231c07f70a1a9a989087b757422e1d167ec3640fd7eb8a538bd6008b3df400c4c11ed07a6c2a92d9aafc1f98ffaa04731a9442c781 + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.4 resolution: "@types/istanbul-lib-coverage@npm:2.0.4" @@ -1441,6 +1448,16 @@ __metadata: languageName: node linkType: hard +"array-buffer-byte-length@npm:^1.0.0": + version: 1.0.0 + resolution: "array-buffer-byte-length@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + is-array-buffer: ^3.0.1 + checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 + languageName: node + linkType: hard + "array-union@npm:^2.1.0": version: 2.1.0 resolution: "array-union@npm:2.1.0" @@ -1469,6 +1486,13 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.5": + version: 1.0.5 + resolution: "available-typed-arrays@npm:1.0.5" + checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -1540,6 +1564,16 @@ __metadata: languageName: node linkType: hard +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind@npm:1.0.2" + dependencies: + function-bind: ^1.1.1 + get-intrinsic: ^1.0.2 + checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 + languageName: node + linkType: hard + "callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -1839,6 +1873,32 @@ __metadata: languageName: node linkType: hard +"deep-equal@npm:^2.2.2": + version: 2.2.2 + resolution: "deep-equal@npm:2.2.2" + dependencies: + array-buffer-byte-length: ^1.0.0 + call-bind: ^1.0.2 + es-get-iterator: ^1.1.3 + get-intrinsic: ^1.2.1 + is-arguments: ^1.1.1 + is-array-buffer: ^3.0.2 + is-date-object: ^1.0.5 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.2 + isarray: ^2.0.5 + object-is: ^1.1.5 + object-keys: ^1.1.1 + object.assign: ^4.1.4 + regexp.prototype.flags: ^1.5.0 + side-channel: ^1.0.4 + which-boxed-primitive: ^1.0.2 + which-collection: ^1.0.1 + which-typed-array: ^1.1.9 + checksum: eb61c35157b6ecb96a5359b507b083fbff8ddb4c86a78a781ee38485f77a667465e45d63ee2ebd8a00e86d94c80e499906900cd82c2debb400237e1662cd5397 + languageName: node + linkType: hard + "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -1846,6 +1906,16 @@ __metadata: languageName: node linkType: hard +"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0": + version: 1.2.0 + resolution: "define-properties@npm:1.2.0" + dependencies: + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: e60aee6a19b102df4e2b1f301816804e81ab48bb91f00d0d935f269bf4b3f79c88b39e4f89eaa132890d23267335fd1140dfcd8d5ccd61031a0a2c41a54e33a6 + languageName: node + linkType: hard + "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -2004,6 +2074,23 @@ __metadata: languageName: node linkType: hard +"es-get-iterator@npm:^1.1.3": + version: 1.1.3 + resolution: "es-get-iterator@npm:1.1.3" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.3 + has-symbols: ^1.0.3 + is-arguments: ^1.1.1 + is-map: ^2.0.2 + is-set: ^2.0.2 + is-string: ^1.0.7 + isarray: ^2.0.5 + stop-iteration-iterator: ^1.0.0 + checksum: 8fa118da42667a01a7c7529f8a8cca514feeff243feec1ce0bb73baaa3514560bd09d2b3438873cf8a5aaec5d52da248131de153b28e2638a061b6e4df13267d + languageName: node + linkType: hard + "esbuild@npm:^0.18.10": version: 0.18.17 resolution: "esbuild@npm:0.18.17" @@ -2461,6 +2548,15 @@ __metadata: languageName: node linkType: hard +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: ^1.1.3 + checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 + languageName: node + linkType: hard + "foreground-child@npm:^3.1.0": version: 3.1.1 resolution: "foreground-child@npm:3.1.1" @@ -2522,6 +2618,13 @@ __metadata: languageName: node linkType: hard +"functions-have-names@npm:^1.2.3": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 + languageName: node + linkType: hard + "gauge@npm:^3.0.0": version: 3.0.2 resolution: "gauge@npm:3.0.2" @@ -2569,6 +2672,18 @@ __metadata: languageName: node linkType: hard +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1": + version: 1.2.1 + resolution: "get-intrinsic@npm:1.2.1" + dependencies: + function-bind: ^1.1.1 + has: ^1.0.3 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + checksum: 5b61d88552c24b0cf6fa2d1b3bc5459d7306f699de060d76442cce49a4721f52b8c560a33ab392cf5575b7810277d54ded9d4d39a1ea61855619ebc005aa7e5f + languageName: node + linkType: hard + "get-stream@npm:^5.0.0": version: 5.2.0 resolution: "get-stream@npm:5.2.0" @@ -2662,6 +2777,15 @@ __metadata: languageName: node linkType: hard +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: ^1.1.3 + checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + languageName: node + linkType: hard + "graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" @@ -2701,6 +2825,13 @@ __metadata: languageName: node linkType: hard +"has-bigints@npm:^1.0.1": + version: 1.0.2 + resolution: "has-bigints@npm:1.0.2" + checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b + languageName: node + linkType: hard + "has-flag@npm:^3.0.0": version: 3.0.0 resolution: "has-flag@npm:3.0.0" @@ -2715,6 +2846,38 @@ __metadata: languageName: node linkType: hard +"has-property-descriptors@npm:^1.0.0": + version: 1.0.0 + resolution: "has-property-descriptors@npm:1.0.0" + dependencies: + get-intrinsic: ^1.1.1 + checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "has-proto@npm:1.0.1" + checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0": + version: 1.0.0 + resolution: "has-tostringtag@npm:1.0.0" + dependencies: + has-symbols: ^1.0.2 + checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + languageName: node + linkType: hard + "has-unicode@npm:^2.0.1": version: 2.0.1 resolution: "has-unicode@npm:2.0.1" @@ -2871,6 +3034,17 @@ __metadata: languageName: node linkType: hard +"internal-slot@npm:^1.0.4": + version: 1.0.5 + resolution: "internal-slot@npm:1.0.5" + dependencies: + get-intrinsic: ^1.2.0 + has: ^1.0.3 + side-channel: ^1.0.4 + checksum: 97e84046bf9e7574d0956bd98d7162313ce7057883b6db6c5c7b5e5f05688864b0978ba07610c726d15d66544ffe4b1050107d93f8a39ebc59b15d8b429b497a + languageName: node + linkType: hard + "ip@npm:^2.0.0": version: 2.0.0 resolution: "ip@npm:2.0.0" @@ -2895,6 +3069,27 @@ __metadata: languageName: node linkType: hard +"is-arguments@npm:^1.1.1": + version: 1.1.1 + resolution: "is-arguments@npm:1.1.1" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27 + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": + version: 3.0.2 + resolution: "is-array-buffer@npm:3.0.2" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.0 + is-typed-array: ^1.1.10 + checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -2902,6 +3097,32 @@ __metadata: languageName: node linkType: hard +"is-bigint@npm:^1.0.1": + version: 1.0.4 + resolution: "is-bigint@npm:1.0.4" + dependencies: + has-bigints: ^1.0.1 + checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 + languageName: node + linkType: hard + +"is-boolean-object@npm:^1.1.0": + version: 1.1.2 + resolution: "is-boolean-object@npm:1.1.2" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + "is-core-module@npm:^2.1.0, is-core-module@npm:^2.5.0": version: 2.12.1 resolution: "is-core-module@npm:2.12.1" @@ -2911,6 +3132,15 @@ __metadata: languageName: node linkType: hard +"is-date-object@npm:^1.0.5": + version: 1.0.5 + resolution: "is-date-object@npm:1.0.5" + dependencies: + has-tostringtag: ^1.0.0 + checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc + languageName: node + linkType: hard + "is-decimal@npm:^1.0.0": version: 1.0.4 resolution: "is-decimal@npm:1.0.4" @@ -2962,6 +3192,22 @@ __metadata: languageName: node linkType: hard +"is-map@npm:^2.0.1, is-map@npm:^2.0.2": + version: 2.0.2 + resolution: "is-map@npm:2.0.2" + checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728 + languageName: node + linkType: hard + +"is-number-object@npm:^1.0.4": + version: 1.0.7 + resolution: "is-number-object@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -2983,6 +3229,32 @@ __metadata: languageName: node linkType: hard +"is-regex@npm:^1.1.4": + version: 1.1.4 + resolution: "is-regex@npm:1.1.4" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 + languageName: node + linkType: hard + +"is-set@npm:^2.0.1, is-set@npm:^2.0.2": + version: 2.0.2 + resolution: "is-set@npm:2.0.2" + checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "is-shared-array-buffer@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + languageName: node + linkType: hard + "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -2997,6 +3269,57 @@ __metadata: languageName: node linkType: hard +"is-string@npm:^1.0.5, is-string@npm:^1.0.7": + version: 1.0.7 + resolution: "is-string@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 + languageName: node + linkType: hard + +"is-symbol@npm:^1.0.3": + version: 1.0.4 + resolution: "is-symbol@npm:1.0.4" + dependencies: + has-symbols: ^1.0.2 + checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.10": + version: 1.1.12 + resolution: "is-typed-array@npm:1.1.12" + dependencies: + which-typed-array: ^1.1.11 + checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + languageName: node + linkType: hard + +"is-weakmap@npm:^2.0.1": + version: 2.0.1 + resolution: "is-weakmap@npm:2.0.1" + checksum: 1222bb7e90c32bdb949226e66d26cb7bce12e1e28e3e1b40bfa6b390ba3e08192a8664a703dff2a00a84825f4e022f9cd58c4599ff9981ab72b1d69479f4f7f6 + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.1": + version: 2.0.2 + resolution: "is-weakset@npm:2.0.2" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.1 + checksum: 5d8698d1fa599a0635d7ca85be9c26d547b317ed8fd83fc75f03efbe75d50001b5eececb1e9971de85fcde84f69ae6f8346bc92d20d55d46201d328e4c74a367 + languageName: node + linkType: hard + +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: bd5bbe4104438c4196ba58a54650116007fa0262eccef13a4c55b2e09a5b36b59f1e75b9fcc49883dd9d4953892e6fc007eef9e9155648ceea036e184b0f930a + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -3819,13 +4142,42 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.12.3": +"object-inspect@npm:^1.12.3, object-inspect@npm:^1.9.0": version: 1.12.3 resolution: "object-inspect@npm:1.12.3" checksum: dabfd824d97a5f407e6d5d24810d888859f6be394d8b733a77442b277e0808860555176719c5905e765e3743a7cada6b8b0a3b85e5331c530fd418cc8ae991db languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.5 + resolution: "object-is@npm:1.1.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + languageName: node + linkType: hard + +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a + languageName: node + linkType: hard + +"object.assign@npm:^4.1.4": + version: 4.1.4 + resolution: "object.assign@npm:4.1.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.4 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 + languageName: node + linkType: hard + "once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" @@ -3876,12 +4228,14 @@ __metadata: "@discordjs/voice": ^0.16.0 "@js-temporal/polyfill": ^0.4.3 "@trivago/prettier-plugin-sort-imports": ^4.1.1 + "@types/deep-equal": ^1.0.1 "@types/node": ^20.0.0 "@types/yargs": ^17.0.22 "@typescript-eslint/eslint-plugin": ^6.0.0 "@typescript-eslint/parser": ^6.0.0 "@vitest/coverage-v8": ^0.34.0 date-fns: ^2.29.3 + deep-equal: ^2.2.2 discord.js: ^14.7.1 dotenv: ^16.0.3 esbuild: ^0.19.0 @@ -4233,6 +4587,17 @@ __metadata: languageName: node linkType: hard +"regexp.prototype.flags@npm:^1.5.0": + version: 1.5.0 + resolution: "regexp.prototype.flags@npm:1.5.0" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + functions-have-names: ^1.2.3 + checksum: c541687cdbdfff1b9a07f6e44879f82c66bbf07665f9a7544c5fd16acdb3ec8d1436caab01662d2fbcad403f3499d49ab0b77fbc7ef29ef961d98cc4bc9755b4 + languageName: node + linkType: hard + "require-directory@npm:^2.1.1": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -4398,6 +4763,17 @@ __metadata: languageName: node linkType: hard +"side-channel@npm:^1.0.4": + version: 1.0.4 + resolution: "side-channel@npm:1.0.4" + dependencies: + call-bind: ^1.0.0 + get-intrinsic: ^1.0.2 + object-inspect: ^1.9.0 + checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + languageName: node + linkType: hard + "siginfo@npm:^2.0.0": version: 2.0.0 resolution: "siginfo@npm:2.0.0" @@ -4564,6 +4940,15 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.0.0": + version: 1.0.0 + resolution: "stop-iteration-iterator@npm:1.0.0" + dependencies: + internal-slot: ^1.0.4 + checksum: d04173690b2efa40e24ab70e5e51a3ff31d56d699550cfad084104ab3381390daccb36652b25755e420245f3b0737de66c1879eaa2a8d4fc0a78f9bf892fcb42 + languageName: node + linkType: hard + "streamsearch@npm:^1.1.0": version: 1.1.0 resolution: "streamsearch@npm:1.1.0" @@ -5135,6 +5520,44 @@ __metadata: languageName: node linkType: hard +"which-boxed-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "which-boxed-primitive@npm:1.0.2" + dependencies: + is-bigint: ^1.0.1 + is-boolean-object: ^1.1.0 + is-number-object: ^1.0.4 + is-string: ^1.0.5 + is-symbol: ^1.0.3 + checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e + languageName: node + linkType: hard + +"which-collection@npm:^1.0.1": + version: 1.0.1 + resolution: "which-collection@npm:1.0.1" + dependencies: + is-map: ^2.0.1 + is-set: ^2.0.1 + is-weakmap: ^2.0.1 + is-weakset: ^2.0.1 + checksum: c815bbd163107ef9cb84f135e6f34453eaf4cca994e7ba85ddb0d27cea724c623fae2a473ceccfd5549c53cc65a5d82692de418166df3f858e1e5dc60818581c + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.9": + version: 1.1.11 + resolution: "which-typed-array@npm:1.1.11" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.2 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + checksum: 711ffc8ef891ca6597b19539075ec3e08bb9b4c2ca1f78887e3c07a977ab91ac1421940505a197758fb5939aa9524976d0a5bbcac34d07ed6faa75cedbb17206 + languageName: node + linkType: hard + "which@npm:^2.0.1, which@npm:^2.0.2": version: 2.0.2 resolution: "which@npm:2.0.2"