diff --git a/package.json b/package.json index 729782c..24790a1 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@discordjs/opus": "^0.9.0", "@discordjs/voice": "^0.16.1", - "@navy.gif/commandparser": "^1.6.8", + "@navy.gif/commandparser": "^1.8.2", "@navy.gif/logger": "^2.5.4", "@navy.gif/timestring": "^6.0.6", "@types/node": "^20.11.30", diff --git a/src/client/components/Resolver.ts b/src/client/components/Resolver.ts index 023805e..358b6f4 100644 --- a/src/client/components/Resolver.ts +++ b/src/client/components/Resolver.ts @@ -1,15 +1,16 @@ -import { IResolver } from '@navy.gif/commandparser'; +import { DefaultResolver } from '@navy.gif/commandparser'; import { Channel, Guild, GuildMember, Role, User } from 'discord.js'; import DiscordClient from '../DiscordClient.js'; import { ChannelResolveable, MemberResolveable, RoleResolveable, UserResolveable } from '../../../@types/DiscordClient.js'; import Util from '../../utilities/Util.js'; import timestring from '@navy.gif/timestring'; -class Resolver implements IResolver +class Resolver extends DefaultResolver { #client: DiscordClient; constructor (client: DiscordClient) { + super(); this.#client = client; } @@ -71,7 +72,7 @@ class Resolver implements IResolver return resolved; } - async resolveUser (resolveable: UserResolveable, strict?: boolean): Promise + override async resolveUser (resolveable: UserResolveable, strict?: boolean): Promise { if (!resolveable) return null; @@ -151,7 +152,7 @@ class Resolver implements IResolver return resolved; } - async resolveMember (resolveable: MemberResolveable, strict = false, guild: G) + override async resolveMember (resolveable: MemberResolveable, strict = false, guild: G) { if (!resolveable) return null; @@ -225,7 +226,7 @@ class Resolver implements IResolver return resolved; } - async resolveChannel ( + override async resolveChannel ( resolveable: ChannelResolveable, strict?: boolean, guild?: G | null, filter?: (channel: Channel) => boolean ) @@ -286,7 +287,7 @@ class Resolver implements IResolver return resolved; } - async resolveRole (resolveable: RoleResolveable, strict = false, guild: G | null) + override async resolveRole (resolveable: RoleResolveable, strict = false, guild: G | null) { if (!resolveable) return null; @@ -296,7 +297,7 @@ class Resolver implements IResolver return (result as R) || null; } - resolveBoolean (input: string | boolean) + override resolveBoolean (input: string | boolean) { // Ensure input is a string input = `${input}`.toLowerCase(); @@ -315,7 +316,7 @@ class Resolver implements IResolver } - resolveTime (string: string): number | null + override resolveTime (string: string): number | null { let time = null; try diff --git a/src/client/components/commands/List.ts b/src/client/components/commands/List.ts index 0abfb90..ccd574d 100644 --- a/src/client/components/commands/List.ts +++ b/src/client/components/commands/List.ts @@ -1,4 +1,4 @@ -import { CommandOpts, OptionType } from '@navy.gif/commandparser'; +import { CommandArgs, OptionType } from '@navy.gif/commandparser'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; import { Message } from 'discord.js'; @@ -24,10 +24,10 @@ class ListCommand extends Command }); } - async execute (_message: Message, { subcommand, args }: CommandOpts) + async execute (_message: Message, { subCommand, map }: CommandArgs) { - const { all } = args; - if (subcommand === 'commands') + const [ all ] = map.get('all') ?? []; + if (subCommand === 'commands') return this.#listCommands(all?.value as boolean); return 'Invalid subcommand'; } diff --git a/src/client/components/commands/Queue.ts b/src/client/components/commands/Queue.ts index f504fbc..d5884a2 100644 --- a/src/client/components/commands/Queue.ts +++ b/src/client/components/commands/Queue.ts @@ -1,7 +1,7 @@ import { Message } from 'discord.js'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; -import { CommandOpts, OptionType } from '@navy.gif/commandparser'; +import { CommandArgs, OptionType } from '@navy.gif/commandparser'; class QueueCommand extends Command { @@ -24,12 +24,12 @@ class QueueCommand extends Command }); } - async execute (message: Message, { args }: CommandOpts) + async execute (message: Message, { map }: CommandArgs) { const { member, guild } = message; const { me } = guild.members; - if (!Object.keys(args).length) + if (!map.size) { const { queue, current } = this.client.musicPlayer; const base = `**Now playing:** \`${current?.title} by ${current?.artist}\`\n`; @@ -41,10 +41,13 @@ class QueueCommand extends Command if (!member?.voice || member.voice.channelId !== me?.voice.channelId) return 'Only vc participants can queue songs'; + const [ song ]= map.get('song') ?? []; + const [ artist ]= map.get('artist') ?? []; + const [ id ]= map.get('id') ?? []; const query = { - title: args.song?.value as string | undefined, - artist: args.artist?.value as string | undefined, - id: args.id?.value as number | undefined + title: song?.value as string | undefined, + artist: artist?.value as string | undefined, + id: id?.value as number | undefined }; const result = this.client.musicPlayer.queueSong(query); diff --git a/src/client/components/commands/Request.ts b/src/client/components/commands/Request.ts index 909cc25..400a9cf 100644 --- a/src/client/components/commands/Request.ts +++ b/src/client/components/commands/Request.ts @@ -1,6 +1,6 @@ import assert from 'node:assert'; import { Message } from 'discord.js'; -import { CommandOpts } from '@navy.gif/commandparser'; +import { CommandArgs } from '@navy.gif/commandparser'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; import MusicPlayerError from '../../../errors/MusicPlayerError.js'; @@ -17,20 +17,22 @@ class RequestCommand extends Command sameVc: true, showUsage: true, options: [{ - name: 'link' + name: 'link', + required: true }] }); } - async execute (message: Message, { args }: CommandOpts) + async execute (message: Message, { map }: CommandArgs) { const { author } = message; - assert(args.link); - this.logger.info(`${author.displayName} (${author.id}) is requesting ${args.link.value}`); + const [ link ]= map.get('link') ?? []; + assert(link); + this.logger.info(`${author.displayName} (${author.id}) is requesting ${link.value}`); const response = await message.reply('Processing request, song will be queued after download'); try { - const result = await this.client.musicPlayer.request(args.link.value as string); + const result = await this.client.musicPlayer.request(link.value as string); if (!result) return response.edit('Failed to download song'); return response.edit(`Successfully downloaded and queued **${result.title}** by ${result.artist}`); diff --git a/src/client/components/commands/Rescan.ts b/src/client/components/commands/Rescan.ts index bc2302c..130444c 100644 --- a/src/client/components/commands/Rescan.ts +++ b/src/client/components/commands/Rescan.ts @@ -1,7 +1,7 @@ import { Message } from 'discord.js'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; -import { CommandOpts, OptionType } from '@navy.gif/commandparser'; +import { CommandArgs, OptionType } from '@navy.gif/commandparser'; class PingCommand extends Command { @@ -21,9 +21,10 @@ class PingCommand extends Command }); } - async execute (_message: Message, { args }: CommandOpts) + async execute (_message: Message, args: CommandArgs) { - const diff = await this.client.musicPlayer.library.scanLibrary(args.rebuild?.value as boolean); + const [ rebuild ] = args.map.get('rebuild') ?? []; + const diff = await this.client.musicPlayer.library.scanLibrary(rebuild?.value as boolean); const songs = this.client.musicPlayer.library.size; this.client.musicPlayer.reshuffle(); return `Found ${songs} tracks with ${diff} new ones`; diff --git a/src/client/components/commands/Search.ts b/src/client/components/commands/Search.ts index 14395b1..6b5311a 100644 --- a/src/client/components/commands/Search.ts +++ b/src/client/components/commands/Search.ts @@ -1,7 +1,7 @@ import { Message } from 'discord.js'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; -import { CommandOpts } from '@navy.gif/commandparser'; +import { CommandArgs } from '@navy.gif/commandparser'; class SearchCommand extends Command { @@ -24,12 +24,15 @@ class SearchCommand extends Command }); } - async execute (_message: Message, { args }: CommandOpts) + async execute (_message: Message, { map }: CommandArgs) { + const [ song ] = map.get('song') ?? []; + const [ artist ] = map.get('artist') ?? []; + const [ keyword ] = map.get('keyword') ?? []; const query = { - title: args.song?.value as string | undefined, - artist: args.artist?.value as string | undefined, - keyword: args.keyword?.value as string | undefined + title: song?.value as string | undefined, + artist: artist?.value as string | undefined, + keyword: keyword?.value as string | undefined }; const results = this.client.musicPlayer.library.search(query); diff --git a/src/client/components/commands/SetAvatar.ts b/src/client/components/commands/SetAvatar.ts index c4d2583..b65492f 100644 --- a/src/client/components/commands/SetAvatar.ts +++ b/src/client/components/commands/SetAvatar.ts @@ -1,4 +1,4 @@ -import { ArgsResult, CommandOpts, OptionType } from '@navy.gif/commandparser'; +import { CommandArgs, CommandOption, OptionType } from '@navy.gif/commandparser'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; import { Message } from 'discord.js'; @@ -22,16 +22,16 @@ class SetAvatarCommand extends Command }); } - async execute (message: Message, { subcommand, args }: CommandOpts) + async execute (message: Message, { subCommand, ...args }: CommandArgs) { - if (subcommand === 'avatar') - return this.#setAvatar(message, args); + if (subCommand === 'avatar') + return this.#setAvatar(message, args.map); return 'Unknown subcommand'; } - async #setAvatar (_message: Message, args : ArgsResult) + async #setAvatar (_message: Message, args : Map) { - const { asset } = args; + const [ asset ] = args.get('asset') ?? []; if (!asset?.value) return 'Missing value'; await this.client.user?.setAvatar(asset.value as string); diff --git a/src/client/components/commands/Stats.ts b/src/client/components/commands/Stats.ts index 2ba5e28..b9a9205 100644 --- a/src/client/components/commands/Stats.ts +++ b/src/client/components/commands/Stats.ts @@ -1,4 +1,4 @@ -import { CommandOpts, OptionType } from '@navy.gif/commandparser'; +import { CommandArgs, OptionType } from '@navy.gif/commandparser'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; import { Message } from 'discord.js'; @@ -23,9 +23,10 @@ class StatsCommand extends Command }); } - async execute (_message: Message, { args }: CommandOpts) + async execute (_message: Message, args: CommandArgs) { - if (args.reset?.value) + const [ reset ] = args.map.get('reset') ?? []; + if (reset?.value) { this.client.musicPlayer.library.resetStats(); return 'Stats reset'; diff --git a/src/client/components/commands/Volume.ts b/src/client/components/commands/Volume.ts index 5f61c4b..df0278b 100644 --- a/src/client/components/commands/Volume.ts +++ b/src/client/components/commands/Volume.ts @@ -1,4 +1,4 @@ -import { CommandOpts, OptionType } from '@navy.gif/commandparser'; +import { CommandArgs, OptionType } from '@navy.gif/commandparser'; import Command from '../../../interfaces/Command.js'; import DiscordClient from '../../DiscordClient.js'; import { Message } from 'discord.js'; @@ -27,9 +27,9 @@ class VolumeCommand extends Command }); } - async execute (message: Message, { args }: CommandOpts) + async execute (message: Message, args: CommandArgs) { - const { volume } = args; + const [ volume ] = args.map.get('volume') ?? []; if (!volume) return `Volume is currently at ${this.client.musicPlayer.volume}`; diff --git a/src/client/components/observers/CommandHandler.ts b/src/client/components/observers/CommandHandler.ts index 7b2efc3..e87f960 100644 --- a/src/client/components/observers/CommandHandler.ts +++ b/src/client/components/observers/CommandHandler.ts @@ -1,7 +1,7 @@ import { inspect } from 'node:util'; import { APIEmbed, ChannelType, DiscordAPIError, EmbedBuilder, Events, Message, MessagePayload } from 'discord.js'; -import { CommandOpts, ICommand, OptionType, Parser, ParserError } from '@navy.gif/commandparser'; +import { CommandArgs, ICommand, OptionType, Parser, ParserError } from '@navy.gif/commandparser'; import Observer from '../../../interfaces/Observer.js'; import DiscordClient from '../../DiscordClient.js'; @@ -131,7 +131,7 @@ class CommandHandler extends Observer }); } - const restrictedArgs = Object.values(rest.args).filter((arg) => (arg as ExtendedCommandOption).restricted); + const restrictedArgs = Object.values(rest.options).filter((arg) => (arg as ExtendedCommandOption).restricted); const insufficientPerms = (restrictedArgs.length && !this.client.isDeveloper(author)); if (insufficientPerms) { @@ -146,10 +146,10 @@ class CommandHandler extends Observer }); } - if (rest.globalFlags.help) + if (rest.globalFlags.find(val => val.name === 'help')) return this.#showUsage(message, command as Command, rest); - if ((command as Command).showUsage && !Object.keys(rest.args).length && !rest.subcommand && !rest.subcommandGroup) + if ((command as Command).showUsage && !rest.options.length && !rest.subCommand && !rest.subCommandGroup) return this.#showUsage(message, command as Command, rest); this.#executeCommand(message, command, rest); @@ -169,7 +169,7 @@ class CommandHandler extends Observer return errors.sort((a, b) => a.inhibitor.priority - b.inhibitor.priority); } - async #executeCommand (message: Message, command: ICommand, rest: CommandOpts) + async #executeCommand (message: Message, command: ICommand, rest: CommandArgs) { let response: string | APIEmbed | null | unknown = null; try @@ -252,14 +252,14 @@ class CommandHandler extends Observer } } - #showUsage (message: Message, command: Command, opts: CommandOpts): void | PromiseLike + #showUsage (message: Message, command: Command, opts: CommandArgs): void | PromiseLike { - const { subcommand, subcommandGroup } = opts; + const { subCommand, subCommandGroup } = opts; let sbcmdstr = ''; - if (subcommandGroup) - sbcmdstr += `${subcommand}`; - if (subcommand) - sbcmdstr += ` ${subcommand}`; + if (subCommandGroup) + sbcmdstr += `${subCommand}`; + if (subCommand) + sbcmdstr += ` ${subCommand}`; sbcmdstr = sbcmdstr.trim(); let { options } = command; @@ -273,14 +273,14 @@ class CommandHandler extends Observer USAGE: \`${usageStr.trim()} [FLAGS]\` `; - if (subcommand) + if (subCommand) { - const sbcmd = command.subcommand(subcommand); + const sbcmd = command.subcommand(subCommand); ({ options } = sbcmd!); } - else if (subcommandGroup) + else if (subCommandGroup) { - const group = command.subcommandGroup(subcommandGroup); + const group = command.subcommandGroup(subCommandGroup); ({ options } = group!); } const flags = options.filter(option => option.flag); diff --git a/src/interfaces/Command.ts b/src/interfaces/Command.ts index 19110e8..9de9c9e 100644 --- a/src/interfaces/Command.ts +++ b/src/interfaces/Command.ts @@ -1,4 +1,4 @@ -import { ICommand, OptionType, SubcommandOption, SubcommandGroupOption, CommandOpts, CommandOption } from '@navy.gif/commandparser'; +import { ICommand, OptionType, SubcommandOption, SubcommandGroupOption, CommandArgs, CommandOption } from '@navy.gif/commandparser'; import { LoggerClient } from '@navy.gif/logger'; import Component from './Component.js'; import { Snowflake, User } from 'discord.js'; @@ -60,7 +60,7 @@ abstract class Command extends Component implements ICommand } - abstract execute(message: unknown, args: CommandOpts): Promise; + abstract execute(message: unknown, args: CommandArgs): Promise; protected get logger () { diff --git a/yarn.lock b/yarn.lock index 78baa64..9845d0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1628,10 +1628,12 @@ __metadata: languageName: node linkType: hard -"@navy.gif/commandparser@npm:^1.6.8": - version: 1.6.8 - resolution: "@navy.gif/commandparser@npm:1.6.8" - checksum: 10/53f2d4f9a8f98a83d2304297bcabbe7defe5cf5500024f9d9c63efb4d0e631fe6545b2621421b43f05f8e9af1a2dad3ac79b5898faceb995fbb5b7db2cb3bb1d +"@navy.gif/commandparser@npm:^1.8.2": + version: 1.8.2 + resolution: "@navy.gif/commandparser@npm:1.8.2" + dependencies: + "@navy.gif/timestring": "npm:^6.0.6" + checksum: 10/d1b9f6bd661b4a1e320037e651cf083202f3525957e0e70d011ecaa6865ca3c95a066b5aad13fdebf1143a2714fe3d223cb75fe4f50488c67f05eae49bdd7088 languageName: node linkType: hard @@ -3577,7 +3579,7 @@ __metadata: "@babel/preset-typescript": "npm:^7.24.1" "@discordjs/opus": "npm:^0.9.0" "@discordjs/voice": "npm:^0.16.1" - "@navy.gif/commandparser": "npm:^1.6.8" + "@navy.gif/commandparser": "npm:^1.8.2" "@navy.gif/logger": "npm:^2.5.4" "@navy.gif/timestring": "npm:^6.0.6" "@types/babel__core": "npm:^7"