Skip to content

Commit

Permalink
feat(commands): dynamic guilds
Browse files Browse the repository at this point in the history
now the CommandsService will update the metadata from all commands(slash|sub)
using the `CommandsPermissionsDecorator` values to determine
what command will be posted in specific guilds

Thanks @wolffparkinson
https://github.com/wolffparkinson/necord-playground/tree/dynamic-guilds
  • Loading branch information
NedcloarBR committed May 3, 2024
1 parent 5ede6cf commit 5c72e16
Show file tree
Hide file tree
Showing 22 changed files with 117 additions and 21 deletions.
8 changes: 5 additions & 3 deletions src/common/decorators/CommandPermissions.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Reflector } from "@nestjs/core";
import { PermissionResolvable } from "discord.js";

interface CommandPermissionsOptions {
export interface CommandPermissionsOptions {
user: PermissionResolvable[];
bot: PermissionResolvable[];
guildOnly?: boolean;
ownerOnly?: boolean;
guildOnly: boolean;
testOnly: boolean;
ownerOnly: boolean;
guilds?: string[];
}

export const CommandPermissions = Reflector.createDecorator<CommandPermissionsOptions>();
3 changes: 2 additions & 1 deletion src/modules/commands/Commands.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Module } from "@nestjs/common";
import * as Commands from "./index";
import { CommandsService } from "./Commands.service";

@Module({
imports: [...Object.values(Commands)],
providers: [...Object.values(Commands), CommandsService],
})
export class CommandsModule {}
90 changes: 90 additions & 0 deletions src/modules/commands/Commands.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { CommandPermissions } from "@/common/decorators";
import { Injectable, Logger, OnApplicationBootstrap } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Reflector } from "@nestjs/core";
import { Client } from "discord.js";
import { CommandsService as _CommandsService, SlashCommand, SlashCommandDiscovery, SlashCommandsService, Subcommand } from "necord";
import { ExplorerService } from "necord/dist/necord-explorer.service";
import { Config } from "../config/types";
import { CommandPermissionsOptions } from "@/common/decorators/CommandPermissions.decorator";

@Injectable()
export class CommandsService implements OnApplicationBootstrap {
private readonly logger = new Logger(CommandsService.name);

constructor(
private readonly slashCommandService: SlashCommandsService,
private readonly explorerService: ExplorerService<SlashCommandDiscovery>,
private readonly commandService: _CommandsService,
private readonly reflector: Reflector,
private readonly configService: ConfigService,
private readonly client: Client,
) {}

async onApplicationBootstrap() {
this.client.once("ready", async (client) => this.commandService.registerAllCommands());
await this.updateMeta();
}

async updateMeta() {
this.logger.verbose("Updating metadata for SlashCommands | SubCommands");

this.updateSlashCommands();
this.updateSubCommands();

if (!this.client.isReady()) return;
await this.commandService.registerAllCommands();
}

private updateSlashCommands(): void {
const slashCommands = this.explorerService.explore(SlashCommand.KEY);
this.logger.verbose(`${slashCommands.length} SlashCommand (s) explored`);
for (const command of slashCommands) {
const perms: CommandPermissionsOptions = this.reflector.get(CommandPermissions.KEY, command.getHandler());
this.slashCommandService.add(command);
const guilds = [];
if (perms.guildOnly) {
guilds.push(this.configService.getOrThrow<Config["Discord"]>("Discord").Servers.NDCommunity);
}
if (perms.testOnly) {
guilds.push(this.configService.getOrThrow<Config["Discord"]>("Discord").Servers.TestGuild);
}
if(perms.guilds) {
guilds.push(perms.guilds.values())
}

if (!guilds) return;

this.logger.verbose(`Updating metadata for SlashCommand : ${command.getName()}`);

command["meta"]["guilds"] = guilds ?? [];
this.slashCommandService.add(command);
}
}

private updateSubCommands(): void {
const subCommands = this.explorerService.explore(Subcommand.KEY);
this.logger.verbose(`${subCommands.length} SubCommand (s) explored`);
for (const command of subCommands) {
const perms: CommandPermissionsOptions = this.reflector.get(CommandPermissions.KEY, command.getHandler());
this.slashCommandService.add(command);
const guilds = [];
if (perms.guildOnly) {
guilds.push(this.configService.getOrThrow<Config["Discord"]>("Discord").Servers.NDCommunity);
}
if (perms.testOnly) {
guilds.push(this.configService.getOrThrow<Config["Discord"]>("Discord").Servers.TestGuild);
}
if(perms.guilds) {
guilds.push(perms.guilds.values())
}

if (!guilds) return;

this.logger.verbose(`Updating metadata for SubCommand : ${command.getName()}`);

command["meta"]["guilds"] = guilds ?? [];
this.slashCommandService.addSubCommand(command);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class EvalCommand {
user: [],
bot: [],
guildOnly: false,
testOnly: true,
ownerOnly: true,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class TestCommand {
user: [],
bot: [],
guildOnly: false,
testOnly: true,
ownerOnly: true,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ export const ModerationCommand = createCommandGroupDecorator({
description: "Category 🛡️ Moderation",
nameLocalizations: localizationMapByKey("Moderation.category.name"),
descriptionLocalizations: localizationMapByKey("Moderation.category.description"),
guilds: ["679066351456878633"],
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class ClearCommand {
bot: [],
user: ["ManageMessages"],
guildOnly: false,
testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/config/NecordConfig.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class NecordConfigService {
createNecordOptions(): NecordModuleOptions {
return {
token: this.config.getOrThrow<Config["Discord"]>("Discord").Token,
skipRegistration: false,
skipRegistration: true,
shards: "auto",
rest: {
version: GatewayVersion,
Expand Down
1 change: 1 addition & 0 deletions src/modules/music/commands/Join.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class JoinCommand {
bot: ["Connect", "EmbedLinks", "DeafenMembers", "Speak"],
user: ["Connect", "SendMessages"],
guildOnly: false,
testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
8 changes: 4 additions & 4 deletions src/modules/music/commands/Leave.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { CommandConfig, CommandPermissions } from "@/common/decorators";
import { CommandConfigGuard, CommandPermissionsGuard } from "@/common/guards";
import {
CurrentTranslate,
localizationMapByKey,
type TranslationFn,
localizationMapByKey,
} from "@necord/localization";
import { Inject, Logger, UseGuards } from "@nestjs/common";
import {
channelMention,
type GuildMember,
type VoiceChannel,
channelMention,
} from "discord.js";
import { Ctx, Subcommand, type SlashCommandContext } from "necord";
import { Ctx, type SlashCommandContext, Subcommand } from "necord";
import { Music } from "..";
import { MusicCommand } from "../Music.decorator";
import type { IMusicService } from "../interfaces";
Expand All @@ -32,7 +32,7 @@ export class LeaveCommand {
@CommandPermissions({
bot: ["Connect", "EmbedLinks", "DeafenMembers", "Speak"],
user: ["Connect", "SendMessages"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/music/commands/NowPlaying.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class NowPlayingCommand {
@CommandPermissions({
bot: ["Connect", "EmbedLinks", "DeafenMembers", "Speak"],
user: ["Connect", "SendMessages"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/music/commands/Pause.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class PauseCommand {
@CommandPermissions({
bot: ["SendMessages"],
user: ["SendMessages"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/music/commands/Queue.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class QueueCommand {
@CommandPermissions({
bot: ["Connect", "EmbedLinks", "DeafenMembers", "Speak"],
user: ["Connect", "SendMessages"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/music/commands/Resume.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class ResumeCommand {
@CommandPermissions({
bot: ["SendMessages"],
user: ["SendMessages"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/music/commands/Stop.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class StopCommand {
@CommandPermissions({
bot: ["SendMessages"],
user: ["SendMessages"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
1 change: 1 addition & 0 deletions src/modules/music/commands/play/play.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class PlayCommand {
bot: ["Connect", "EmbedLinks", "DeafenMembers", "Speak"],
user: ["Connect", "SendMessages"],
guildOnly: false,
testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
1 change: 0 additions & 1 deletion src/modules/reactionRoles/ReactionRoles.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ export const ReactionRolesCommand = createCommandGroupDecorator({
nameLocalizations: localizationMapByKey("ReactionRoles.category.name"),
descriptionLocalizations: localizationMapByKey("ReactionRoles.category.description"),
dmPermission: false,
guilds: ["717094267243462688"]
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class CreateReactionCommand {
@CommandPermissions({
user: ["SendMessages", "AddReactions", "ManageRoles"],
bot: ["EmbedLinks", "AddReactions", "ManageRoles"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class DeleteAllReactionsCommand {
@CommandPermissions({
user: ["SendMessages", "AddReactions", "ManageRoles"],
bot: ["EmbedLinks", "AddReactions", "ManageRoles"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class DeleteReactionCommand {
@CommandPermissions({
user: ["SendMessages", "AddReactions", "ManageRoles"],
bot: ["EmbedLinks", "AddReactions", "ManageRoles"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class EditReactionCommand {
@CommandPermissions({
user: ["SendMessages", "AddReactions", "ManageRoles"],
bot: ["EmbedLinks", "AddReactions", "ManageRoles"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class ReactionTypesCommand {
@CommandPermissions({
user: ["SendMessages", "AddReactions", "ManageRoles"],
bot: ["EmbedLinks", "AddReactions", "ManageRoles"],
guildOnly: false,
guildOnly: false,testOnly: true,
ownerOnly: false,
})
@UseGuards(CommandConfigGuard, CommandPermissionsGuard)
Expand Down

0 comments on commit 5c72e16

Please sign in to comment.