diff --git a/src/client/components/commands/moderation/Case.ts b/src/client/components/commands/moderation/Case.ts index 363afd6..0b7e324 100644 --- a/src/client/components/commands/moderation/Case.ts +++ b/src/client/components/commands/moderation/Case.ts @@ -6,6 +6,7 @@ import { inspect } from 'util'; import Util from '../../../../utilities/Util.js'; import { EmbedDefaultColor, InfractionColors } from '../../../../constants/Constants.js'; import { APIEmbed, GuildChannel, User } from 'discord.js'; +import Infraction from '../../../interfaces/Infraction.js'; class CaseCommand extends SlashCommand { @@ -22,12 +23,13 @@ class CaseCommand extends SlashCommand minimum: 0, required: true }, { - name: [ 'export', 'verbose', 'changes' ], // + name: [ 'export', 'verbose', 'changes', 'delete' ], // type: CommandOptionType.BOOLEAN, description: [ 'Print out raw infraction data in JSON form', 'Print out more detailed information about the case', - 'List changes to the case' + 'List changes to the case', + 'Delete the case' ], dependsOn: [ 'id' ], flag: true, @@ -41,24 +43,32 @@ class CaseCommand extends SlashCommand }); } - async execute (invoker: InvokerWrapper, opts: CommandParams) + async execute (invoker: InvokerWrapper, opts: CommandParams) { - const { id, verbose, export: exp, changes } = opts; + const { id, verbose, export: exp, changes, delete: remove } = opts; const guild = invoker.guild!; - const infraction = await this.client.storageManager.mongodb.infractions.findOne({ - id: `${guild.id}:${id?.asNumber}` - }, { projection: { _id: 0 } }); + const infraction = await new Infraction(this.client, this.logger, { guild, case: id!.asNumber }).fetch(true).catch(() => null); if (!infraction) return { emoji: 'failure', index: 'COMMAND_CASE_NOTFOUND', params: { caseID: id!.asNumber } }; + if (remove?.asBool === true) + { + if (!invoker.member?.permissions.has('Administrator')) + return { emoji: 'failure', index: 'ERR_MISSING_PERMISSIONS' }; + await infraction.resolve(invoker.member, invoker.format('COMMAND_CASE_DELETED_LOG'), false); + await this.client.storageManager.mongodb.infractions.deleteOne({ + id: `${guild.id}:${id?.asNumber}` + }); + return { emoji: 'success', index: 'COMMAND_CASE_DELETED', params: { caseID: id!.asNumber } }; + } if (exp?.asString) return `\`\`\`js\n${inspect(infraction)}\`\`\``; if (changes?.asString) - return { embed: await this._listChanges(invoker, infraction) }; + return { embed: await this._listChanges(invoker, infraction.json) }; - const target = infraction.targetType === 'USER' ? await this.client.resolver.resolveUser(infraction.target) : await guild.resolveChannel(infraction.target); - const staff = await this.client.resolver.resolveUser(infraction.executor); + const target = infraction.targetType === 'USER' ? await this.client.resolver.resolveUser(infraction.targetId!) : await guild.resolveChannel(infraction.targetId); + const staff = await this.client.resolver.resolveUser(infraction.executor!); let index = 'COMMAND_CASE_TEMPLATE', caseTitleIndex = 'COMMAND_CASE_TITLE', @@ -75,7 +85,7 @@ class CaseCommand extends SlashCommand targetUserIndex += '_VERBOSE'; targetChannelIndex += '_VERBOSE'; } - + const { json } = infraction; let description = invoker.format(index, { uniqueID: infraction.id, type: infraction.type, @@ -86,25 +96,25 @@ class CaseCommand extends SlashCommand target: infraction.targetType === 'USER' ? invoker.format(targetUserIndex, { target: (target as User).tag, targetID: target!.id }) : invoker.format(targetChannelIndex, { target: (target as GuildChannel).name, targetID: target!.id }), staff: staff?.tag??'N/A', staffID: staff?.id??'N/A', - nrChanges: infraction.changes?.length || 0, - changes: infraction.changes?.map((change) => change.type).join(', ') || 'N/A', + nrChanges: json.changes?.length || 0, + changes: json.changes?.map((change) => change.type).join(', ') || 'N/A', guild: guild.id, - channel: infraction.channel, - message: infraction.message + channel: json.channel, + message: json.message }); if (infraction.data?.seconds) description += '\n' + invoker.format(caseSlowmodeIndex, { readable: Util.humanise(infraction.data.seconds), seconds: infraction.data.seconds }); - if (infraction.duration !== null) + if (json.duration !== null) { - const duration = Math.floor(infraction.duration / 1000); + const duration = Math.floor(json.duration / 1000); description += '\n' + invoker.format(caseLengthIndex, { time: Util.humanise(duration), inSeconds: duration }); } if (guild._settings.modpoints.enabled) description += '\n' + invoker.format('COMMAND_CASE_MODPOINTS', { points: infraction.points, - expires: infraction.expiration ? `` : false + expires: json.expiration ? `` : false }); description += '\n\n' + invoker.format('COMMAND_CASE_REASON', { reason: infraction.reason }); diff --git a/src/client/components/commands/moderation/Mute.ts b/src/client/components/commands/moderation/Mute.ts index d2585da..c15f891 100644 --- a/src/client/components/commands/moderation/Mute.ts +++ b/src/client/components/commands/moderation/Mute.ts @@ -3,7 +3,7 @@ import DiscordClient from '../../../DiscordClient.js'; import { Mute } from '../../../infractions/index.js'; import { CommandError, ModerationCommand } from '../../../interfaces/index.js'; import InvokerWrapper from '../../wrappers/InvokerWrapper.js'; -import UserWrapper from '../../wrappers/UserWrapper.js'; +import MemberWrapper from '../../wrappers/MemberWrapper.js'; class MuteCommand extends ModerationCommand { @@ -41,9 +41,9 @@ class MuteCommand extends ModerationCommand else if (!me!.permissions.has('ManageRoles')) throw new CommandError(invoker, { index: 'INHIBITOR_CLIENTPERMISSIONS_ERROR', formatParams: { command: this.name, missing: 'ManageRoles' } }); - const wrappers = await Promise.all(users.asUsers.map(user => this.client.getUserWrapper(user))); + const wrappers = await Promise.all(users!.asUsers.map(user => guild.memberWrapper(user))); return this.client.moderation.handleInfraction(Mute, invoker, { - targets: wrappers.filter(Boolean) as UserWrapper[], + targets: wrappers.filter(Boolean) as MemberWrapper[], args }); diff --git a/src/client/components/commands/moderation/Nickname.ts b/src/client/components/commands/moderation/Nickname.ts index 4b8dc5a..90027fa 100644 --- a/src/client/components/commands/moderation/Nickname.ts +++ b/src/client/components/commands/moderation/Nickname.ts @@ -3,7 +3,7 @@ import DiscordClient from '../../../DiscordClient.js'; import { Nickname } from '../../../infractions/index.js'; import { CommandError, ModerationCommand } from '../../../interfaces/index.js'; import InvokerWrapper from '../../wrappers/InvokerWrapper.js'; -import UserWrapper from '../../wrappers/UserWrapper.js'; +import MemberWrapper from '../../wrappers/MemberWrapper.js'; class NicknameCommand extends ModerationCommand { @@ -28,15 +28,15 @@ class NicknameCommand extends ModerationCommand } - async execute (invoker: InvokerWrapper, { users, name, ...args }: CommandParams) + async execute (invoker: InvokerWrapper, { users, name, ...args }: CommandParams) { if (!users) throw new CommandError(invoker, { index: 'MODERATION_MISSING_USERS' }); - const wrappers = await Promise.all(users.asUsers.map(user => this.client.getUserWrapper(user))); + const wrappers = await Promise.all(users!.asUsers.map(user => invoker.guild.memberWrapper(user))); return this.client.moderation.handleInfraction(Nickname, invoker, { - targets: wrappers.filter(Boolean) as UserWrapper[], + targets: wrappers.filter(Boolean) as MemberWrapper[], args, data: { name: name?.asString diff --git a/src/client/infractions/Mute.ts b/src/client/infractions/Mute.ts index 37bc525..dcd10b5 100644 --- a/src/client/infractions/Mute.ts +++ b/src/client/infractions/Mute.ts @@ -21,7 +21,6 @@ class MuteInfraction extends Infraction } member?: MemberWrapper; - duration?: number; constructor (client: DiscordClient, logger: LoggerClient, opts: MuteData) { @@ -51,11 +50,8 @@ class MuteInfraction extends Infraction throw new Error('Guild member required'); this.member = opts.target; const { mute } = this.guild._settings; - if (!this.duration && (!mute.permanent || mute.type === MuteType.Timeout)) - { + if (!this.duration && (!mute.permanent || mute.type === MuteType.Timeout)) this.duration = mute.default * 1000; - } - } } @@ -277,6 +273,7 @@ class MuteInfraction extends Infraction break; } } + await super.resolve(_staff, _reason, _notify); return { message, error }; } diff --git a/src/client/interfaces/CommandOption.ts b/src/client/interfaces/CommandOption.ts index 5aa7abd..001b05f 100644 --- a/src/client/interfaces/CommandOption.ts +++ b/src/client/interfaces/CommandOption.ts @@ -8,6 +8,7 @@ import Command from './commands/Command.js'; import moment from 'moment'; import { GuildBasedChannel, GuildMember, Role, User } from 'discord.js'; import Module from './Module.js'; +import { Max32BitInt } from '../../constants/Constants.js'; const PointsReg = /^([-+]?[0-9]+) ?(points|point|pts|pt|p)$/iu; const ChannelType: {[key: string]: number} = { @@ -100,6 +101,8 @@ class CommandOption this.#minimum = options.minimum; if (typeof options.maximum === 'number') this.#maximum = options.maximum; + if (typeof this.#maximum === 'undefined' || this.#maximum > Number.MAX_SAFE_INTEGER) + this.#maximum = Number.MAX_SAFE_INTEGER; this.#slashOption = options.slashOption || false; this.#flag = options.flag ?? false; // used with message based command options @@ -277,7 +280,7 @@ class CommandOption POINTS: async () => { if (this.slashOption) - return { value: this.#rawValue }; + return { value: parseInt(this.#rawValue as string) }; let value = null, removed = null; if (!this.#rawValue) @@ -470,6 +473,8 @@ class CommandOption const value = this.client.resolver.resolveTime(this.#rawValue); if (value === null) return { error: true }; + if ((value*1000) > Max32BitInt) + return { error: true, index: 'O_COMMANDHANDLER_TYPETIME_MAX', params: { maximum: Util.humanise(Max32BitInt/1000) } }; if (typeof this.#maximum !== 'undefined' && value > this.#maximum) return { error: true, index: 'O_COMMANDHANDLER_TYPETIME_MAX', params: { maximum: Util.humanise(this.#maximum) } }; return { value, removed: [ this.#rawValue ] }; diff --git a/src/client/interfaces/Infraction.ts b/src/client/interfaces/Infraction.ts index 01a873b..af08f2b 100644 --- a/src/client/interfaces/Infraction.ts +++ b/src/client/interfaces/Infraction.ts @@ -244,9 +244,12 @@ class Infraction async save () { + const { json } = this; const filter: {id: string, _id?: ObjectId} = { id: this.id }; if (this.#mongoId) filter._id = this.#mongoId; + if (json.points && typeof json.points !== 'number') + throw new Error('Invalid points type'); return this.#client.mongodb.infractions.updateOne(filter, { $set: this.json }) .catch((error: Error) => { @@ -566,6 +569,16 @@ class Infraction return InfractionColors[this.#type!]; } + get duration () + { + return this.#duration; + } + + set duration (duration: number | null) + { + this.#duration = duration; + } + // Super Functions protected _succeed (): InfractionSuccess { diff --git a/src/constants/Constants.ts b/src/constants/Constants.ts index 52a72b2..c1b065c 100644 --- a/src/constants/Constants.ts +++ b/src/constants/Constants.ts @@ -2,6 +2,7 @@ import { InfractionType } from "../../@types/Client.js"; const ZeroWidthChar = '\u200b'; const EmbedDefaultColor = 619452; +const Max32BitInt = 2147483647; const UploadLimit = { '0': 8, @@ -235,6 +236,7 @@ export { UploadLimit, ZeroWidthChar, EmbedDefaultColor, + Max32BitInt, PermissionNames, EmbedLimits, InfractionResolves, diff --git a/src/localization/en_gb/commands/en_gb_moderation.lang b/src/localization/en_gb/commands/en_gb_moderation.lang index 52b4261..3a37798 100644 --- a/src/localization/en_gb/commands/en_gb_moderation.lang +++ b/src/localization/en_gb/commands/en_gb_moderation.lang @@ -1,539 +1,545 @@ -[MODERATION_OWNER] -unable to moderate the user - -[MODERATION_MISSING_USERS] -You must provide target users. - -[MODERATION_MISSING_CHANNELS] -You must provide target channels. - -[INFRACTION_NOT_FOUND] -Could not find the infraction. - -//Note Command -[COMMAND_NOTE_HELP] -Note members with a description, will not be logged. -The only way to view notes is through moderation history. - -[C_NOTE_MISSINGMEMBERS] -You must provide members to assign notes to. - -[C_NOTE_MISSINGMEMBERPERMISSIONS] - -//Warn Command -[COMMAND_WARN_HELP] -Warn members for a particular reason. - -[COMMAND_WARN_INSUFFICIENTPERMISSIONS] -you don't have permission to run this command. - -//Unmute Command -[COMMAND_UNMUTE_HELP] -Unmute members from the server. - -[C_UNMUTE_MISSINGMEMBERS] -You must provide members to unmute. - -[C_UNMUTE_INSUFFICIENTPERMISSIONS] -I don't have permission to manage roles - -[C_UNMUTE_CANNOTFINDMUTE] -they were not previously muted - -[C_UNMUTE_ROLEDOESNOTEXIST] -the mute role does not exist anymore - -[C_UNMUTE_1FAIL] -I had an issue removing the role - -[C_UNMUTE_2FAIL] -I had issues assigning roles to them - -[C_UNMUTE_3FAIL] -I had issues granting roles to them - -//Mute Command -[COMMAND_MUTE_HELP] -Assign members to be muted from the server for a specified amount of time. - -[C_MUTE_MISSINGMEMBERS] -You must provide members to mute. - -[C_MUTE_DURATIONEXCEPTION] -The duration must be more than `1 minute` and less than `1 month`. - -[C_MUTE_INSUFFICIENTPERMISSIONS] -I don't have permission to manage roles - -[COMMAND_MUTE_NOMUTEROLE] -You don't have a mute role set in your server, use the command `/moderation mute` for more information. - -[COMMAND_MUTE_INVALIDMUTEROLE] -It seems like the mute role was deleted, use the command `/moderation mute` for more information. - -[COMMAND_MUTE_MISSING_MODERATE_PERM] -Missing permissions to timeout users (Moderate Member) - -[COMMAND_MUTE_HIERARCHY_ERROR] -the bot cannot timeout a user above its highest role - -[COMMAND_MUTE_MISSING_MANAGEROLE_PERM] -Missing permissions to manage roles. - -[COMMAND_MUTE_1FAIL] -I had an issue adding the role - -[COMMAND_MUTE_2FAIL] -I had issues assigning roles to them - -[COMMAND_MUTE_3FAIL] -I had issues revoking roles from them - -[COMMAND_MUTE_4FAIL] -request rejected (likely permission issue) - -//Kick Command -[COMMAND_KICK_HELP] -Kick provided members from the server. - -[C_KICK_INSUFFICIENTPERMISSIONS] -I don't have permission to kick members - -[C_KICK_CANNOTBEKICKED] -they are unable to be kicked - -[C_KICK_CANNOTBEKICKED_AUTOMOD] -Member is not kickable by the bot. - -//Softban Command -[COMMAND_SOFTBAN_HELP] -Bans and then unbans the member from the server. -Primarily used to prune the member's messages in all channels. - -[C_SOFTBAN_MISSINGMEMBERS] -You must provide members to softban. - -[C_SOFTBAN_INSUFFICIENTPERMISSIONS] -I don't have permission to ban members - -[C_SOFTBAN_CANNOTBESOFTBANNED] -they are unable to be softbanned - -//Ban Command -[COMMAND_BAN_HELP] -Ban provided members or users from the server. Works with users not in the server. -Optionally assign a time to ban them for. - -[C_BAN_MISSINGMEMBERS] -You must provide members to ban. - -[C_BAN_DURATIONREQUIRED] -You must provide a duration while using the **tempban** alias. - -[C_BAN_DURATIONEXCEPTION] -The duration must be more than `1 minute` and less than `3 months`. - -[C_BAN_INSUFFICIENTPERMISSIONS] -I don't have permission to ban members - -[C_BAN_CANNOTBEBANNED] -they are unable to be banned - -[C_BAN_ALREADYBANNED] -they are already banned - -//Unban Command -[COMMAND_UNBAN_HELP] -Unban provided users from the server. - -[C_UNBAN_MISSINGMEMBERS] -You must provide users to unban. - -[C_UNBAN_INSUFFICIENTPERMISSIONS] -I don't have permission to unban members - -[C_UNBAN_NOTBANNED] -they are not banned - -//MassBan Command -[COMMAND_MASSBAN_HELP] -Ban members based on user metadata provided by arguments. - -[C_MASSBAN_NORESULTS] -Failed to find any members with those arguments. - -[C_MASSBAN_VERIFICATION] -Found `{amount}` users with the provided arguments. Are you sure you want to continue banning the listed users? -This action cannot be undone easily. *(__y__es, __n__o)* - -[C_MASSBAN_INVALIDABORT] -You provided an invalid input, operation was aborted. - -[C_MASSBAN_ABORT] -Successfully aborted the operation. - -[C_MASSBAN_SUCCESS] -Successfully started massbanning specified users. This could take a while, you will be mentioned when it is completed. - -[C_MASSBAN_COMPLETED] -Completed the massban of all `{max}` users, where `{success}/{max}` succeeded. - -//Prune Command -[COMMAND_PRUNE_HELP] -Mass delete messages from provided channels. The amount provided is the amount of messages it searches, not deletes. Filters messages using a logical OR by default. **You cannot prune messages older than 2 weeks.** - -[C_PRUNE_CHANNELEXCEPTION] -You are only able to prune up to `3` channels at a time. - -[COMMAND_PRUNE_MISSING_AMOUNT] -You must provide an amount to prune. - -[C_PRUNE_INTEGEREXCEPTION] -The amount must be more than `1` and less than `300`. - -[C_PRUNE_INSUFFICIENTPERMISSIONS] -I don't have permission to manage messages - -[C_PRUNE_NON_TEXTCHANNEL] -Cannot prune a non-text based channel - -[C_PRUNE_NOTFETCHED] -I was unable to fetch any messages - -[C_PRUNE_NOTDELETABLE] -I could not delete those messages - -[C_PRUNE_NOFILTERRESULTS] -I could not find any messages with those arguments - -[C_PRUNE_NODELETE] -I had issues deleting those messages - -[C_PRUNE_MISSING_ACCESS] -Missing access to read messages in the channel. Ensure the bot has permissions to view channel and read message history. - -//Vckick Command -[COMMAND_VCKICK_HELP] -Kick provided members from their connected voice-channel. - -[C_VCKICK_MISSINGMEMBERS] -You must provide members to voice kick. - -[C_VCKICK_INSUFFICIENTPERMISSIONS] -I don't have permission to move members - -[C_VCKICK_NOCHANNEL] -they are not in a voice-channel - -//Slowmode Command -[COMMAND_SLOWMODE_HELP] -Set the slowmode in provided channels. Primarily used for setting the slowmode in smaller increments, while Discord will not let you. - -[C_SLOWMODE_SECONDREQUIRED] -You must provide a duration to set the slowmode to. - -[C_SLOWMODE_SECONDEXCEPTION] -The duration must be `0 seconds` or more, and less than `6 hours`. - -[C_SLOWMODE_INSUFFICIENTPERMISSIONS] -I don't have permission to manage channels - -[C_SLOWMODE_NOCHANGE] -the slowmode was already set to that - -//Nickname Command -[COMMAND_NICKNAME_HELP] -Change the nickname of provided members. You will have to put the nickname in quotes in order to allow for spaced nicknames. - -[C_NICKNAME_MISSINGMEMBERS] -You must provide members to nickname. - -[C_NICKNAME_MISSINGNAME] -You must provide arguments to change their nickname to. - -[C_NICKNAME_NOCHARACTERS] -they had no hoisted characters in their nickname - -[C_NICKNAME_INSUFFICIENTPERMISSIONS] -I don't have permission to manage nicknames - -[C_NICKNAME_MISSINGPERMISSIONS] -they have a higher role than I do - -//Dehoist Command -[COMMAND_DEHOIST_HELP] -Removes special characters from username or nickname that allow users to hoist themselves ontop of the member list. - -[C_DEHOIST_MISSINGMEMBERS] -You must provide members to dehoist. - -[COMMAND_ROLES_NO_ROLES] -No roles given. - -//Addrole Command -[COMMAND_ADDROLE_HELP] -Add roles to provided members. The added roles cannot be a higher position than the executor's highest role. - -[C_ADDROLE_MISSINGMEMBERS] -You must provide members to add roles to. - -[C_ADDROLE_MISSINGROLES] -You must provide roles to add to members. - -[C_ADDROLE_INSUFFICIENTPERMISSIONS] -I don't have permission to manage roles - -[C_ADDROLE_ROLEHIERARCHY] -the provided role(s) have a higher position than yours - -[C_ADDROLE_ROLEHIERARCHYBOT] -the provided role(s) are higher than the bot, I cannot add them - -[C_ADDROLE_ROLEGRANTABLEFAIL] -the provided role(s) are not on the grantable list - -//Removerole Command -[COMMAND_REMOVEROLE_HELP] -Remove roles to provided members. The removes roles cannot be a higher position than the executor's highest role. - -[C_REMOVEROLE_MISSINGMEMBERS] -You must provide members to remove roles from. - -[C_REMOVEROLE_MISSINGROLES] -You must provide roles to remove from members. - -[C_REMOVEROLE_INSUFFICIENTPERMISSIONS] -I don't have permission to manage roles - -[C_REMOVEROLE_ROLEHIERARCHY] -the provided role(s) have a higher position than yours - -[C_REMOVEROLE_ROLEHIERARCHYBOT] -the provided role(s) are higher than the bot, I cannot add them - -[C_REMOVEROLE_ROLEGRANTABLEFAIL] -the provided role(s) are not on the grantable list - -//History Command -[COMMAND_HISTORY_HELP] -Display moderation history in the server. -Narrow the search down by using the parameters below. - -[COMMAND_HISTORY_HISTORY] -Display moderation history for the server or for certain users. - -[COMMAND_HISTORY_ERROR] -I had issues finding moderation history in your server. - -[COMMAND_HISTORY_NORESULTS] -There are no results for that search query. - -[COMMAND_HISTORY_SUCCESSTYPE] -switch({old}) { - case true: - 'oldest'; - break; - case false: - 'newest'; - break; -} - -[COMMAND_HISTORY_SUCCESS] -Fetched the {type} moderation cases {targets}. - -[COMMAND_HISTORY_FAILTOOLONG] -Failed to display cases in one embed, try a smaller page size. - -[COMMAND_HISTORY_SUCCESSTARGETS] - for {targets} -//target{plural}: - -[COMMAND_HISTORY_SUCCESSMODERATOR] - by {moderator} - -[COMMAND_HISTORY_NO_EXPORT_PERMS] -Must be admin to export moderation history. - -[COMMAND_HISTORY_SUCCESSEXPORT] -Attached the JSON-formatted moderation file in the file below. -# You may want to format this file for easier viewing. - -[COMMAND_HISTORY_FAILEXPORT] -Unable to upload JSON file, the file is too large to upload here. **`[{amount}/{max}]`** -If you absolutely need this, contact a bot developer in our support server. - -//Case Command -[COMMAND_CASE_HELP] -View a specific case - -[COMMAND_CASE_NOTFOUND] -No case matching ID `{caseID}` was found. - -[COMMAND_CASE_TITLE] -{emoji_book} Case **#{caseID}** - -[COMMAND_CASE_TITLE_VERBOSE] -{emoji_book} Case **#{caseID} (verbose)** - -[COMMAND_CASE_CHANGES_TITLE] -{emoji_note} Changes to case **#{case}** - -[COMMAND_CASE_CHANGES_NONE] -No changes have been made to the case. - -[COMMAND_CASE_CHANGE_BASE] -**Timestamp:** {date} | {timeAgo} ago -**Staff:** {staff} - -[COMMAND_CASE_CHANGES_RESOLVE] -**Reason:** {reason} - -[COMMAND_CASE_CHANGES_REASON] -**Old reason:** {reason} - -[COMMAND_CASE_CHANGES_DURATION] -**Old duration:** {duration} - -[COMMAND_CASE_CHANGES_POINTS] -**Old points:** {points} - -[COMMAND_CASE_CHANGES_EXPIRATION] -**Old expiration:** {expiration} - -[COMMAND_CASE_CHANGES_AMOUNT] -• {changes} alterations - -[COMMAND_CASE_CHANGE_NOREASON] -`No reason given` - -[COMMAND_CASE_TEMPLATE] -**[Jump to message (if available)](https://discord.com/channels/{guild}/{channel}/{message})** - -**Unique ID:** {uniqueID} -**Type:** {type} -**Timestamp:** {date} | {relativeTime} -{target} -**Staff:** {staff} -**Changes:** {nrChanges} - -[COMMAND_CASE_TEMPLATE_VERBOSE] -**[Jump to message (if available)](https://discord.com/channels/{guild}/{channel}/{message})** -**Unique ID:** {uniqueID} -**Type:** {type} -**Timestamp:** {date} | {relativeTime} -**UNIX timestamp:** {unix} | {relativeTimeSeconds} seconds ago -{target} -**Staff:** {staff} ({staffID}) -**Amount of changes:** {nrChanges} -**Changes:** {changes} - -[COMMAND_CASE_MODPOINTS] -**Points:** {points} -**Expires:** {expires} - -[COMMAND_CASE_REASON] -**Reason:** -```{reason}``` - -[COMMAND_CASE_SLOWMODE] -**Slowmode:** {readable} - -[COMMAND_CASE_SLOWMODE_VERBOSE] -**Slowmode:** {readable} ({seconds}) seconds - -[COMMAND_CASE_TARGET_USER] -**User:** {target} - -[COMMAND_CASE_TARGET_CHANNEL] -**Channel:** #{target} - -[COMMAND_CASE_TARGET_USER_VERBOSE] -**User:** {target} ({targetID}) - -[COMMAND_CASE_TARGET_CHANNEL_VERBOSE] -**Channel:** #{target} ({targetID}) - -[COMMAND_CASE_LENGTH] -**Length:** {time} - -[COMMAND_CASE_LENGTH_VERBOSE] -**Length:** {time} ({inSeconds} seconds) - -// Edit command -[COMMAND_EDIT_HELP] -Edit case data, such as reason, duration, points and expiration. - -[COMMAND_EDIT_LONG] -Please respond with the new reason. -Timeout in {time} seconds - -[COMMAND_EDIT_NO_ARGS] -Must specify at least one property to edit. - -[COMMAND_EDIT_ISSUES] -The command ran into the following errors: -{issues} - -*Note that some of the edits were successful* - -[COMMAND_EDIT_FAILURE] -Failed to edit the infraction. -The following errors occurred: -- {issues} - -[COMMAND_EDIT_SUCCESS] -Successfully edited the infraction. - -//Resolve -[COMMAND_RESOLVE_HELP] -Resolve a case, undoes actions for bans & mutes. - -[COMMAND_RESOLVE_WARNING] -An issue arose while resolving the case: -{message} - -*Note that the infraction was resolved but actions may not have been reverted properly* - -[COMMAND_RESOLVE_SUCCESS] -Successfully resolved the case. - -// Staff command -[COMMAND_STAFF_HELP] -Summons staff if configured. - -[COMMAND_STAFF_CONFIRM] -**Are you sure your reason for mentioning staff is valid?** -{rule} - -This message will time out in 30 seconds. -*Click on the reaction to proceed* - -[COMMAND_STAFF_TIMEOUT] -Command timed out. - -[COMMAND_STAFF_ERROR] -Role seems to have been deleted. - -[COMMAND_STAFF_SUMMON] -<@&{role}> -Summoned by **{author}** - -[COMMAND_STAFF_NOT_SET] -No staff role set. - -// Modtimers -[COMMAND_MODTIMERS_HELP] -List currently active timed infractions, e.g. mutes & bans. - -[COMMAND_MODTIMERS_TITLE] -Currently active timed infractions - -[COMMAND_MODTIMERS_DESC] -**Target:** {target} -**Moderator:** {moderator} -**Issued:** , -**Ends:** , -**Reason:** {reason} - -[COMMAND_MODTIMERS_NONE] +[MODERATION_OWNER] +unable to moderate the user + +[MODERATION_MISSING_USERS] +You must provide target users. + +[MODERATION_MISSING_CHANNELS] +You must provide target channels. + +[INFRACTION_NOT_FOUND] +Could not find the infraction. + +//Note Command +[COMMAND_NOTE_HELP] +Note members with a description, will not be logged. +The only way to view notes is through moderation history. + +[C_NOTE_MISSINGMEMBERS] +You must provide members to assign notes to. + +[C_NOTE_MISSINGMEMBERPERMISSIONS] + +//Warn Command +[COMMAND_WARN_HELP] +Warn members for a particular reason. + +[COMMAND_WARN_INSUFFICIENTPERMISSIONS] +you don't have permission to run this command. + +//Unmute Command +[COMMAND_UNMUTE_HELP] +Unmute members from the server. + +[C_UNMUTE_MISSINGMEMBERS] +You must provide members to unmute. + +[C_UNMUTE_INSUFFICIENTPERMISSIONS] +I don't have permission to manage roles + +[C_UNMUTE_CANNOTFINDMUTE] +they were not previously muted + +[C_UNMUTE_ROLEDOESNOTEXIST] +the mute role does not exist anymore + +[C_UNMUTE_1FAIL] +I had an issue removing the role + +[C_UNMUTE_2FAIL] +I had issues assigning roles to them + +[C_UNMUTE_3FAIL] +I had issues granting roles to them + +//Mute Command +[COMMAND_MUTE_HELP] +Assign members to be muted from the server for a specified amount of time. + +[C_MUTE_MISSINGMEMBERS] +You must provide members to mute. + +[C_MUTE_DURATIONEXCEPTION] +The duration must be more than `1 minute` and less than `1 month`. + +[C_MUTE_INSUFFICIENTPERMISSIONS] +I don't have permission to manage roles + +[COMMAND_MUTE_NOMUTEROLE] +You don't have a mute role set in your server, use the command `/moderation mute` for more information. + +[COMMAND_MUTE_INVALIDMUTEROLE] +It seems like the mute role was deleted, use the command `/moderation mute` for more information. + +[COMMAND_MUTE_MISSING_MODERATE_PERM] +Missing permissions to timeout users (Moderate Member) + +[COMMAND_MUTE_HIERARCHY_ERROR] +the bot cannot timeout a user above its highest role + +[COMMAND_MUTE_MISSING_MANAGEROLE_PERM] +Missing permissions to manage roles. + +[COMMAND_MUTE_1FAIL] +I had an issue adding the role + +[COMMAND_MUTE_2FAIL] +I had issues assigning roles to them + +[COMMAND_MUTE_3FAIL] +I had issues revoking roles from them + +[COMMAND_MUTE_4FAIL] +request rejected (likely permission issue) + +//Kick Command +[COMMAND_KICK_HELP] +Kick provided members from the server. + +[C_KICK_INSUFFICIENTPERMISSIONS] +I don't have permission to kick members + +[C_KICK_CANNOTBEKICKED] +they are unable to be kicked + +[C_KICK_CANNOTBEKICKED_AUTOMOD] +Member is not kickable by the bot. + +//Softban Command +[COMMAND_SOFTBAN_HELP] +Bans and then unbans the member from the server. +Primarily used to prune the member's messages in all channels. + +[C_SOFTBAN_MISSINGMEMBERS] +You must provide members to softban. + +[C_SOFTBAN_INSUFFICIENTPERMISSIONS] +I don't have permission to ban members + +[C_SOFTBAN_CANNOTBESOFTBANNED] +they are unable to be softbanned + +//Ban Command +[COMMAND_BAN_HELP] +Ban provided members or users from the server. Works with users not in the server. +Optionally assign a time to ban them for. + +[C_BAN_MISSINGMEMBERS] +You must provide members to ban. + +[C_BAN_DURATIONREQUIRED] +You must provide a duration while using the **tempban** alias. + +[C_BAN_DURATIONEXCEPTION] +The duration must be more than `1 minute` and less than `3 months`. + +[C_BAN_INSUFFICIENTPERMISSIONS] +I don't have permission to ban members + +[C_BAN_CANNOTBEBANNED] +they are unable to be banned + +[C_BAN_ALREADYBANNED] +they are already banned + +//Unban Command +[COMMAND_UNBAN_HELP] +Unban provided users from the server. + +[C_UNBAN_MISSINGMEMBERS] +You must provide users to unban. + +[C_UNBAN_INSUFFICIENTPERMISSIONS] +I don't have permission to unban members + +[C_UNBAN_NOTBANNED] +they are not banned + +//MassBan Command +[COMMAND_MASSBAN_HELP] +Ban members based on user metadata provided by arguments. + +[C_MASSBAN_NORESULTS] +Failed to find any members with those arguments. + +[C_MASSBAN_VERIFICATION] +Found `{amount}` users with the provided arguments. Are you sure you want to continue banning the listed users? +This action cannot be undone easily. *(__y__es, __n__o)* + +[C_MASSBAN_INVALIDABORT] +You provided an invalid input, operation was aborted. + +[C_MASSBAN_ABORT] +Successfully aborted the operation. + +[C_MASSBAN_SUCCESS] +Successfully started massbanning specified users. This could take a while, you will be mentioned when it is completed. + +[C_MASSBAN_COMPLETED] +Completed the massban of all `{max}` users, where `{success}/{max}` succeeded. + +//Prune Command +[COMMAND_PRUNE_HELP] +Mass delete messages from provided channels. The amount provided is the amount of messages it searches, not deletes. Filters messages using a logical OR by default. **You cannot prune messages older than 2 weeks.** + +[C_PRUNE_CHANNELEXCEPTION] +You are only able to prune up to `3` channels at a time. + +[COMMAND_PRUNE_MISSING_AMOUNT] +You must provide an amount to prune. + +[C_PRUNE_INTEGEREXCEPTION] +The amount must be more than `1` and less than `300`. + +[C_PRUNE_INSUFFICIENTPERMISSIONS] +I don't have permission to manage messages + +[C_PRUNE_NON_TEXTCHANNEL] +Cannot prune a non-text based channel + +[C_PRUNE_NOTFETCHED] +I was unable to fetch any messages + +[C_PRUNE_NOTDELETABLE] +I could not delete those messages + +[C_PRUNE_NOFILTERRESULTS] +I could not find any messages with those arguments + +[C_PRUNE_NODELETE] +I had issues deleting those messages + +[C_PRUNE_MISSING_ACCESS] +Missing access to read messages in the channel. Ensure the bot has permissions to view channel and read message history. + +//Vckick Command +[COMMAND_VCKICK_HELP] +Kick provided members from their connected voice-channel. + +[C_VCKICK_MISSINGMEMBERS] +You must provide members to voice kick. + +[C_VCKICK_INSUFFICIENTPERMISSIONS] +I don't have permission to move members + +[C_VCKICK_NOCHANNEL] +they are not in a voice-channel + +//Slowmode Command +[COMMAND_SLOWMODE_HELP] +Set the slowmode in provided channels. Primarily used for setting the slowmode in smaller increments, while Discord will not let you. + +[C_SLOWMODE_SECONDREQUIRED] +You must provide a duration to set the slowmode to. + +[C_SLOWMODE_SECONDEXCEPTION] +The duration must be `0 seconds` or more, and less than `6 hours`. + +[C_SLOWMODE_INSUFFICIENTPERMISSIONS] +I don't have permission to manage channels + +[C_SLOWMODE_NOCHANGE] +the slowmode was already set to that + +//Nickname Command +[COMMAND_NICKNAME_HELP] +Change the nickname of provided members. You will have to put the nickname in quotes in order to allow for spaced nicknames. + +[C_NICKNAME_MISSINGMEMBERS] +You must provide members to nickname. + +[C_NICKNAME_MISSINGNAME] +You must provide arguments to change their nickname to. + +[C_NICKNAME_NOCHARACTERS] +they had no hoisted characters in their nickname + +[C_NICKNAME_INSUFFICIENTPERMISSIONS] +I don't have permission to manage nicknames + +[C_NICKNAME_MISSINGPERMISSIONS] +they have a higher role than I do + +//Dehoist Command +[COMMAND_DEHOIST_HELP] +Removes special characters from username or nickname that allow users to hoist themselves ontop of the member list. + +[C_DEHOIST_MISSINGMEMBERS] +You must provide members to dehoist. + +[COMMAND_ROLES_NO_ROLES] +No roles given. + +//Addrole Command +[COMMAND_ADDROLE_HELP] +Add roles to provided members. The added roles cannot be a higher position than the executor's highest role. + +[C_ADDROLE_MISSINGMEMBERS] +You must provide members to add roles to. + +[C_ADDROLE_MISSINGROLES] +You must provide roles to add to members. + +[C_ADDROLE_INSUFFICIENTPERMISSIONS] +I don't have permission to manage roles + +[C_ADDROLE_ROLEHIERARCHY] +the provided role(s) have a higher position than yours + +[C_ADDROLE_ROLEHIERARCHYBOT] +the provided role(s) are higher than the bot, I cannot add them + +[C_ADDROLE_ROLEGRANTABLEFAIL] +the provided role(s) are not on the grantable list + +//Removerole Command +[COMMAND_REMOVEROLE_HELP] +Remove roles to provided members. The removes roles cannot be a higher position than the executor's highest role. + +[C_REMOVEROLE_MISSINGMEMBERS] +You must provide members to remove roles from. + +[C_REMOVEROLE_MISSINGROLES] +You must provide roles to remove from members. + +[C_REMOVEROLE_INSUFFICIENTPERMISSIONS] +I don't have permission to manage roles + +[C_REMOVEROLE_ROLEHIERARCHY] +the provided role(s) have a higher position than yours + +[C_REMOVEROLE_ROLEHIERARCHYBOT] +the provided role(s) are higher than the bot, I cannot add them + +[C_REMOVEROLE_ROLEGRANTABLEFAIL] +the provided role(s) are not on the grantable list + +//History Command +[COMMAND_HISTORY_HELP] +Display moderation history in the server. +Narrow the search down by using the parameters below. + +[COMMAND_HISTORY_HISTORY] +Display moderation history for the server or for certain users. + +[COMMAND_HISTORY_ERROR] +I had issues finding moderation history in your server. + +[COMMAND_HISTORY_NORESULTS] +There are no results for that search query. + +[COMMAND_HISTORY_SUCCESSTYPE] +switch({old}) { + case true: + 'oldest'; + break; + case false: + 'newest'; + break; +} + +[COMMAND_HISTORY_SUCCESS] +Fetched the {type} moderation cases {targets}. + +[COMMAND_HISTORY_FAILTOOLONG] +Failed to display cases in one embed, try a smaller page size. + +[COMMAND_HISTORY_SUCCESSTARGETS] + for {targets} +//target{plural}: + +[COMMAND_HISTORY_SUCCESSMODERATOR] + by {moderator} + +[COMMAND_HISTORY_NO_EXPORT_PERMS] +Must be admin to export moderation history. + +[COMMAND_HISTORY_SUCCESSEXPORT] +Attached the JSON-formatted moderation file in the file below. +# You may want to format this file for easier viewing. + +[COMMAND_HISTORY_FAILEXPORT] +Unable to upload JSON file, the file is too large to upload here. **`[{amount}/{max}]`** +If you absolutely need this, contact a bot developer in our support server. + +//Case Command +[COMMAND_CASE_HELP] +View a specific case + +[COMMAND_CASE_NOTFOUND] +No case matching ID `{caseID}` was found. + +[COMMAND_CASE_DELETED] +Case `{caseID}` was deleted. + +[COMMAND_CASE_DELETED_LOG] +Case deleted. + +[COMMAND_CASE_TITLE] +{emoji_book} Case **#{caseID}** + +[COMMAND_CASE_TITLE_VERBOSE] +{emoji_book} Case **#{caseID} (verbose)** + +[COMMAND_CASE_CHANGES_TITLE] +{emoji_note} Changes to case **#{case}** + +[COMMAND_CASE_CHANGES_NONE] +No changes have been made to the case. + +[COMMAND_CASE_CHANGE_BASE] +**Timestamp:** {date} | {timeAgo} ago +**Staff:** {staff} + +[COMMAND_CASE_CHANGES_RESOLVE] +**Reason:** {reason} + +[COMMAND_CASE_CHANGES_REASON] +**Old reason:** {reason} + +[COMMAND_CASE_CHANGES_DURATION] +**Old duration:** {duration} + +[COMMAND_CASE_CHANGES_POINTS] +**Old points:** {points} + +[COMMAND_CASE_CHANGES_EXPIRATION] +**Old expiration:** {expiration} + +[COMMAND_CASE_CHANGES_AMOUNT] +• {changes} alterations + +[COMMAND_CASE_CHANGE_NOREASON] +`No reason given` + +[COMMAND_CASE_TEMPLATE] +**[Jump to message (if available)](https://discord.com/channels/{guild}/{channel}/{message})** + +**Unique ID:** {uniqueID} +**Type:** {type} +**Timestamp:** {date} | {relativeTime} +{target} +**Staff:** {staff} +**Changes:** {nrChanges} + +[COMMAND_CASE_TEMPLATE_VERBOSE] +**[Jump to message (if available)](https://discord.com/channels/{guild}/{channel}/{message})** +**Unique ID:** {uniqueID} +**Type:** {type} +**Timestamp:** {date} | {relativeTime} +**UNIX timestamp:** {unix} | {relativeTimeSeconds} seconds ago +{target} +**Staff:** {staff} ({staffID}) +**Amount of changes:** {nrChanges} +**Changes:** {changes} + +[COMMAND_CASE_MODPOINTS] +**Points:** {points} +**Expires:** {expires} + +[COMMAND_CASE_REASON] +**Reason:** +```{reason}``` + +[COMMAND_CASE_SLOWMODE] +**Slowmode:** {readable} + +[COMMAND_CASE_SLOWMODE_VERBOSE] +**Slowmode:** {readable} ({seconds}) seconds + +[COMMAND_CASE_TARGET_USER] +**User:** {target} + +[COMMAND_CASE_TARGET_CHANNEL] +**Channel:** #{target} + +[COMMAND_CASE_TARGET_USER_VERBOSE] +**User:** {target} ({targetID}) + +[COMMAND_CASE_TARGET_CHANNEL_VERBOSE] +**Channel:** #{target} ({targetID}) + +[COMMAND_CASE_LENGTH] +**Length:** {time} + +[COMMAND_CASE_LENGTH_VERBOSE] +**Length:** {time} ({inSeconds} seconds) + +// Edit command +[COMMAND_EDIT_HELP] +Edit case data, such as reason, duration, points and expiration. + +[COMMAND_EDIT_LONG] +Please respond with the new reason. +Timeout in {time} seconds + +[COMMAND_EDIT_NO_ARGS] +Must specify at least one property to edit. + +[COMMAND_EDIT_ISSUES] +The command ran into the following errors: +{issues} + +*Note that some of the edits were successful* + +[COMMAND_EDIT_FAILURE] +Failed to edit the infraction. +The following errors occurred: +- {issues} + +[COMMAND_EDIT_SUCCESS] +Successfully edited the infraction. + +//Resolve +[COMMAND_RESOLVE_HELP] +Resolve a case, undoes actions for bans & mutes. + +[COMMAND_RESOLVE_WARNING] +An issue arose while resolving the case: +{message} + +*Note that the infraction was resolved but actions may not have been reverted properly* + +[COMMAND_RESOLVE_SUCCESS] +Successfully resolved the case. + +// Staff command +[COMMAND_STAFF_HELP] +Summons staff if configured. + +[COMMAND_STAFF_CONFIRM] +**Are you sure your reason for mentioning staff is valid?** +{rule} + +This message will time out in 30 seconds. +*Click on the reaction to proceed* + +[COMMAND_STAFF_TIMEOUT] +Command timed out. + +[COMMAND_STAFF_ERROR] +Role seems to have been deleted. + +[COMMAND_STAFF_SUMMON] +<@&{role}> +Summoned by **{author}** + +[COMMAND_STAFF_NOT_SET] +No staff role set. + +// Modtimers +[COMMAND_MODTIMERS_HELP] +List currently active timed infractions, e.g. mutes & bans. + +[COMMAND_MODTIMERS_TITLE] +Currently active timed infractions + +[COMMAND_MODTIMERS_DESC] +**Target:** {target} +**Moderator:** {moderator} +**Issued:** , +**Ends:** , +**Reason:** {reason} + +[COMMAND_MODTIMERS_NONE] No active timed infractions. \ No newline at end of file