mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-07-15 03:45:03 +02:00
Change new podcast modal to remove episode download list #494, Fix error when importing many episodes (set max size to 5MB) #493, show podcast episodes downloading and in queue on podcast landing page
This commit is contained in:
parent
ebc9e1a888
commit
034d858f18
14 changed files with 222 additions and 126 deletions
|
@ -153,8 +153,8 @@ class Server {
|
|||
|
||||
app.use(this.auth.cors)
|
||||
app.use(fileUpload())
|
||||
app.use(express.urlencoded({ extended: true, limit: "3mb" }));
|
||||
app.use(express.json({ limit: "3mb" }))
|
||||
app.use(express.urlencoded({ extended: true, limit: "5mb" }));
|
||||
app.use(express.json({ limit: "5mb" }))
|
||||
|
||||
// Static path to generated nuxt
|
||||
const distPath = Path.join(global.appRoot, '/client/dist')
|
||||
|
|
|
@ -21,6 +21,9 @@ class LibraryItemController {
|
|||
}
|
||||
}).filter(au => au)
|
||||
}
|
||||
} else if (includeEntities.includes('downloads')) {
|
||||
var downloadsInQueue = this.podcastManager.getEpisodeDownloadsInQueue(req.libraryItem.id)
|
||||
item.episodesDownloading = downloadsInQueue.map(d => d.toJSONForClient())
|
||||
}
|
||||
|
||||
return res.json(item)
|
||||
|
|
|
@ -29,8 +29,8 @@ class PodcastController {
|
|||
|
||||
var podcastPath = payload.path.replace(/\\/g, '/')
|
||||
if (await fs.pathExists(podcastPath)) {
|
||||
Logger.error(`[PodcastController] Attempt to create podcast when folder path already exists "${podcastPath}"`)
|
||||
return res.status(400).send('Path already exists')
|
||||
Logger.error(`[PodcastController] Podcast folder already exists "${podcastPath}"`)
|
||||
return res.status(400).send('Podcast already exists')
|
||||
}
|
||||
|
||||
var success = await fs.ensureDir(podcastPath).then(() => true).catch((error) => {
|
||||
|
@ -63,7 +63,8 @@ class PodcastController {
|
|||
// Download and save cover image
|
||||
if (payload.media.metadata.imageUrl) {
|
||||
// TODO: Scan cover image to library files
|
||||
var coverResponse = await this.coverManager.downloadCoverFromUrl(libraryItem, payload.media.metadata.imageUrl)
|
||||
// Podcast cover will always go into library item folder
|
||||
var coverResponse = await this.coverManager.downloadCoverFromUrl(libraryItem, payload.media.metadata.imageUrl, true)
|
||||
if (coverResponse) {
|
||||
if (coverResponse.error) {
|
||||
Logger.error(`[PodcastController] Download cover error from "${payload.media.metadata.imageUrl}": ${coverResponse.error}`)
|
||||
|
@ -101,6 +102,7 @@ class PodcastController {
|
|||
Logger.error('Invalid podcast feed request response')
|
||||
return res.status(500).send('Bad response from feed request')
|
||||
}
|
||||
Logger.debug(`[PdocastController] Podcast feed size ${(data.data.length / 1024 / 1024).toFixed(2)}MB`)
|
||||
var payload = await parsePodcastRssFeedXml(data.data, includeRaw)
|
||||
if (!payload) {
|
||||
return res.status(500).send('Invalid podcast RSS feed')
|
||||
|
@ -128,6 +130,26 @@ class PodcastController {
|
|||
})
|
||||
}
|
||||
|
||||
clearEpisodeDownloadQueue(req, res) {
|
||||
if (!req.user.canUpdate) {
|
||||
Logger.error(`[PodcastController] User attempting to clear download queue without permission "${req.user.username}"`)
|
||||
return res.sendStatus(500)
|
||||
}
|
||||
this.podcastManager.clearDownloadQueue(req.params.id)
|
||||
res.sendStatus(200)
|
||||
}
|
||||
|
||||
getEpisodeDownloads(req, res) {
|
||||
var libraryItem = this.db.getLibraryItem(req.params.id)
|
||||
if (!libraryItem || libraryItem.mediaType !== 'podcast') {
|
||||
return res.sendStatus(404)
|
||||
}
|
||||
var downloadsInQueue = this.podcastManager.getEpisodeDownloadsInQueue(libraryItem.id)
|
||||
res.json({
|
||||
downloads: downloadsInQueue.map(d => d.toJSONForClient())
|
||||
})
|
||||
}
|
||||
|
||||
async downloadEpisodes(req, res) {
|
||||
var libraryItem = this.db.getLibraryItem(req.params.id)
|
||||
if (!libraryItem || libraryItem.mediaType !== 'podcast') {
|
||||
|
|
|
@ -119,9 +119,10 @@ class CoverManager {
|
|||
}
|
||||
}
|
||||
|
||||
async downloadCoverFromUrl(libraryItem, url) {
|
||||
async downloadCoverFromUrl(libraryItem, url, forceLibraryItemFolder = false) {
|
||||
try {
|
||||
var coverDirPath = this.getCoverDirectory(libraryItem)
|
||||
// Force save cover with library item is used for adding new podcasts
|
||||
var coverDirPath = forceLibraryItemFolder ? libraryItem.path : this.getCoverDirectory(libraryItem)
|
||||
await fs.ensureDir(coverDirPath)
|
||||
|
||||
var temppath = Path.posix.join(coverDirPath, 'cover')
|
||||
|
|
|
@ -35,6 +35,23 @@ class PodcastManager {
|
|||
}
|
||||
}
|
||||
|
||||
getEpisodeDownloadsInQueue(libraryItemId) {
|
||||
return this.downloadQueue.filter(d => d.libraryItemId === libraryItemId)
|
||||
}
|
||||
|
||||
clearDownloadQueue(libraryItemId = null) {
|
||||
if (!this.downloadQueue.length) return
|
||||
|
||||
if (!libraryItemId) {
|
||||
Logger.info(`[PodcastManager] Clearing all downloads in queue (${this.downloadQueue.length})`)
|
||||
this.downloadQueue = []
|
||||
} else {
|
||||
var itemDownloads = this.getEpisodeDownloadsInQueue(libraryItemId)
|
||||
Logger.info(`[PodcastManager] Clearing downloads in queue for item "${libraryItemId}" (${itemDownloads.length})`)
|
||||
this.downloadQueue = this.downloadQueue.filter(d => d.libraryItemId !== libraryItemId)
|
||||
}
|
||||
}
|
||||
|
||||
async downloadPodcastEpisodes(libraryItem, episodesToDownload) {
|
||||
var index = libraryItem.media.episodes.length + 1
|
||||
episodesToDownload.forEach((ep) => {
|
||||
|
@ -50,8 +67,11 @@ class PodcastManager {
|
|||
async startPodcastEpisodeDownload(podcastEpisodeDownload) {
|
||||
if (this.currentDownload) {
|
||||
this.downloadQueue.push(podcastEpisodeDownload)
|
||||
this.emitter('episode_download_queued', podcastEpisodeDownload.toJSONForClient())
|
||||
return
|
||||
}
|
||||
|
||||
this.emitter('episode_download_started', podcastEpisodeDownload.toJSONForClient())
|
||||
this.currentDownload = podcastEpisodeDownload
|
||||
|
||||
// Ignores all added files to this dir
|
||||
|
@ -65,11 +85,17 @@ class PodcastManager {
|
|||
success = await this.scanAddPodcastEpisodeAudioFile()
|
||||
if (!success) {
|
||||
await fs.remove(this.currentDownload.targetPath)
|
||||
this.currentDownload.setFinished(false)
|
||||
} else {
|
||||
Logger.info(`[PodcastManager] Successfully downloaded podcast episode "${this.currentDownload.podcastEpisode.title}"`)
|
||||
this.currentDownload.setFinished(true)
|
||||
}
|
||||
} else {
|
||||
this.currentDownload.setFinished(false)
|
||||
}
|
||||
|
||||
this.emitter('episode_download_finished', this.currentDownload.toJSONForClient())
|
||||
|
||||
this.watcher.removeIgnoreDir(this.currentDownload.libraryItem.path)
|
||||
this.currentDownload = null
|
||||
if (this.downloadQueue.length) {
|
||||
|
|
|
@ -10,22 +10,42 @@ class PodcastEpisodeDownload {
|
|||
this.libraryItem = null
|
||||
|
||||
this.isDownloading = false
|
||||
this.isFinished = false
|
||||
this.failed = false
|
||||
|
||||
this.startedAt = null
|
||||
this.createdAt = null
|
||||
this.finishedAt = null
|
||||
}
|
||||
|
||||
toJSONForClient() {
|
||||
return {
|
||||
id: this.id,
|
||||
// podcastEpisode: this.podcastEpisode ? this.podcastEpisode.toJSON() : null,
|
||||
episodeDisplayTitle: this.podcastEpisode ? this.podcastEpisode.bestFilename : null,
|
||||
url: this.url,
|
||||
libraryItemId: this.libraryItem ? this.libraryItem.id : null,
|
||||
isDownloading: this.isDownloading,
|
||||
isFinished: this.isFinished,
|
||||
failed: this.failed,
|
||||
startedAt: this.startedAt,
|
||||
createdAt: this.createdAt,
|
||||
finishedAt: this.finishedAt
|
||||
}
|
||||
}
|
||||
|
||||
get targetFilename() {
|
||||
return sanitizeFilename(`${this.podcastEpisode.bestFilename}.mp3`)
|
||||
}
|
||||
|
||||
get targetPath() {
|
||||
return Path.join(this.libraryItem.path, this.targetFilename)
|
||||
}
|
||||
|
||||
get targetRelPath() {
|
||||
return this.targetFilename
|
||||
}
|
||||
get libraryItemId() {
|
||||
return this.libraryItem ? this.libraryItem.id : null
|
||||
}
|
||||
|
||||
setData(podcastEpisode, libraryItem) {
|
||||
this.id = getId('epdl')
|
||||
|
@ -34,5 +54,11 @@ class PodcastEpisodeDownload {
|
|||
this.libraryItem = libraryItem
|
||||
this.createdAt = Date.now()
|
||||
}
|
||||
|
||||
setFinished(success) {
|
||||
this.finishedAt = Date.now()
|
||||
this.isFinished = true
|
||||
this.failed = !success
|
||||
}
|
||||
}
|
||||
module.exports = PodcastEpisodeDownload
|
|
@ -178,6 +178,8 @@ class ApiRouter {
|
|||
this.router.post('/podcasts', PodcastController.create.bind(this))
|
||||
this.router.post('/podcasts/feed', PodcastController.getPodcastFeed.bind(this))
|
||||
this.router.get('/podcasts/:id/checknew', PodcastController.checkNewEpisodes.bind(this))
|
||||
this.router.get('/podcasts/:id/downloads', PodcastController.getEpisodeDownloads.bind(this))
|
||||
this.router.get('/podcasts/:id/clear-queue', PodcastController.clearEpisodeDownloadQueue.bind(this))
|
||||
this.router.post('/podcasts/:id/download-episodes', PodcastController.downloadEpisodes.bind(this))
|
||||
this.router.patch('/podcasts/:id/episode/:episodeId', PodcastController.updateEpisode.bind(this))
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ module.exports = {
|
|||
} else if (filterBy === 'issues') {
|
||||
filtered = filtered.filter(ab => {
|
||||
// TODO: Update filter for issues
|
||||
return ab.isMissing
|
||||
return ab.isMissing || ab.isInvalid
|
||||
// return ab.numMissingParts || ab.numInvalidParts || ab.isMissing || ab.isInvalid
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue