Use GuildSavedMessages events in logs. Fix code blocks in edit logs.
This commit is contained in:
parent
1a6e680d81
commit
2c8603ca70
4 changed files with 95 additions and 37 deletions
|
@ -11,6 +11,8 @@ const RETENTION_PERIOD = 7 * 24 * 60 * 60 * 1000; // 1 week
|
|||
|
||||
export class GuildSavedMessages extends BaseRepository {
|
||||
private messages: Repository<SavedMessage>;
|
||||
protected toBePermanent: Set<string>;
|
||||
|
||||
public events: QueuedEventEmitter;
|
||||
|
||||
constructor(guildId) {
|
||||
|
@ -18,6 +20,8 @@ export class GuildSavedMessages extends BaseRepository {
|
|||
this.messages = getRepository(SavedMessage);
|
||||
this.events = new QueuedEventEmitter();
|
||||
|
||||
this.toBePermanent = new Set();
|
||||
|
||||
this.cleanup();
|
||||
setInterval(() => this.cleanup(), CLEANUP_INTERVAL);
|
||||
}
|
||||
|
@ -84,6 +88,12 @@ export class GuildSavedMessages extends BaseRepository {
|
|||
}
|
||||
|
||||
async create(data) {
|
||||
const isPermanent = this.toBePermanent.has(data.id);
|
||||
if (isPermanent) {
|
||||
data.is_permanent = true;
|
||||
this.toBePermanent.delete(data.id);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.messages.insert(data);
|
||||
} catch (e) {
|
||||
|
@ -145,4 +155,18 @@ export class GuildSavedMessages extends BaseRepository {
|
|||
const newData = this.msgToSavedMessageData(msg);
|
||||
return this.saveEdit(msg.id, newData);
|
||||
}
|
||||
|
||||
async setPermanent(id: string) {
|
||||
const savedMsg = await this.find(id);
|
||||
if (savedMsg) {
|
||||
await this.messages.update(
|
||||
{ id },
|
||||
{
|
||||
is_permanent: true
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.toBePermanent.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,20 @@ import { decorators as d, Plugin } from "knub";
|
|||
import { GuildLogs } from "../data/GuildLogs";
|
||||
import { LogType } from "../data/LogType";
|
||||
import { Channel, Constants as ErisConstants, Member, Message, TextChannel, User } from "eris";
|
||||
import { findRelevantAuditLogEntry, formatTemplateString, stripObjectToScalars } from "../utils";
|
||||
import {
|
||||
deactivateMentions,
|
||||
disableCodeBlocks,
|
||||
findRelevantAuditLogEntry,
|
||||
formatTemplateString,
|
||||
stripObjectToScalars
|
||||
} from "../utils";
|
||||
import DefaultLogMessages from "../data/DefaultLogMessages.json";
|
||||
import moment from "moment-timezone";
|
||||
import humanizeDuration from "humanize-duration";
|
||||
import isEqual from "lodash.isequal";
|
||||
import diff from "lodash.difference";
|
||||
import { GuildSavedMessages } from "../data/GuildSavedMessages";
|
||||
import { SavedMessage } from "../data/entities/SavedMessage";
|
||||
|
||||
interface ILogChannel {
|
||||
include?: string[];
|
||||
|
@ -26,8 +34,14 @@ const unknownUser = {
|
|||
|
||||
export class LogsPlugin extends Plugin {
|
||||
protected serverLogs: GuildLogs;
|
||||
protected savedMessages: GuildSavedMessages;
|
||||
|
||||
protected logListener;
|
||||
|
||||
private onMessageDeleteFn;
|
||||
private onMessageDeleteBulkFn;
|
||||
private onMessageUpdateFn;
|
||||
|
||||
getDefaultOptions() {
|
||||
return {
|
||||
config: {
|
||||
|
@ -42,13 +56,22 @@ export class LogsPlugin extends Plugin {
|
|||
|
||||
onLoad() {
|
||||
this.serverLogs = new GuildLogs(this.guildId);
|
||||
this.savedMessages = GuildSavedMessages.getInstance(this.guildId);
|
||||
|
||||
this.logListener = ({ type, data }) => this.log(type, data);
|
||||
this.serverLogs.on("log", this.logListener);
|
||||
|
||||
this.savedMessages.events.on("delete", this.onMessageDelete.bind(this));
|
||||
this.savedMessages.events.on("deleteBulk", this.onMessageDeleteBulk.bind(this));
|
||||
this.savedMessages.events.on("update", this.onMessageUpdate.bind(this));
|
||||
}
|
||||
|
||||
onUnload() {
|
||||
this.serverLogs.removeListener("log", this.logListener);
|
||||
|
||||
this.savedMessages.events.off("delete", this.onMessageDelete.bind(this));
|
||||
this.savedMessages.events.off("deleteBulk", this.onMessageDeleteBulk.bind(this));
|
||||
this.savedMessages.events.off("update", this.onMessageUpdate.bind(this));
|
||||
}
|
||||
|
||||
async log(type, data) {
|
||||
|
@ -59,10 +82,7 @@ export class LogsPlugin extends Plugin {
|
|||
const channel = this.guild.channels.get(channelId);
|
||||
if (!channel || !(channel instanceof TextChannel)) continue;
|
||||
|
||||
if (
|
||||
(opts.include && opts.include.includes(typeStr)) ||
|
||||
(opts.exclude && !opts.exclude.includes(typeStr))
|
||||
) {
|
||||
if ((opts.include && opts.include.includes(typeStr)) || (opts.exclude && !opts.exclude.includes(typeStr))) {
|
||||
const message = this.getLogMessage(type, data);
|
||||
// TODO: Split log messages that are too long
|
||||
if (message) await channel.createMessage(message).catch(() => {});
|
||||
|
@ -234,55 +254,64 @@ export class LogsPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
@d.event("messageUpdate")
|
||||
onMessageUpdate(msg: Message, oldMsg: Message) {
|
||||
if (!msg.author) return;
|
||||
if (oldMsg && msg.content === oldMsg.content) return;
|
||||
if (msg.type !== 0) return;
|
||||
// Uses events from savesMessages
|
||||
onMessageUpdate(savedMessage: SavedMessage, oldSavedMessage: SavedMessage) {
|
||||
if (oldSavedMessage && JSON.stringify(savedMessage.data) === JSON.stringify(oldSavedMessage.data)) return;
|
||||
|
||||
const member = this.guild.members.get(savedMessage.user_id);
|
||||
const channel = this.guild.channels.get(savedMessage.channel_id);
|
||||
|
||||
const before = oldSavedMessage
|
||||
? disableCodeBlocks(deactivateMentions(oldSavedMessage.data.content || ""))
|
||||
: "Unknown pre-edit content";
|
||||
const after = disableCodeBlocks(deactivateMentions(savedMessage.data.content || ""));
|
||||
|
||||
this.serverLogs.log(LogType.MESSAGE_EDIT, {
|
||||
member: stripObjectToScalars(msg.member, ["user"]),
|
||||
channel: stripObjectToScalars(msg.channel),
|
||||
before: oldMsg ? oldMsg.cleanContent || oldMsg.content || "" : "Unavailable due to restart",
|
||||
after: msg.cleanContent || msg.content || ""
|
||||
member: stripObjectToScalars(member, ["user"]),
|
||||
channel: stripObjectToScalars(channel),
|
||||
before,
|
||||
after
|
||||
});
|
||||
}
|
||||
|
||||
@d.event("messageDelete")
|
||||
onMessageDelete(msg: Message) {
|
||||
if (msg.type != null && msg.type !== 0) return;
|
||||
// Uses events from savesMessages
|
||||
onMessageDelete(savedMessage: SavedMessage) {
|
||||
const member = this.guild.members.get(savedMessage.user_id);
|
||||
const channel = this.guild.channels.get(savedMessage.channel_id);
|
||||
|
||||
if (msg.member) {
|
||||
if (member) {
|
||||
this.serverLogs.log(
|
||||
LogType.MESSAGE_DELETE,
|
||||
{
|
||||
member: stripObjectToScalars(msg.member, ["user"]),
|
||||
channel: stripObjectToScalars(msg.channel),
|
||||
messageText: msg.cleanContent || msg.content || ""
|
||||
member: stripObjectToScalars(member, ["user"]),
|
||||
channel: stripObjectToScalars(channel),
|
||||
messageText: disableCodeBlocks(deactivateMentions(savedMessage.data.content || ""))
|
||||
},
|
||||
msg.id
|
||||
savedMessage.id
|
||||
);
|
||||
} else {
|
||||
this.serverLogs.log(
|
||||
LogType.MESSAGE_DELETE_BARE,
|
||||
{
|
||||
messageId: msg.id,
|
||||
channel: stripObjectToScalars(msg.channel)
|
||||
messageId: savedMessage.id,
|
||||
channel: stripObjectToScalars(channel)
|
||||
},
|
||||
msg.id
|
||||
savedMessage.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@d.event("messageDeleteBulk")
|
||||
onMessageDeleteBulk(messages: Message[]) {
|
||||
// Uses events from savesMessages
|
||||
onMessageDeleteBulk(savedMessages: SavedMessage[]) {
|
||||
const channel = this.guild.channels.get(savedMessages[0].channel_id);
|
||||
|
||||
this.serverLogs.log(
|
||||
LogType.MESSAGE_DELETE_BULK,
|
||||
{
|
||||
count: messages.length,
|
||||
channel: messages[0] ? messages[0].channel : null
|
||||
count: savedMessages.length,
|
||||
channel
|
||||
},
|
||||
messages[0] && messages[0].id
|
||||
savedMessages[0].id
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ export class PostPlugin extends Plugin {
|
|||
}
|
||||
|
||||
const createdMsg = await args.channel.createMessage(args.content);
|
||||
await this.savedMessages.createFromMsg(createdMsg, { is_permanent: true });
|
||||
await this.savedMessages.setPermanent(createdMsg.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,6 +64,5 @@ export class PostPlugin extends Plugin {
|
|||
}
|
||||
|
||||
const edited = await this.bot.editMessage(savedMessage.channel_id, savedMessage.id, args.content);
|
||||
await this.savedMessages.saveEditFromMsg(edited);
|
||||
}
|
||||
}
|
||||
|
|
16
src/utils.ts
16
src/utils.ts
|
@ -1,8 +1,9 @@
|
|||
import at = require("lodash.at");
|
||||
import { Client, Guild, GuildAuditLogEntry, Message, TextChannel } from "eris";
|
||||
import { Client, Guild, GuildAuditLogEntry, GuildChannel, Message, TextChannel } from "eris";
|
||||
import url from "url";
|
||||
import tlds from "tlds";
|
||||
import emojiRegex from "emoji-regex";
|
||||
import { GuildSavedMessages } from "./data/GuildSavedMessages";
|
||||
|
||||
/**
|
||||
* Turns a "delay string" such as "1h30m" to milliseconds
|
||||
|
@ -166,10 +167,7 @@ export function getInviteCodesInString(str: string): string[] {
|
|||
|
||||
export const unicodeEmojiRegex = emojiRegex();
|
||||
export const customEmojiRegex = /<:(?:.*?):(\d+)>/g;
|
||||
export const anyEmojiRegex = new RegExp(
|
||||
`(?:(?:${unicodeEmojiRegex.source})|(?:${customEmojiRegex.source}))`,
|
||||
"g"
|
||||
);
|
||||
export const anyEmojiRegex = new RegExp(`(?:(?:${unicodeEmojiRegex.source})|(?:${customEmojiRegex.source}))`, "g");
|
||||
|
||||
export function getEmojiInString(str: string): string[] {
|
||||
return str.match(anyEmojiRegex) || [];
|
||||
|
@ -275,4 +273,12 @@ export function disableLinkPreviews(str: string): string {
|
|||
return str.replace(/(?<!\<)(https?:\/\/\S+)/gi, "<$1>");
|
||||
}
|
||||
|
||||
export function deactivateMentions(content: string): string {
|
||||
return content.replace(/@/g, "@\u200b");
|
||||
}
|
||||
|
||||
export function disableCodeBlocks(content: string): string {
|
||||
return content.replace(/`/g, "`\u200b");
|
||||
}
|
||||
|
||||
export const DBDateFormat = "YYYY-MM-DD HH:mm:ss";
|
||||
|
|
Loading…
Add table
Reference in a new issue