Add:Parsing tags from OPF metadata #602, Update:OPF parser to check for prefix on package/metadata/meta objects

This commit is contained in:
advplyr 2022-05-18 19:25:18 -05:00
parent 7e5ab477b2
commit 139ee013a7
2 changed files with 47 additions and 19 deletions

View File

@ -225,6 +225,7 @@ class Book {
// Look for desc.txt, reader.txt, metadata.abs and opf file then update details if found
async syncMetadataFiles(textMetadataFiles, opfMetadataOverrideDetails) {
var metadataUpdatePayload = {}
var tagsUpdated = false
var descTxt = textMetadataFiles.find(lf => lf.metadata.filename === 'desc.txt')
if (descTxt) {
@ -264,8 +265,13 @@ class Book {
var opfMetadata = await parseOpfMetadataXML(xmlText)
if (opfMetadata) {
for (const key in opfMetadata) {
// Add genres only if genres are empty
if (key === 'genres') {
if (key === 'tags') { // Add tags only if tags are empty
if (opfMetadata.tags.length && (!this.tags.length || opfMetadataOverrideDetails)) {
this.tags = opfMetadata.tags
tagsUpdated = true
}
} else if (key === 'genres') { // Add genres only if genres are empty
if (opfMetadata.genres.length && (!this.metadata.genres.length || opfMetadataOverrideDetails)) {
metadataUpdatePayload[key] = opfMetadata.genres
}
@ -290,9 +296,9 @@ class Book {
}
if (Object.keys(metadataUpdatePayload).length) {
return this.metadata.update(metadataUpdatePayload)
return this.metadata.update(metadataUpdatePayload) || tagsUpdated
}
return false
return tagsUpdated
}
searchQuery(query) {

View File

@ -70,14 +70,14 @@ function fetchLanguage(metadata) {
return fetchTagString(metadata, 'dc:language')
}
function fetchSeries(metadata) {
if (typeof metadata.meta == "undefined") return null
return fetchTagString(metadata.meta, "calibre:series")
function fetchSeries(metadataMeta) {
if (!metadataMeta) return null
return fetchTagString(metadataMeta, "calibre:series")
}
function fetchVolumeNumber(metadata) {
if (typeof metadata.meta == "undefined") return null
return fetchTagString(metadata.meta, "calibre:series_index")
function fetchVolumeNumber(metadataMeta) {
if (!metadataMeta) return null
return fetchTagString(metadataMeta, "calibre:series_index")
}
function fetchNarrators(creators, metadata) {
@ -91,21 +91,42 @@ function fetchNarrators(creators, metadata) {
}
}
function fetchTags(metadata) {
if (!metadata['dc:tag'] || !metadata['dc:tag'].length) return []
return metadata['dc:tag'].filter(tag => (typeof tag === 'string'))
}
function stripPrefix(str) {
if (!str) return ''
return str.split(':').pop()
}
module.exports.parseOpfMetadataXML = async (xml) => {
var json = await xmlToJSON(xml)
if (!json || !json.package || !json.package.metadata) return null
var metadata = json.package.metadata
if (!json) return null
// Handle <package ...> or with prefix <ns0:package ...>
const packageKey = Object.keys(json).find(key => stripPrefix(key) === 'package')
if (!packageKey) return null
const prefix = packageKey.split(':').shift()
var metadata = prefix ? json[packageKey][`${prefix}:metadata`] || json[packageKey].metadata : json[packageKey].metadata
if (!metadata) return null
if (Array.isArray(metadata)) {
if (!metadata.length) return null
metadata = metadata[0]
}
if (typeof metadata.meta != "undefined") {
metadata.meta = {}
for (var match of xml.matchAll(/<meta name="(?<name>.+)" content="(?<content>.+)"\/>/g)) {
metadata.meta[match.groups['name']] = [match.groups['content']]
}
const metadataMeta = prefix ? metadata[`${prefix}:meta`] || metadata.meta : metadata.meta
metadata.meta = {}
if (metadataMeta && metadataMeta.length) {
metadataMeta.forEach((meta) => {
if (meta && meta['$'] && meta['$'].name) {
metadata.meta[meta['$'].name] = [meta['$'].content || '']
}
})
}
var creators = parseCreators(metadata)
@ -119,8 +140,9 @@ module.exports.parseOpfMetadataXML = async (xml) => {
description: fetchDescription(metadata),
genres: fetchGenres(metadata),
language: fetchLanguage(metadata),
series: fetchSeries(metadata),
sequence: fetchVolumeNumber(metadata)
series: fetchSeries(metadata.meta),
sequence: fetchVolumeNumber(metadata.meta),
tags: fetchTags(metadata)
}
return data
}