|
@@ -25,9 +25,52 @@ interface ViolationInfo {
|
|
|
|
|
|
type TimedViolation = Violation & { endsAt: Date };
|
|
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
|
|
@Plugin
|
|
export class ViolationPlugin {
|
|
export class ViolationPlugin {
|
|
jobs: Record<number, Job> = {};
|
|
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({
|
|
@Command({
|
|
type: "prefix",
|
|
type: "prefix",
|
|
@@ -53,31 +96,29 @@ export class ViolationPlugin {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
const muteRole = muteRoleResolve.result;
|
|
const muteRole = muteRoleResolve.result;
|
|
-
|
|
|
|
|
|
+
|
|
const apply = async (member: GuildMember) => {
|
|
const apply = async (member: GuildMember) => {
|
|
await member.roles.add(muteRole);
|
|
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.applyTimedViolation(Mute, info, "mute", apply, remove);
|
|
await this.sendViolationMessage(message, info, "User has been muted for server violation");
|
|
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)
|
|
if (info.dryRun)
|
|
return;
|
|
return;
|
|
-
|
|
|
|
|
|
+
|
|
const violationRepo = getRepository(type);
|
|
const violationRepo = getRepository(type);
|
|
const existingViolation = await violationRepo.findOne({
|
|
const existingViolation = await violationRepo.findOne({
|
|
where: {
|
|
where: {
|
|
@@ -100,14 +141,21 @@ export class ViolationPlugin {
|
|
endsAt: info.endDate,
|
|
endsAt: info.endDate,
|
|
valid: true,
|
|
valid: true,
|
|
} as unknown as DeepPartial<T>);
|
|
} 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);
|
|
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 () => {
|
|
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 repo = getRepository(type);
|
|
const violation = await repo.findOne({
|
|
const violation = await repo.findOne({
|
|
where: {
|
|
where: {
|
|
@@ -138,7 +186,7 @@ export class ViolationPlugin {
|
|
}
|
|
}
|
|
const user = userResolve.result;
|
|
const user = userResolve.result;
|
|
|
|
|
|
- await handle(user);
|
|
|
|
|
|
+ await handle(user, settings);
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|