import { RssSubscription } from "@linkwarden/prisma/client"; import { hasPassedLimit } from "./verifyCapacity"; import Parser from "rss-parser"; import { prisma } from "@linkwarden/prisma"; export const rssHandler = async ( rssSubscription: RssSubscription, parser: Parser ) => { try { const feed = await parser.parseURL(rssSubscription.url); const feedLastPubDate = feed.lastBuildDate ?? feed.items.reduce((acc, item) => { const itemPubDate = item.pubDate ? new Date(item.pubDate) : null; return itemPubDate && itemPubDate > acc ? itemPubDate : acc; }, new Date(0)); if (!feedLastPubDate) throw new Error( `No lastBuildDate or pubDate found in the following RSS feed: ${rssSubscription.url}` ); if ( !rssSubscription.lastBuildDate || (rssSubscription.lastBuildDate && new Date(rssSubscription.lastBuildDate) < new Date(feedLastPubDate)) ) { console.log( "\x1b[34m%s\x1b[0m", `Processing new RSS feed items for ${rssSubscription.name}` ); const newItems = feed.items.filter((item) => { const itemPubDate = item.pubDate ? new Date(item.pubDate) : null; return itemPubDate && itemPubDate > rssSubscription.lastBuildDate!; }); const hasTooManyLinks = await hasPassedLimit( rssSubscription.ownerId, newItems.length ); if (hasTooManyLinks) { console.log( "\x1b[34m%s\x1b[0m", `User ${rssSubscription.ownerId} has too many links. Skipping new RSS feed items.` ); return; } // Create all links concurrently await Promise.all( newItems.map(async (item) => { return prisma.link.create({ data: { name: item.title, url: item.link, type: "url", createdBy: { connect: { id: rssSubscription.ownerId, }, }, collection: { connect: { id: rssSubscription.collectionId, }, }, }, }); }) ); // Update the lastBuildDate in the database await prisma.rssSubscription.update({ where: { id: rssSubscription.id }, data: { lastBuildDate: new Date(feedLastPubDate) }, }); } } catch (error) { console.error( "\x1b[34m%s\x1b[0m", `Error processing RSS feed ${rssSubscription.url}:`, error ); } };