From 8de31844d541d4a1423008eaf6f0699a575f0a6e Mon Sep 17 00:00:00 2001 From: Dragory Date: Sun, 13 Jan 2019 17:56:14 +0200 Subject: [PATCH] Add support for hiding cases with !hidecase --- src/data/GuildCases.ts | 9 +++ src/data/entities/Case.ts | 2 + .../1547393619900-AddIsHiddenToCases.ts | 25 +++++++ src/plugins/Cases.ts | 4 ++ src/plugins/ModActions.ts | 67 ++++++++++++++++--- src/plugins/Utility.ts | 11 +-- 6 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 src/migrations/1547393619900-AddIsHiddenToCases.ts diff --git a/src/data/GuildCases.ts b/src/data/GuildCases.ts index 3f52c25e..0a09a28a 100644 --- a/src/data/GuildCases.ts +++ b/src/data/GuildCases.ts @@ -53,6 +53,15 @@ export class GuildCases extends BaseRepository { }); } + async setHidden(id: number, hidden: boolean): Promise { + await this.cases.update( + { id }, + { + is_hidden: hidden + } + ); + } + async create(data): Promise { const result = await this.cases.insert({ ...data, diff --git a/src/data/entities/Case.ts b/src/data/entities/Case.ts index 6cb779b5..fd9dd4db 100644 --- a/src/data/entities/Case.ts +++ b/src/data/entities/Case.ts @@ -23,6 +23,8 @@ export class Case { @Column() created_at: string; + @Column() is_hidden: boolean; + @OneToMany(type => CaseNote, note => note.case) notes: CaseNote[]; } diff --git a/src/migrations/1547393619900-AddIsHiddenToCases.ts b/src/migrations/1547393619900-AddIsHiddenToCases.ts new file mode 100644 index 00000000..8b456cf6 --- /dev/null +++ b/src/migrations/1547393619900-AddIsHiddenToCases.ts @@ -0,0 +1,25 @@ +import { MigrationInterface, QueryRunner, TableColumn, TableIndex } from "typeorm"; + +export class AddIsHiddenToCases1547393619900 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.addColumn( + "cases", + new TableColumn({ + name: "is_hidden", + type: "tinyint", + unsigned: true, + default: 0 + }) + ); + await queryRunner.createIndex( + "cases", + new TableIndex({ + columnNames: ["is_hidden"] + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropColumn("cases", "is_hidden"); + } +} diff --git a/src/plugins/Cases.ts b/src/plugins/Cases.ts index bb22fdd3..2a484f8d 100644 --- a/src/plugins/Cases.ts +++ b/src/plugins/Cases.ts @@ -180,6 +180,10 @@ export class CasesPlugin extends ZeppelinPlugin { ] }; + if (theCase.is_hidden) { + embed.title += " (hidden)"; + } + if (CaseTypeColors[theCase.type]) { embed.color = CaseTypeColors[theCase.type]; } diff --git a/src/plugins/ModActions.ts b/src/plugins/ModActions.ts index deb579f2..d5deb9a0 100644 --- a/src/plugins/ModActions.ts +++ b/src/plugins/ModActions.ts @@ -84,7 +84,8 @@ export class ModActionsPlugin extends ZeppelinPlugin { ban: false, view: false, addcase: false, - massban: true + massban: true, + hidecase: false }, overrides: [ { @@ -102,7 +103,8 @@ export class ModActionsPlugin extends ZeppelinPlugin { { level: ">=100", permissions: { - massban: true + massban: true, + hidecase: true } } ] @@ -885,10 +887,13 @@ export class ModActionsPlugin extends ZeppelinPlugin { }); } - @d.command(/cases|usercases/, " [expanded:string$]") + @d.command(/cases|usercases/, " [opts:string$]") @d.permission("view") - async usercasesCmd(msg: Message, args: { userId: string; expanded?: string }) { + async usercasesCmd(msg: Message, args: { userId: string; opts?: string }) { const cases = await this.cases.with("notes").getByUserId(args.userId); + const normalCases = cases.filter(c => !c.is_hidden); + const hiddenCases = cases.filter(c => c.is_hidden); + const user = this.bot.users.get(args.userId); const userName = user ? `${user.username}#${user.discriminator}` : "Unknown#0000"; const prefix = this.knub.getGuildData(this.guildId).config.prefix; @@ -896,14 +901,17 @@ export class ModActionsPlugin extends ZeppelinPlugin { if (cases.length === 0) { msg.channel.createMessage(`No cases found for ${user ? `**${userName}**` : "the specified user"}`); } else { - if (args.expanded && args.expanded.startsWith("expand")) { - if (cases.length > 8) { + const showHidden = args.opts && args.opts.match(/\bhidden\b/); + const casesToDisplay = showHidden ? cases : normalCases; + + if (args.opts && args.opts.match(/\bexpand\b/)) { + if (casesToDisplay.length > 8) { msg.channel.createMessage("Too many cases for expanded view. Please use compact view instead."); return; } // Expanded view (= individual case embeds) - for (const theCase of cases) { + for (const theCase of casesToDisplay) { await this.actions.fire("postCase", { caseId: theCase.id, channel: msg.channel @@ -912,7 +920,7 @@ export class ModActionsPlugin extends ZeppelinPlugin { } else { // Compact view (= regular message with a preview of each case) const lines = []; - for (const theCase of cases) { + for (const theCase of casesToDisplay) { theCase.notes.sort((a, b) => (a.created_at > b.created_at ? 1 : -1)); const firstNote = theCase.notes[0]; let reason = firstNote ? firstNote.body : ""; @@ -928,12 +936,25 @@ export class ModActionsPlugin extends ZeppelinPlugin { reason = disableLinkPreviews(reason); let line = `Case \`#${theCase.case_number}\` __${CaseTypes[theCase.type]}__ ${reason}`; - if (theCase.notes.length > 1) + if (theCase.notes.length > 1) { line += ` *(+${theCase.notes.length - 1} ${theCase.notes.length === 2 ? "note" : "notes"})*`; + } + + if (theCase.is_hidden) { + line += " *(hidden)*"; + } lines.push(line); } + if (!showHidden && hiddenCases.length) { + if (hiddenCases.length === 1) { + lines.push(`*+${hiddenCases.length} hidden case, use "hidden" to show it*`); + } else { + lines.push(`*+${hiddenCases.length} hidden cases, use "hidden" to show them*`); + } + } + const finalMessage = trimLines(` Cases for **${userName}**: @@ -947,6 +968,34 @@ export class ModActionsPlugin extends ZeppelinPlugin { } } + @d.command("hidecase", "") + @d.permission("hidecase") + async hideCaseCmd(msg: Message, args: { caseNum: number }) { + const theCase = await this.cases.findByCaseNumber(args.caseNum); + if (!theCase) { + msg.channel.createMessage(errorMessage("Case not found!")); + return; + } + + await this.cases.setHidden(theCase.id, true); + msg.channel.createMessage( + successMessage(`Case #${theCase.case_number} is now hidden! Use \`unhidecase\` to unhide it.`) + ); + } + + @d.command("unhidecase", "") + @d.permission("hidecase") + async unhideCaseCmd(msg: Message, args: { caseNum: number }) { + const theCase = await this.cases.findByCaseNumber(args.caseNum); + if (!theCase) { + msg.channel.createMessage(errorMessage("Case not found!")); + return; + } + + await this.cases.setHidden(theCase.id, false); + msg.channel.createMessage(successMessage(`Case #${theCase.case_number} is no longer hidden!`)); + } + /** * Attempts to message the specified user through DMs and/or the message channel. * Returns a promise that resolves to a boolean indicating whether we were able to message them or not. diff --git a/src/plugins/Utility.ts b/src/plugins/Utility.ts index fe6139b1..a56b0a00 100644 --- a/src/plugins/Utility.ts +++ b/src/plugins/Utility.ts @@ -19,7 +19,7 @@ const CLEAN_COMMAND_DELETE_DELAY = 5000; const activeReloads: Map = new Map(); export class UtilityPlugin extends ZeppelinPlugin { - public static pluginName = 'utility'; + public static pluginName = "utility"; protected logs: GuildLogs; protected cases: GuildCases; @@ -292,9 +292,12 @@ export class UtilityPlugin extends ZeppelinPlugin { return a.created_at < b.created_at ? 1 : -1; }); - const caseSummary = cases.slice(0, 3).map(c => { - return `${CaseTypes[c.type]} (#${c.case_number})`; - }); + const caseSummary = cases + .filter(c => !c.is_hidden) + .slice(0, 3) + .map(c => { + return `${CaseTypes[c.type]} (#${c.case_number})`; + }); const summaryText = cases.length > 3 ? "Last 3 cases" : "Summary";