const Logger = require('../Logger') const Database = require('../Database') const libraryItemsBookFilters = require('../utils/queries/libraryItemsBookFilters') class RSSFeedController { constructor() { } async getAll(req, res) { const feeds = await this.rssFeedManager.getFeeds() res.json({ feeds: feeds.map(f => f.toJSON()), minified: feeds.map(f => f.toJSONMinified()) }) } // POST: api/feeds/item/:itemId/open async openRSSFeedForItem(req, res) { const options = req.body || {} const item = await Database.libraryItemModel.getOldById(req.params.itemId) if (!item) return res.sendStatus(404) // Check user can access this library item if (!req.user.checkCanAccessLibraryItem(item)) { Logger.error(`[RSSFeedController] User "${req.user.username}" attempted to open an RSS feed for item "${item.media.metadata.title}" that they don\'t have access to`) return res.sendStatus(403) } // Check request body options exist if (!options.serverAddress || !options.slug) { Logger.error(`[RSSFeedController] Invalid request body to open RSS feed`) return res.status(400).send('Invalid request body') } // Check item has audio tracks if (!item.media.numTracks) { Logger.error(`[RSSFeedController] Cannot open RSS feed for item "${item.media.metadata.title}" because it has no audio tracks`) return res.status(400).send('Item has no audio tracks') } // Check that this slug is not being used for another feed (slug will also be the Feed id) if (await this.rssFeedManager.findFeedBySlug(options.slug)) { Logger.error(`[RSSFeedController] Cannot open RSS feed because slug "${options.slug}" is already in use`) return res.status(400).send('Slug already in use') } const feed = await this.rssFeedManager.openFeedForItem(req.user, item, req.body) res.json({ feed: feed.toJSONMinified() }) } // POST: api/feeds/collection/:collectionId/open async openRSSFeedForCollection(req, res) { const options = req.body || {} const collection = await Database.collectionModel.findByPk(req.params.collectionId) if (!collection) return res.sendStatus(404) // Check request body options exist if (!options.serverAddress || !options.slug) { Logger.error(`[RSSFeedController] Invalid request body to open RSS feed`) return res.status(400).send('Invalid request body') } // Check that this slug is not being used for another feed (slug will also be the Feed id) if (await this.rssFeedManager.findFeedBySlug(options.slug)) { Logger.error(`[RSSFeedController] Cannot open RSS feed because slug "${options.slug}" is already in use`) return res.status(400).send('Slug already in use') } const collectionExpanded = await collection.getOldJsonExpanded() const collectionItemsWithTracks = collectionExpanded.books.filter(li => li.media.tracks.length) // Check collection has audio tracks if (!collectionItemsWithTracks.length) { Logger.error(`[RSSFeedController] Cannot open RSS feed for collection "${collection.name}" because it has no audio tracks`) return res.status(400).send('Collection has no audio tracks') } const feed = await this.rssFeedManager.openFeedForCollection(req.user, collectionExpanded, req.body) res.json({ feed: feed.toJSONMinified() }) } // POST: api/feeds/series/:seriesId/open async openRSSFeedForSeries(req, res) { const options = req.body || {} const series = await Database.seriesModel.getOldById(req.params.seriesId) if (!series) return res.sendStatus(404) // Check request body options exist if (!options.serverAddress || !options.slug) { Logger.error(`[RSSFeedController] Invalid request body to open RSS feed`) return res.status(400).send('Invalid request body') } // Check that this slug is not being used for another feed (slug will also be the Feed id) if (await this.rssFeedManager.findFeedBySlug(options.slug)) { Logger.error(`[RSSFeedController] Cannot open RSS feed because slug "${options.slug}" is already in use`) return res.status(400).send('Slug already in use') } const seriesJson = series.toJSON() // Get books in series that have audio tracks seriesJson.books = (await libraryItemsBookFilters.getLibraryItemsForSeries(series)).filter(li => li.media.numTracks) // Check series has audio tracks if (!seriesJson.books.length) { Logger.error(`[RSSFeedController] Cannot open RSS feed for series "${seriesJson.name}" because it has no audio tracks`) return res.status(400).send('Series has no audio tracks') } const feed = await this.rssFeedManager.openFeedForSeries(req.user, seriesJson, req.body) res.json({ feed: feed.toJSONMinified() }) } // POST: api/feeds/:id/close closeRSSFeed(req, res) { this.rssFeedManager.closeRssFeed(req, res) } middleware(req, res, next) { if (!req.user.isAdminOrUp) { // Only admins can manage rss feeds Logger.error(`[RSSFeedController] Non-admin user attempted to make a request to an RSS feed route`, req.user.username) return res.sendStatus(403) } next() } } module.exports = new RSSFeedController()