Fix fetchSeries so it deduplicates returned series

This commit is contained in:
mikiher 2024-07-12 12:42:42 +03:00
parent f0a1ea4d6d
commit c0004dd532

View File

@ -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),
@ -193,4 +197,4 @@ module.exports.parseOpfMetadataXML = async (xml) => {
const json = await xmlToJSON(xml)
if (!json) return null
return this.parseOpfMetadataJson(json)
}
}