diff --git a/src/commands/rank.ts b/src/commands/rank.ts index 7ccebed..0c42caa 100644 --- a/src/commands/rank.ts +++ b/src/commands/rank.ts @@ -1,5 +1,7 @@ +import ms from 'ms'; import Discord from 'discord.js'; import TClient from '../client.js'; +import Formatters from '../helpers/Formatters.js'; import MessageTool from '../helpers/MessageTool.js'; import CanvasBuilder from '../components/CanvasGraph.js'; export default class Rank { @@ -53,6 +55,30 @@ export default class Rank { await findUserInDatabase.update({pingToggle: false}, {where: {id: interaction.user.id}}) interaction.reply({content: 'You won\'t '+textDeco, ephemeral: true}) } + }, + temp_block: async()=>{ + if (!(MessageTool.isModerator(interaction.member) || client.config.whitelist.includes(interaction.member.id))) return MessageTool.youNeedRole(interaction, 'dcmod'); + const member = interaction.options.getMember('member'); + const duration = ms(interaction.options.getString('duration')); + const reason = interaction.options.getString('reason'); + const botlog = interaction.guild.channels.cache.get(client.config.dcServer.channels.logs) as Discord.TextChannel; + + if (await client.userLevels.blockUser(member.id, Date.now() + duration)) { + await interaction.reply(`Done, DM has been sent to **${member.displayName}** with the reason.`); + botlog.send({embeds: [new client.embed() + .setColor(client.config.embedColor) + .setTitle('[Rank] Member temporarily blocked') + .setFields( + {name: 'Member', value: `${member.displayName} (\`${member.id}\`)`}, + {name: 'Duration', value: Formatters.timeFormat(duration, 2, {longNames: true, commas: false}), inline: true}, + {name: 'Reason', value: reason, inline: true} + ) + ]}); + member.send(MessageTool.concatMessage( + `You have been blocked from incrementing your messages for **${Formatters.timeFormat(duration, 2, {longNames: true, commas: false})}** in **${interaction.guild.name}**.`, + `Reason: \`${reason}\`` + )).catch(()=>null); + } else interaction.reply(`**${member.displayName}** is already blocked.`); } } as any)[interaction.options.getSubcommand()](); } @@ -71,4 +97,19 @@ export default class Rank { .addSubcommand(x=>x .setName('notification') .setDescription('Allow the bot to ping you or not when you level up')) + .addSubcommand(x=>x + .setName('temp_block') + .setDescription('Temporarily block the member from incrementing their messages') + .addUserOption(x=>x + .setName('member') + .setDescription('Which member do you want to prevent?') + .setRequired(true)) + .addStringOption(x=>x + .setName('duration') + .setDescription('How long do you want to block the member for?') + .setRequired(true)) + .addStringOption(x=>x + .setName('reason') + .setDescription('Reason for blocking the member') + .setRequired(true))) } diff --git a/src/index.ts b/src/index.ts index a5d6946..43284cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,6 +28,13 @@ setInterval(()=>YTModule(client), 180000); // 3 minutes setInterval(async()=>{ const now = Date.now(); + const checkExpiration = await client.userLevels.fetchEveryone(); + checkExpiration.filter(x=>x.isBlocked && x.time <= now).forEach(async user=>{ + Logger.console('log', 'LevelSystem', `${user.dataValues.id}'s block should expire now`); + user.update({isBlocked: false, time: null}, {where: {id: user.dataValues.id}}); + client.users.send(user.dataValues.id, `Your rank block has expired, you can now continue to progress your level.`); + }); + const punishments = await client.punishments.findInCache(); punishments.filter((x:Punishment)=>x.endTime && x.endTime <= now && !x.expired).forEach(async (punishment:Punishment)=>{ Logger.console('log', 'Punishment', `${punishment.member}\'s ${punishment.type} should expire now`); diff --git a/src/models/punishments.ts b/src/models/punishments.ts index 85d2dcc..16fd1ff 100644 --- a/src/models/punishments.ts +++ b/src/models/punishments.ts @@ -216,7 +216,7 @@ export class PunishmentsSvc { const guild = this.client.guilds.cache.get(this.client.config.dcServer.id) as Discord.Guild; const auditLogReason = `${reason ?? 'Reason unspecified'} | Case #${ID}`; const user = await this.client.users.fetch(punishment.member); - const guildUser = await guild.members.fetch(punishment.member).catch(()=>null); + const guildUser:Discord.GuildMember = await guild.members.fetch(punishment.member).catch(()=>null); let removePunishmentData:Punishment = {type: `un${punishment.type}`, case_id: ID, cancels: punishment.case_id, member: punishment.member, reason, moderator, time: now}; let removePunishmentResult:any; diff --git a/src/models/userLevels.ts b/src/models/userLevels.ts index 8d6b8e3..cd2708f 100644 --- a/src/models/userLevels.ts +++ b/src/models/userLevels.ts @@ -12,6 +12,8 @@ class userLevels extends Model { declare public messages: number; declare public level: number; declare public pingToggle: boolean; + declare public time: number; + declare public isBlocked: boolean; } export class UserLevelsSvc { @@ -29,15 +31,23 @@ export class UserLevelsSvc { }, messages: { type: DataTypes.INTEGER, - allowNull: false, + allowNull: false }, level: { type: DataTypes.INTEGER, - allowNull: false, + allowNull: false }, pingToggle: { type: DataTypes.BOOLEAN, - allowNull: true, + allowNull: true + }, + time: { + type: DataTypes.BIGINT, + allowNull: true + }, + isBlocked: { + type: DataTypes.BOOLEAN, + allowNull: true } }, { tableName: 'userlevels', @@ -54,12 +64,21 @@ export class UserLevelsSvc { await this.model.update({messages: updatedMessages}, {where: {id: userId}}); return (await this.model.findByPk(userId)).dataValues; } + async blockUser(userId:string, duration:number):Promise { + const data = await this.model.findByPk(userId); + if (data && data.dataValues.isBlocked) return false; + else if (data) { + await this.model.update({time: duration, isBlocked: true}, {where: {id: userId}}); + return true; + } + } async getActiveUsers() { const members = (await this.model.findAll()).sort((a,b)=>b.dataValues.messages-a.dataValues.messages); return members.slice(0, 5); } async messageIncremental(userId:string) { const data = await this.model.findByPk(userId); + if (data && data.dataValues.isBlocked) return; if (data) { await this.model.update({messages: data.dataValues.messages + 1}, {where: {id: userId}}); if (data.messages >= this.algorithm(data.dataValues.level+2)) { @@ -73,7 +92,7 @@ export class UserLevelsSvc { const levelUpMsg = `${getUser.pingToggle === true ? `<@${userId}>` : `**${(await this.client.users.fetch(userId)).displayName}**`} has reached level **${getUser.level}**. Well done!`; (this.client.channels.resolve(this.client.config.dcServer.channels.botcommands) as Discord.TextChannel).send({content: levelUpMsg, allowedMentions: {parse: ['users']}}); } - } else await this.model.create({id: userId, messages: 1, level: 0, pingToggle: true}); + } else await this.model.create({id: userId, messages: 1, level: 0, pingToggle: true, isBlocked: false}); } async dataSweeper() { // Every Monday at 12:00 (Sydney Time)