Create timeout command (#302)
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
- Create timeout command #98 Co-authored-by: Ethan Lane <ethan@vylpes.com> Reviewed-on: https://gitea.vylpes.xyz/RabbitLabs/vylbot-app/pulls/302
This commit is contained in:
parent
46226d37a7
commit
4f2c186244
7 changed files with 1036 additions and 9 deletions
151
src/commands/timeout.ts
Normal file
151
src/commands/timeout.ts
Normal file
|
@ -0,0 +1,151 @@
|
|||
import { CacheType, CommandInteraction, EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandBuilder, TextChannel } from "discord.js";
|
||||
import { AuditType } from "../constants/AuditType";
|
||||
import EmbedColours from "../constants/EmbedColours";
|
||||
import Audit from "../database/entities/Audit";
|
||||
import SettingsHelper from "../helpers/SettingsHelper";
|
||||
import TimeLengthInput from "../helpers/TimeLengthInput";
|
||||
import { Command } from "../type/command";
|
||||
|
||||
export default class Timeout extends Command {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
super.CommandBuilder = new SlashCommandBuilder()
|
||||
.setName("timeout")
|
||||
.setDescription("Timeouts a user out, sending them a DM with the reason if possible")
|
||||
.setDefaultMemberPermissions(PermissionsBitField.Flags.ModerateMembers)
|
||||
.addUserOption(option =>
|
||||
option
|
||||
.setName('target')
|
||||
.setDescription('The user')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("length")
|
||||
.setDescription("How long to timeout for? (Example: 24h, 60m)")
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName('reason')
|
||||
.setDescription('The reason'));
|
||||
}
|
||||
|
||||
public override async execute(interaction: CommandInteraction<CacheType>) {
|
||||
if (!interaction.guild || !interaction.guildId) return;
|
||||
|
||||
// Interaction Inputs
|
||||
const targetUser = interaction.options.get('target');
|
||||
const lengthInput = interaction.options.get('length');
|
||||
const reasonInput = interaction.options.get('reason');
|
||||
|
||||
// Validation
|
||||
if (!targetUser || !targetUser.user || !targetUser.member) {
|
||||
await interaction.reply('Fields are required.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lengthInput || !lengthInput.value) {
|
||||
await interaction.reply('Fields are required.');
|
||||
return;
|
||||
}
|
||||
|
||||
// General Variables
|
||||
const targetMember = targetUser.member as GuildMember;
|
||||
const reason = reasonInput && reasonInput.value ? reasonInput.value.toString() : null;
|
||||
|
||||
const timeLength = new TimeLengthInput(lengthInput.value.toString());
|
||||
|
||||
const logEmbed = new EmbedBuilder()
|
||||
.setColor(EmbedColours.Ok)
|
||||
.setTitle("Member Timed Out")
|
||||
.setDescription(`<@${targetUser.user.id}> \`${targetUser.user.tag}\``)
|
||||
.addFields([
|
||||
{
|
||||
name: "Moderator",
|
||||
value: `<@${interaction.user.id}>`,
|
||||
},
|
||||
{
|
||||
name: "Reason",
|
||||
value: reason || "*none*",
|
||||
},
|
||||
{
|
||||
name: "Length",
|
||||
value: timeLength.GetLengthShort(),
|
||||
},
|
||||
{
|
||||
name: "Until",
|
||||
value: timeLength.GetDateFromNow().toString(),
|
||||
},
|
||||
]);
|
||||
|
||||
// Bot Permissions Check
|
||||
if (!targetMember.manageable) {
|
||||
await interaction.reply('Insufficient bot permissions. Please contact a moderator.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute Timeout
|
||||
await targetMember.timeout(timeLength.GetMilliseconds(), reason || "");
|
||||
|
||||
// Log Embed To Channel
|
||||
const channelName = await SettingsHelper.GetSetting('channels.logs.mod', interaction.guildId);
|
||||
|
||||
if (!channelName) return;
|
||||
|
||||
const channel = interaction.guild.channels.cache.find(x => x.name == channelName) as TextChannel;
|
||||
|
||||
if (channel) {
|
||||
await channel.send({ embeds: [ logEmbed ]});
|
||||
}
|
||||
|
||||
// Create Audit
|
||||
const audit = new Audit(targetUser.user.id, AuditType.Timeout, reason || "*none*", interaction.user.id, interaction.guildId);
|
||||
await audit.Save(Audit, audit);
|
||||
|
||||
// DM User, if possible
|
||||
const resultEmbed = new EmbedBuilder()
|
||||
.setColor(EmbedColours.Ok)
|
||||
.setDescription(`<@${targetUser.user.id}> has been timed out`);
|
||||
|
||||
const dmEmbed = new EmbedBuilder()
|
||||
.setColor(EmbedColours.Ok)
|
||||
.setDescription(`You have been timed out in ${interaction.guild.name}`)
|
||||
.addFields([
|
||||
{
|
||||
name: "Reason",
|
||||
value: reason || "*none*"
|
||||
},
|
||||
{
|
||||
name: "Length",
|
||||
value: timeLength.GetLengthShort(),
|
||||
},
|
||||
{
|
||||
name: "Until",
|
||||
value: timeLength.GetDateFromNow().toString(),
|
||||
},
|
||||
]);
|
||||
|
||||
try {
|
||||
const dmChannel = await targetUser.user.createDM();
|
||||
|
||||
await dmChannel.send({ embeds: [ dmEmbed ]});
|
||||
|
||||
resultEmbed.addFields([
|
||||
{
|
||||
name: "DM Sent",
|
||||
value: "true",
|
||||
},
|
||||
]);
|
||||
} catch {
|
||||
resultEmbed.addFields([
|
||||
{
|
||||
name: "DM Sent",
|
||||
value: "false",
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
// Success Reply
|
||||
await interaction.reply({ embeds: [ resultEmbed ]});
|
||||
}
|
||||
}
|
|
@ -4,4 +4,5 @@ export enum AuditType {
|
|||
Mute,
|
||||
Kick,
|
||||
Ban,
|
||||
Timeout,
|
||||
}
|
|
@ -13,6 +13,8 @@ export default class AuditTools {
|
|||
return "Kick";
|
||||
case AuditType.Ban:
|
||||
return "Ban";
|
||||
case AuditType.Timeout:
|
||||
return "Timeout";
|
||||
default:
|
||||
return "Other";
|
||||
}
|
||||
|
@ -30,6 +32,8 @@ export default class AuditTools {
|
|||
return AuditType.Kick;
|
||||
case "ban":
|
||||
return AuditType.Ban;
|
||||
case "timeout":
|
||||
return AuditType.Timeout;
|
||||
default:
|
||||
return AuditType.General;
|
||||
}
|
||||
|
|
119
src/helpers/TimeLengthInput.ts
Normal file
119
src/helpers/TimeLengthInput.ts
Normal file
|
@ -0,0 +1,119 @@
|
|||
export default class TimeLengthInput {
|
||||
public readonly value: string;
|
||||
|
||||
constructor(input: string) {
|
||||
this.value = input;
|
||||
}
|
||||
|
||||
public GetDays(): number {
|
||||
return this.GetValue('d');
|
||||
}
|
||||
|
||||
public GetHours(): number {
|
||||
return this.GetValue('h');
|
||||
}
|
||||
|
||||
public GetMinutes(): number {
|
||||
return this.GetValue('m');
|
||||
}
|
||||
|
||||
public GetSeconds(): number {
|
||||
return this.GetValue('s');
|
||||
}
|
||||
|
||||
public GetMilliseconds(): number {
|
||||
const days = this.GetDays();
|
||||
const hours = this.GetHours();
|
||||
const minutes = this.GetMinutes();
|
||||
const seconds = this.GetSeconds();
|
||||
|
||||
let milliseconds = 0;
|
||||
|
||||
milliseconds += seconds * 1000;
|
||||
milliseconds += minutes * 60 * 1000;
|
||||
milliseconds += hours * 60 * 60 * 1000;
|
||||
milliseconds += days * 24 * 60 * 60 * 1000;
|
||||
|
||||
return milliseconds;
|
||||
}
|
||||
|
||||
public GetDateFromNow(): Date {
|
||||
const now = Date.now();
|
||||
|
||||
const dateFromNow = now
|
||||
+ (1000 * this.GetSeconds())
|
||||
+ (1000 * 60 * this.GetMinutes())
|
||||
+ (1000 * 60 * 60 * this.GetHours())
|
||||
+ (1000 * 60 * 60 * 24 * this.GetDays());
|
||||
|
||||
return new Date(dateFromNow);
|
||||
}
|
||||
|
||||
public GetLength(): string {
|
||||
const days = this.GetDays();
|
||||
const hours = this.GetHours();
|
||||
const minutes = this.GetMinutes();
|
||||
const seconds = this.GetSeconds();
|
||||
|
||||
const value = [];
|
||||
|
||||
if (days) {
|
||||
value.push(`${days} days`);
|
||||
}
|
||||
|
||||
if (hours) {
|
||||
value.push(`${hours} hours`);
|
||||
}
|
||||
|
||||
if (minutes) {
|
||||
value.push(`${minutes} minutes`);
|
||||
}
|
||||
|
||||
if (seconds) {
|
||||
value.push(`${seconds} seconds`);
|
||||
}
|
||||
|
||||
return value.join(", ");
|
||||
}
|
||||
|
||||
public GetLengthShort(): string {
|
||||
const days = this.GetDays();
|
||||
const hours = this.GetHours();
|
||||
const minutes = this.GetMinutes();
|
||||
const seconds = this.GetSeconds();
|
||||
|
||||
const value = [];
|
||||
|
||||
if (days) {
|
||||
value.push(`${days}d`);
|
||||
}
|
||||
|
||||
if (hours) {
|
||||
value.push(`${hours}h`);
|
||||
}
|
||||
|
||||
if (minutes) {
|
||||
value.push(`${minutes}m`);
|
||||
}
|
||||
|
||||
if (seconds) {
|
||||
value.push(`${seconds}s`);
|
||||
}
|
||||
|
||||
return value.join(" ");
|
||||
}
|
||||
|
||||
private GetValue(designation: string): number {
|
||||
const valueSplit = this.value.split(' ');
|
||||
|
||||
const desString = valueSplit.find(x => x.charAt(x.length - 1) == designation);
|
||||
|
||||
if (!desString) return 0;
|
||||
|
||||
const desNumber = Number(desString.substring(0, desString.length - 1));
|
||||
|
||||
if (!desNumber) return 0;
|
||||
|
||||
return desNumber;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import Role from "./commands/Role/role";
|
|||
import ConfigRole from "./commands/Role/config";
|
||||
import Rules from "./commands/rules";
|
||||
import Setup from "./commands/setup";
|
||||
import Timeout from "./commands/timeout";
|
||||
import Unmute from "./commands/unmute";
|
||||
import Warn from "./commands/warn";
|
||||
|
||||
|
@ -38,6 +39,7 @@ import MessageCreate from "./events/MessageEvents/MessageCreate";
|
|||
export default class Registry {
|
||||
public static RegisterCommands() {
|
||||
CoreClient.RegisterCommand("about", new About());
|
||||
CoreClient.RegisterCommand("audits", new Audits());
|
||||
CoreClient.RegisterCommand("ban", new Ban());
|
||||
CoreClient.RegisterCommand("bunny", new Bunny());
|
||||
CoreClient.RegisterCommand("clear", new Clear());
|
||||
|
@ -48,10 +50,10 @@ export default class Registry {
|
|||
CoreClient.RegisterCommand("kick", new Kick());
|
||||
CoreClient.RegisterCommand("mute", new Mute());
|
||||
CoreClient.RegisterCommand("rules", new Rules());
|
||||
CoreClient.RegisterCommand("setup", new Setup());
|
||||
CoreClient.RegisterCommand("timeout", new Timeout());
|
||||
CoreClient.RegisterCommand("unmute", new Unmute());
|
||||
CoreClient.RegisterCommand("warn", new Warn());
|
||||
CoreClient.RegisterCommand("setup", new Setup());
|
||||
CoreClient.RegisterCommand("audits", new Audits());
|
||||
|
||||
CoreClient.RegisterCommand("role", new Role());
|
||||
CoreClient.RegisterCommand("configrole", new ConfigRole());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue