From 82d820ea8f341d74cc6125475a8a3a67e8e98ace Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Thu, 3 Aug 2023 13:05:26 +0800 Subject: [PATCH] get link following the order of preference: via, self, alternate --- .../api/src/resolvers/subscriptions/index.ts | 4 +- packages/rss-handler/src/index.ts | 43 +++++++++++++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/api/src/resolvers/subscriptions/index.ts b/packages/api/src/resolvers/subscriptions/index.ts index fcb1e2d96..6cff3e8ce 100644 --- a/packages/api/src/resolvers/subscriptions/index.ts +++ b/packages/api/src/resolvers/subscriptions/index.ts @@ -34,7 +34,9 @@ import { authorized } from '../../utils/helpers' type PartialSubscription = Omit -const parser = new Parser() +const parser = new Parser({ + timeout: 5000, // 5 seconds +}) export type SubscriptionsSuccessPartial = Merge< SubscriptionsSuccess, diff --git a/packages/rss-handler/src/index.ts b/packages/rss-handler/src/index.ts index 49abc27a3..7cebf59db 100644 --- a/packages/rss-handler/src/index.ts +++ b/packages/rss-handler/src/index.ts @@ -12,6 +12,12 @@ interface RssFeedRequest { lastFetchedAt: number // unix timestamp in milliseconds } +interface RssFeedItemLink { + rel?: string + href: string + type?: string +} + function isRssFeedRequest(body: any): body is RssFeedRequest { return ( 'subscriptionId' in body && 'feedUrl' in body && 'lastFetchedAt' in body @@ -114,7 +120,32 @@ Sentry.GCPFunction.init({ }) const signToken = promisify(jwt.sign) -const parser = new Parser() +const parser = new Parser({ + customFields: { + item: [['link', 'links', { keepArray: true }]], + }, +}) + +// get link following the order of preference: via, self, alternate +const getLink = (links: RssFeedItemLink[]) => { + // sort links by preference + const sortedLinks: string[] = [] + + links.forEach((link) => { + if (link.rel === 'via') { + sortedLinks[0] = link.href + } + if (link.rel === 'self' || !link.rel) { + sortedLinks[1] = link.href + } + if (link.rel === 'alternate') { + sortedLinks[2] = link.href + } + }) + + // return the first link that is not undefined + return sortedLinks.find((link) => !!link) +} export const rssHandler = Sentry.GCPFunction.wrapHttpFunction( async (req, res) => { @@ -159,13 +190,19 @@ export const rssHandler = Sentry.GCPFunction.wrapHttpFunction( // save each item in the feed for (const item of feed.items) { - console.log('Processing feed item', item.link, item.isoDate) + console.log('Processing feed item', item.links, item.isoDate) - if (!item.link) { + if (!item.links || item.links.length === 0) { console.log('Invalid feed item', item) continue } + item.link = getLink(item.links as RssFeedItemLink[]) + if (!item.link) { + console.log('Invalid feed item links', item.links) + continue + } + const publishedAt = item.isoDate ? new Date(item.isoDate) : new Date() // remember the last valid item if (