mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-04 02:05:06 +02:00
Add:OPML Export #1260
This commit is contained in:
parent
019063e6f4
commit
15aaf2863c
16 changed files with 124 additions and 40 deletions
|
@ -848,6 +848,12 @@ class LibraryController {
|
|||
res.json(payload)
|
||||
}
|
||||
|
||||
getOPMLFile(req, res) {
|
||||
const opmlText = this.podcastManager.generateOPMLFileText(req.libraryItems)
|
||||
res.type('application/xml')
|
||||
res.send(opmlText)
|
||||
}
|
||||
|
||||
middleware(req, res, next) {
|
||||
if (!req.user.checkCanAccessLibrary(req.params.id)) {
|
||||
Logger.warn(`[LibraryController] Library ${req.params.id} not accessible to user ${req.user.username}`)
|
||||
|
|
|
@ -109,7 +109,7 @@ class PodcastController {
|
|||
res.json({ podcast })
|
||||
}
|
||||
|
||||
async getOPMLFeeds(req, res) {
|
||||
async getFeedsFromOPMLText(req, res) {
|
||||
if (!req.body.opmlText) {
|
||||
return res.sendStatus(400)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ const { removeFile, downloadFile } = require('../utils/fileUtils')
|
|||
const filePerms = require('../utils/filePerms')
|
||||
const { levenshteinDistance } = require('../utils/index')
|
||||
const opmlParser = require('../utils/parsers/parseOPML')
|
||||
const opmlGenerator = require('../utils/generators/opmlGenerator')
|
||||
const prober = require('../utils/prober')
|
||||
const ffmpegHelpers = require('../utils/ffmpegHelpers')
|
||||
|
||||
|
@ -373,6 +374,10 @@ class PodcastManager {
|
|||
}
|
||||
}
|
||||
|
||||
generateOPMLFileText(libraryItems) {
|
||||
return opmlGenerator.generate(libraryItems)
|
||||
}
|
||||
|
||||
getDownloadQueueDetails(libraryId = null) {
|
||||
let _currentDownload = this.currentDownload
|
||||
if (libraryId && _currentDownload?.libraryId !== libraryId) _currentDownload = null
|
||||
|
|
|
@ -2,7 +2,7 @@ const fs = require('../libs/fsExtra')
|
|||
const Path = require('path')
|
||||
const { version } = require('../../package.json')
|
||||
const Logger = require('../Logger')
|
||||
const abmetadataGenerator = require('../utils/abmetadataGenerator')
|
||||
const abmetadataGenerator = require('../utils/generators/abmetadataGenerator')
|
||||
const LibraryFile = require('./files/LibraryFile')
|
||||
const Book = require('./mediaTypes/Book')
|
||||
const Podcast = require('./mediaTypes/Podcast')
|
||||
|
|
|
@ -10,7 +10,7 @@ const Ffmpeg = require('../libs/fluentFfmpeg')
|
|||
const { secondsToTimestamp } = require('../utils/index')
|
||||
const { writeConcatFile } = require('../utils/ffmpegHelpers')
|
||||
const { AudioMimeType } = require('../utils/constants')
|
||||
const hlsPlaylistGenerator = require('../utils/hlsPlaylistGenerator')
|
||||
const hlsPlaylistGenerator = require('../utils/generators/hlsPlaylistGenerator')
|
||||
const AudioTrack = require('./files/AudioTrack')
|
||||
|
||||
class Stream extends EventEmitter {
|
||||
|
|
|
@ -4,7 +4,7 @@ const BookMetadata = require('../metadata/BookMetadata')
|
|||
const { areEquivalent, copyValue, cleanStringForSearch } = require('../../utils/index')
|
||||
const { parseOpfMetadataXML } = require('../../utils/parsers/parseOpfMetadata')
|
||||
const { parseOverdriveMediaMarkersAsChapters } = require('../../utils/parsers/parseOverdriveMediaMarkers')
|
||||
const abmetadataGenerator = require('../../utils/abmetadataGenerator')
|
||||
const abmetadataGenerator = require('../../utils/generators/abmetadataGenerator')
|
||||
const { readTextFile, filePathToPOSIX } = require('../../utils/fileUtils')
|
||||
const AudioFile = require('../files/AudioFile')
|
||||
const AudioTrack = require('../files/AudioTrack')
|
||||
|
|
|
@ -2,7 +2,7 @@ const Logger = require('../../Logger')
|
|||
const PodcastEpisode = require('../entities/PodcastEpisode')
|
||||
const PodcastMetadata = require('../metadata/PodcastMetadata')
|
||||
const { areEquivalent, copyValue, cleanStringForSearch } = require('../../utils/index')
|
||||
const abmetadataGenerator = require('../../utils/abmetadataGenerator')
|
||||
const abmetadataGenerator = require('../../utils/generators/abmetadataGenerator')
|
||||
const { readTextFile, filePathToPOSIX } = require('../../utils/fileUtils')
|
||||
const { createNewSortInstance } = require('../../libs/fastSort')
|
||||
const naturalSort = createNewSortInstance({
|
||||
|
|
|
@ -90,7 +90,7 @@ class ApiRouter {
|
|||
this.router.get('/libraries/:id/matchall', LibraryController.middleware.bind(this), LibraryController.matchAll.bind(this))
|
||||
this.router.post('/libraries/:id/scan', LibraryController.middleware.bind(this), LibraryController.scan.bind(this))
|
||||
this.router.get('/libraries/:id/recent-episodes', LibraryController.middleware.bind(this), LibraryController.getRecentEpisodes.bind(this))
|
||||
|
||||
this.router.get('/libraries/:id/opml', LibraryController.middleware.bind(this), LibraryController.getOPMLFile.bind(this))
|
||||
this.router.post('/libraries/order', LibraryController.reorder.bind(this))
|
||||
|
||||
//
|
||||
|
@ -236,7 +236,7 @@ class ApiRouter {
|
|||
//
|
||||
this.router.post('/podcasts', PodcastController.create.bind(this))
|
||||
this.router.post('/podcasts/feed', PodcastController.getPodcastFeed.bind(this))
|
||||
this.router.post('/podcasts/opml', PodcastController.getOPMLFeeds.bind(this))
|
||||
this.router.post('/podcasts/opml', PodcastController.getFeedsFromOPMLText.bind(this))
|
||||
this.router.get('/podcasts/:id/checknew', PodcastController.middleware.bind(this), PodcastController.checkNewEpisodes.bind(this))
|
||||
this.router.get('/podcasts/:id/downloads', PodcastController.middleware.bind(this), PodcastController.getEpisodeDownloads.bind(this))
|
||||
this.router.get('/podcasts/:id/clear-queue', PodcastController.middleware.bind(this), PodcastController.clearEpisodeDownloadQueue.bind(this))
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
const fs = require('../libs/fsExtra')
|
||||
const filePerms = require('./filePerms')
|
||||
const package = require('../../package.json')
|
||||
const Logger = require('../Logger')
|
||||
const { getId } = require('./index')
|
||||
const areEquivalent = require('../utils/areEquivalent')
|
||||
const fs = require('../../libs/fsExtra')
|
||||
const filePerms = require('../filePerms')
|
||||
const package = require('../../../package.json')
|
||||
const Logger = require('../../Logger')
|
||||
const { getId } = require('../index')
|
||||
const areEquivalent = require('../areEquivalent')
|
||||
|
||||
|
||||
const CurrentAbMetadataVersion = 2
|
|
@ -1,4 +1,4 @@
|
|||
const fs = require('../libs/fsExtra')
|
||||
const fs = require('../../libs/fsExtra')
|
||||
|
||||
function getPlaylistStr(segmentName, duration, segmentLength, hlsSegmentType, token) {
|
||||
var ext = hlsSegmentType === 'fmp4' ? 'm4s' : 'ts'
|
52
server/utils/generators/opmlGenerator.js
Normal file
52
server/utils/generators/opmlGenerator.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
const xml = require('../../libs/xml')
|
||||
|
||||
module.exports.generate = (libraryItems, indent = true) => {
|
||||
const bodyItems = []
|
||||
libraryItems.forEach((item) => {
|
||||
if (!item.media.metadata.feedUrl) return
|
||||
const feedAttributes = {
|
||||
type: 'rss',
|
||||
text: item.media.metadata.title,
|
||||
title: item.media.metadata.title,
|
||||
xmlUrl: item.media.metadata.feedUrl
|
||||
}
|
||||
if (item.media.metadata.description) {
|
||||
feedAttributes.description = item.media.metadata.description
|
||||
}
|
||||
if (item.media.metadata.itunesPageUrl) {
|
||||
feedAttributes.htmlUrl = item.media.metadata.itunesPageUrl
|
||||
}
|
||||
if (item.media.metadata.language) {
|
||||
feedAttributes.language = item.media.metadata.language
|
||||
}
|
||||
bodyItems.push({
|
||||
outline: {
|
||||
_attr: feedAttributes
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const data = [
|
||||
{
|
||||
opml: [
|
||||
{
|
||||
_attr: {
|
||||
version: '1.0'
|
||||
}
|
||||
},
|
||||
{
|
||||
head: [
|
||||
{
|
||||
title: 'Audiobookshelf Podcast Subscriptions'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
body: bodyItems
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
return '<?xml version="1.0" encoding="UTF-8"?>\n' + xml(data, indent)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue