From ab71481b8fa53390d2cc0e113ff9fd58e53f719c Mon Sep 17 00:00:00 2001 From: Dragory Date: Sun, 13 Jan 2019 17:29:26 +0200 Subject: [PATCH] Allow making archives permanent. Make archives permanent when attached to a case. Add log file metadata dynamically when served (instead of in the body directly). Add missing index on archives.expires_at. --- src/data/GuildArchives.ts | 20 ++++++++++-------- src/data/entities/ArchiveEntry.ts | 2 +- ...47392046629-AddIndexToArchivesExpiresAt.ts | 21 +++++++++++++++++++ src/plugins/Cases.ts | 11 +++++++++- src/plugins/LogServer.ts | 18 ++++++++++++++-- 5 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 src/migrations/1547392046629-AddIndexToArchivesExpiresAt.ts diff --git a/src/data/GuildArchives.ts b/src/data/GuildArchives.ts index 4539d474..d33d68a4 100644 --- a/src/data/GuildArchives.ts +++ b/src/data/GuildArchives.ts @@ -14,10 +14,6 @@ const MESSAGE_ARCHIVE_HEADER_FORMAT = trimLines(` `); const MESSAGE_ARCHIVE_MESSAGE_FORMAT = "[#{channel.name}] [{user.id}] [{timestamp}] {user.username}#{user.discriminator}: {content}{attachments}"; -const MESSAGE_ARCHIVE_FOOTER_FORMAT = trimLines(` - Log file generated on {timestamp} - Expires at {expires} -`); export class GuildArchives extends BaseRepository { protected archives: Repository; @@ -35,6 +31,7 @@ export class GuildArchives extends BaseRepository { this.archives .createQueryBuilder() .where("guild_id = :guild_id", { guild_id: this.guildId }) + .andWhere("expires_at IS NOT NULL") .andWhere("expires_at <= NOW()") .delete() .execute(); @@ -47,6 +44,15 @@ export class GuildArchives extends BaseRepository { }); } + async makePermanent(id: string): Promise { + await this.archives.update( + { id }, + { + expires_at: null + } + ); + } + /** * @returns ID of the created entry */ @@ -81,11 +87,7 @@ export class GuildArchives extends BaseRepository { }); }); const messagesStr = msgLines.join("\n"); - const footerStr = formatTemplateString(MESSAGE_ARCHIVE_FOOTER_FORMAT, { - timestamp: moment().format("YYYY-MM-DD [at] HH:mm:ss (Z)"), - expires: expiresAt.format("YYYY-MM-DD [at] HH:mm:ss (Z)") - }); - return this.create([headerStr, messagesStr, footerStr].join("\n\n"), expiresAt); + return this.create([headerStr, messagesStr].join("\n\n"), expiresAt); } } diff --git a/src/data/entities/ArchiveEntry.ts b/src/data/entities/ArchiveEntry.ts index e3250665..cb9698b2 100644 --- a/src/data/entities/ArchiveEntry.ts +++ b/src/data/entities/ArchiveEntry.ts @@ -1,4 +1,4 @@ -import { Entity, Column, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"; +import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"; @Entity("archives") export class ArchiveEntry { diff --git a/src/migrations/1547392046629-AddIndexToArchivesExpiresAt.ts b/src/migrations/1547392046629-AddIndexToArchivesExpiresAt.ts new file mode 100644 index 00000000..030f32c6 --- /dev/null +++ b/src/migrations/1547392046629-AddIndexToArchivesExpiresAt.ts @@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner, TableColumn, TableIndex } from "typeorm"; + +export class AddIndexToArchivesExpiresAt1547392046629 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createIndex( + "archives", + new TableIndex({ + columnNames: ["expires_at"] + }) + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropIndex( + "archives", + new TableIndex({ + columnNames: ["expires_at"] + }) + ); + } +} diff --git a/src/plugins/Cases.ts b/src/plugins/Cases.ts index 08c5552d..bb22fdd3 100644 --- a/src/plugins/Cases.ts +++ b/src/plugins/Cases.ts @@ -6,12 +6,14 @@ import moment from "moment-timezone"; import { CaseTypeColors } from "../data/CaseTypeColors"; import { ZeppelinPlugin } from "./ZeppelinPlugin"; import { GuildActions } from "../data/GuildActions"; +import { GuildArchives } from "../data/GuildArchives"; export class CasesPlugin extends ZeppelinPlugin { - public static pluginName = 'cases'; + public static pluginName = "cases"; protected actions: GuildActions; protected cases: GuildCases; + protected archives: GuildArchives; getDefaultOptions() { return { @@ -25,6 +27,7 @@ export class CasesPlugin extends ZeppelinPlugin { onLoad() { this.actions = GuildActions.getInstance(this.guildId); this.cases = GuildCases.getInstance(this.guildId); + this.archives = GuildArchives.getInstance(this.guildId); this.actions.register("createCase", args => { return this.createCase( @@ -135,6 +138,12 @@ export class CasesPlugin extends ZeppelinPlugin { }); } + const archiveLinkMatch = body && body.match(/\/archives\/([a-zA-Z0-9\-]+)/); + if (archiveLinkMatch) { + const archiveId = archiveLinkMatch[1]; + this.archives.makePermanent(archiveId); + } + if ((!automatic || this.configValue("log_automatic_actions")) && postInCaseLogOverride !== false) { try { await this.postCaseToCaseLogChannel(theCase.id); diff --git a/src/plugins/LogServer.ts b/src/plugins/LogServer.ts index 9ad4f214..3fc352c5 100644 --- a/src/plugins/LogServer.ts +++ b/src/plugins/LogServer.ts @@ -2,6 +2,7 @@ import http, { ServerResponse } from "http"; import { GlobalPlugin } from "knub"; import { GuildArchives } from "../data/GuildArchives"; import { sleep } from "../utils"; +import moment from "moment-timezone"; const DEFAULT_PORT = 9920; const archivesRegex = /^\/(spam-logs|archives)\/([a-z0-9\-]+)\/?$/i; @@ -12,7 +13,7 @@ function notFound(res: ServerResponse) { } export class LogServerPlugin extends GlobalPlugin { - public static pluginName = 'log_server'; + public static pluginName = "log_server"; protected archives: GuildArchives; protected server: http.Server; @@ -36,8 +37,21 @@ export class LogServerPlugin extends GlobalPlugin { const log = await this.archives.find(logId); if (!log) return notFound(res); + let body = log.body; + + // Add some metadata at the end of the log file (but only if it doesn't already have it directly in the body) + if (log.body.indexOf("Log file generated on") === -1) { + const createdAt = moment(log.created_at).format("YYYY-MM-DD [at] HH:mm:ss [(+00:00)]"); + body += `\n\nLog file generated on ${createdAt}`; + + if (log.expires_at !== null) { + const expiresAt = moment(log.expires_at).format("YYYY-MM-DD [at] HH:mm:ss [(+00:00)]"); + body += `\nExpires at ${expiresAt}`; + } + } + res.setHeader("Content-Type", "text/plain; charset=UTF-8"); - res.end(log.body); + res.end(body); } });