diff --git a/data/config.txt b/data/config.txt index efa13ed..37365fa 100644 --- a/data/config.txt +++ b/data/config.txt @@ -6,6 +6,7 @@ commands.disabled.message: The message to show when a disabled command is ran (D role.assignable: List of roles assignable to user (Default: []) role.moderator: The moderator role name (Default: "Moderator") +role.administrator: The administrator role name (Default: "Administrator") role.muted: The muted role name (Default: "Muted") rules.file: The location of the rules file (Default: "data/rules/rules") diff --git a/ormconfig.json.template b/ormconfig.json.template index 5e24f5c..6c48598 100644 --- a/ormconfig.json.template +++ b/ormconfig.json.template @@ -4,7 +4,7 @@ "port": 3306, "username": "dev", "password": "dev", - "database": "droplet", + "database": "vylbot", "synchronize": true, "logging": false, "entities": [ diff --git a/src/client/events.ts b/src/client/events.ts index ca0d058..6752b82 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -21,7 +21,7 @@ export class Events { // Emit when a message is sent // Used to check for commands - public onMessage(message: Message, commands: ICommandItem[]): IEventResponse { + public async onMessage(message: Message, commands: ICommandItem[]): Promise { if (!message.guild) return { valid: false, message: "Message was not sent in a guild, ignoring.", @@ -43,7 +43,7 @@ export class Events { message: "Command name was not found", }; - const res = this._util.loadCommand(name, args, message, commands); + const res = await this._util.loadCommand(name, args, message, commands); if (!res.valid) { return { diff --git a/src/client/util.ts b/src/client/util.ts index 61ec0f9..07d1fef 100644 --- a/src/client/util.ts +++ b/src/client/util.ts @@ -7,6 +7,10 @@ import { Event } from "../type/event"; import { ICommandContext } from "../contracts/ICommandContext"; import ICommandItem from "../contracts/ICommandItem"; import IEventItem from "../contracts/IEventItem"; +import SettingsHelper from "../helpers/SettingsHelper"; +import StringTools from "../helpers/StringTools"; +import { CommandResponse } from "../constants/CommandResponse"; +import ErrorMessages from "../constants/ErrorMessages"; export interface IUtilResponse extends IBaseResponse { context?: { @@ -18,7 +22,7 @@ export interface IUtilResponse extends IBaseResponse { // Util Class export class Util { - public loadCommand(name: string, args: string[], message: Message, commands: ICommandItem[]): IUtilResponse { + public async loadCommand(name: string, args: string[], message: Message, commands: ICommandItem[]): Promise { if (!message.member) return { valid: false, message: "Member is not part of message", @@ -51,13 +55,26 @@ export class Util { const requiredRoles = item.Command._roles; for (const i in requiredRoles) { - if (!message.member.roles.cache.find(role => role.name == requiredRoles[i])) { - message.reply(`You require the \`${requiredRoles[i]}\` role to run this command`); + if (message.guild) { + const setting = await SettingsHelper.GetSetting(`role.${requiredRoles[i]}`, message.guild?.id); - return { - valid: false, - message: `You require the \`${requiredRoles[i]}\` role to run this command` - }; + if (!setting) { + message.reply("Unable to verify if you have this role, please contact your bot administrator"); + + return { + valid: false, + message: "Unable to verify if you have this role, please contact your bot administrator" + }; + } + + if (!message.member.roles.cache.find(role => role.name == setting)) { + message.reply(`You require the \`${StringTools.Capitalise(setting)}\` role to run this command`); + + return { + valid: false, + message: `You require the \`${StringTools.Capitalise(setting)}\` role to run this command` + }; + } } } @@ -67,6 +84,27 @@ export class Util { message: message }; + const precheckResponse = item.Command.precheck(context); + const precheckAsyncResponse = await item.Command.precheckAsync(context); + + if (precheckResponse != CommandResponse.Ok) { + message.reply(ErrorMessages.GetErrorMessage(precheckResponse)); + + return { + valid: false, + message: ErrorMessages.GetErrorMessage(precheckResponse) + }; + } + + if (precheckAsyncResponse != CommandResponse.Ok) { + message.reply(ErrorMessages.GetErrorMessage(precheckAsyncResponse)); + + return { + valid: false, + message: ErrorMessages.GetErrorMessage(precheckAsyncResponse) + }; + } + item.Command.execute(context); return { diff --git a/src/commands/ban.ts b/src/commands/ban.ts index c80deb8..865a0cf 100644 --- a/src/commands/ban.ts +++ b/src/commands/ban.ts @@ -12,7 +12,7 @@ export default class Ban extends Command { super._category = "Moderation"; super._roles = [ - process.env.ROLES_MODERATOR! + "moderator" ]; } diff --git a/src/commands/clear.ts b/src/commands/clear.ts index 4f8f893..f8e1534 100644 --- a/src/commands/clear.ts +++ b/src/commands/clear.ts @@ -11,7 +11,7 @@ export default class Clear extends Command { super._category = "Moderation"; super._roles = [ - process.env.ROLES_MODERATOR! + "moderator" ]; } diff --git a/src/commands/config.ts b/src/commands/config.ts index 7e719da..5a6a6ef 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -1,5 +1,6 @@ import { Guild } from "discord.js"; import { readFileSync } from "fs"; +import { CommandResponse } from "../constants/CommandResponse"; import DefaultValues from "../constants/DefaultValues"; import { ICommandContext } from "../contracts/ICommandContext"; import ICommandReturnContext from "../contracts/ICommandReturnContext"; @@ -13,6 +14,25 @@ export default class Config extends Command { constructor() { super(); super._category = "Administration"; + super._roles = [ + "administrator" + ] + } + + public override async precheckAsync(context: ICommandContext): Promise { + if (!context.message.guild) { + return CommandResponse.ServerNotSetup; + } + + const server = await Server.FetchOneById(Server, context.message.guild?.id, [ + "Settings", + ]); + + if (!server) { + return CommandResponse.ServerNotSetup; + } + + return CommandResponse.Ok; } public override async execute(context: ICommandContext) { @@ -25,8 +45,6 @@ export default class Config extends Command { ]); if (!server) { - const embed = new ErrorEmbed(context, "This server hasn't been setup yet, please run the setup command"); - embed.SendToCurrentChannel(); return; } diff --git a/src/commands/kick.ts b/src/commands/kick.ts index ae6a55d..6a741a7 100644 --- a/src/commands/kick.ts +++ b/src/commands/kick.ts @@ -12,7 +12,7 @@ export default class Kick extends Command { super._category = "Moderation"; super._roles = [ - process.env.ROLES_MODERATOR! + "moderator" ]; } diff --git a/src/commands/mute.ts b/src/commands/mute.ts index e12b756..79a21ba 100644 --- a/src/commands/mute.ts +++ b/src/commands/mute.ts @@ -12,7 +12,7 @@ export default class Mute extends Command { super._category = "Moderation"; super._roles = [ - process.env.ROLES_MODERATOR! + "moderator" ]; } diff --git a/src/commands/rules.ts b/src/commands/rules.ts index c41f381..a5066c7 100644 --- a/src/commands/rules.ts +++ b/src/commands/rules.ts @@ -18,7 +18,7 @@ export default class Rules extends Command { super._category = "Admin"; super._roles = [ - process.env.ROLES_MODERATOR! + "administrator" ]; } diff --git a/src/commands/setup.ts b/src/commands/setup.ts index 73ae1ab..ee20012 100644 --- a/src/commands/setup.ts +++ b/src/commands/setup.ts @@ -9,6 +9,9 @@ export default class Setup extends Command { constructor() { super(); super._category = "Administration"; + super._roles = [ + "moderator" + ] } public override async execute(context: ICommandContext) { diff --git a/src/commands/unmute.ts b/src/commands/unmute.ts index 70a1363..243d772 100644 --- a/src/commands/unmute.ts +++ b/src/commands/unmute.ts @@ -12,7 +12,7 @@ export default class Unmute extends Command { super._category = "Moderation"; super._roles = [ - process.env.ROLES_MODERATOR! + "moderator" ]; } diff --git a/src/commands/warn.ts b/src/commands/warn.ts index be15344..858f7c3 100644 --- a/src/commands/warn.ts +++ b/src/commands/warn.ts @@ -11,7 +11,7 @@ export default class Warn extends Command { super._category = "Moderation"; super._roles = [ - process.env.ROLES_MODERATOR! + "moderator" ]; } diff --git a/src/constants/CommandResponse.ts b/src/constants/CommandResponse.ts new file mode 100644 index 0000000..968f352 --- /dev/null +++ b/src/constants/CommandResponse.ts @@ -0,0 +1,5 @@ +export enum CommandResponse { + Ok, + Unauthorised, + ServerNotSetup, +} \ No newline at end of file diff --git a/src/constants/DefaultValues.ts b/src/constants/DefaultValues.ts index 12f8142..2f33b12 100644 --- a/src/constants/DefaultValues.ts +++ b/src/constants/DefaultValues.ts @@ -1,5 +1,5 @@ export default class DefaultValues { - public static readonly values: ISettingValue[] = []; + public static values: ISettingValue[] = []; public static GetValue(key: string): string | undefined { this.SetValues(); @@ -22,6 +22,7 @@ export default class DefaultValues { // Role (Command) this.values.push({ Key: "role.assignable", Value: "" }); this.values.push({ Key: "role.moderator", Value: "Moderator" }); + this.values.push({ Key: "role.administrator", Value: "Administrator"}); this.values.push({ Key: "role.muted", Value: "Muted" }); // Rules (Command) diff --git a/src/constants/ErrorMessages.ts b/src/constants/ErrorMessages.ts index a397dcf..f096a8a 100644 --- a/src/constants/ErrorMessages.ts +++ b/src/constants/ErrorMessages.ts @@ -1,5 +1,21 @@ +import { CommandResponse } from "./CommandResponse"; + export default class ErrorMessages { public static readonly InsufficientBotPermissions = "Unable to do this action, am I missing permissions?"; public static readonly ChannelNotFound = "Unable to find channel"; public static readonly RoleNotFound = "Unable to find role"; + + public static readonly UserUnauthorised = "You are not authorised to use this command"; + public static readonly ServerNotSetup = "This server hasn't been setup yet, please run the setup command"; + + public static GetErrorMessage(response: CommandResponse): string { + switch (response) { + case CommandResponse.Unauthorised: + return this.UserUnauthorised; + case CommandResponse.ServerNotSetup: + return this.ServerNotSetup; + default: + return ""; + } + } } \ No newline at end of file diff --git a/src/type/command.ts b/src/type/command.ts index 5a3ae45..a8cfdd7 100644 --- a/src/type/command.ts +++ b/src/type/command.ts @@ -1,3 +1,4 @@ +import { CommandResponse } from "../constants/CommandResponse"; import { ICommandContext } from "../contracts/ICommandContext"; export class Command { @@ -9,6 +10,14 @@ export class Command { this._roles = []; } + public precheck(context: ICommandContext): CommandResponse { + return CommandResponse.Ok; + } + + public async precheckAsync(context: ICommandContext): Promise { + return CommandResponse.Ok; + } + public execute(context: ICommandContext) { }