From ff0d6326d3ba5beb00bd7e47e1258135ccfdd6b7 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 19 Aug 2023 15:19:27 -0500 Subject: [PATCH] Update OPML api route to load podcasts from db --- server/controllers/LibraryController.js | 24 +++++++++++++++++-- server/managers/PodcastManager.js | 9 +++++-- server/routers/ApiRouter.js | 2 +- server/utils/generators/opmlGenerator.js | 30 ++++++++++++++---------- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index 8d2cbc80..b9cf29a8 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -1047,8 +1047,28 @@ class LibraryController { res.json(payload) } - getOPMLFile(req, res) { - const opmlText = this.podcastManager.generateOPMLFileText(req.libraryItems) + /** + * GET: /api/libraries/:id/opml + * Get OPML file for a podcast library + * @param {import('express').Request} req + * @param {import('express').Response} res + */ + async getOPMLFile(req, res) { + const userPermissionPodcastWhere = libraryItemsPodcastFilters.getUserPermissionPodcastWhereQuery(req.user) + const podcasts = await Database.podcastModel.findAll({ + attributes: ['id', 'feedURL', 'title', 'description', 'itunesPageURL', 'language'], + where: userPermissionPodcastWhere.podcastWhere, + replacements: userPermissionPodcastWhere.replacements, + include: { + model: Database.libraryItemModel, + attributes: ['id', 'libraryId'], + where: { + libraryId: req.library.id + } + } + }) + + const opmlText = this.podcastManager.generateOPMLFileText(podcasts) res.type('application/xml') res.send(opmlText) } diff --git a/server/managers/PodcastManager.js b/server/managers/PodcastManager.js index 743cb60b..b99a4c7a 100644 --- a/server/managers/PodcastManager.js +++ b/server/managers/PodcastManager.js @@ -372,8 +372,13 @@ class PodcastManager { } } - generateOPMLFileText(libraryItems) { - return opmlGenerator.generate(libraryItems) + /** + * OPML file string for podcasts in a library + * @param {import('../models/Podcast')[]} podcasts + * @returns {string} XML string + */ + generateOPMLFileText(podcasts) { + return opmlGenerator.generate(podcasts) } getDownloadQueueDetails(libraryId = null) { diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js index e95cf1c3..fff3bc91 100644 --- a/server/routers/ApiRouter.js +++ b/server/routers/ApiRouter.js @@ -95,7 +95,7 @@ class ApiRouter { this.router.get('/libraries/:id/matchall', LibraryController.middlewareNew.bind(this), LibraryController.matchAll.bind(this)) this.router.post('/libraries/:id/scan', LibraryController.middlewareNew.bind(this), LibraryController.scan.bind(this)) this.router.get('/libraries/:id/recent-episodes', LibraryController.middlewareNew.bind(this), LibraryController.getRecentEpisodes.bind(this)) - this.router.get('/libraries/:id/opml', LibraryController.middleware.bind(this), LibraryController.getOPMLFile.bind(this)) + this.router.get('/libraries/:id/opml', LibraryController.middlewareNew.bind(this), LibraryController.getOPMLFile.bind(this)) this.router.post('/libraries/order', LibraryController.reorder.bind(this)) // diff --git a/server/utils/generators/opmlGenerator.js b/server/utils/generators/opmlGenerator.js index 60d3d450..8cc3f7fb 100644 --- a/server/utils/generators/opmlGenerator.js +++ b/server/utils/generators/opmlGenerator.js @@ -1,23 +1,29 @@ const xml = require('../../libs/xml') -module.exports.generate = (libraryItems, indent = true) => { +/** + * Generate OPML file string for podcasts in a library + * @param {import('../../models/Podcast')[]} podcasts + * @param {boolean} [indent=true] + * @returns {string} + */ +module.exports.generate = (podcasts, indent = true) => { const bodyItems = [] - libraryItems.forEach((item) => { - if (!item.media.metadata.feedUrl) return + podcasts.forEach((podcast) => { + if (!podcast.feedURL) return const feedAttributes = { type: 'rss', - text: item.media.metadata.title, - title: item.media.metadata.title, - xmlUrl: item.media.metadata.feedUrl + text: podcast.title, + title: podcast.title, + xmlUrl: podcast.feedURL } - if (item.media.metadata.description) { - feedAttributes.description = item.media.metadata.description + if (podcast.description) { + feedAttributes.description = podcast.description } - if (item.media.metadata.itunesPageUrl) { - feedAttributes.htmlUrl = item.media.metadata.itunesPageUrl + if (podcast.itunesPageUrl) { + feedAttributes.htmlUrl = podcast.itunesPageUrl } - if (item.media.metadata.language) { - feedAttributes.language = item.media.metadata.language + if (podcast.language) { + feedAttributes.language = podcast.language } bodyItems.push({ outline: {