Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Add /help command to list all available commands.

## [2.11.5] - 2026-06-04

- Fix queue-empty crashes when auto-announce is enabled or playback ends without a next song.
Expand Down
2 changes: 2 additions & 0 deletions src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export default class {
}
}

this.commandsByName.get('help')?.setCommands?.([...this.commandsByName.values()]);

// Register event handlers
// eslint-disable-next-line complexity
this.client.on('interactionCreate', async interaction => {
Expand Down
25 changes: 25 additions & 0 deletions src/commands/help.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {ChatInputCommandInteraction} from 'discord.js';
import {injectable} from 'inversify';
import Command from './index.js';
import {SlashCommandBuilder} from '@discordjs/builders';

@injectable()
export default class implements Command {
public readonly slashCommand = new SlashCommandBuilder()
.setName('help')
.setDescription('shows all available commands');

private commands: Command[] = [];

public setCommands(commands: Command[]) {
this.commands = commands;
}

public async execute(interaction: ChatInputCommandInteraction): Promise<void> {
const commandList = this.commands
.map(c => `**/${c.slashCommand.name ?? ''}** — ${c.slashCommand.description ?? ''}`)
.join('\n');

await interaction.reply({content: commandList, ephemeral: true});
}
}
1 change: 1 addition & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export default interface Command {
execute: (interaction: ChatInputCommandInteraction) => Promise<void>;
handleButtonInteraction?: (interaction: ButtonInteraction) => Promise<void>;
handleAutocompleteInteraction?: (interaction: AutocompleteInteraction) => Promise<void>;
setCommands?: (commands: Command[]) => void;
}
2 changes: 2 additions & 0 deletions src/inversify.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import Skip from './commands/skip.js';
import Stop from './commands/stop.js';
import Unskip from './commands/unskip.js';
import Volume from './commands/volume.js';
import Help from './commands/help.js';
import ThirdParty from './services/third-party.js';
import FileCacheProvider from './services/file-cache.js';
import KeyValueCacheProvider from './services/key-value-cache.js';
Expand Down Expand Up @@ -96,6 +97,7 @@ if (config.SPOTIFY_CLIENT_ID !== '' && config.SPOTIFY_CLIENT_SECRET !== '') {
Stop,
Unskip,
Volume,
Help,
].forEach(command => {
container.bind<Command>(TYPES.Command).to(command).inSingletonScope();
});
Expand Down