2022-05-02 21:41:59 +02:00
|
|
|
const Path = require('path')
|
2022-05-03 00:21:16 +02:00
|
|
|
const fs = require('fs-extra')
|
2022-05-02 21:41:59 +02:00
|
|
|
const { Podcast } = require('podcast')
|
|
|
|
const { getId } = require('../utils/index')
|
|
|
|
const Logger = require('../Logger')
|
|
|
|
|
|
|
|
// Not functional at the moment
|
|
|
|
class RssFeedManager {
|
2022-05-02 23:42:30 +02:00
|
|
|
constructor(db, emitter) {
|
2022-05-02 21:41:59 +02:00
|
|
|
this.db = db
|
2022-05-02 23:42:30 +02:00
|
|
|
this.emitter = emitter
|
2022-05-02 21:41:59 +02:00
|
|
|
this.feeds = {}
|
|
|
|
}
|
|
|
|
|
2022-05-02 23:42:30 +02:00
|
|
|
findFeedForItem(libraryItemId) {
|
|
|
|
return Object.values(this.feeds).find(feed => feed.libraryItemId === libraryItemId)
|
|
|
|
}
|
|
|
|
|
2022-05-02 21:41:59 +02:00
|
|
|
getFeed(req, res) {
|
|
|
|
var feedData = this.feeds[req.params.id]
|
|
|
|
if (!feedData) {
|
|
|
|
Logger.error(`[RssFeedManager] Feed not found ${req.params.id}`)
|
|
|
|
res.sendStatus(404)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var xml = feedData.feed.buildXml()
|
|
|
|
res.set('Content-Type', 'text/xml')
|
|
|
|
res.send(xml)
|
|
|
|
}
|
|
|
|
|
|
|
|
getFeedItem(req, res) {
|
|
|
|
var feedData = this.feeds[req.params.id]
|
|
|
|
if (!feedData) {
|
|
|
|
Logger.error(`[RssFeedManager] Feed not found ${req.params.id}`)
|
|
|
|
res.sendStatus(404)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var remainingPath = req.params['0']
|
|
|
|
var fullPath = Path.join(feedData.libraryItemPath, remainingPath)
|
|
|
|
res.sendFile(fullPath)
|
|
|
|
}
|
|
|
|
|
2022-05-02 23:42:30 +02:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2022-05-04 01:52:34 +02:00
|
|
|
openFeed(userId, slug, libraryItem, serverAddress) {
|
2022-05-02 21:41:59 +02:00
|
|
|
const podcast = libraryItem.media
|
|
|
|
|
2022-05-04 01:52:34 +02:00
|
|
|
const feedUrl = `${serverAddress}/feed/${slug}`
|
2022-05-02 21:41:59 +02:00
|
|
|
// Removed Podcast npm package and ip package
|
|
|
|
const feed = new Podcast({
|
|
|
|
title: podcast.metadata.title,
|
|
|
|
description: podcast.metadata.description,
|
|
|
|
feedUrl,
|
2022-05-02 23:42:30 +02:00
|
|
|
siteUrl: serverAddress,
|
2022-05-04 01:52:34 +02:00
|
|
|
imageUrl: podcast.coverPath ? `${serverAddress}/feed/${slug}/cover` : `${serverAddress}/Logo.png`,
|
2022-05-02 21:41:59 +02:00
|
|
|
author: podcast.metadata.author || 'advplyr',
|
|
|
|
language: 'en'
|
|
|
|
})
|
|
|
|
podcast.episodes.forEach((episode) => {
|
|
|
|
var contentUrl = episode.audioTrack.contentUrl.replace(/\\/g, '/')
|
2022-05-04 01:52:34 +02:00
|
|
|
contentUrl = contentUrl.replace(`/s/item/${libraryItem.id}`, `/feed/${slug}/item`)
|
2022-05-02 21:41:59 +02:00
|
|
|
|
|
|
|
feed.addItem({
|
|
|
|
title: episode.title,
|
|
|
|
description: episode.description || '',
|
|
|
|
enclosure: {
|
|
|
|
url: `${serverAddress}${contentUrl}`,
|
|
|
|
type: episode.audioTrack.mimeType,
|
|
|
|
size: episode.size
|
|
|
|
},
|
2022-05-02 23:42:30 +02:00
|
|
|
date: episode.pubDate || '',
|
2022-05-02 21:41:59 +02:00
|
|
|
url: `${serverAddress}${contentUrl}`,
|
|
|
|
author: podcast.metadata.author || 'advplyr'
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
const feedData = {
|
2022-05-04 01:52:34 +02:00
|
|
|
id: slug,
|
|
|
|
slug,
|
2022-05-02 23:42:30 +02:00
|
|
|
userId,
|
2022-05-02 21:41:59 +02:00
|
|
|
libraryItemId: libraryItem.id,
|
|
|
|
libraryItemPath: libraryItem.path,
|
2022-05-02 23:42:30 +02:00
|
|
|
mediaCoverPath: podcast.coverPath,
|
2022-05-02 21:41:59 +02:00
|
|
|
serverAddress: serverAddress,
|
|
|
|
feedUrl,
|
|
|
|
feed
|
|
|
|
}
|
2022-05-04 01:52:34 +02:00
|
|
|
this.feeds[slug] = feedData
|
2022-05-02 21:41:59 +02:00
|
|
|
return feedData
|
|
|
|
}
|
|
|
|
|
|
|
|
openPodcastFeed(user, libraryItem, options) {
|
|
|
|
const serverAddress = options.serverAddress
|
2022-05-04 01:52:34 +02:00
|
|
|
const slug = options.slug
|
|
|
|
|
|
|
|
if (this.feeds[slug]) {
|
|
|
|
Logger.error(`[RssFeedManager] Slug already in use`)
|
|
|
|
return {
|
|
|
|
error: `Slug "${slug}" already in use`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const feedData = this.openFeed(user.id, slug, libraryItem, serverAddress)
|
2022-05-02 21:41:59 +02:00
|
|
|
Logger.debug(`[RssFeedManager] Opened podcast feed ${feedData.feedUrl}`)
|
2022-05-02 23:42:30 +02:00
|
|
|
this.emitter('rss_feed_open', { libraryItemId: libraryItem.id, feedUrl: feedData.feedUrl })
|
2022-05-02 21:41:59 +02:00
|
|
|
return feedData
|
|
|
|
}
|
2022-05-02 23:42:30 +02:00
|
|
|
|
|
|
|
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}"`)
|
|
|
|
}
|
2022-05-02 21:41:59 +02:00
|
|
|
}
|
|
|
|
module.exports = RssFeedManager
|