mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-01 08:44:40 +02:00
Fix:Podcast episodes store RSS feed guid so they can be matched if the RSS feed changes the episode URL #2207
This commit is contained in:
parent
48a590df4a
commit
0d5792405f
6 changed files with 59 additions and 39 deletions
|
@ -4,7 +4,7 @@ const { xmlToJSON, levenshteinDistance } = require('./index')
|
|||
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||
|
||||
function extractFirstArrayItem(json, key) {
|
||||
if (!json[key] || !json[key].length) return null
|
||||
if (!json[key]?.length) return null
|
||||
return json[key][0]
|
||||
}
|
||||
|
||||
|
@ -110,13 +110,24 @@ function extractEpisodeData(item) {
|
|||
const pubDate = extractFirstArrayItem(item, 'pubDate')
|
||||
if (typeof pubDate === 'string') {
|
||||
episode.pubDate = pubDate
|
||||
} else if (pubDate && typeof pubDate._ === 'string') {
|
||||
} else if (typeof pubDate?._ === 'string') {
|
||||
episode.pubDate = pubDate._
|
||||
} else {
|
||||
Logger.error(`[podcastUtils] Invalid pubDate ${item['pubDate']} for ${episode.enclosure.url}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (item['guid']) {
|
||||
const guidItem = extractFirstArrayItem(item, 'guid')
|
||||
if (typeof guidItem === 'string') {
|
||||
episode.guid = guidItem
|
||||
} else if (typeof guidItem?._ === 'string') {
|
||||
episode.guid = guidItem._
|
||||
} else {
|
||||
Logger.error(`[podcastUtils] Invalid guid ${item['guid']} for ${episode.enclosure.url}`)
|
||||
}
|
||||
}
|
||||
|
||||
const arrayFields = ['title', 'itunes:episodeType', 'itunes:season', 'itunes:episode', 'itunes:author', 'itunes:duration', 'itunes:explicit', 'itunes:subtitle']
|
||||
arrayFields.forEach((key) => {
|
||||
const cleanKey = key.split(':').pop()
|
||||
|
@ -142,6 +153,7 @@ function cleanEpisodeData(data) {
|
|||
explicit: data.explicit || '',
|
||||
publishedAt,
|
||||
enclosure: data.enclosure,
|
||||
guid: data.guid || null,
|
||||
chaptersUrl: data.chaptersUrl || null,
|
||||
chaptersType: data.chaptersType || null
|
||||
}
|
||||
|
@ -159,16 +171,16 @@ function extractPodcastEpisodes(items) {
|
|||
}
|
||||
|
||||
function cleanPodcastJson(rssJson, excludeEpisodeMetadata) {
|
||||
if (!rssJson.channel || !rssJson.channel.length) {
|
||||
if (!rssJson.channel?.length) {
|
||||
Logger.error(`[podcastUtil] Invalid podcast no channel object`)
|
||||
return null
|
||||
}
|
||||
var channel = rssJson.channel[0]
|
||||
if (!channel.item || !channel.item.length) {
|
||||
const channel = rssJson.channel[0]
|
||||
if (!channel.item?.length) {
|
||||
Logger.error(`[podcastUtil] Invalid podcast no episodes`)
|
||||
return null
|
||||
}
|
||||
var podcast = {
|
||||
const podcast = {
|
||||
metadata: extractPodcastMetadata(channel)
|
||||
}
|
||||
if (!excludeEpisodeMetadata) {
|
||||
|
@ -181,8 +193,8 @@ function cleanPodcastJson(rssJson, excludeEpisodeMetadata) {
|
|||
|
||||
module.exports.parsePodcastRssFeedXml = async (xml, excludeEpisodeMetadata = false, includeRaw = false) => {
|
||||
if (!xml) return null
|
||||
var json = await xmlToJSON(xml)
|
||||
if (!json || !json.rss) {
|
||||
const json = await xmlToJSON(xml)
|
||||
if (!json?.rss) {
|
||||
Logger.error('[podcastUtils] Invalid XML or RSS feed')
|
||||
return null
|
||||
}
|
||||
|
@ -215,12 +227,12 @@ module.exports.getPodcastFeed = (feedUrl, excludeEpisodeMetadata = false) => {
|
|||
data.data = data.data.toString()
|
||||
}
|
||||
|
||||
if (!data || !data.data) {
|
||||
if (!data?.data) {
|
||||
Logger.error(`[podcastUtils] getPodcastFeed: Invalid podcast feed request response (${feedUrl})`)
|
||||
return false
|
||||
}
|
||||
Logger.debug(`[podcastUtils] getPodcastFeed for "${feedUrl}" success - parsing xml`)
|
||||
var payload = await this.parsePodcastRssFeedXml(data.data, excludeEpisodeMetadata)
|
||||
const payload = await this.parsePodcastRssFeedXml(data.data, excludeEpisodeMetadata)
|
||||
if (!payload) {
|
||||
return false
|
||||
}
|
||||
|
@ -246,7 +258,7 @@ module.exports.findMatchingEpisodes = async (feedUrl, searchTitle) => {
|
|||
|
||||
module.exports.findMatchingEpisodesInFeed = (feed, searchTitle) => {
|
||||
searchTitle = searchTitle.toLowerCase().trim()
|
||||
if (!feed || !feed.episodes) {
|
||||
if (!feed?.episodes) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue