mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Merge pull request #3152 from mikiher/fix-opf-fetch-series
Fix OPF fetchSeries so it deduplicates found series
This commit is contained in:
		
						commit
						b6875a44cf
					
				@ -5,7 +5,7 @@ function parseCreators(metadata) {
 | 
			
		||||
  if (!metadata['dc:creator']) return null
 | 
			
		||||
  const creators = metadata['dc:creator']
 | 
			
		||||
  if (!creators.length) return null
 | 
			
		||||
  return creators.map(c => {
 | 
			
		||||
  return creators.map((c) => {
 | 
			
		||||
    if (typeof c !== 'object' || !c['$'] || !c['_']) return false
 | 
			
		||||
    return {
 | 
			
		||||
      value: c['_'],
 | 
			
		||||
@ -17,7 +17,7 @@ function parseCreators(metadata) {
 | 
			
		||||
 | 
			
		||||
function fetchCreators(creators, role) {
 | 
			
		||||
  if (!creators?.length) return null
 | 
			
		||||
  return [...new Set(creators.filter(c => c.role === role && c.value).map(c => c.value))]
 | 
			
		||||
  return [...new Set(creators.filter((c) => c.role === role && c.value).map((c) => c.value))]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fetchTagString(metadata, tag) {
 | 
			
		||||
@ -62,14 +62,14 @@ function fetchPublisher(metadata) {
 | 
			
		||||
function fetchISBN(metadata) {
 | 
			
		||||
  if (!metadata['dc:identifier'] || !metadata['dc:identifier'].length) return null
 | 
			
		||||
  const identifiers = metadata['dc:identifier']
 | 
			
		||||
  const isbnObj = identifiers.find(i => i['$'] && i['$']['opf:scheme'] === 'ISBN')
 | 
			
		||||
  const isbnObj = identifiers.find((i) => i['$'] && i['$']['opf:scheme'] === 'ISBN')
 | 
			
		||||
  return isbnObj ? isbnObj['_'] || null : null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fetchASIN(metadata) {
 | 
			
		||||
  if (!metadata['dc:identifier'] || !metadata['dc:identifier'].length) return null
 | 
			
		||||
  const identifiers = metadata['dc:identifier']
 | 
			
		||||
  const asinObj = identifiers.find(i => i['$'] && i['$']['opf:scheme'] === 'ASIN')
 | 
			
		||||
  const asinObj = identifiers.find((i) => i['$'] && i['$']['opf:scheme'] === 'ASIN')
 | 
			
		||||
  return asinObj ? asinObj['_'] || null : null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@ function fetchDescription(metadata) {
 | 
			
		||||
 | 
			
		||||
function fetchGenres(metadata) {
 | 
			
		||||
  if (!metadata['dc:subject'] || !metadata['dc:subject'].length) return []
 | 
			
		||||
  return [...new Set(metadata['dc:subject'].filter(g => g && typeof g === 'string'))]
 | 
			
		||||
  return [...new Set(metadata['dc:subject'].filter((g) => g && typeof g === 'string'))]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fetchLanguage(metadata) {
 | 
			
		||||
@ -116,20 +116,24 @@ function fetchSeries(metadataMeta) {
 | 
			
		||||
  // If one series was found with no series_index then check if any series_index meta can be found
 | 
			
		||||
  //   this is to support when calibre:series_index is not directly underneath calibre:series
 | 
			
		||||
  if (result.length === 1 && !result[0].sequence) {
 | 
			
		||||
    const seriesIndexMeta = metadataMeta.find(m => m.$?.name === 'calibre:series_index' && m.$.content?.trim())
 | 
			
		||||
    const seriesIndexMeta = metadataMeta.find((m) => m.$?.name === 'calibre:series_index' && m.$.content?.trim())
 | 
			
		||||
    if (seriesIndexMeta) {
 | 
			
		||||
      result[0].sequence = seriesIndexMeta.$.content.trim()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return result
 | 
			
		||||
 | 
			
		||||
  // Remove duplicates
 | 
			
		||||
  const dedupedResult = result.filter((se, idx) => result.findIndex((s) => s.name === se.name) === idx)
 | 
			
		||||
 | 
			
		||||
  return dedupedResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fetchNarrators(creators, metadata) {
 | 
			
		||||
  const narrators = fetchCreators(creators, 'nrt')
 | 
			
		||||
  if (narrators?.length) return narrators
 | 
			
		||||
  try {
 | 
			
		||||
    const narratorsJSON = JSON.parse(fetchTagString(metadata.meta, "calibre:user_metadata:#narrators").replace(/"/g, '"'))
 | 
			
		||||
    return narratorsJSON["#value#"]
 | 
			
		||||
    const narratorsJSON = JSON.parse(fetchTagString(metadata.meta, 'calibre:user_metadata:#narrators').replace(/"/g, '"'))
 | 
			
		||||
    return narratorsJSON['#value#']
 | 
			
		||||
  } catch {
 | 
			
		||||
    return null
 | 
			
		||||
  }
 | 
			
		||||
@ -137,7 +141,7 @@ function fetchNarrators(creators, metadata) {
 | 
			
		||||
 | 
			
		||||
function fetchTags(metadata) {
 | 
			
		||||
  if (!metadata['dc:tag'] || !metadata['dc:tag'].length) return []
 | 
			
		||||
  return [...new Set(metadata['dc:tag'].filter(tag => tag && typeof tag === 'string'))]
 | 
			
		||||
  return [...new Set(metadata['dc:tag'].filter((tag) => tag && typeof tag === 'string'))]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function stripPrefix(str) {
 | 
			
		||||
@ -147,7 +151,7 @@ function stripPrefix(str) {
 | 
			
		||||
 | 
			
		||||
module.exports.parseOpfMetadataJson = (json) => {
 | 
			
		||||
  // Handle <package ...> or with prefix <ns0:package ...>
 | 
			
		||||
  const packageKey = Object.keys(json).find(key => stripPrefix(key) === 'package')
 | 
			
		||||
  const packageKey = Object.keys(json).find((key) => stripPrefix(key) === 'package')
 | 
			
		||||
  if (!packageKey) return null
 | 
			
		||||
  const prefix = packageKey.split(':').shift()
 | 
			
		||||
  let metadata = prefix ? json[packageKey][`${prefix}:metadata`] || json[packageKey].metadata : json[packageKey].metadata
 | 
			
		||||
@ -170,8 +174,8 @@ module.exports.parseOpfMetadataJson = (json) => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const creators = parseCreators(metadata)
 | 
			
		||||
  const authors = (fetchCreators(creators, 'aut') || []).map(au => au?.trim()).filter(au => au)
 | 
			
		||||
  const narrators = (fetchNarrators(creators, metadata) || []).map(nrt => nrt?.trim()).filter(nrt => nrt)
 | 
			
		||||
  const authors = (fetchCreators(creators, 'aut') || []).map((au) => au?.trim()).filter((au) => au)
 | 
			
		||||
  const narrators = (fetchNarrators(creators, metadata) || []).map((nrt) => nrt?.trim()).filter((nrt) => nrt)
 | 
			
		||||
  return {
 | 
			
		||||
    title: fetchTitle(metadata),
 | 
			
		||||
    subtitle: fetchSubtitle(metadata),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user