Skip to content

Commit e5e9d54

Browse files
committed
feat: guild commands
1 parent 1b24de2 commit e5e9d54

File tree

5 files changed

+96
-22
lines changed

5 files changed

+96
-22
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { CommandData, SlashCommand, MessageCommand } from 'commandkit';
2+
3+
export const command: CommandData = {
4+
name: 'server',
5+
description: 'server command',
6+
guilds: [process.env.DEV_GUILD_ID],
7+
};
8+
9+
export const chatInput: SlashCommand = async (ctx) => {
10+
await ctx.interaction.reply('Hello from server!');
11+
};
12+
13+
export const message: MessageCommand = async (ctx) => {
14+
await ctx.message.reply('Hello from server!');
15+
};

packages/commandkit/src/app/command-handler/AppCommandHandler.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface AppCommandMiddleware {
3232
interface LoadedCommand {
3333
command: ParsedCommand;
3434
data: AppCommand;
35+
guilds?: string[];
3536
}
3637

3738
interface LoadedMiddleware {
@@ -99,6 +100,13 @@ export class AppCommandHandler {
99100

100101
if (!loadedCommand) return null;
101102

103+
if (
104+
source.guildId &&
105+
loadedCommand.guilds?.length &&
106+
!loadedCommand.guilds.includes(source.guildId!)
107+
)
108+
return null;
109+
102110
const json =
103111
'toJSON' in loadedCommand.data.command
104112
? loadedCommand.data.command.toJSON()
@@ -226,6 +234,7 @@ export class AppCommandHandler {
226234

227235
this.loadedCommands.set(name, {
228236
command,
237+
guilds: data.guilds,
229238
data: {
230239
...data,
231240
command: localizedCommand,

packages/commandkit/src/legacy/handlers/command-handler/functions/loadCommandsWithRest.ts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,19 @@ async function handleLoading(
8181
type?: ReloadOptions,
8282
) {
8383
commands = commands.filter((cmd) => !cmd.options?.deleted);
84-
const devOnlyCommands = commands.filter((cmd) => cmd.options?.devOnly);
85-
const globalCommands = commands.filter((cmd) => !cmd.options?.devOnly);
84+
const devOnlyCommands = commands.filter(
85+
(cmd) => cmd.options?.devOnly || cmd.data?.guilds?.length,
86+
);
87+
const globalCommands = commands.filter(
88+
(cmd) => !cmd.options?.devOnly && !cmd.data?.guilds?.length,
89+
);
8690

8791
if (type === 'dev') {
88-
await loadDevCommands(client, devOnlyCommands, devGuildIds, reloading);
92+
await loadGuildCommands(client, devOnlyCommands, devGuildIds, reloading);
8993
} else if (type === 'global') {
9094
await loadGlobalCommands(client, globalCommands, reloading);
9195
} else {
92-
await loadDevCommands(client, devOnlyCommands, devGuildIds, reloading);
96+
await loadGuildCommands(client, devOnlyCommands, devGuildIds, reloading);
9397
await loadGlobalCommands(client, globalCommands, reloading);
9498
}
9599
}
@@ -130,6 +134,25 @@ async function loadGlobalCommands(
130134
);
131135
}
132136

137+
async function loadGuildCommands(
138+
client: Client<true>,
139+
commands: CommandFileObject[],
140+
guildIds: string[],
141+
reloading?: boolean,
142+
) {
143+
const guildDefined = commands.filter((cmd) => cmd.data.guilds?.length);
144+
const guildNotDefined = commands.filter((cmd) => !cmd.data.guilds?.length);
145+
146+
await loadDevCommands(client, guildNotDefined, guildIds, reloading);
147+
await loadDevCommands(
148+
client,
149+
guildDefined,
150+
guildDefined.flatMap((c) => c.data.guilds).filter((c) => c !== undefined),
151+
reloading,
152+
'guild',
153+
);
154+
}
155+
133156
/**
134157
* Load commands for dev guilds.
135158
* @param client - The discord.js client instance.
@@ -142,8 +165,12 @@ async function loadDevCommands(
142165
commands: CommandFileObject[],
143166
guildIds: string[],
144167
reloading?: boolean,
168+
type = 'developer',
145169
) {
146-
const requestBody = commands.map((cmd) => cmd.data);
170+
const requestBody = commands.map((cmd) => {
171+
delete cmd.data.guilds;
172+
return cmd.data;
173+
});
147174

148175
for (const guildId of guildIds) {
149176
const targetGuild =
@@ -166,7 +193,7 @@ async function loadDevCommands(
166193
colors.red(
167194
`Error ${
168195
reloading ? 'reloading' : 'loading'
169-
} developer application commands in guild "${
196+
} ${type || 'developer'} application commands in guild "${
170197
targetGuild?.name || guildId
171198
}".\n`,
172199
),
@@ -178,7 +205,7 @@ async function loadDevCommands(
178205
colors.green(
179206
`${reloading ? 'Reloaded' : 'Loaded'} ${
180207
requestBody.length
181-
} developer commands in guild "${targetGuild.name}".`,
208+
} ${type || 'developer'} commands in guild "${targetGuild.name}".`,
182209
),
183210
);
184211
}

packages/commandkit/src/legacy/handlers/command-handler/functions/registerCommands.ts

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,19 @@ async function handleRegistration(
5959
devGuildIds: string[],
6060
type?: ReloadOptions,
6161
) {
62-
const devOnlyCommands = commands.filter((cmd) => cmd.options?.devOnly);
63-
const globalCommands = commands.filter((cmd) => !cmd.options?.devOnly);
62+
const devOnlyCommands = commands.filter(
63+
(cmd) => cmd.options?.devOnly || cmd.data?.guilds?.length,
64+
);
65+
const globalCommands = commands.filter(
66+
(cmd) => !cmd.options?.devOnly && !cmd.data?.guilds?.length,
67+
);
6468

6569
if (type === 'dev') {
66-
await registerDevCommands(client, devOnlyCommands, devGuildIds);
70+
await registerGuildCommands(client, devOnlyCommands, devGuildIds);
6771
} else if (type === 'global') {
6872
await registerGlobalCommands(client, globalCommands);
6973
} else {
70-
await registerDevCommands(client, devOnlyCommands, devGuildIds);
74+
await registerGuildCommands(client, devOnlyCommands, devGuildIds);
7175
await registerGlobalCommands(client, globalCommands);
7276
}
7377
}
@@ -255,16 +259,17 @@ async function registerDevCommands(
255259
// <!-- Register guild command -->
256260
if (targetCommand) continue;
257261

258-
await guildCommands
259-
.create(command.data as ApplicationCommandDataResolvable)
260-
.catch((error) => {
261-
throw new Error(
262-
colors.red(
263-
`Failed to register command "${command.data.name}" in ${guildCommands.guild.name}.\n`,
264-
),
265-
error,
266-
);
267-
});
262+
delete command.data.guilds;
263+
const commandData = command.data as ApplicationCommandDataResolvable;
264+
265+
await guildCommands.create(commandData).catch((error) => {
266+
throw new Error(
267+
colors.red(
268+
`Failed to register command "${command.data.name}" in ${guildCommands.guild.name}.\n`,
269+
),
270+
error,
271+
);
272+
});
268273

269274
Logger.log(
270275
colors.green(
@@ -274,3 +279,19 @@ async function registerDevCommands(
274279
}
275280
}
276281
}
282+
283+
async function registerGuildCommands(
284+
client: Client<true>,
285+
commands: CommandFileObject[],
286+
devGuildIds: string[],
287+
) {
288+
const guildCommands = commands.filter((c) => c.data.guilds?.length);
289+
const notGuildCommands = commands.filter((c) => c.options?.devOnly);
290+
291+
await registerDevCommands(client, notGuildCommands, devGuildIds);
292+
await registerDevCommands(
293+
client,
294+
guildCommands,
295+
guildCommands.flatMap((c) => c.data.guilds).filter((c) => c !== undefined),
296+
);
297+
}

packages/commandkit/src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,9 @@ export interface CommandOptions {
258258
[key: string]: any;
259259
}
260260

261-
export type CommandData = RESTPostAPIApplicationCommandsJSONBody;
261+
export type CommandData = RESTPostAPIApplicationCommandsJSONBody & {
262+
guilds?: string[];
263+
};
262264

263265
export type CommandObject = {
264266
/**

0 commit comments

Comments
 (0)