mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-01 00:18:14 +01:00
Fix:Podcast download new episode check to compare both GUID and enclosure URL for existing episodes #2986
This commit is contained in:
parent
ab3a137db9
commit
6d89721371
@ -32,7 +32,7 @@ class PodcastManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getEpisodeDownloadsInQueue(libraryItemId) {
|
getEpisodeDownloadsInQueue(libraryItemId) {
|
||||||
return this.downloadQueue.filter(d => d.libraryItemId === libraryItemId)
|
return this.downloadQueue.filter((d) => d.libraryItemId === libraryItemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearDownloadQueue(libraryItemId = null) {
|
clearDownloadQueue(libraryItemId = null) {
|
||||||
@ -44,12 +44,12 @@ class PodcastManager {
|
|||||||
} else {
|
} else {
|
||||||
var itemDownloads = this.getEpisodeDownloadsInQueue(libraryItemId)
|
var itemDownloads = this.getEpisodeDownloadsInQueue(libraryItemId)
|
||||||
Logger.info(`[PodcastManager] Clearing downloads in queue for item "${libraryItemId}" (${itemDownloads.length})`)
|
Logger.info(`[PodcastManager] Clearing downloads in queue for item "${libraryItemId}" (${itemDownloads.length})`)
|
||||||
this.downloadQueue = this.downloadQueue.filter(d => d.libraryItemId !== libraryItemId)
|
this.downloadQueue = this.downloadQueue.filter((d) => d.libraryItemId !== libraryItemId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadPodcastEpisodes(libraryItem, episodesToDownload, isAutoDownload) {
|
async downloadPodcastEpisodes(libraryItem, episodesToDownload, isAutoDownload) {
|
||||||
let index = Math.max(...libraryItem.media.episodes.filter(ep => ep.index == null || isNaN(ep.index)).map(ep => Number(ep.index))) + 1
|
let index = Math.max(...libraryItem.media.episodes.filter((ep) => ep.index == null || isNaN(ep.index)).map((ep) => Number(ep.index))) + 1
|
||||||
for (const ep of episodesToDownload) {
|
for (const ep of episodesToDownload) {
|
||||||
const newPe = new PodcastEpisode()
|
const newPe = new PodcastEpisode()
|
||||||
newPe.setData(ep, index++)
|
newPe.setData(ep, index++)
|
||||||
@ -72,7 +72,7 @@ class PodcastManager {
|
|||||||
const taskDescription = `Downloading episode "${podcastEpisodeDownload.podcastEpisode.title}".`
|
const taskDescription = `Downloading episode "${podcastEpisodeDownload.podcastEpisode.title}".`
|
||||||
const taskData = {
|
const taskData = {
|
||||||
libraryId: podcastEpisodeDownload.libraryId,
|
libraryId: podcastEpisodeDownload.libraryId,
|
||||||
libraryItemId: podcastEpisodeDownload.libraryItemId,
|
libraryItemId: podcastEpisodeDownload.libraryItemId
|
||||||
}
|
}
|
||||||
const task = TaskManager.createAndAddTask('download-podcast-episode', 'Downloading Episode', taskDescription, false, taskData)
|
const task = TaskManager.createAndAddTask('download-podcast-episode', 'Downloading Episode', taskDescription, false, taskData)
|
||||||
|
|
||||||
@ -104,10 +104,12 @@ class PodcastManager {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Download episode only
|
// Download episode only
|
||||||
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath).then(() => true).catch((error) => {
|
success = await downloadFile(this.currentDownload.url, this.currentDownload.targetPath)
|
||||||
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
.then(() => true)
|
||||||
return false
|
.catch((error) => {
|
||||||
})
|
Logger.error(`[PodcastManager] Podcast Episode download failed`, error)
|
||||||
|
return false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
@ -156,7 +158,7 @@ class PodcastManager {
|
|||||||
podcastEpisode.audioFile = audioFile
|
podcastEpisode.audioFile = audioFile
|
||||||
|
|
||||||
if (audioFile.chapters?.length) {
|
if (audioFile.chapters?.length) {
|
||||||
podcastEpisode.chapters = audioFile.chapters.map(ch => ({ ...ch }))
|
podcastEpisode.chapters = audioFile.chapters.map((ch) => ({ ...ch }))
|
||||||
}
|
}
|
||||||
|
|
||||||
libraryItem.media.addPodcastEpisode(podcastEpisode)
|
libraryItem.media.addPodcastEpisode(podcastEpisode)
|
||||||
@ -181,7 +183,8 @@ class PodcastManager {
|
|||||||
podcastEpisodeExpanded.libraryItem = libraryItem.toJSONExpanded()
|
podcastEpisodeExpanded.libraryItem = libraryItem.toJSONExpanded()
|
||||||
SocketAuthority.emitter('episode_added', podcastEpisodeExpanded)
|
SocketAuthority.emitter('episode_added', podcastEpisodeExpanded)
|
||||||
|
|
||||||
if (this.currentDownload.isAutoDownload) { // Notifications only for auto downloaded episodes
|
if (this.currentDownload.isAutoDownload) {
|
||||||
|
// Notifications only for auto downloaded episodes
|
||||||
this.notificationManager.onPodcastEpisodeDownloaded(libraryItem, podcastEpisode)
|
this.notificationManager.onPodcastEpisodeDownloaded(libraryItem, podcastEpisode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,12 +194,14 @@ class PodcastManager {
|
|||||||
async removeOldestEpisode(libraryItem, episodeIdJustDownloaded) {
|
async removeOldestEpisode(libraryItem, episodeIdJustDownloaded) {
|
||||||
var smallestPublishedAt = 0
|
var smallestPublishedAt = 0
|
||||||
var oldestEpisode = null
|
var oldestEpisode = null
|
||||||
libraryItem.media.episodesWithPubDate.filter(ep => ep.id !== episodeIdJustDownloaded).forEach((ep) => {
|
libraryItem.media.episodesWithPubDate
|
||||||
if (!smallestPublishedAt || ep.publishedAt < smallestPublishedAt) {
|
.filter((ep) => ep.id !== episodeIdJustDownloaded)
|
||||||
smallestPublishedAt = ep.publishedAt
|
.forEach((ep) => {
|
||||||
oldestEpisode = ep
|
if (!smallestPublishedAt || ep.publishedAt < smallestPublishedAt) {
|
||||||
}
|
smallestPublishedAt = ep.publishedAt
|
||||||
})
|
oldestEpisode = ep
|
||||||
|
}
|
||||||
|
})
|
||||||
// TODO: Should we check for open playback sessions for this episode?
|
// TODO: Should we check for open playback sessions for this episode?
|
||||||
// TODO: remove all user progress for this episode
|
// TODO: remove all user progress for this episode
|
||||||
if (oldestEpisode?.audioFile) {
|
if (oldestEpisode?.audioFile) {
|
||||||
@ -246,7 +251,8 @@ class PodcastManager {
|
|||||||
var newEpisodes = await this.checkPodcastForNewEpisodes(libraryItem, dateToCheckForEpisodesAfter, libraryItem.media.maxNewEpisodesToDownload)
|
var newEpisodes = await this.checkPodcastForNewEpisodes(libraryItem, dateToCheckForEpisodesAfter, libraryItem.media.maxNewEpisodesToDownload)
|
||||||
Logger.debug(`[PodcastManager] runEpisodeCheck: ${newEpisodes?.length || 'N/A'} episodes found`)
|
Logger.debug(`[PodcastManager] runEpisodeCheck: ${newEpisodes?.length || 'N/A'} episodes found`)
|
||||||
|
|
||||||
if (!newEpisodes) { // Failed
|
if (!newEpisodes) {
|
||||||
|
// Failed
|
||||||
// Allow up to MaxFailedEpisodeChecks failed attempts before disabling auto download
|
// Allow up to MaxFailedEpisodeChecks failed attempts before disabling auto download
|
||||||
if (!this.failedCheckMap[libraryItem.id]) this.failedCheckMap[libraryItem.id] = 0
|
if (!this.failedCheckMap[libraryItem.id]) this.failedCheckMap[libraryItem.id] = 0
|
||||||
this.failedCheckMap[libraryItem.id]++
|
this.failedCheckMap[libraryItem.id]++
|
||||||
@ -285,7 +291,7 @@ class PodcastManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter new and not already has
|
// Filter new and not already has
|
||||||
let newEpisodes = feed.episodes.filter(ep => ep.publishedAt > dateToCheckForEpisodesAfter && !podcastLibraryItem.media.checkHasEpisodeByFeedUrl(ep.enclosure.url))
|
let newEpisodes = feed.episodes.filter((ep) => ep.publishedAt > dateToCheckForEpisodesAfter && !podcastLibraryItem.media.checkHasEpisodeByFeedEpisode(ep))
|
||||||
|
|
||||||
if (maxNewEpisodes > 0) {
|
if (maxNewEpisodes > 0) {
|
||||||
newEpisodes = newEpisodes.slice(0, maxNewEpisodes)
|
newEpisodes = newEpisodes.slice(0, maxNewEpisodes)
|
||||||
@ -322,7 +328,7 @@ class PodcastManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const matches = []
|
const matches = []
|
||||||
feed.episodes.forEach(ep => {
|
feed.episodes.forEach((ep) => {
|
||||||
if (!ep.title) return
|
if (!ep.title) return
|
||||||
|
|
||||||
const epTitle = ep.title.toLowerCase().trim()
|
const epTitle = ep.title.toLowerCase().trim()
|
||||||
@ -383,7 +389,7 @@ class PodcastManager {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
currentDownload: _currentDownload?.toJSONForClient(),
|
currentDownload: _currentDownload?.toJSONForClient(),
|
||||||
queue: this.downloadQueue.filter(item => !libraryId || item.libraryId === libraryId).map(item => item.toJSONForClient())
|
queue: this.downloadQueue.filter((item) => !libraryId || item.libraryId === libraryId).map((item) => item.toJSONForClient())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const uuidv4 = require("uuid").v4
|
const uuidv4 = require('uuid').v4
|
||||||
const { areEquivalent, copyValue } = require('../../utils/index')
|
const { areEquivalent, copyValue } = require('../../utils/index')
|
||||||
const AudioFile = require('../files/AudioFile')
|
const AudioFile = require('../files/AudioFile')
|
||||||
const AudioTrack = require('../files/AudioTrack')
|
const AudioTrack = require('../files/AudioTrack')
|
||||||
@ -47,7 +47,7 @@ class PodcastEpisode {
|
|||||||
this.enclosure = episode.enclosure ? { ...episode.enclosure } : null
|
this.enclosure = episode.enclosure ? { ...episode.enclosure } : null
|
||||||
this.guid = episode.guid || null
|
this.guid = episode.guid || null
|
||||||
this.pubDate = episode.pubDate
|
this.pubDate = episode.pubDate
|
||||||
this.chapters = episode.chapters?.map(ch => ({ ...ch })) || []
|
this.chapters = episode.chapters?.map((ch) => ({ ...ch })) || []
|
||||||
this.audioFile = episode.audioFile ? new AudioFile(episode.audioFile) : null
|
this.audioFile = episode.audioFile ? new AudioFile(episode.audioFile) : null
|
||||||
this.publishedAt = episode.publishedAt
|
this.publishedAt = episode.publishedAt
|
||||||
this.addedAt = episode.addedAt
|
this.addedAt = episode.addedAt
|
||||||
@ -74,7 +74,7 @@ class PodcastEpisode {
|
|||||||
enclosure: this.enclosure ? { ...this.enclosure } : null,
|
enclosure: this.enclosure ? { ...this.enclosure } : null,
|
||||||
guid: this.guid,
|
guid: this.guid,
|
||||||
pubDate: this.pubDate,
|
pubDate: this.pubDate,
|
||||||
chapters: this.chapters.map(ch => ({ ...ch })),
|
chapters: this.chapters.map((ch) => ({ ...ch })),
|
||||||
audioFile: this.audioFile?.toJSON() || null,
|
audioFile: this.audioFile?.toJSON() || null,
|
||||||
publishedAt: this.publishedAt,
|
publishedAt: this.publishedAt,
|
||||||
addedAt: this.addedAt,
|
addedAt: this.addedAt,
|
||||||
@ -98,7 +98,7 @@ class PodcastEpisode {
|
|||||||
enclosure: this.enclosure ? { ...this.enclosure } : null,
|
enclosure: this.enclosure ? { ...this.enclosure } : null,
|
||||||
guid: this.guid,
|
guid: this.guid,
|
||||||
pubDate: this.pubDate,
|
pubDate: this.pubDate,
|
||||||
chapters: this.chapters.map(ch => ({ ...ch })),
|
chapters: this.chapters.map((ch) => ({ ...ch })),
|
||||||
audioFile: this.audioFile?.toJSON() || null,
|
audioFile: this.audioFile?.toJSON() || null,
|
||||||
audioTrack: this.audioTrack?.toJSON() || null,
|
audioTrack: this.audioTrack?.toJSON() || null,
|
||||||
publishedAt: this.publishedAt,
|
publishedAt: this.publishedAt,
|
||||||
@ -121,7 +121,9 @@ class PodcastEpisode {
|
|||||||
get duration() {
|
get duration() {
|
||||||
return this.audioFile?.duration || 0
|
return this.audioFile?.duration || 0
|
||||||
}
|
}
|
||||||
get size() { return this.audioFile?.metadata.size || 0 }
|
get size() {
|
||||||
|
return this.audioFile?.metadata.size || 0
|
||||||
|
}
|
||||||
get enclosureUrl() {
|
get enclosureUrl() {
|
||||||
return this.enclosure?.url || null
|
return this.enclosure?.url || null
|
||||||
}
|
}
|
||||||
@ -151,9 +153,9 @@ class PodcastEpisode {
|
|||||||
let hasUpdates = false
|
let hasUpdates = false
|
||||||
for (const key in this.toJSON()) {
|
for (const key in this.toJSON()) {
|
||||||
let newValue = payload[key]
|
let newValue = payload[key]
|
||||||
if (newValue === "") newValue = null
|
if (newValue === '') newValue = null
|
||||||
let existingValue = this[key]
|
let existingValue = this[key]
|
||||||
if (existingValue === "") existingValue = null
|
if (existingValue === '') existingValue = null
|
||||||
|
|
||||||
if (newValue != undefined && !areEquivalent(newValue, existingValue)) {
|
if (newValue != undefined && !areEquivalent(newValue, existingValue)) {
|
||||||
this[key] = copyValue(newValue)
|
this[key] = copyValue(newValue)
|
||||||
@ -177,7 +179,7 @@ class PodcastEpisode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEqualsEnclosureUrl(url) {
|
checkEqualsEnclosureUrl(url) {
|
||||||
if (!this.enclosure || !this.enclosure.url) return false
|
if (!this.enclosure?.url) return false
|
||||||
return this.enclosure.url == url
|
return this.enclosure.url == url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ class Podcast {
|
|||||||
metadata: this.metadata.toJSON(),
|
metadata: this.metadata.toJSON(),
|
||||||
coverPath: this.coverPath,
|
coverPath: this.coverPath,
|
||||||
tags: [...this.tags],
|
tags: [...this.tags],
|
||||||
episodes: this.episodes.map(e => e.toJSON()),
|
episodes: this.episodes.map((e) => e.toJSON()),
|
||||||
autoDownloadEpisodes: this.autoDownloadEpisodes,
|
autoDownloadEpisodes: this.autoDownloadEpisodes,
|
||||||
autoDownloadSchedule: this.autoDownloadSchedule,
|
autoDownloadSchedule: this.autoDownloadSchedule,
|
||||||
lastEpisodeCheck: this.lastEpisodeCheck,
|
lastEpisodeCheck: this.lastEpisodeCheck,
|
||||||
@ -90,7 +90,7 @@ class Podcast {
|
|||||||
metadata: this.metadata.toJSONExpanded(),
|
metadata: this.metadata.toJSONExpanded(),
|
||||||
coverPath: this.coverPath,
|
coverPath: this.coverPath,
|
||||||
tags: [...this.tags],
|
tags: [...this.tags],
|
||||||
episodes: this.episodes.map(e => e.toJSONExpanded()),
|
episodes: this.episodes.map((e) => e.toJSONExpanded()),
|
||||||
autoDownloadEpisodes: this.autoDownloadEpisodes,
|
autoDownloadEpisodes: this.autoDownloadEpisodes,
|
||||||
autoDownloadSchedule: this.autoDownloadSchedule,
|
autoDownloadSchedule: this.autoDownloadSchedule,
|
||||||
lastEpisodeCheck: this.lastEpisodeCheck,
|
lastEpisodeCheck: this.lastEpisodeCheck,
|
||||||
@ -121,7 +121,7 @@ class Podcast {
|
|||||||
|
|
||||||
get size() {
|
get size() {
|
||||||
var total = 0
|
var total = 0
|
||||||
this.episodes.forEach((ep) => total += ep.size)
|
this.episodes.forEach((ep) => (total += ep.size))
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
get hasMediaEntities() {
|
get hasMediaEntities() {
|
||||||
@ -129,7 +129,7 @@ class Podcast {
|
|||||||
}
|
}
|
||||||
get duration() {
|
get duration() {
|
||||||
let total = 0
|
let total = 0
|
||||||
this.episodes.forEach((ep) => total += ep.duration)
|
this.episodes.forEach((ep) => (total += ep.duration))
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
get numTracks() {
|
get numTracks() {
|
||||||
@ -145,7 +145,7 @@ class Podcast {
|
|||||||
return largestPublishedAt
|
return largestPublishedAt
|
||||||
}
|
}
|
||||||
get episodesWithPubDate() {
|
get episodesWithPubDate() {
|
||||||
return this.episodes.filter(ep => !!ep.publishedAt)
|
return this.episodes.filter((ep) => !!ep.publishedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
update(payload) {
|
update(payload) {
|
||||||
@ -169,7 +169,7 @@ class Podcast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateEpisode(id, payload) {
|
updateEpisode(id, payload) {
|
||||||
var episode = this.episodes.find(ep => ep.id == id)
|
var episode = this.episodes.find((ep) => ep.id == id)
|
||||||
if (!episode) return false
|
if (!episode) return false
|
||||||
return episode.update(payload)
|
return episode.update(payload)
|
||||||
}
|
}
|
||||||
@ -182,15 +182,15 @@ class Podcast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeFileWithInode(inode) {
|
removeFileWithInode(inode) {
|
||||||
const hasEpisode = this.episodes.some(ep => ep.audioFile.ino === inode)
|
const hasEpisode = this.episodes.some((ep) => ep.audioFile.ino === inode)
|
||||||
if (hasEpisode) {
|
if (hasEpisode) {
|
||||||
this.episodes = this.episodes.filter(ep => ep.audioFile.ino !== inode)
|
this.episodes = this.episodes.filter((ep) => ep.audioFile.ino !== inode)
|
||||||
}
|
}
|
||||||
return hasEpisode
|
return hasEpisode
|
||||||
}
|
}
|
||||||
|
|
||||||
findFileWithInode(inode) {
|
findFileWithInode(inode) {
|
||||||
var episode = this.episodes.find(ep => ep.audioFile.ino === inode)
|
var episode = this.episodes.find((ep) => ep.audioFile.ino === inode)
|
||||||
if (episode) return episode.audioFile
|
if (episode) return episode.audioFile
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -208,21 +208,23 @@ class Podcast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkHasEpisode(episodeId) {
|
checkHasEpisode(episodeId) {
|
||||||
return this.episodes.some(ep => ep.id === episodeId)
|
return this.episodes.some((ep) => ep.id === episodeId)
|
||||||
}
|
}
|
||||||
checkHasEpisodeByFeedUrl(url) {
|
checkHasEpisodeByFeedEpisode(feedEpisode) {
|
||||||
return this.episodes.some(ep => ep.checkEqualsEnclosureUrl(url))
|
const guid = feedEpisode.guid
|
||||||
|
const url = feedEpisode.enclosure.url
|
||||||
|
return this.episodes.some((ep) => (ep.guid && ep.guid === guid) || ep.checkEqualsEnclosureUrl(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only checks container format
|
// Only checks container format
|
||||||
checkCanDirectPlay(payload, episodeId) {
|
checkCanDirectPlay(payload, episodeId) {
|
||||||
var episode = this.episodes.find(ep => ep.id === episodeId)
|
var episode = this.episodes.find((ep) => ep.id === episodeId)
|
||||||
if (!episode) return false
|
if (!episode) return false
|
||||||
return episode.checkCanDirectPlay(payload)
|
return episode.checkCanDirectPlay(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
getDirectPlayTracklist(episodeId) {
|
getDirectPlayTracklist(episodeId) {
|
||||||
var episode = this.episodes.find(ep => ep.id === episodeId)
|
var episode = this.episodes.find((ep) => ep.id === episodeId)
|
||||||
if (!episode) return false
|
if (!episode) return false
|
||||||
return episode.getDirectPlayTracklist()
|
return episode.getDirectPlayTracklist()
|
||||||
}
|
}
|
||||||
@ -241,15 +243,15 @@ class Podcast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeEpisode(episodeId) {
|
removeEpisode(episodeId) {
|
||||||
const episode = this.episodes.find(ep => ep.id === episodeId)
|
const episode = this.episodes.find((ep) => ep.id === episodeId)
|
||||||
if (episode) {
|
if (episode) {
|
||||||
this.episodes = this.episodes.filter(ep => ep.id !== episodeId)
|
this.episodes = this.episodes.filter((ep) => ep.id !== episodeId)
|
||||||
}
|
}
|
||||||
return episode
|
return episode
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlaybackTitle(episodeId) {
|
getPlaybackTitle(episodeId) {
|
||||||
var episode = this.episodes.find(ep => ep.id == episodeId)
|
var episode = this.episodes.find((ep) => ep.id == episodeId)
|
||||||
if (!episode) return this.metadata.title
|
if (!episode) return this.metadata.title
|
||||||
return episode.title
|
return episode.title
|
||||||
}
|
}
|
||||||
@ -259,7 +261,7 @@ class Podcast {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getEpisodeDuration(episodeId) {
|
getEpisodeDuration(episodeId) {
|
||||||
var episode = this.episodes.find(ep => ep.id == episodeId)
|
var episode = this.episodes.find((ep) => ep.id == episodeId)
|
||||||
if (!episode) return 0
|
if (!episode) return 0
|
||||||
return episode.duration
|
return episode.duration
|
||||||
}
|
}
|
||||||
@ -268,13 +270,13 @@ class Podcast {
|
|||||||
if (!episodeId) return null
|
if (!episodeId) return null
|
||||||
|
|
||||||
// Support old episode ids for mobile downloads
|
// Support old episode ids for mobile downloads
|
||||||
if (episodeId.startsWith('ep_')) return this.episodes.find(ep => ep.oldEpisodeId == episodeId)
|
if (episodeId.startsWith('ep_')) return this.episodes.find((ep) => ep.oldEpisodeId == episodeId)
|
||||||
|
|
||||||
return this.episodes.find(ep => ep.id == episodeId)
|
return this.episodes.find((ep) => ep.id == episodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
getChapters(episodeId) {
|
getChapters(episodeId) {
|
||||||
return this.getEpisode(episodeId)?.chapters?.map(ch => ({ ...ch })) || []
|
return this.getEpisode(episodeId)?.chapters?.map((ch) => ({ ...ch })) || []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = Podcast
|
module.exports = Podcast
|
||||||
|
Loading…
Reference in New Issue
Block a user