|
@@ -1,4 +1,4 @@
|
|
-import TurndownService, { Options } from "turndown";
|
|
|
|
|
|
+import TurndownService from "turndown";
|
|
import interval from "interval-promise";
|
|
import interval from "interval-promise";
|
|
import { client, FORUMS_DOMAIN } from "../client";
|
|
import { client, FORUMS_DOMAIN } from "../client";
|
|
import sha1 from "sha1";
|
|
import sha1 from "sha1";
|
|
@@ -32,30 +32,30 @@ export class ForumsNewsChecker {
|
|
replacement: () => ""
|
|
replacement: () => ""
|
|
});
|
|
});
|
|
this.turndown.addRule("link", {
|
|
this.turndown.addRule("link", {
|
|
- filter: (node: HTMLElement, opts: Options) => node.nodeName === "A" && node.getAttribute("href") != null,
|
|
|
|
|
|
+ filter: (node: HTMLElement) => node.nodeName === "A" && node.getAttribute("href") != null,
|
|
replacement: (content: string, node: Node) => (node instanceof HTMLElement ? node.getAttribute("href") : null) ?? ""
|
|
replacement: (content: string, node: Node) => (node instanceof HTMLElement ? node.getAttribute("href") : null) ?? ""
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- bbCodeToMarkdown(bbCode: string) {
|
|
|
|
- let html = render(bbCode).replace(/\n/gm, "</br>");
|
|
|
|
|
|
+ bbCodeToMarkdown(bbCode: string): string {
|
|
|
|
+ const html = render(bbCode).replace(/\n/gm, "</br>");
|
|
|
|
|
|
return this.turndown.turndown(html).trim();//.replace(/( {2}\n|\n\n){2,}/gm, "\n");
|
|
return this.turndown.turndown(html).trim();//.replace(/( {2}\n|\n\n){2,}/gm, "\n");
|
|
}
|
|
}
|
|
|
|
|
|
- checkFeeds = async () => {
|
|
|
|
|
|
+ checkFeeds = async (): Promise<void> => {
|
|
try {
|
|
try {
|
|
console.log(`Checking feeds on ${new Date().toISOString()}`);
|
|
console.log(`Checking feeds on ${new Date().toISOString()}`);
|
|
- let forumsNewsRepo = getRepository(PostedForumNewsItem);
|
|
|
|
- let postVerifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
|
|
+ const forumsNewsRepo = getRepository(PostedForumNewsItem);
|
|
|
|
+ const postVerifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
|
|
- let forumThreads = await client.forum.getForumThreads(NEWS_FORUM_ID);
|
|
|
|
|
|
+ const forumThreads = await client.forum.getForumThreads(NEWS_FORUM_ID);
|
|
|
|
|
|
- for (let thread of [...forumThreads.threads, ...forumThreads.sticky]) {
|
|
|
|
- let firstPost = await client.forum.getPost(thread.first_post_id);
|
|
|
|
|
|
+ for (const thread of [...forumThreads.threads, ...forumThreads.sticky]) {
|
|
|
|
+ const firstPost = await client.forum.getPost(thread.first_post_id);
|
|
|
|
|
|
- let contents = this.bbCodeToMarkdown(firstPost.message);
|
|
|
|
|
|
+ const contents = this.bbCodeToMarkdown(firstPost.message);
|
|
let itemObj = forumsNewsRepo.create({
|
|
let itemObj = forumsNewsRepo.create({
|
|
id: thread.thread_id.toString(),
|
|
id: thread.thread_id.toString(),
|
|
hash: sha1(firstPost.message),
|
|
hash: sha1(firstPost.message),
|
|
@@ -68,7 +68,7 @@ export class ForumsNewsChecker {
|
|
})
|
|
})
|
|
});
|
|
});
|
|
|
|
|
|
- let postItem = await forumsNewsRepo.findOne({
|
|
|
|
|
|
+ const postItem = await forumsNewsRepo.findOne({
|
|
where: { id: itemObj.id },
|
|
where: { id: itemObj.id },
|
|
relations: ["verifyMessage"]
|
|
relations: ["verifyMessage"]
|
|
});
|
|
});
|
|
@@ -79,14 +79,14 @@ export class ForumsNewsChecker {
|
|
await forumsNewsRepo.update({
|
|
await forumsNewsRepo.update({
|
|
id: postItem.id
|
|
id: postItem.id
|
|
}, {
|
|
}, {
|
|
- hash: itemObj.hash
|
|
|
|
- });
|
|
|
|
|
|
+ hash: itemObj.hash
|
|
|
|
+ });
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
// Add message ID to mark for edit
|
|
// Add message ID to mark for edit
|
|
if (postItem.hash != itemObj.hash) {
|
|
if (postItem.hash != itemObj.hash) {
|
|
- let newHash = itemObj.hash;
|
|
|
|
|
|
+ const newHash = itemObj.hash;
|
|
if (!postItem.verifyMessage)
|
|
if (!postItem.verifyMessage)
|
|
postItem.verifyMessage = itemObj.verifyMessage;
|
|
postItem.verifyMessage = itemObj.verifyMessage;
|
|
|
|
|
|
@@ -109,70 +109,72 @@ export class ForumsNewsChecker {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- async initPendingReactors() {
|
|
|
|
|
|
+ async initPendingReactors(): Promise<void> {
|
|
if (!this.verifyChannelId)
|
|
if (!this.verifyChannelId)
|
|
return;
|
|
return;
|
|
|
|
|
|
- let verifyChannel = client.bot.channels.resolve(this.verifyChannelId);
|
|
|
|
|
|
+ const verifyChannel = client.bot.channels.resolve(this.verifyChannelId);
|
|
|
|
|
|
if (!verifyChannel)
|
|
if (!verifyChannel)
|
|
return;
|
|
return;
|
|
|
|
|
|
- let repo = getRepository(PostedForumNewsItem);
|
|
|
|
- let verifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
|
|
+ const repo = getRepository(PostedForumNewsItem);
|
|
|
|
+ const verifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
|
|
- let pendingVerifyMessages = await repo.find({
|
|
|
|
|
|
+ const pendingVerifyMessages = await repo.find({
|
|
where: { verifyMessage: Not(IsNull()) },
|
|
where: { verifyMessage: Not(IsNull()) },
|
|
select: ["id"],
|
|
select: ["id"],
|
|
relations: ["verifyMessage"]
|
|
relations: ["verifyMessage"]
|
|
});
|
|
});
|
|
|
|
|
|
- for (let msg of pendingVerifyMessages) {
|
|
|
|
- let m = await this.tryFetchMessage(verifyChannel, msg.verifyMessage!.messageId);
|
|
|
|
|
|
+ for (const msg of pendingVerifyMessages) {
|
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
|
|
+ const m = await this.tryFetchMessage(verifyChannel, msg.verifyMessage!.messageId);
|
|
|
|
|
|
if (!m) {
|
|
if (!m) {
|
|
await repo.update({ id: msg.id }, { verifyMessage: undefined });
|
|
await repo.update({ id: msg.id }, { verifyMessage: undefined });
|
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
await verifyMessageRepo.delete(msg.verifyMessage!);
|
|
await verifyMessageRepo.delete(msg.verifyMessage!);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- let collector = m.createReactionCollector(this.isVerifyReaction, { maxEmojis: 1 });
|
|
|
|
|
|
+ const collector = m.createReactionCollector(this.isVerifyReaction, { maxEmojis: 1 });
|
|
collector.on("collect", this.collectReaction);
|
|
collector.on("collect", this.collectReaction);
|
|
this.reactionCollectors[m.id] = collector;
|
|
this.reactionCollectors[m.id] = collector;
|
|
this.verifyMessageIdToPost[m.id] = msg.id;
|
|
this.verifyMessageIdToPost[m.id] = msg.id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- async addVerifyMessage(item: PostedForumNewsItem) {
|
|
|
|
|
|
+ async addVerifyMessage(item: PostedForumNewsItem): Promise<void> {
|
|
if (!this.verifyChannelId)
|
|
if (!this.verifyChannelId)
|
|
return;
|
|
return;
|
|
if (!item.verifyMessage)
|
|
if (!item.verifyMessage)
|
|
throw new Error("No verify message! This shouldn't happen!");
|
|
throw new Error("No verify message! This shouldn't happen!");
|
|
|
|
|
|
- let verifyChannel = client.bot.channels.resolve(this.verifyChannelId) as TextChannel;
|
|
|
|
|
|
+ const verifyChannel = client.bot.channels.resolve(this.verifyChannelId) as TextChannel;
|
|
|
|
|
|
if (!verifyChannel) {
|
|
if (!verifyChannel) {
|
|
console.log(`Skipping adding item ${item.id} because no verify channel is set up!`);
|
|
console.log(`Skipping adding item ${item.id} because no verify channel is set up!`);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- let verifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
- let forumsNewsRepo = getRepository(PostedForumNewsItem);
|
|
|
|
|
|
+ const verifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
+ const forumsNewsRepo = getRepository(PostedForumNewsItem);
|
|
|
|
|
|
if (item.verifyMessage.messageId) {
|
|
if (item.verifyMessage.messageId) {
|
|
- let oldMessage = await this.tryFetchMessage(verifyChannel, item.verifyMessage.messageId);
|
|
|
|
|
|
+ const oldMessage = await this.tryFetchMessage(verifyChannel, item.verifyMessage.messageId);
|
|
if (oldMessage)
|
|
if (oldMessage)
|
|
await oldMessage.delete();
|
|
await oldMessage.delete();
|
|
}
|
|
}
|
|
|
|
|
|
- let newMessage = await verifyChannel.send(this.toVerifyString(item.id, item.verifyMessage)) as Message;
|
|
|
|
|
|
+ const newMessage = await verifyChannel.send(this.toVerifyString(item.id, item.verifyMessage)) as Message;
|
|
item.verifyMessage.messageId = newMessage.id;
|
|
item.verifyMessage.messageId = newMessage.id;
|
|
|
|
|
|
await newMessage.react("✅");
|
|
await newMessage.react("✅");
|
|
await newMessage.react("❌");
|
|
await newMessage.react("❌");
|
|
|
|
|
|
- let collector = newMessage.createReactionCollector(this.isVerifyReaction, { maxEmojis: 1 });
|
|
|
|
- collector.on("collect", this.collectReaction)
|
|
|
|
|
|
+ const collector = newMessage.createReactionCollector(this.isVerifyReaction, { maxEmojis: 1 });
|
|
|
|
+ collector.on("collect", this.collectReaction);
|
|
this.reactionCollectors[newMessage.id] = collector;
|
|
this.reactionCollectors[newMessage.id] = collector;
|
|
this.verifyMessageIdToPost[newMessage.id] = item.id;
|
|
this.verifyMessageIdToPost[newMessage.id] = item.id;
|
|
|
|
|
|
@@ -180,16 +182,16 @@ export class ForumsNewsChecker {
|
|
await forumsNewsRepo.save(item);
|
|
await forumsNewsRepo.save(item);
|
|
}
|
|
}
|
|
|
|
|
|
- collectReaction = async (reaction: MessageReaction, collector: Collector<string, MessageReaction>) => {
|
|
|
|
- let verifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
- let postRepo = getRepository(PostedForumNewsItem);
|
|
|
|
|
|
+ collectReaction = async (reaction: MessageReaction, collector: Collector<string, MessageReaction>): Promise<void> => {
|
|
|
|
+ const verifyMessageRepo = getRepository(PostVerifyMessage);
|
|
|
|
+ const postRepo = getRepository(PostedForumNewsItem);
|
|
|
|
|
|
- let m = reaction.message;
|
|
|
|
|
|
+ const m = reaction.message;
|
|
collector.stop();
|
|
collector.stop();
|
|
delete this.reactionCollectors[m.id];
|
|
delete this.reactionCollectors[m.id];
|
|
- let postId = this.verifyMessageIdToPost[m.id];
|
|
|
|
|
|
+ const postId = this.verifyMessageIdToPost[m.id];
|
|
|
|
|
|
- let post = await postRepo.findOne({
|
|
|
|
|
|
+ const post = await postRepo.findOne({
|
|
where: { id: postId },
|
|
where: { id: postId },
|
|
relations: ["verifyMessage"]
|
|
relations: ["verifyMessage"]
|
|
});
|
|
});
|
|
@@ -208,18 +210,18 @@ export class ForumsNewsChecker {
|
|
delete this.verifyMessageIdToPost[m.id];
|
|
delete this.verifyMessageIdToPost[m.id];
|
|
}
|
|
}
|
|
|
|
|
|
- async sendNews(item: PostedForumNewsItem) {
|
|
|
|
- let channelRepo = getRepository(KnownChannel);
|
|
|
|
- let newsPostRepo = getRepository(PostedForumNewsItem);
|
|
|
|
|
|
+ async sendNews(item: PostedForumNewsItem): Promise<void> {
|
|
|
|
+ const channelRepo = getRepository(KnownChannel);
|
|
|
|
+ const newsPostRepo = getRepository(PostedForumNewsItem);
|
|
|
|
|
|
- let outChannel = await channelRepo.findOne({
|
|
|
|
|
|
+ const outChannel = await channelRepo.findOne({
|
|
where: { channelType: NEWS_FEED_CHANNEL }
|
|
where: { channelType: NEWS_FEED_CHANNEL }
|
|
});
|
|
});
|
|
|
|
|
|
if (!outChannel)
|
|
if (!outChannel)
|
|
return;
|
|
return;
|
|
|
|
|
|
- let sentMessage = await this.postNewsItem(outChannel.channelId, item);
|
|
|
|
|
|
+ const sentMessage = await this.postNewsItem(outChannel.channelId, item);
|
|
|
|
|
|
item.postedMessageId = sentMessage?.id;
|
|
item.postedMessageId = sentMessage?.id;
|
|
item.verifyMessage = undefined;
|
|
item.verifyMessage = undefined;
|
|
@@ -227,11 +229,11 @@ export class ForumsNewsChecker {
|
|
await newsPostRepo.save(item);
|
|
await newsPostRepo.save(item);
|
|
}
|
|
}
|
|
|
|
|
|
- isVerifyReaction = (reaction: MessageReaction, user: User) => {
|
|
|
|
|
|
+ isVerifyReaction = (reaction: MessageReaction, user: User): boolean => {
|
|
return (reaction.emoji.name == "✅" || reaction.emoji.name == "❌") && !user.bot;
|
|
return (reaction.emoji.name == "✅" || reaction.emoji.name == "❌") && !user.bot;
|
|
}
|
|
}
|
|
|
|
|
|
- async tryFetchMessage(channel?: Channel, messageId?: string) {
|
|
|
|
|
|
+ async tryFetchMessage(channel?: Channel, messageId?: string): Promise<Message | null> {
|
|
if(!channel || !messageId)
|
|
if(!channel || !messageId)
|
|
return null;
|
|
return null;
|
|
try {
|
|
try {
|
|
@@ -243,7 +245,7 @@ export class ForumsNewsChecker {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- get shouldVerify() {
|
|
|
|
|
|
+ get shouldVerify(): boolean {
|
|
return this.verifyChannelId != undefined;
|
|
return this.verifyChannelId != undefined;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -251,14 +253,14 @@ export class ForumsNewsChecker {
|
|
if (!item.verifyMessage)
|
|
if (!item.verifyMessage)
|
|
throw new Error("No message to send!");
|
|
throw new Error("No message to send!");
|
|
|
|
|
|
- let newsMessage = this.toNewsString(item.verifyMessage);
|
|
|
|
- let ch = client.bot.channels.resolve(channel);
|
|
|
|
|
|
+ const newsMessage = this.toNewsString(item.verifyMessage);
|
|
|
|
+ const ch = client.bot.channels.resolve(channel);
|
|
|
|
|
|
if (!(ch instanceof TextChannel))
|
|
if (!(ch instanceof TextChannel))
|
|
return null;
|
|
return null;
|
|
|
|
|
|
if (item.postedMessageId) {
|
|
if (item.postedMessageId) {
|
|
- let message = await this.tryFetchMessage(ch, item.postedMessageId);
|
|
|
|
|
|
+ const message = await this.tryFetchMessage(ch, item.postedMessageId);
|
|
if (message)
|
|
if (message)
|
|
return await message.edit(newsMessage);
|
|
return await message.edit(newsMessage);
|
|
else
|
|
else
|
|
@@ -268,7 +270,7 @@ export class ForumsNewsChecker {
|
|
return await ch.send(newsMessage) as Message;
|
|
return await ch.send(newsMessage) as Message;
|
|
}
|
|
}
|
|
|
|
|
|
- toNewsString(item: PostVerifyMessage) {
|
|
|
|
|
|
+ toNewsString(item: PostVerifyMessage): string {
|
|
return `**${item.title}**
|
|
return `**${item.title}**
|
|
Posted by ${item.author}
|
|
Posted by ${item.author}
|
|
${item.link}
|
|
${item.link}
|
|
@@ -276,7 +278,7 @@ ${item.link}
|
|
${item.text}`;
|
|
${item.text}`;
|
|
}
|
|
}
|
|
|
|
|
|
- toVerifyString(postId: string, item: PostVerifyMessage) {
|
|
|
|
|
|
+ toVerifyString(postId: string, item: PostVerifyMessage): string {
|
|
return `[${item.isNew ? "🆕 ADD" : "✏️ EDIT"}]
|
|
return `[${item.isNew ? "🆕 ADD" : "✏️ EDIT"}]
|
|
Post ID: **${postId}**
|
|
Post ID: **${postId}**
|
|
|
|
|
|
@@ -288,17 +290,17 @@ React with ✅ (approve) or ❌ (deny).`;
|
|
@Command({
|
|
@Command({
|
|
pattern: /^edit (\d+)\s+((.*[\n\r]*)+)$/i
|
|
pattern: /^edit (\d+)\s+((.*[\n\r]*)+)$/i
|
|
})
|
|
})
|
|
- async editPreview(msg: Message, contests: string, match: RegExpMatchArray) {
|
|
|
|
|
|
+ async editPreview(msg: Message, contests: string, match: RegExpMatchArray): Promise<void> {
|
|
if (msg.channel.id != this.verifyChannelId)
|
|
if (msg.channel.id != this.verifyChannelId)
|
|
return;
|
|
return;
|
|
|
|
|
|
- let id = match[1];
|
|
|
|
- let newContents = match[2].trim();
|
|
|
|
|
|
+ const id = match[1];
|
|
|
|
+ const newContents = match[2].trim();
|
|
|
|
|
|
- let repo = getRepository(PostedForumNewsItem);
|
|
|
|
- let verifyRepo = getRepository(PostVerifyMessage);
|
|
|
|
|
|
+ const repo = getRepository(PostedForumNewsItem);
|
|
|
|
+ const verifyRepo = getRepository(PostVerifyMessage);
|
|
|
|
|
|
- let post = await repo.findOne({
|
|
|
|
|
|
+ const post = await repo.findOne({
|
|
where: { id: id },
|
|
where: { id: id },
|
|
relations: ["verifyMessage"]
|
|
relations: ["verifyMessage"]
|
|
});
|
|
});
|
|
@@ -308,7 +310,7 @@ React with ✅ (approve) or ❌ (deny).`;
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- let editMsg = await this.tryFetchMessage(client.bot.channels.resolve(this.verifyChannelId) ?? undefined, post.verifyMessage.messageId);
|
|
|
|
|
|
+ const editMsg = await this.tryFetchMessage(client.bot.channels.resolve(this.verifyChannelId) ?? undefined, post.verifyMessage.messageId);
|
|
|
|
|
|
if (!editMsg) {
|
|
if (!editMsg) {
|
|
msg.channel.send(`${msg.author.toString()} No verify message found for ${id}! This is a bug: report to horse.`);
|
|
msg.channel.send(`${msg.author.toString()} No verify message found for ${id}! This is a bug: report to horse.`);
|
|
@@ -322,10 +324,10 @@ React with ✅ (approve) or ❌ (deny).`;
|
|
await msg.delete();
|
|
await msg.delete();
|
|
}
|
|
}
|
|
|
|
|
|
- async onStart() {
|
|
|
|
- let repo = getRepository(KnownChannel);
|
|
|
|
|
|
+ async onStart(): Promise<void> {
|
|
|
|
+ const repo = getRepository(KnownChannel);
|
|
|
|
|
|
- let verifyChannel = await repo.findOne({
|
|
|
|
|
|
+ const verifyChannel = await repo.findOne({
|
|
channelType: NEWS_POST_VERIFY_CHANNEL
|
|
channelType: NEWS_POST_VERIFY_CHANNEL
|
|
});
|
|
});
|
|
|
|
|
|
@@ -334,10 +336,10 @@ React with ✅ (approve) or ❌ (deny).`;
|
|
|
|
|
|
this.verifyChannelId = verifyChannel.channelId;
|
|
this.verifyChannelId = verifyChannel.channelId;
|
|
|
|
|
|
- let user = await client.forum.getMe();
|
|
|
|
|
|
+ const user = await client.forum.getMe();
|
|
this.botUserId = user.user_id;
|
|
this.botUserId = user.user_id;
|
|
|
|
|
|
await this.initPendingReactors();
|
|
await this.initPendingReactors();
|
|
interval(this.checkFeeds, RSS_UPDATE_INTERVAL_MIN * 60 * 1000);
|
|
interval(this.checkFeeds, RSS_UPDATE_INTERVAL_MIN * 60 * 1000);
|
|
}
|
|
}
|
|
-};
|
|
|
|
|
|
+}
|