Add:Experimental generate podcast RSS feed #553

This commit is contained in:
advplyr 2022-05-02 16:42:30 -05:00
parent 8b38dda229
commit 678dceefed
7 changed files with 208 additions and 12 deletions

View file

@ -75,7 +75,7 @@ class Server {
this.coverManager = new CoverManager(this.db, this.cacheManager)
this.podcastManager = new PodcastManager(this.db, this.watcher, this.emitter.bind(this))
this.audioMetadataManager = new AudioMetadataMangaer(this.db, this.emitter.bind(this), this.clientEmitter.bind(this))
this.rssFeedManager = new RssFeedManager(this.db)
this.rssFeedManager = new RssFeedManager(this.db, this.emitter.bind(this))
this.scanner = new Scanner(this.db, this.coverManager, this.emitter.bind(this))
@ -205,6 +205,9 @@ class Server {
Logger.info(`[Server] requesting rss feed ${req.params.id}`)
this.rssFeedManager.getFeed(req, res)
})
app.get('/feed/:id/cover', (req, res) => {
this.rssFeedManager.getFeedCover(req, res)
})
app.get('/feed/:id/item/*', (req, res) => {
Logger.info(`[Server] requesting rss feed ${req.params.id}`)
this.rssFeedManager.getFeedItem(req, res)

View file

@ -17,6 +17,11 @@ class LibraryItemController {
item.userMediaProgress = req.user.getMediaProgress(item.id, episodeId)
}
if (includeEntities.includes('rssfeed')) {
var feedData = this.rssFeedManager.findFeedForItem(item.id)
item.rssFeedUrl = feedData ? feedData.feedUrl : null
}
if (item.mediaType == 'book') {
if (includeEntities.includes('authors')) {
item.media.metadata.authors = item.media.metadata.authors.map(au => {

View file

@ -168,7 +168,7 @@ class PodcastController {
async openPodcastFeed(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[PodcastController] Non-admin user attempted to open podcast feed`, req.user)
Logger.error(`[PodcastController] Non-admin user attempted to open podcast feed`, req.user.username)
return res.sendStatus(500)
}
@ -180,6 +180,17 @@ class PodcastController {
})
}
async closePodcastFeed(req, res) {
if (!req.user.isAdminOrUp) {
Logger.error(`[PodcastController] Non-admin user attempted to close podcast feed`, req.user.username)
return res.sendStatus(500)
}
this.rssFeedManager.closePodcastFeedForItem(req.params.id)
res.sendStatus(200)
}
async updateEpisode(req, res) {
var libraryItem = req.libraryItem

View file

@ -5,11 +5,16 @@ const Logger = require('../Logger')
// Not functional at the moment
class RssFeedManager {
constructor(db) {
constructor(db, emitter) {
this.db = db
this.emitter = emitter
this.feeds = {}
}
findFeedForItem(libraryItemId) {
return Object.values(this.feeds).find(feed => feed.libraryItemId === libraryItemId)
}
getFeed(req, res) {
var feedData = this.feeds[req.params.id]
if (!feedData) {
@ -34,7 +39,26 @@ class RssFeedManager {
res.sendFile(fullPath)
}
openFeed(feedId, libraryItem, serverAddress) {
getFeedCover(req, res) {
var feedData = this.feeds[req.params.id]
if (!feedData) {
Logger.error(`[RssFeedManager] Feed not found ${req.params.id}`)
res.sendStatus(404)
return
}
if (!feedData.mediaCoverPath) {
res.sendStatus(404)
return
}
const extname = Path.extname(feedData.mediaCoverPath).toLowerCase().slice(1)
res.type(`image/${extname}`)
var readStream = fs.createReadStream(feedData.mediaCoverPath)
readStream.pipe(res)
}
openFeed(userId, feedId, libraryItem, serverAddress) {
const podcast = libraryItem.media
const feedUrl = `${serverAddress}/feed/${feedId}`
@ -43,7 +67,8 @@ class RssFeedManager {
title: podcast.metadata.title,
description: podcast.metadata.description,
feedUrl,
imageUrl: `${serverAddress}/Logo.png`,
siteUrl: serverAddress,
imageUrl: podcast.coverPath ? `${serverAddress}/feed/${feedId}/cover` : `${serverAddress}/Logo.png`,
author: podcast.metadata.author || 'advplyr',
language: 'en'
})
@ -59,6 +84,7 @@ class RssFeedManager {
type: episode.audioTrack.mimeType,
size: episode.size
},
date: episode.pubDate || '',
url: `${serverAddress}${contentUrl}`,
author: podcast.metadata.author || 'advplyr'
})
@ -66,8 +92,10 @@ class RssFeedManager {
const feedData = {
id: feedId,
userId,
libraryItemId: libraryItem.id,
libraryItemPath: libraryItem.path,
mediaCoverPath: podcast.coverPath,
serverAddress: serverAddress,
feedUrl,
feed
@ -79,9 +107,24 @@ class RssFeedManager {
openPodcastFeed(user, libraryItem, options) {
const serverAddress = options.serverAddress
const feedId = getId('feed')
const feedData = this.openFeed(feedId, libraryItem, serverAddress)
const feedData = this.openFeed(user.id, feedId, libraryItem, serverAddress)
Logger.debug(`[RssFeedManager] Opened podcast feed ${feedData.feedUrl}`)
this.emitter('rss_feed_open', { libraryItemId: libraryItem.id, feedUrl: feedData.feedUrl })
return feedData
}
closePodcastFeedForItem(libraryItemId) {
var feed = this.findFeedForItem(libraryItemId)
if (!feed) return
this.closeRssFeed(feed.id)
}
closeRssFeed(id) {
if (!this.feeds[id]) return
var feedData = this.feeds[id]
this.emitter('rss_feed_closed', { libraryItemId: feedData.libraryItemId, feedUrl: feedData.feedUrl })
delete this.feeds[id]
Logger.info(`[RssFeedManager] Closed RSS feed "${feedData.feedUrl}"`)
}
}
module.exports = RssFeedManager

View file

@ -186,6 +186,7 @@ class ApiRouter {
this.router.get('/podcasts/:id/clear-queue', PodcastController.middleware.bind(this), PodcastController.clearEpisodeDownloadQueue.bind(this))
this.router.post('/podcasts/:id/download-episodes', PodcastController.middleware.bind(this), PodcastController.downloadEpisodes.bind(this))
this.router.post('/podcasts/:id/open-feed', PodcastController.middleware.bind(this), PodcastController.openPodcastFeed.bind(this))
this.router.post('/podcasts/:id/close-feed', PodcastController.middleware.bind(this), PodcastController.closePodcastFeed.bind(this))
this.router.patch('/podcasts/:id/episode/:episodeId', PodcastController.middleware.bind(this), PodcastController.updateEpisode.bind(this))
//