|
@@ -3,6 +3,12 @@ const RSSParser = require("rss-parser");
|
|
|
const db = require("../db.js");
|
|
|
const interval = require("interval-promise");
|
|
|
const client = require("../client.js");
|
|
|
+const sha1 = require("sha1");
|
|
|
+
|
|
|
+const verifyChannelID = db.get("newsPostVerifyChannel").value();
|
|
|
+
|
|
|
+const reactionCollectors = {};
|
|
|
+const verifyMessageIdToPostId = {};
|
|
|
|
|
|
const turndown = new TurndownService();
|
|
|
turndown.addRule("image", {
|
|
@@ -27,7 +33,6 @@ function getThreadId(url) {
|
|
|
async function checkFeeds() {
|
|
|
console.log(`Checking feeds on ${new Date().toISOString()}`);
|
|
|
let feeds = db.get("rssFeeds").value();
|
|
|
- let outlets = db.get("feedOutputs").value();
|
|
|
let oldNews = db.get("postedNewsGuids");
|
|
|
for(let feedEntry of feeds) {
|
|
|
let feed = await parser.parseURL(feedEntry.url);
|
|
@@ -37,12 +42,37 @@ async function checkFeeds() {
|
|
|
if(printableItems.length > 0) {
|
|
|
printableItems.forEach(item => {
|
|
|
let itemID = getThreadId(item.guid);
|
|
|
- if(oldNews.has(itemID).value())
|
|
|
- return;
|
|
|
- outlets.forEach(ch => {
|
|
|
- client.channels.get(ch).send(`**${item.title}**\nPosted by ${item.creator}\n${item.link}\n\n${turndown.turndown(item[feedEntry.contentElement]).replace(/( {2}\n|\n\n){2,}/gm, "\n").replace(item.link, "")}`);
|
|
|
- });
|
|
|
- oldNews.set(itemID, true).write();
|
|
|
+
|
|
|
+ let contents = item[feedEntry.contentElement];
|
|
|
+ let itemObj = {
|
|
|
+ id: itemID,
|
|
|
+ title: item.title,
|
|
|
+ link: item.link,
|
|
|
+ creator: item.creator,
|
|
|
+ contents: contents,
|
|
|
+ hash: sha1(contents),
|
|
|
+ messageId: null,
|
|
|
+ verifyMessageId: null
|
|
|
+ };
|
|
|
+
|
|
|
+ if(oldNews.has(itemObj.id).value()){
|
|
|
+ let data = oldNews.get(itemObj.id).value();
|
|
|
+ // Old type, don't care
|
|
|
+ if(data === true)
|
|
|
+ return;
|
|
|
+
|
|
|
+ // Add message ID to mark for edit
|
|
|
+ if(data.hash != itemObj.hash)
|
|
|
+ itemObj.messageId = data.messageId;
|
|
|
+ else
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!shouldVerify())
|
|
|
+ sendNews(itemObj);
|
|
|
+ else
|
|
|
+ addVerifyMessage(itemObj);
|
|
|
+
|
|
|
});
|
|
|
let lastUpdateDate = printableItems[printableItems.length - 1].isoDate;
|
|
|
console.log(`Setting last update marker on ${feedEntry.url} to ${lastUpdateDate}`);
|
|
@@ -51,7 +81,118 @@ async function checkFeeds() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+function initPendingReactors() {
|
|
|
+ let verifyChannel = client.channels.get(verifyChannelID);
|
|
|
+ db.get("newsCache").forOwn(async i => {
|
|
|
+ let m = await verifyChannel.fetchMessage(i.verifyMessageId);
|
|
|
+ let collector = m.createReactionCollector(isVerifyReaction, { maxEmojis: 1 });
|
|
|
+ collector.on("collect", collectReaction)
|
|
|
+ reactionCollectors[m.id] = collector;
|
|
|
+ verifyMessageIdToPostId[m.id] = i.id;
|
|
|
+ }).value();
|
|
|
+}
|
|
|
+
|
|
|
+async function addVerifyMessage(item) {
|
|
|
+ let verifyChannel = client.channels.get(verifyChannelID);
|
|
|
+ let cache = db.get("newsCache");
|
|
|
+ let postedNews = db.get("postedNewsGuids");
|
|
|
+ let process = "🆕 ADD";
|
|
|
+
|
|
|
+ if(postedNews.has(item.id).value())
|
|
|
+ process = "✏️ EDIT";
|
|
|
+
|
|
|
+ if(cache.has(item.id).value()) {
|
|
|
+ let oldItem = cache.get(item.id).value();
|
|
|
+ let oldMessage = await verifyChannel.fetchMessage(oldItem.verifyMessageId);
|
|
|
+ if(oldMessage)
|
|
|
+ await oldMessage.delete();
|
|
|
+ }
|
|
|
+
|
|
|
+ let newMessage = await verifyChannel.send(`[${process}]
|
|
|
+Post ID: **${item.id}**
|
|
|
+
|
|
|
+${newsToString(item)}
|
|
|
+
|
|
|
+React with ✅ (approve) or ❌ (deny).`
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+ await newMessage.react("✅");
|
|
|
+ await newMessage.react("❌");
|
|
|
+
|
|
|
+ var collector = newMessage.createReactionCollector(isVerifyReaction, { maxEmojis: 1 });
|
|
|
+ collector.on("collect", collectReaction)
|
|
|
+ reactionCollectors[newMessage.id] = collector;
|
|
|
+ verifyMessageIdToPostId[newMessage.id] = item.id;
|
|
|
+ item.verifyMessageId = newMessage.id;
|
|
|
+ cache.set(item.id, item).write();
|
|
|
+}
|
|
|
+
|
|
|
+function collectReaction(reaction, collector) {
|
|
|
+ let cache = db.get("newsCache");
|
|
|
+ let oldNews = db.get("postedNewsGuids");
|
|
|
+ let m = reaction.message;
|
|
|
+ collector.stop();
|
|
|
+ delete reactionCollectors[m.id];
|
|
|
+ let postId = verifyMessageIdToPostId[m.id];
|
|
|
+ let item = cache.get(postId).value();
|
|
|
+ cache.unset(postId).write();
|
|
|
+ m.delete();
|
|
|
+
|
|
|
+ if(reaction.emoji.name == "✅")
|
|
|
+ sendNews(item);
|
|
|
+ else
|
|
|
+ oldNews.set(item.id, {
|
|
|
+ hash: item.hash,
|
|
|
+ messageId: null
|
|
|
+ }).write();
|
|
|
+}
|
|
|
+
|
|
|
+async function sendNews(item) {
|
|
|
+ let outChannel = db.get("feedOutputChannel").value();
|
|
|
+ let oldNews = db.get("postedNewsGuids");
|
|
|
+
|
|
|
+ let sentMessage = await postNewsItem(outChannel, item);
|
|
|
+ oldNews.set(item.id, {
|
|
|
+ hash: item.hash,
|
|
|
+ messageId: sentMessage.id
|
|
|
+ }).write();
|
|
|
+}
|
|
|
+
|
|
|
+function isVerifyReaction(reaction, user) {
|
|
|
+ return (reaction.emoji.name == "✅" || reaction.emoji.name == "❌") && !user.bot;
|
|
|
+}
|
|
|
+
|
|
|
+function shouldVerify() {
|
|
|
+ return verifyChannelID != "";
|
|
|
+}
|
|
|
+
|
|
|
+async function postNewsItem(channel, item) {
|
|
|
+ let newsText = newsToString(item);
|
|
|
+
|
|
|
+ let ch = client.channels.get(channel);
|
|
|
+
|
|
|
+ if(item.messageId) {
|
|
|
+ let message = await ch.fetchMessage(item.messageId);
|
|
|
+ if(message)
|
|
|
+ return await message.edit(newsText);
|
|
|
+ else
|
|
|
+ return await ch.send(newsText);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return await ch.send(newsText);
|
|
|
+}
|
|
|
+
|
|
|
+function newsToString(item) {
|
|
|
+ return `**${item.title}**
|
|
|
+Posted by ${item.creator}
|
|
|
+${item.link}
|
|
|
+
|
|
|
+${turndown.turndown(item.contents).replace(/( {2}\n|\n\n){2,}/gm, "\n").replace(item.link, "")}`;
|
|
|
+}
|
|
|
+
|
|
|
const onStart = () => {
|
|
|
+ initPendingReactors();
|
|
|
interval(checkFeeds, RSS_UPDATE_INTERVAL_MIN * 60 * 1000);
|
|
|
};
|
|
|
|