Skip to content

Commit 67393b8

Browse files
authored
Merge pull request #274 from underctrl-io/fix-command-aliases
fix: command handler bugs
2 parents dc08c94 + 0c30645 commit 67393b8

File tree

13 files changed

+154
-56
lines changed

13 files changed

+154
-56
lines changed

apps/test-bot/src/app/commands/(developer)/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const command: CommandData = {
99
name: 'server',
1010
description: 'server command',
1111
guilds: [process.env.DEV_GUILD_ID!],
12+
aliases: ['s', 'serv'],
1213
};
1314

1415
export const chatInput: ChatInputCommand = async (ctx) => {

apps/test-bot/src/app/commands/(general)/components-test.tsx renamed to apps/test-bot/src/app/commands/(general)/componentsTest.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import {
22
ChatInputCommand,
33
CommandData,
44
Container,
5+
MessageCommand,
56
TextDisplay,
67
} from 'commandkit';
78
import { Colors, MessageFlags } from 'discord.js';
89

910
export const command: CommandData = {
1011
name: 'components-test',
1112
description: 'Test components v2 again',
13+
aliases: ['ct'],
1214
};
1315

1416
export const chatInput: ChatInputCommand = async (ctx) => {
@@ -20,6 +22,19 @@ export const chatInput: ChatInputCommand = async (ctx) => {
2022

2123
await ctx.interaction.reply({
2224
components: [container],
25+
flags: MessageFlags.IsComponentsV2,
26+
});
27+
};
28+
29+
export const message: MessageCommand = async (ctx) => {
30+
const container = (
31+
<Container accentColor={Colors.Fuchsia}>
32+
<TextDisplay content="# CommandKit Components v2 test" />
33+
</Container>
34+
);
35+
36+
await ctx.message.reply({
37+
components: [container],
2338

2439
flags: MessageFlags.IsComponentsV2,
2540
});

packages/commandkit/logger.cjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
const { DefaultLogger } = require('./dist/logger/DefaultLogger.js');
22
const { Logger, createLogger } = require('./dist/logger/Logger.js');
3+
const { NoopLogger } = require('./dist/logger/NoopLogger.js');
34

45
module.exports = {
56
DefaultLogger,
67
Logger,
78
createLogger,
9+
NoopLogger,
810
useLogger(logger) {
911
Logger.configure({ provider: logger });
1012
},

packages/commandkit/logger.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
export * from './dist/logger/DefaultLogger';
22
export * from './dist/logger/Logger';
33
export * from './dist/logger/ILogger';
4+
export * from './dist/logger/NoopLogger';
5+
6+
import type { ILogger } from './dist/logger/ILogger';
47

58
/**
69
* Use a custom logger provider.

packages/commandkit/src/CommandKit.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { Logger } from './logger/Logger';
2121
import { AsyncFunction, GenericFunction } from './context/async-context';
2222
import { FlagStore } from './flags/store';
2323
import { AnalyticsEngine } from './analytics/analytics-engine';
24+
import { ResolvedCommandKitConfig } from './config/utils';
25+
import { getConfig } from './config/config';
2426

2527
/**
2628
* Configurations for the CommandKit instance.
@@ -110,11 +112,16 @@ export class CommandKit extends EventEmitter {
110112
/**
111113
* The configuration for the CommandKit instance.
112114
*/
113-
public readonly config: CommandKitConfiguration = {
115+
public readonly appConfig: CommandKitConfiguration = {
114116
defaultLocale: Locale.EnglishUS,
115117
getMessageCommandPrefix: () => '!',
116118
};
117119

120+
/**
121+
* The configuration for the CommandKit environment.
122+
*/
123+
public config: ResolvedCommandKitConfig = getConfig();
124+
118125
/**
119126
* A key-value store for storing arbitrary data.
120127
*/
@@ -178,6 +185,9 @@ export class CommandKit extends EventEmitter {
178185

179186
super();
180187

188+
// lazily load the actual config file
189+
loadConfigFile().then((config) => (this.config = config));
190+
181191
if (!CommandKit.instance) {
182192
CommandKit.instance = this;
183193
}
@@ -313,7 +323,7 @@ export class CommandKit extends EventEmitter {
313323
setPrefixResolver(
314324
resolver: (message: Message) => Awaitable<string | string[]>,
315325
) {
316-
this.config.getMessageCommandPrefix = resolver;
326+
this.appConfig.getMessageCommandPrefix = resolver;
317327
return this;
318328
}
319329

@@ -322,7 +332,7 @@ export class CommandKit extends EventEmitter {
322332
* @param locale The default locale.
323333
*/
324334
setDefaultLocale(locale: Locale) {
325-
this.config.defaultLocale = locale;
335+
this.appConfig.defaultLocale = locale;
326336
return this;
327337
}
328338

packages/commandkit/src/app/commands/Context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ export class Context<
500500
const locale = preferUser ? this.getUserLocale() : this.getGuildLocale();
501501

502502
if (!locale) {
503-
return this.commandkit.config.defaultLocale;
503+
return this.commandkit.appConfig.defaultLocale;
504504
}
505505

506506
return locale;

packages/commandkit/src/app/handlers/AppCommandHandler.ts

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export interface AppCommandNative {
4949
* Custom properties that can be added to an AppCommand.
5050
* This allows for additional metadata or configuration to be associated with a command.
5151
*/
52-
// export type CustomAppCommandProps = Record<string, any>;
5352
export interface CustomAppCommandProps {
5453
[key: string]: any;
5554
}
@@ -160,19 +159,6 @@ export class AppCommandHandler {
160159
*/
161160
private loadedMiddlewares = new Collection<string, LoadedMiddleware>();
162161

163-
// Name-to-ID mapping for easier lookup
164-
/**
165-
* @private
166-
* @internal
167-
*/
168-
private commandNameToId = new Map<string, string>();
169-
170-
/**
171-
* @private
172-
* @internal
173-
*/
174-
private subcommandPathToId = new Map<string, string>();
175-
176162
/**
177163
* Command registrar for handling Discord API registration.
178164
*/
@@ -434,7 +420,7 @@ export class AppCommandHandler {
434420
if (source.author.bot) return null;
435421

436422
const prefix =
437-
await this.commandkit.config.getMessageCommandPrefix(source);
423+
await this.commandkit.appConfig.getMessageCommandPrefix(source);
438424

439425
if (!prefix || !prefix.length) return null;
440426

@@ -443,11 +429,18 @@ export class AppCommandHandler {
443429
Array.isArray(prefix) ? prefix : [prefix],
444430
(command: string) => {
445431
// Find the command by name
446-
const commandId = this.commandNameToId.get(command);
447-
if (!commandId) return null;
448-
449-
const loadedCommand = this.loadedCommands.get(commandId);
450-
if (!loadedCommand) return null;
432+
const loadedCommand = this.findCommandByName(command);
433+
if (!loadedCommand) {
434+
if (
435+
COMMANDKIT_IS_DEV &&
436+
this.commandkit.config.showUnknownPrefixCommandsWarning
437+
) {
438+
Logger.error(
439+
`Prefix command "${command}" was not found.\nNote: This warning is only shown in development mode as an alert to help you find the command. If you wish to remove this warning, set \`showUnknownPrefixCommandsWarning\` to \`false\` in your commandkit config.`,
440+
);
441+
}
442+
return null;
443+
}
451444

452445
if (
453446
source.guildId &&
@@ -498,10 +491,7 @@ export class AppCommandHandler {
498491
}
499492

500493
// Find the command by name
501-
const commandId = this.commandNameToId.get(cmdName);
502-
if (!commandId) return null;
503-
504-
const loadedCommand = this.loadedCommands.get(commandId);
494+
const loadedCommand = this.findCommandByName(cmdName);
505495
if (!loadedCommand) return null;
506496

507497
// If this is a guild specific command, check if we're in the right guild
@@ -534,14 +524,32 @@ export class AppCommandHandler {
534524
};
535525
}
536526

527+
/**
528+
* Finds a command by name.
529+
* @param name - The command name to search for
530+
* @returns The loaded command or null if not found
531+
*/
532+
private findCommandByName(name: string): LoadedCommand | null {
533+
for (const [, loadedCommand] of this.loadedCommands) {
534+
if (loadedCommand.data.command.name === name) {
535+
return loadedCommand;
536+
}
537+
538+
// Check aliases for prefix commands
539+
const aliases = loadedCommand.data.command.aliases;
540+
if (aliases && Array.isArray(aliases) && aliases.includes(name)) {
541+
return loadedCommand;
542+
}
543+
}
544+
return null;
545+
}
546+
537547
/**
538548
* Reloads all commands and middleware from scratch.
539549
*/
540550
public async reloadCommands() {
541551
this.loadedCommands.clear();
542552
this.loadedMiddlewares.clear();
543-
this.commandNameToId.clear();
544-
this.subcommandPathToId.clear();
545553
this.externalCommandData.clear();
546554
this.externalMiddlewareData.clear();
547555

@@ -589,7 +597,6 @@ export class AppCommandHandler {
589597
public async registerExternalLoadedCommands(data: LoadedCommand[]) {
590598
for (const command of data) {
591599
this.loadedCommands.set(command.command.id, command);
592-
this.commandNameToId.set(command.command.name, command.command.id);
593600
}
594601
}
595602

@@ -629,12 +636,17 @@ export class AppCommandHandler {
629636

630637
// generate types
631638
if (COMMANDKIT_IS_DEV) {
639+
const commandNames = Array.from(this.loadedCommands.values()).map(
640+
(v) => v.data.command.name,
641+
);
642+
const aliases = Array.from(this.loadedCommands.values()).flatMap(
643+
(v) => v.data.command.aliases || [],
644+
);
645+
646+
const allNames = [...commandNames, ...aliases];
647+
632648
await rewriteCommandDeclaration(
633-
`type CommandTypeData = ${Array.from(
634-
this.loadedCommands
635-
.mapValues((v) => JSON.stringify(v.command.name))
636-
.values(),
637-
).join(' | ')}`,
649+
`type CommandTypeData = ${allNames.map((name) => JSON.stringify(name)).join(' | ')}`,
638650
);
639651
}
640652

@@ -707,13 +719,18 @@ export class AppCommandHandler {
707719
);
708720
}
709721

710-
if (
711-
(!commandFileData.command.type ||
712-
commandFileData.command.type === ApplicationCommandType.ChatInput) &&
713-
!commandFileData.command.description
714-
) {
715-
commandFileData.command.description = `${command.name} command`;
716-
}
722+
// Apply the specified logic for name and description
723+
const commandName = commandFileData.command.name || command.name;
724+
const commandDescription =
725+
commandFileData.command.description || `${commandName} command`;
726+
727+
// Update the command data with resolved name and description
728+
const updatedCommandData = {
729+
...commandFileData.command,
730+
name: commandName,
731+
description: commandDescription,
732+
aliases: commandFileData.command.aliases,
733+
} as CommandData;
717734

718735
let handlerCount = 0;
719736

@@ -743,13 +760,13 @@ export class AppCommandHandler {
743760
);
744761
}
745762

746-
let lastUpdated = commandFileData.command;
763+
let lastUpdated = updatedCommandData;
747764

748765
await this.commandkit.plugins.execute(async (ctx, plugin) => {
749766
const res = await plugin.prepareCommand(ctx, lastUpdated);
750767

751768
if (res) {
752-
lastUpdated = res;
769+
lastUpdated = res as CommandData;
753770
}
754771
});
755772

@@ -758,12 +775,12 @@ export class AppCommandHandler {
758775
guilds: commandFileData.command.guilds,
759776
data: {
760777
...commandFileData,
761-
command: 'toJSON' in lastUpdated ? lastUpdated.toJSON() : lastUpdated,
778+
command:
779+
'toJSON' in lastUpdated && typeof lastUpdated.toJSON === 'function'
780+
? lastUpdated.toJSON()
781+
: lastUpdated,
762782
},
763783
});
764-
765-
// Map command name to ID for easier lookup
766-
this.commandNameToId.set(command.name, id);
767784
} catch (error) {
768785
Logger.error(`Failed to load command ${command.name} (${id})`, error);
769786
}

packages/commandkit/src/cli/development.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,17 +223,21 @@ export async function bootstrapDevelopmentServer(configPath?: string) {
223223
console.error(e);
224224
});
225225

226-
ps = await buildAndStart(cwd);
227-
228-
const end = performance.now();
229-
230-
console.log(
231-
`${colors.greenBright('Development server started in')} ${colors.yellowBright(`${(end - start).toFixed(2)}ms`)}
226+
console.log(`${colors.greenBright('Bootstrapped CommandKit Development Environment in')} ${colors.yellowBright(`${(performance.now() - start).toFixed(2)}ms`)}
232227
${colors.greenBright('Watching for changes in')} ${colors.yellowBright('src')} ${colors.greenBright('directory')}
233228
234229
${colors.greenBright('Commands:')}
235230
${colors.yellowBright('r')} - Restart the server
236231
${colors.yellowBright('rc')} - Reload all commands
237-
${colors.yellowBright('re')} - Reload all events`,
232+
${colors.yellowBright('re')} - Reload all events`);
233+
234+
const buildStart = performance.now();
235+
236+
ps = await buildAndStart(cwd);
237+
238+
const buildEnd = performance.now();
239+
240+
console.log(
241+
`\n${colors.greenBright('Development mode compilation took')} ${colors.yellowBright(`${(buildEnd - buildStart).toFixed(2)}ms`)}\n`,
238242
);
239243
}

packages/commandkit/src/config/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ export function defineConfig(
5656
},
5757
disablePrefixCommands:
5858
config.disablePrefixCommands ?? defaultConfig.disablePrefixCommands,
59+
showUnknownPrefixCommandsWarning:
60+
config.showUnknownPrefixCommandsWarning ??
61+
defaultConfig.showUnknownPrefixCommandsWarning,
5962
};
6063

6164
return defined;

packages/commandkit/src/config/default.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ export const defaultConfig: ResolvedCommandKitConfig = {
2525
},
2626
typedCommands: true,
2727
disablePrefixCommands: false,
28+
showUnknownPrefixCommandsWarning: true,
2829
};

packages/commandkit/src/config/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,9 @@ export interface CommandKitConfig {
7171
* @default false
7272
*/
7373
disablePrefixCommands?: boolean;
74+
/**
75+
* Whether or not to show a warning when a prefix command is not found. This only affects development mode.
76+
* @default true
77+
*/
78+
showUnknownPrefixCommandsWarning?: boolean;
7479
}

0 commit comments

Comments
 (0)