2018-11-24 14:01:06 +02:00
|
|
|
import { Brackets, getRepository, Repository } from "typeorm";
|
|
|
|
import { BaseRepository } from "./BaseRepository";
|
|
|
|
import { ISavedMessageData, SavedMessage } from "./entities/SavedMessage";
|
2018-11-24 14:58:54 +02:00
|
|
|
import { QueuedEventEmitter } from "../QueuedEventEmitter";
|
2018-11-24 14:18:48 +02:00
|
|
|
import { GuildChannel, Message } from "eris";
|
|
|
|
import moment from "moment-timezone";
|
2018-11-24 14:01:06 +02:00
|
|
|
|
|
|
|
const CLEANUP_INTERVAL = 5 * 60 * 1000;
|
|
|
|
|
|
|
|
const RETENTION_PERIOD = 7 * 24 * 60 * 60 * 1000; // 1 week
|
|
|
|
|
|
|
|
export class GuildSavedMessages extends BaseRepository {
|
|
|
|
private messages: Repository<SavedMessage>;
|
2018-11-24 17:59:05 +02:00
|
|
|
protected toBePermanent: Set<string>;
|
|
|
|
|
2018-11-24 14:58:54 +02:00
|
|
|
public events: QueuedEventEmitter;
|
2018-11-24 14:01:06 +02:00
|
|
|
|
|
|
|
constructor(guildId) {
|
|
|
|
super(guildId);
|
|
|
|
this.messages = getRepository(SavedMessage);
|
2018-11-24 14:58:54 +02:00
|
|
|
this.events = new QueuedEventEmitter();
|
2018-11-24 14:01:06 +02:00
|
|
|
|
2018-11-24 17:59:05 +02:00
|
|
|
this.toBePermanent = new Set();
|
|
|
|
|
2018-11-24 14:01:06 +02:00
|
|
|
this.cleanup();
|
|
|
|
setInterval(() => this.cleanup(), CLEANUP_INTERVAL);
|
|
|
|
}
|
|
|
|
|
2018-11-24 14:18:48 +02:00
|
|
|
public msgToSavedMessageData(msg: Message): ISavedMessageData {
|
2018-11-24 14:53:55 +02:00
|
|
|
const data: ISavedMessageData = {
|
2018-11-24 14:18:48 +02:00
|
|
|
author: {
|
|
|
|
username: msg.author.username,
|
|
|
|
discriminator: msg.author.discriminator
|
|
|
|
},
|
2018-11-24 14:53:55 +02:00
|
|
|
content: msg.content
|
2018-11-24 14:18:48 +02:00
|
|
|
};
|
2018-11-24 14:53:55 +02:00
|
|
|
|
|
|
|
if (msg.attachments.length) data.attachments = msg.attachments;
|
|
|
|
if (msg.embeds.length) data.embeds = msg.embeds;
|
|
|
|
|
|
|
|
return data;
|
2018-11-24 14:18:48 +02:00
|
|
|
}
|
|
|
|
|
2018-11-24 14:01:06 +02:00
|
|
|
async cleanup() {
|
|
|
|
await this.messages
|
|
|
|
.createQueryBuilder("messages")
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere(
|
|
|
|
new Brackets(qb => {
|
|
|
|
// Clear deleted messages
|
|
|
|
qb.orWhere(
|
|
|
|
new Brackets(qb2 => {
|
|
|
|
qb2.where("deleted_at IS NOT NULL");
|
|
|
|
qb2.andWhere(`deleted_at <= (NOW() - INTERVAL ${CLEANUP_INTERVAL}000 MICROSECOND)`);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
// Clear old messages
|
|
|
|
qb.orWhere(
|
|
|
|
new Brackets(qb2 => {
|
|
|
|
qb2.where("is_permanent = 0");
|
|
|
|
qb2.andWhere(`posted_at <= (NOW() - INTERVAL ${RETENTION_PERIOD}000 MICROSECOND)`);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
})
|
|
|
|
)
|
|
|
|
.delete()
|
|
|
|
.execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
find(id) {
|
2018-11-24 14:33:43 +02:00
|
|
|
return this.messages
|
|
|
|
.createQueryBuilder()
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere("id = :id", { id })
|
|
|
|
.andWhere("deleted_at IS NULL")
|
|
|
|
.getOne();
|
2018-11-24 14:01:06 +02:00
|
|
|
}
|
|
|
|
|
2018-11-24 18:39:17 +02:00
|
|
|
getLatestBotMessagesByChannel(channelId, limit) {
|
2018-11-24 17:12:36 +02:00
|
|
|
return this.messages
|
|
|
|
.createQueryBuilder()
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
2018-11-24 18:39:17 +02:00
|
|
|
.andWhere("channel_id = :channel_id", { channel_id: channelId })
|
|
|
|
.andWhere("is_bot = 1")
|
2018-11-24 19:42:51 +02:00
|
|
|
.andWhere("deleted_at IS NULL")
|
2018-11-24 18:39:17 +02:00
|
|
|
.orderBy("id", "DESC")
|
|
|
|
.limit(limit)
|
2018-11-24 17:12:36 +02:00
|
|
|
.getMany();
|
|
|
|
}
|
|
|
|
|
2018-11-24 18:39:17 +02:00
|
|
|
getLatestByChannelBeforeId(channelId, beforeId, limit) {
|
|
|
|
return this.messages
|
|
|
|
.createQueryBuilder()
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere("channel_id = :channel_id", { channel_id: channelId })
|
|
|
|
.andWhere("id < :beforeId", { beforeId })
|
2018-11-24 19:42:51 +02:00
|
|
|
.andWhere("deleted_at IS NULL")
|
2018-11-24 18:39:17 +02:00
|
|
|
.orderBy("id", "DESC")
|
|
|
|
.limit(limit)
|
|
|
|
.getMany();
|
|
|
|
}
|
|
|
|
|
|
|
|
getLatestByChannelAndUser(channelId, userId, limit) {
|
|
|
|
return this.messages
|
|
|
|
.createQueryBuilder()
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere("channel_id = :channel_id", { channel_id: channelId })
|
|
|
|
.andWhere("user_id = :user_id", { user_id: userId })
|
2018-11-24 19:42:51 +02:00
|
|
|
.andWhere("deleted_at IS NULL")
|
2018-11-24 18:39:17 +02:00
|
|
|
.orderBy("id", "DESC")
|
|
|
|
.limit(limit)
|
|
|
|
.getMany();
|
|
|
|
}
|
|
|
|
|
|
|
|
getUserMessagesByChannelAfterId(userId, channelId, afterId, limit = null) {
|
|
|
|
let query = this.messages
|
|
|
|
.createQueryBuilder()
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere("user_id = :user_id", { user_id: userId })
|
|
|
|
.andWhere("channel_id = :channel_id", { channel_id: channelId })
|
2018-11-24 19:42:51 +02:00
|
|
|
.andWhere("id > :afterId", { afterId })
|
|
|
|
.andWhere("deleted_at IS NULL");
|
2018-11-24 18:39:17 +02:00
|
|
|
|
|
|
|
if (limit != null) {
|
|
|
|
query = query.limit(limit);
|
|
|
|
}
|
|
|
|
|
|
|
|
return query.getMany();
|
|
|
|
}
|
|
|
|
|
2018-11-24 14:01:06 +02:00
|
|
|
async create(data) {
|
2018-11-24 17:59:05 +02:00
|
|
|
const isPermanent = this.toBePermanent.has(data.id);
|
|
|
|
if (isPermanent) {
|
|
|
|
data.is_permanent = true;
|
|
|
|
this.toBePermanent.delete(data.id);
|
|
|
|
}
|
|
|
|
|
2018-11-24 14:01:06 +02:00
|
|
|
try {
|
2018-11-24 14:23:10 +02:00
|
|
|
await this.messages.insert(data);
|
2018-11-24 14:01:06 +02:00
|
|
|
} catch (e) {
|
2018-11-24 14:18:48 +02:00
|
|
|
console.warn(e);
|
2018-11-24 14:01:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const inserted = await this.messages.findOne(data.id);
|
|
|
|
this.events.emit("create", [inserted]);
|
|
|
|
}
|
|
|
|
|
2018-11-24 14:18:48 +02:00
|
|
|
async createFromMsg(msg: Message, overrides = {}) {
|
|
|
|
const savedMessageData = this.msgToSavedMessageData(msg);
|
|
|
|
const postedAt = moment.utc(msg.timestamp, "x").format("YYYY-MM-DD HH:mm:ss.SSS");
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
id: msg.id,
|
|
|
|
guild_id: (msg.channel as GuildChannel).guild.id,
|
|
|
|
channel_id: msg.channel.id,
|
|
|
|
user_id: msg.author.id,
|
|
|
|
is_bot: msg.author.bot,
|
|
|
|
data: savedMessageData,
|
|
|
|
posted_at: postedAt
|
|
|
|
};
|
|
|
|
|
|
|
|
return this.create({ ...data, ...overrides });
|
|
|
|
}
|
|
|
|
|
2018-11-24 14:01:06 +02:00
|
|
|
async markAsDeleted(id) {
|
|
|
|
await this.messages
|
|
|
|
.createQueryBuilder("messages")
|
|
|
|
.update()
|
|
|
|
.set({
|
|
|
|
deleted_at: () => "NOW(3)"
|
|
|
|
})
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere("id = :id", { id })
|
|
|
|
.execute();
|
|
|
|
|
|
|
|
const deleted = await this.messages.findOne(id);
|
|
|
|
this.events.emit("delete", [deleted]);
|
|
|
|
}
|
|
|
|
|
2018-11-24 18:39:17 +02:00
|
|
|
async markBulkAsDeleted(ids) {
|
|
|
|
await this.messages
|
|
|
|
.createQueryBuilder()
|
|
|
|
.update()
|
|
|
|
.set({
|
|
|
|
deleted_at: () => "NOW(3)"
|
|
|
|
})
|
|
|
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
|
|
|
.andWhere("id IN (:ids)", { ids })
|
|
|
|
.execute();
|
|
|
|
|
2018-11-24 19:33:29 +02:00
|
|
|
const deleted = await this.messages
|
2018-11-24 18:39:17 +02:00
|
|
|
.createQueryBuilder()
|
|
|
|
.where("id IN (:ids)", { ids })
|
|
|
|
.getMany();
|
2018-11-24 19:33:29 +02:00
|
|
|
|
|
|
|
this.events.emit("deleteBulk", [deleted]);
|
2018-11-24 18:39:17 +02:00
|
|
|
}
|
|
|
|
|
2018-11-24 14:18:48 +02:00
|
|
|
async saveEdit(id, newData: ISavedMessageData) {
|
2018-11-24 14:01:06 +02:00
|
|
|
const oldMessage = await this.messages.findOne(id);
|
2018-12-15 23:07:19 +02:00
|
|
|
if (!oldMessage) return;
|
|
|
|
|
2018-11-24 14:01:06 +02:00
|
|
|
const newMessage = { ...oldMessage, data: newData };
|
|
|
|
|
|
|
|
await this.messages.update(
|
|
|
|
{ id },
|
|
|
|
{
|
|
|
|
data: newData
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2018-11-24 17:12:36 +02:00
|
|
|
this.events.emit("update", [newMessage, oldMessage]);
|
2018-11-24 14:01:06 +02:00
|
|
|
}
|
2018-11-24 14:18:48 +02:00
|
|
|
|
|
|
|
async saveEditFromMsg(msg: Message) {
|
|
|
|
const newData = this.msgToSavedMessageData(msg);
|
|
|
|
return this.saveEdit(msg.id, newData);
|
|
|
|
}
|
2018-11-24 17:59:05 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2018-11-24 14:01:06 +02:00
|
|
|
}
|