From d1916495cf6e1441e7bf174d07a7f16be01f26c6 Mon Sep 17 00:00:00 2001 From: Eric P Date: Fri, 4 Nov 2022 00:10:14 -0500 Subject: [PATCH 1/2] Added live episodes to the front page --- server/index.js | 21 +++++++++++++ ui/src/components/RecentPodcasts/index.tsx | 5 ++-- ui/src/pages/landing.tsx | 34 ++++++++++++++++++---- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/server/index.js b/server/index.js index fd595fde..f08d0db7 100644 --- a/server/index.js +++ b/server/index.js @@ -112,6 +112,27 @@ app.use('/api/episodes/byfeedid', async (req, res) => { res.send(response) }) +app.use('/api/episodes/live', async (req, res) => { + let max = req.query.max + const response = await api.custom('episodes/live', {pretty: true, max: max}) + const minPublished = Math.floor(new Date().getTime() / 1000) - 3600 + + // assume live episodes posted within the past hour are live + // since the api doesn't provide start and end times + + response.items = response.items.filter(item => { + return item.datePublished >= minPublished + }) + + response.count = response.items.length; + + if (response.count === 0) { + response.description = 'No matching items' + } + + res.send(response) +}) + app.use('/api/add/byfeedurl', async (req, res) => { let feedUrl = req.query.url const response = await apiAdd.addByFeedUrl(feedUrl) diff --git a/ui/src/components/RecentPodcasts/index.tsx b/ui/src/components/RecentPodcasts/index.tsx index 20b37848..d6734575 100644 --- a/ui/src/components/RecentPodcasts/index.tsx +++ b/ui/src/components/RecentPodcasts/index.tsx @@ -11,6 +11,7 @@ import {Link} from "react-router-dom"; interface IProps { title?: string + liveTitle?: string podcasts?: Array loading?: boolean } @@ -60,7 +61,7 @@ export default class RecentPodcasts extends React.Component { } render() { - const {loading, title, podcasts} = this.props + const {loading, title, liveTitle, podcasts} = this.props const {index} = this.state const selectedPodcast = podcasts[index] return ( @@ -87,7 +88,7 @@ export default class RecentPodcasts extends React.Component { {title && (
- {title} + {selectedPodcast.live ? liveTitle : title}
)}
diff --git a/ui/src/pages/landing.tsx b/ui/src/pages/landing.tsx index ae520457..743100a3 100644 --- a/ui/src/pages/landing.tsx +++ b/ui/src/pages/landing.tsx @@ -11,14 +11,14 @@ import './styles.scss' interface IProps {} interface IState { loading?: boolean - recentPodcasts?: Array + podcasts?: Array stats?: {} } export default class Landing extends React.Component { state = { loading: true, - recentPodcasts: [], + podcasts: [], stats: { feedCountTotal: '1,318,328', feedCount3days: '81,919', @@ -36,13 +36,13 @@ export default class Landing extends React.Component { async componentDidMount(): Promise { this._isMounted = true - const recentPodcasts = (await this.getRecentEpisodes()).items + const podcasts = await this.getEpisodes() const stats = await this.getStats() if (this._isMounted) { this.setState({ loading: false, - recentPodcasts, + podcasts, stats, }) } @@ -68,8 +68,29 @@ export default class Landing extends React.Component { return await response.json() } + async getLiveEpisodes() { + let response = await fetch(`/api/episodes/live?max=3`, { + credentials: 'same-origin', + method: 'GET', + }) + return await response.json() + } + + async getEpisodes() { + let liveResponse = await this.getLiveEpisodes() + let episodes = liveResponse.items.map(ep => { + ep.live = true + return ep + }) + + let recentResponse = await this.getRecentEpisodes() + episodes = episodes.concat(recentResponse.items) + + return episodes; + } + render() { - const { loading, recentPodcasts, stats } = this.state + const { loading, podcasts, stats } = this.state updateTitle('Home') return (
@@ -108,8 +129,9 @@ export default class Landing extends React.Component {
From a956dd392e9cf3f60905d7e1085e8f0377f4d01c Mon Sep 17 00:00:00 2001 From: Eric P Date: Thu, 9 Mar 2023 22:41:11 -0600 Subject: [PATCH 2/2] Check the episodes endpoint to see if updated live items are actually live --- server/index.js | 50 ++++++++++++++++++++++++++++++---------- ui/src/pages/landing.tsx | 2 +- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/server/index.js b/server/index.js index f08d0db7..0fcf5813 100644 --- a/server/index.js +++ b/server/index.js @@ -113,24 +113,50 @@ app.use('/api/episodes/byfeedid', async (req, res) => { }) app.use('/api/episodes/live', async (req, res) => { - let max = req.query.max - const response = await api.custom('episodes/live', {pretty: true, max: max}) - const minPublished = Math.floor(new Date().getTime() / 1000) - 3600 + const max = req.query.max - // assume live episodes posted within the past hour are live - // since the api doesn't provide start and end times + // grab live items from recently updated feeds + // (large max value to work around sorting issue `docs-api#96`) + const updatedLiveItems = await api.custom('episodes/live', {max: 100}) - response.items = response.items.filter(item => { - return item.datePublished >= minPublished - }) + // re-sort to put recently updated live items first + updatedLiveItems.items.sort((a, b) => { + return (b.datePublished - a.datePublished) + }); + + const feedIds = new Set(updatedLiveItems.items.map(feed => feed.feedId)) + const feedTitles = updatedLiveItems.items.reduce((result, item) => { + result[item.feedId] = item.feedTitle + return result + }, {}) - response.count = response.items.length; + const liveItems = [] + const liveCutoff = 3600 // cut off perpetually live shows after an hour - if (response.count === 0) { - response.description = 'No matching items' + const now = Math.floor(new Date().getTime() / 1000) + + // check each individual feed and collect live items that are actually live (status = live) + for (const feedId of feedIds) { + const feed = await api.episodesByFeedId(feedId) + + for (const item of feed.liveItems) { + if (item.status === 'live' && now < (item.startTime + liveCutoff) && liveItems.length < max) { + item.feedTitle = feedTitles[item.feedId]; + liveItems.push(item); + } + } + + if (liveItems.length >= max) { + break; + } } - res.send(response) + // sort and put newly started items first + liveItems.sort((a, b) => { + return (b.startTime - a.startTime) + }); + + res.send(liveItems) }) app.use('/api/add/byfeedurl', async (req, res) => { diff --git a/ui/src/pages/landing.tsx b/ui/src/pages/landing.tsx index 743100a3..01e424d4 100644 --- a/ui/src/pages/landing.tsx +++ b/ui/src/pages/landing.tsx @@ -78,7 +78,7 @@ export default class Landing extends React.Component { async getEpisodes() { let liveResponse = await this.getLiveEpisodes() - let episodes = liveResponse.items.map(ep => { + let episodes = liveResponse.map(ep => { ep.live = true return ep })