Skip to content

Commit

Permalink
Merge pull request #13806 from ethereum/homepage-atom-feed
Browse files Browse the repository at this point in the history
Homepage: enable atom feeds
  • Loading branch information
pettinarip authored Sep 6, 2024
2 parents 2dec337 + 6e205c9 commit 4d13857
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 45 deletions.
138 changes: 100 additions & 38 deletions src/lib/api/fetchRSS.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { parseString } from "xml2js"

import type { RSSChannel, RSSItem, RSSResult } from "../types"
import type {
AtomElement,
AtomResult,
RSSChannel,
RSSItem,
RSSResult,
} from "../types"
import { isValidDate } from "../utils/date"

/**
Expand All @@ -12,45 +18,101 @@ export const fetchRSS = async (xmlUrl: string | string[]) => {
const urls = Array.isArray(xmlUrl) ? xmlUrl : [xmlUrl]
const allItems: RSSItem[][] = []
for (const url of urls) {
const rssItems = (await fetchXml(url)) as RSSResult
if (!rssItems.rss) continue
const [mainChannel] = rssItems.rss.channel as RSSChannel[]
const [source] = mainChannel.title
const [sourceUrl] = mainChannel.link
const channelImage = mainChannel.image ? mainChannel.image[0].url[0] : ""
const response = (await fetchXml(url)) as RSSResult | AtomResult
if ("rss" in response) {
const [mainChannel] = response.rss.channel as RSSChannel[]
const [source] = mainChannel.title
const [sourceUrl] = mainChannel.link
const channelImage = mainChannel.image ? mainChannel.image[0].url[0] : ""

const parsedRssItems = mainChannel.item
// Filter out items with invalid dates
.filter((item) => {
if (!item.pubDate) return false
const [pubDate] = item.pubDate
return isValidDate(pubDate)
})
// Sort by pubDate (most recent is first in array
.sort((a, b) => {
const dateA = new Date(a.pubDate[0])
const dateB = new Date(b.pubDate[0])
return dateB.getTime() - dateA.getTime()
})
// Map to RSSItem object
.map((item) => {
const getImgSrc = () => {
if (item.enclosure) return item.enclosure[0].$.url
if (item["media:content"]) return item["media:content"][0].$.url
return channelImage
}
return {
pubDate: item.pubDate[0],
title: item.title[0],
link: item.link[0],
imgSrc: getImgSrc(),
source,
sourceUrl,
sourceFeedUrl: url,
} as RSSItem
})
const parsedRssItems = mainChannel.item
// Filter out items with invalid dates
.filter((item) => {
if (!item.pubDate) return false
const [pubDate] = item.pubDate
return isValidDate(pubDate)
})
// Sort by pubDate (most recent is first in array
.sort((a, b) => {
const dateA = new Date(a.pubDate[0])
const dateB = new Date(b.pubDate[0])
return dateB.getTime() - dateA.getTime()
})
// Map to RSSItem object
.map((item) => {
const getImgSrc = () => {
if (item.enclosure) return item.enclosure[0].$.url
if (item["media:content"]) return item["media:content"][0].$.url
return channelImage
}
return {
pubDate: item.pubDate[0],
title: item.title[0],
link: item.link[0],
imgSrc: getImgSrc(),
source,
sourceUrl,
sourceFeedUrl: url,
} as RSSItem
})

allItems.push(parsedRssItems)
allItems.push(parsedRssItems)
} else if ("feed" in response) {
const [source] = response.feed.title
const [sourceUrl] = response.feed.id
const feedImage = response.feed.icon?.[0]

const parsedAtomItems = response.feed.entry
// Filter out items with invalid dates
.filter((entry) => {
if (!entry.updated) return false
const [published] = entry.updated
return isValidDate(published)
})
// Sort by published (most recent is first in array
.sort((a, b) => {
const dateA = new Date(a.updated[0])
const dateB = new Date(b.updated[0])
return dateB.getTime() - dateA.getTime()
})
// Map to RSSItem object
.map((entry) => {
const getString = (el?: AtomElement[]): string => {
if (!el) return ""
const [firstEl] = el
if (typeof firstEl === "string") return firstEl
return firstEl._ || ""
}
const getHref = (): string => {
if (!entry.link) {
console.warn(`No link found for RSS url: ${url}`)
return ""
}
const link = entry.link[0]
if (typeof link === "string") return link
return link.$.href || ""
}
const getImgSrc = (): string => {
const imgRegEx = /https?:\/\/[^"]*?\.(jpe?g|png|webp)/g
const contentMatch = getString(entry.content).match(imgRegEx)
if (contentMatch) return contentMatch[0]
const summaryMatch = getString(entry.summary).match(imgRegEx)
if (summaryMatch) return summaryMatch[0]
return feedImage || ""
}
return {
pubDate: entry.updated[0],
title: getString(entry.title),
link: getHref(),
imgSrc: getImgSrc(),
source,
sourceUrl,
sourceFeedUrl: url,
} as RSSItem
})

allItems.push(parsedAtomItems)
}
}
return allItems as RSSItem[][]
}
Expand Down
12 changes: 5 additions & 7 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,13 @@ export const COMMUNITY_BLOGS: CommunityBlog[] = [
feed: SOLIDITY_FEED,
},
{
name: "Privacy and Scaling Explorations",
href: "https://mirror.xyz/privacy-scaling-explorations.eth",
// feed: "https://mirror.xyz/privacy-scaling-explorations.eth/feed/atom", // Old xml format
feed: "https://mirror.xyz/privacy-scaling-explorations.eth/feed/atom",
},
{
href: "https://stark.mirror.xyz/",
feed: "https://stark.mirror.xyz/feed/atom",
},
// {
// href: "https://stark.mirror.xyz/",
// feed: "https://stark.mirror.xyz/feed/atom", // Old xml format
// },
// TODO: Add support for old xml format, re-enable above when ready
]

export const BLOG_FEEDS = COMMUNITY_BLOGS.map(({ feed }) => feed).filter(
Expand Down
30 changes: 30 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,36 @@ export type RSSResult = {
}
}

export type AtomElement =
| string
| {
_?: string // children
$: {
href?: string
}
}
export type AtomEntry = {
id: string[]
title: AtomElement[]
updated: string[]
content?: AtomElement[]
link?: AtomElement[]
summary?: AtomElement[]
}

export type AtomResult = {
feed: {
id: string[]
title: string[]
updated: string[]
generator: string[]
link: string[]
subtitle: string[]
icon?: string[]
entry: AtomEntry[]
}
}

export type CommunityBlog = {
href: string
} & ({ name: string; feed?: string } | { name?: string; feed: string })
Expand Down

0 comments on commit 4d13857

Please sign in to comment.