Skip to content

Commit 34193ef

Browse files
authoredJan 13, 2024
fix(ApplicationCommandRegistries): add the right ids in the right place (#716)
* fix(ApplicationCommandRegistries): add the right ids in the right place Doesn't break anything funnily enough but its technically wrong * fix: proper fix for the issue * chore: proper split * chore: dumbass 100 * chore: document commandName * chore: kyra nits
1 parent d41991c commit 34193ef

File tree

2 files changed

+123
-48
lines changed

2 files changed

+123
-48
lines changed
 

‎src/lib/utils/application-commands/ApplicationCommandRegistries.ts

+25-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
/* eslint-disable @typescript-eslint/dot-notation */
12
import { container } from '@sapphire/pieces';
23
import type { RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v10';
3-
import type { ApplicationCommandManager } from 'discord.js';
4+
import { ApplicationCommandType, type ApplicationCommandManager } from 'discord.js';
45
import type { Command } from '../../structures/Command';
56
import type { CommandStore } from '../../structures/CommandStore';
6-
import { RegisterBehavior } from '../../types/Enums';
7+
import { InternalRegistryAPIType, RegisterBehavior } from '../../types/Enums';
78
import { Events } from '../../types/Events';
89
import { ApplicationCommandRegistry } from './ApplicationCommandRegistry';
910
import { getNeededRegistryParameters } from './getNeededParameters';
@@ -125,8 +126,17 @@ export async function handleBulkOverwrite(commandStore: CommandStore, applicatio
125126
if (piece) {
126127
const registry = piece.applicationCommandRegistry;
127128

128-
registry.globalCommandId = id;
129-
registry.addChatInputCommandIds(id);
129+
switch (globalCommand.type) {
130+
case ApplicationCommandType.ChatInput: {
131+
registry['handleIdAddition'](InternalRegistryAPIType.ChatInput, id);
132+
break;
133+
}
134+
case ApplicationCommandType.User:
135+
case ApplicationCommandType.Message: {
136+
registry['handleIdAddition'](InternalRegistryAPIType.ContextMenu, id);
137+
break;
138+
}
139+
}
130140

131141
// idHints are useless, and any manually added id or names could end up not being valid any longer if you use bulk overwrites
132142
// That said, this might be an issue, so we might need to do it like `handleAppendOrUpdate`
@@ -161,9 +171,18 @@ export async function handleBulkOverwrite(commandStore: CommandStore, applicatio
161171

162172
if (piece) {
163173
const registry = piece.applicationCommandRegistry;
164-
registry.guildCommandIds.set(guildId, id);
165174

166-
registry.addChatInputCommandIds(id);
175+
switch (guildCommand.type) {
176+
case ApplicationCommandType.ChatInput: {
177+
registry['handleIdAddition'](InternalRegistryAPIType.ChatInput, id, guildId);
178+
break;
179+
}
180+
case ApplicationCommandType.User:
181+
case ApplicationCommandType.Message: {
182+
registry['handleIdAddition'](InternalRegistryAPIType.ContextMenu, id, guildId);
183+
break;
184+
}
185+
}
167186

168187
// idHints are useless, and any manually added ids or names could no longer be valid if you use bulk overwrites.
169188
// That said, this might be an issue, so we might need to do it like `handleAppendOrUpdate`

‎src/lib/utils/application-commands/ApplicationCommandRegistry.ts

+98-42
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import {
1111
type RESTPostAPIChatInputApplicationCommandsJSONBody,
1212
type RESTPostAPIContextMenuApplicationCommandsJSONBody
1313
} from 'discord-api-types/v10';
14-
import type {
15-
ApplicationCommand,
16-
ApplicationCommandManager,
17-
ChatInputApplicationCommandData,
14+
import {
1815
Collection,
19-
MessageApplicationCommandData,
20-
UserApplicationCommandData
16+
type ApplicationCommand,
17+
type ApplicationCommandManager,
18+
type ChatInputApplicationCommandData,
19+
type MessageApplicationCommandData,
20+
type UserApplicationCommandData
2121
} from 'discord.js';
2222
import { InternalRegistryAPIType, RegisterBehavior } from '../../types/Enums';
2323
import { allGuildIdsToFetchCommandsFor, getDefaultBehaviorWhenNotIdentical, getDefaultGuildIds } from './ApplicationCommandRegistries';
@@ -26,14 +26,61 @@ import { getCommandDifferences, getCommandDifferencesFast } from './computeDiffe
2626
import { convertApplicationCommandToApiData, normalizeChatInputCommand, normalizeContextMenuCommand } from './normalizeInputs';
2727

2828
export class ApplicationCommandRegistry {
29+
/**
30+
* The piece this registry is for.
31+
*/
2932
public readonly commandName: string;
3033

34+
/**
35+
* A set of all chat input command names and ids that point to this registry.
36+
* You should not use this field directly, but instead use {@link ApplicationCommandRegistry.globalChatInputCommandIds}
37+
*/
3138
public readonly chatInputCommands = new Set<string>();
39+
40+
/**
41+
* A set of all context menu command names and ids that point to this registry.
42+
* You should not use this field directly, but instead use {@link ApplicationCommandRegistry.globalContextMenuCommandIds}
43+
*/
3244
public readonly contextMenuCommands = new Set<string>();
45+
46+
/**
47+
* The guild ids that we need to fetch the commands for.
48+
*/
3349
public readonly guildIdsToFetch = new Set<string>();
3450

51+
/**
52+
* The global slash command id for this command.
53+
* @deprecated This field will only show the first global command id registered for this registry.
54+
* Use {@link ApplicationCommandRegistry.globalChatInputCommandIds} instead.
55+
*/
3556
public globalCommandId: string | null = null;
36-
public readonly guildCommandIds = new Map<string, string>();
57+
58+
/**
59+
* A set of all registered and valid global chat input command ids that point to this registry.
60+
*/
61+
public readonly globalChatInputCommandIds = new Set<string>();
62+
63+
/**
64+
* A set of all registered and valid global context menu command ids that point to this registry.
65+
*/
66+
public readonly globalContextMenuCommandIds = new Set<string>();
67+
68+
/**
69+
* The guild command ids for this command.
70+
* @deprecated This field will only show the first guild command id registered for this registry per guild.
71+
* Use {@link ApplicationCommandRegistry.guildIdToChatInputCommandIds} and {@link ApplicationCommandRegistry.guildIdToContextMenuCommandIds} instead.
72+
*/
73+
public readonly guildCommandIds = new Collection<string, string>();
74+
75+
/**
76+
* A map of guild ids to a set of registered and valid chat input command ids that point to this registry.
77+
*/
78+
public readonly guildIdToChatInputCommandIds = new Collection<string, Set<string>>();
79+
80+
/**
81+
* A map of guild ids to a set of registered and valid context menu command ids that point to this registry.
82+
*/
83+
public readonly guildIdToContextMenuCommandIds = new Collection<string, Set<string>>();
3784

3885
private readonly apiCalls: InternalAPICall[] = [];
3986

@@ -225,6 +272,42 @@ export class ApplicationCommandRegistry {
225272
}
226273
}
227274

275+
protected handleIdAddition(type: InternalRegistryAPIType, id: string, guildId?: string | null) {
276+
switch (type) {
277+
case InternalRegistryAPIType.ChatInput: {
278+
this.addChatInputCommandIds(id);
279+
280+
if (guildId) {
281+
this.guildIdToChatInputCommandIds.ensure(guildId, () => new Set()).add(id);
282+
} else {
283+
this.globalChatInputCommandIds.add(id);
284+
}
285+
break;
286+
}
287+
case InternalRegistryAPIType.ContextMenu: {
288+
this.addContextMenuCommandIds(id);
289+
290+
if (guildId) {
291+
this.guildIdToContextMenuCommandIds.ensure(guildId, () => new Set()).add(id);
292+
} else {
293+
this.globalContextMenuCommandIds.add(id);
294+
}
295+
break;
296+
}
297+
}
298+
299+
// Old field handling
300+
if (guildId) {
301+
// Old, wrongly typed field (thx kyra for spotting >_>)
302+
if (!this.guildCommandIds.has(guildId)) {
303+
this.guildCommandIds.set(guildId, id);
304+
}
305+
} else {
306+
// First come, first serve (thx kyra for spotting >_>)
307+
this.globalCommandId ??= id;
308+
}
309+
}
310+
228311
private getGuildIdsToRegister(options?: ApplicationCommandRegistryRegisterOptions) {
229312
let guildIdsToRegister: ApplicationCommandRegistry.RegisterOptions['guildIds'] = undefined;
230313

@@ -298,16 +381,8 @@ export class ApplicationCommandRegistry {
298381
const globalCommand = globalCommands.find(findCallback);
299382

300383
if (globalCommand) {
301-
switch (apiCall.type) {
302-
case InternalRegistryAPIType.ChatInput:
303-
this.addChatInputCommandIds(globalCommand.id);
304-
break;
305-
case InternalRegistryAPIType.ContextMenu:
306-
this.addContextMenuCommandIds(globalCommand.id);
307-
break;
308-
}
309-
310384
this.debug(`Checking if command "${commandName}" is identical with global ${type} command with id "${globalCommand.id}"`);
385+
this.handleIdAddition(apiCall.type, globalCommand.id);
311386
await this.handleCommandPresent(globalCommand, builtData, behaviorIfNotEqual, null);
312387
} else if (registerOptions.registerCommandIfMissing ?? true) {
313388
this.debug(`Creating new global ${type} command with name "${commandName}"`);
@@ -332,16 +407,7 @@ export class ApplicationCommandRegistry {
332407

333408
if (existingGuildCommand) {
334409
this.debug(`Checking if guild ${type} command "${commandName}" is identical to command "${existingGuildCommand.id}"`);
335-
336-
switch (apiCall.type) {
337-
case InternalRegistryAPIType.ChatInput:
338-
this.addChatInputCommandIds(existingGuildCommand.id);
339-
break;
340-
case InternalRegistryAPIType.ContextMenu:
341-
this.addContextMenuCommandIds(existingGuildCommand.id);
342-
break;
343-
}
344-
410+
this.handleIdAddition(apiCall.type, existingGuildCommand.id, guildId);
345411
await this.handleCommandPresent(existingGuildCommand, builtData, behaviorIfNotEqual, guildId);
346412
} else if (registerOptions.registerCommandIfMissing ?? true) {
347413
this.debug(`Creating new guild ${type} command with name "${commandName}" for guild "${guildId}"`);
@@ -358,12 +424,6 @@ export class ApplicationCommandRegistry {
358424
behaviorIfNotEqual: RegisterBehavior,
359425
guildId: string | null
360426
) {
361-
if (guildId) {
362-
this.guildCommandIds.set(guildId, applicationCommand.id);
363-
} else {
364-
this.globalCommandId = applicationCommand.id;
365-
}
366-
367427
if (behaviorIfNotEqual === RegisterBehavior.BulkOverwrite) {
368428
this.debug(
369429
`Command "${this.commandName}" has the behaviorIfNotEqual set to "BulkOverwrite" which is invalid. Using defaultBehaviorWhenNotIdentical instead`
@@ -467,12 +527,6 @@ export class ApplicationCommandRegistry {
467527
try {
468528
const result = await commandsManager.create(apiData, guildId);
469529

470-
if (guildId) {
471-
this.guildCommandIds.set(guildId, result.id);
472-
} else {
473-
this.globalCommandId = result.id;
474-
}
475-
476530
this.info(
477531
`Successfully created ${type}${guildId ? ' guild' : ''} command "${apiData.name}" with id "${
478532
result.id
@@ -481,13 +535,15 @@ export class ApplicationCommandRegistry {
481535

482536
switch (apiData.type) {
483537
case undefined:
484-
case ApplicationCommandType.ChatInput:
485-
this.addChatInputCommandIds(result.id);
538+
case ApplicationCommandType.ChatInput: {
539+
this.handleIdAddition(InternalRegistryAPIType.ChatInput, result.id, guildId);
486540
break;
541+
}
487542
case ApplicationCommandType.Message:
488-
case ApplicationCommandType.User:
489-
this.addContextMenuCommandIds(result.id);
543+
case ApplicationCommandType.User: {
544+
this.handleIdAddition(InternalRegistryAPIType.ContextMenu, result.id, guildId);
490545
break;
546+
}
491547
}
492548
} catch (err) {
493549
this.error(

0 commit comments

Comments
 (0)
Please sign in to comment.