3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-10 20:35:02 +00:00

Notify user for spam detection mutes. Add notification status ('user notified in DMs' etc.) to the case. Log case updates. Add 'unmuted immediately' to the case for unmutes without a time.

This commit is contained in:
Dragory 2019-04-13 17:35:02 +03:00
parent 40cb74ee28
commit fe88766f02
10 changed files with 455 additions and 332 deletions

View file

@ -48,5 +48,7 @@
"MASSBAN": "⚒ {userMention(mod)} massbanned {count} users",
"MEMBER_JOIN_WITH_PRIOR_RECORDS": "⚠ {userMention(member)} joined with prior records. Recent cases:\n{recentCaseSummary}"
"MEMBER_JOIN_WITH_PRIOR_RECORDS": "⚠ {userMention(member)} joined with prior records. Recent cases:\n{recentCaseSummary}",
"CASE_UPDATE": "✏ {userMention(mod)} updated case #{caseNumber} ({caseType}) with note:\n```{note}```"
}

View file

@ -1,6 +1,9 @@
import { BaseRepository } from "./BaseRepository";
import { Member, TextableChannel } from "eris";
import { CaseTypes } from "./CaseTypes";
import { ICaseDetails } from "./GuildCases";
import { Case } from "./entities/Case";
import { INotifyUserResult } from "../utils";
type KnownActions = "mute" | "unmute";
@ -9,30 +12,32 @@ type UnknownAction<T extends string> = T extends KnownActions ? never : T;
type ActionFn<T> = (args: T) => any | Promise<any>;
type MuteActionArgs = { member: Member; muteTime?: number; reason?: string };
type UnmuteActionArgs = { member: Member; unmuteTime?: number; reason?: string };
type CreateCaseActionArgs = {
userId: string;
modId: string;
type: CaseTypes;
auditLogId?: string;
reason?: string;
automatic?: boolean;
postInCaseLog?: boolean;
ppId?: string;
};
type MuteActionArgs = { member: Member; muteTime?: number; reason?: string; caseDetails?: ICaseDetails };
type UnmuteActionArgs = { member: Member; unmuteTime?: number; reason?: string; caseDetails?: ICaseDetails };
type CreateCaseActionArgs = ICaseDetails;
type CreateCaseNoteActionArgs = {
caseId: number;
modId: string;
note: string;
automatic?: boolean;
postInCaseLog?: boolean;
noteDetails?: string[];
};
type PostCaseActionArgs = {
caseId: number;
channel: TextableChannel;
};
export type MuteActionResult = {
case: Case;
notifyResult: INotifyUserResult;
updatedExistingMute: boolean;
};
export type UnmuteActionResult = {
case: Case;
};
export class GuildActions extends BaseRepository {
private actions: Map<string, ActionFn<any>>;
@ -63,8 +68,8 @@ export class GuildActions extends BaseRepository {
this.actions.delete(actionName);
}
public fire(actionName: "mute", args: MuteActionArgs): Promise<any>;
public fire(actionName: "unmute", args: UnmuteActionArgs): Promise<any>;
public fire(actionName: "mute", args: MuteActionArgs): Promise<MuteActionResult>;
public fire(actionName: "unmute", args: UnmuteActionArgs): Promise<UnmuteActionResult>;
public fire(actionName: "createCase", args: CreateCaseActionArgs): Promise<any>;
public fire(actionName: "createCaseNote", args: CreateCaseNoteActionArgs): Promise<any>;
public fire(actionName: "postCase", args: PostCaseActionArgs): Promise<any>;

View file

@ -8,6 +8,22 @@ import moment = require("moment-timezone");
const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
/**
* Used as a config object for functions that create cases
*/
export interface ICaseDetails {
userId?: string;
modId?: string;
ppId?: string;
type?: CaseTypes;
auditLogId?: string;
reason?: string;
automatic?: boolean;
postInCaseLogOverride?: boolean;
noteDetails?: string[];
extraNotes?: string[];
}
export class GuildCases extends BaseRepository {
private cases: Repository<Case>;
private caseNotes: Repository<CaseNote>;

View file

@ -24,11 +24,16 @@ export class GuildMutes extends BaseRepository {
return this.mutes.findOne({
where: {
guild_id: this.guildId,
user_id: userId
}
user_id: userId,
},
});
}
async isMuted(userId: string): Promise<boolean> {
const mute = await this.findExistingMuteForUserId(userId);
return mute != null;
}
async addMute(userId, expiryTime): Promise<Mute> {
const expiresAt = expiryTime
? moment()
@ -39,7 +44,7 @@ export class GuildMutes extends BaseRepository {
const result = await this.mutes.insert({
guild_id: this.guildId,
user_id: userId,
expires_at: expiresAt
expires_at: expiresAt,
});
return this.mutes.findOne({ where: result.identifiers[0] });
@ -55,25 +60,14 @@ export class GuildMutes extends BaseRepository {
return this.mutes.update(
{
guild_id: this.guildId,
user_id: userId
user_id: userId,
},
{
expires_at: expiresAt
}
expires_at: expiresAt,
},
);
}
async addOrUpdateMute(userId, expiryTime): Promise<Mute> {
const existingMute = await this.findExistingMuteForUserId(userId);
if (existingMute) {
await this.updateExpiryTime(userId, expiryTime);
return this.findExistingMuteForUserId(userId);
} else {
return this.addMute(userId, expiryTime);
}
}
async getActiveMutes(): Promise<Mute[]> {
return this.mutes
.createQueryBuilder("mutes")
@ -81,7 +75,7 @@ export class GuildMutes extends BaseRepository {
.andWhere(
new Brackets(qb => {
qb.where("expires_at > NOW()").orWhere("expires_at IS NULL");
})
}),
)
.getMany();
}
@ -90,18 +84,18 @@ export class GuildMutes extends BaseRepository {
await this.mutes.update(
{
guild_id: this.guildId,
user_id: userId
user_id: userId,
},
{
case_id: caseId
}
case_id: caseId,
},
);
}
async clear(userId) {
await this.mutes.delete({
guild_id: this.guildId,
user_id: userId
user_id: userId,
});
}
}

View file

@ -49,4 +49,6 @@ export enum LogType {
MEMBER_ROLE_CHANGES,
VOICE_CHANNEL_FORCE_MOVE,
CASE_UPDATE,
}