|
@@ -1,6 +1,6 @@
|
|
|
-import { Plugin, ICommandData, Command } from "src/model/plugin";
|
|
|
+import { Plugin, ICommandData, Command, Event, BotEventData } from "src/model/plugin";
|
|
|
import { parseArgs, tryDo, parseDuration, UNIT_MEASURES, Option } from "src/util";
|
|
|
-import { GuildMember, Guild, MessageEmbed, Message, TextChannel } from "discord.js";
|
|
|
+import { GuildMember, Guild, MessageEmbed, Message, TextChannel, PartialGuildMember } from "discord.js";
|
|
|
import { logger } from "src/logging";
|
|
|
import { client } from "src/client";
|
|
|
import humanizeDuration from "humanize-duration";
|
|
@@ -25,7 +25,7 @@ interface ViolationInfo {
|
|
|
|
|
|
type TimedViolation = Violation & { endsAt: Date };
|
|
|
|
|
|
-type StartViolationFunction = (member: GuildMember, settings: GuildViolationSettings) => Promise<void>;
|
|
|
+type StartViolationFunction = (member: GuildMember | PartialGuildMember, settings: GuildViolationSettings) => Promise<void>;
|
|
|
type StopViolationFunction = (guild: Guild, userId: string, settings: GuildViolationSettings) => Promise<void>;
|
|
|
interface TimedViolationStopHandler {
|
|
|
type: ObjectType<TimedViolation>;
|
|
@@ -34,6 +34,14 @@ interface TimedViolationStopHandler {
|
|
|
command: string;
|
|
|
}
|
|
|
|
|
|
+function isTimed(violation: Violation): violation is TimedViolation {
|
|
|
+ return Object.prototype.hasOwnProperty.call(violation, "endsAt") && (violation as unknown as Record<string, unknown>)["endsAt"] !== undefined;
|
|
|
+}
|
|
|
+
|
|
|
+function getViolationType(violation: TimedViolation): ObjectType<TimedViolation> {
|
|
|
+ return (violation as { constructor: ObjectType<TimedViolation> }).constructor;
|
|
|
+}
|
|
|
+
|
|
|
@Plugin
|
|
|
export class ViolationPlugin {
|
|
|
jobs: Record<number, Job> = {};
|
|
@@ -41,14 +49,14 @@ export class ViolationPlugin {
|
|
|
{
|
|
|
command: "mute",
|
|
|
type: Mute,
|
|
|
- start: async (member: GuildMember, settings: GuildViolationSettings): Promise<void> => {
|
|
|
+ start: async (member: GuildMember | PartialGuildMember, settings: GuildViolationSettings): Promise<void> => {
|
|
|
const muteRoleResolve = await tryDo(member.guild.roles.fetch(settings.muteRoleId));
|
|
|
if (!muteRoleResolve.ok || !muteRoleResolve.result) {
|
|
|
logger.error(
|
|
|
"mute: Tried to mute user %s#%s (%s) but mute role ID %s is invalid!",
|
|
|
- member.user.username,
|
|
|
- member.user.discriminator,
|
|
|
- member.user.id,
|
|
|
+ member.user?.username,
|
|
|
+ member.user?.discriminator,
|
|
|
+ member.user?.id,
|
|
|
settings.muteRoleId);
|
|
|
return;
|
|
|
}
|
|
@@ -93,6 +101,41 @@ export class ViolationPlugin {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Event("guildMemberAdd")
|
|
|
+ async onUserJoin(data: BotEventData, member: GuildMember | PartialGuildMember): Promise<void> {
|
|
|
+ const settingsRepo = getRepository(GuildViolationSettings);
|
|
|
+ const settings = await settingsRepo.findOne(member.guild.id);
|
|
|
+
|
|
|
+ if (!settings)
|
|
|
+ return;
|
|
|
+
|
|
|
+ const repo = getRepository(Violation);
|
|
|
+ const activeViolations = await repo.find({
|
|
|
+ where: {
|
|
|
+ guildId: member.guild.id,
|
|
|
+ userId: member.id,
|
|
|
+ valid: true
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (activeViolations.length == 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ for (const violation of activeViolations) {
|
|
|
+ if (!isTimed(violation)) {
|
|
|
+ await repo.update({ id: violation.id }, { valid: false });
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const type = getViolationType(violation);
|
|
|
+ const handler = this.getViolationHandler(type);
|
|
|
+ if (violation.endsAt < new Date())
|
|
|
+ await repo.update({ id: violation.id }, { valid: false });
|
|
|
+ else
|
|
|
+ await handler.start(member, settings);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Command({
|
|
|
type: "prefix",
|
|
|
pattern: "mute",
|
|
@@ -104,6 +147,10 @@ export class ViolationPlugin {
|
|
|
return;
|
|
|
|
|
|
const handler = this.getViolationHandler(Mute);
|
|
|
+ if (!handler) {
|
|
|
+ logger.error("Couldn't find handler for Mute");
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
await this.applyTimedViolation(Mute, info, "mute", handler.start, handler.stop);
|
|
|
await this.sendViolationMessage(message, info, "User has been muted for server violation");
|
|
@@ -114,7 +161,7 @@ export class ViolationPlugin {
|
|
|
if (handler.type == type)
|
|
|
return handler;
|
|
|
}
|
|
|
- throw new Error("Cannot find stop handler for violation type!");
|
|
|
+ throw new Error("Couldn't find handler for violation type!");
|
|
|
}
|
|
|
|
|
|
private async applyTimedViolation<T extends TimedViolation>(type: ObjectType<T>, info: ViolationInfo, command = "violation", apply: StartViolationFunction, remove: StopViolationFunction) {
|