Browse Source

Implement violation clear on start

ghorsington 4 years ago
parent
commit
fb16adfcfa
1 changed files with 66 additions and 18 deletions
  1. 66 18
      bot/src/plugins/violation.ts

+ 66 - 18
bot/src/plugins/violation.ts

@@ -25,9 +25,52 @@ interface ViolationInfo {
 
 type TimedViolation = Violation & { endsAt: Date };
 
+type StartViolationFunction = (member: GuildMember) => Promise<void>;
+type StopViolationFunction = (member: GuildMember, settings: GuildViolationSettings) => Promise<void>;
+interface TimedViolationStopHandler {
+    type: ObjectType<TimedViolation>;
+    stop: StopViolationFunction;
+    command: string;
+}
+
 @Plugin
 export class ViolationPlugin {
     jobs: Record<number, Job> = {};
+    stopHandlers: TimedViolationStopHandler[] = [
+        {
+            command: "mute",
+            type: Mute,
+            stop: async (member: GuildMember, settings: GuildViolationSettings): Promise<void> => {
+                const muteRoleResolve = await tryDo(member.guild.roles.fetch(settings.muteRoleId));
+
+                if (!muteRoleResolve.ok || !muteRoleResolve.result) {
+                    logger.warn("mute: couldn't find mute role id %s (removed from server?)", settings.muteRoleId);
+                    return;
+                }
+                const muteRole = muteRoleResolve.result;
+
+                await member.roles.remove(muteRole);
+            }
+        }
+    ];
+
+    async start(): Promise<void> {
+        for (const handler of this.stopHandlers) {
+            const repo = getRepository(handler.type);
+            const validViolations = await repo.find({
+                where: { valid: true }
+            });
+
+            for (const violation of validViolations) {
+                const stopJob = this.scheduleRemoveViolation(handler.type, violation.guildId, violation.userId, handler.stop, handler.command);
+
+                if (violation.endsAt <= new Date())
+                    await stopJob();
+                else
+                    this.jobs[violation.id] = scheduleJob(violation.endsAt, stopJob);
+            }
+        }
+    }
 
     @Command({
         type: "prefix",
@@ -53,31 +96,29 @@ export class ViolationPlugin {
             return;
         }
         const muteRole = muteRoleResolve.result;
-        
+
         const apply = async (member: GuildMember) => {
             await member.roles.add(muteRole);
         };
 
-        const remove = async (member: GuildMember) => {
-            const muteRoleResolve = await tryDo(member.guild.roles.fetch(muteRoleId));
-
-            if (!muteRoleResolve.ok || !muteRoleResolve.result) {
-                logger.warn("mute: couldn't find mute role id %s (removed from server?)", muteRoleId);
-                return;
-            }
-            const muteRole = muteRoleResolve.result;
-
-            await member.roles.remove(muteRole);
-        };
+        const remove = this.getStopHandler(Mute);
 
         await this.applyTimedViolation(Mute, info, "mute", apply, remove);
         await this.sendViolationMessage(message, info, "User has been muted for server violation");
     }
 
-    private async applyTimedViolation<T extends TimedViolation>(type: ObjectType<T>, info: ViolationInfo, command = "violation", apply: (user: GuildMember) => Promise<void>, remove: (user: GuildMember) => Promise<void>) {
+    private getStopHandler(type: ObjectType<TimedViolation>): StopViolationFunction {
+        for (const handler of this.stopHandlers) {
+            if (handler.type == type)
+                return handler.stop;
+        }
+        throw new Error("Cannot find stop handler for violation type!");
+    }
+
+    private async applyTimedViolation<T extends TimedViolation>(type: ObjectType<T>, info: ViolationInfo, command = "violation", apply: StartViolationFunction, remove: StopViolationFunction) {
         if (info.dryRun)
             return;
-        
+
         const violationRepo = getRepository(type);
         const existingViolation = await violationRepo.findOne({
             where: {
@@ -100,14 +141,21 @@ export class ViolationPlugin {
                 endsAt: info.endDate,
                 valid: true,
             } as unknown as DeepPartial<T>);
-            const job = scheduleJob(info.endDate, this.scheduleRemoveViolation(type, info.guild.id, info.member.id, remove, command));
-            this.jobs[newViolation.id] = job;
+            this.jobs[newViolation.id] = scheduleJob(info.endDate, this.scheduleRemoveViolation(type, info.guild.id, info.member.id, remove, command));
         }
         await apply(info.member);
     }
 
-    private scheduleRemoveViolation<T extends TimedViolation>(type: ObjectType<T>, guildId: string, userId: string, handle: (member: GuildMember) => Promise<void>, command = "violation") {
+    private scheduleRemoveViolation<T extends TimedViolation>(type: ObjectType<T>, guildId: string, userId: string, handle: StopViolationFunction, command = "violation") {
         return async () => {
+            const settingsRepo = getRepository(GuildViolationSettings);
+            const settings = await settingsRepo.findOne(guildId);
+
+            if (!settings) {
+                logger.warn("un-%s: no violation settings found for guild %s", command, guildId);
+                return;
+            }
+
             const repo = getRepository(type);
             const violation = await repo.findOne({
                 where: {
@@ -138,7 +186,7 @@ export class ViolationPlugin {
             }
             const user = userResolve.result;
 
-            await handle(user);
+            await handle(user, settings);
         };
     }