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

View File

@ -70,14 +70,14 @@ function fetchLanguage(metadata) {
return fetchTagString(metadata, 'dc:language') return fetchTagString(metadata, 'dc:language')
} }
function fetchSeries(metadata) { function fetchSeries(metadataMeta) {
if (typeof metadata.meta == "undefined") return null if (!metadataMeta) return null
return fetchTagString(metadata.meta, "calibre:series") return fetchTagString(metadataMeta, "calibre:series")
} }
function fetchVolumeNumber(metadata) { function fetchVolumeNumber(metadataMeta) {
if (typeof metadata.meta == "undefined") return null if (!metadataMeta) return null
return fetchTagString(metadata.meta, "calibre:series_index") return fetchTagString(metadataMeta, "calibre:series_index")
} }
function fetchNarrators(creators, metadata) { 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) => { module.exports.parseOpfMetadataXML = async (xml) => {
var json = await xmlToJSON(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 (Array.isArray(metadata)) {
if (!metadata.length) return null if (!metadata.length) return null
metadata = metadata[0] metadata = metadata[0]
} }
if (typeof metadata.meta != "undefined") { const metadataMeta = prefix ? metadata[`${prefix}:meta`] || metadata.meta : metadata.meta
metadata.meta = {}
for (var match of xml.matchAll(/<meta name="(?<name>.+)" content="(?<content>.+)"\/>/g)) { metadata.meta = {}
metadata.meta[match.groups['name']] = [match.groups['content']] if (metadataMeta && metadataMeta.length) {
} metadataMeta.forEach((meta) => {
if (meta && meta['$'] && meta['$'].name) {
metadata.meta[meta['$'].name] = [meta['$'].content || '']
}
})
} }
var creators = parseCreators(metadata) var creators = parseCreators(metadata)
@ -119,8 +140,9 @@ module.exports.parseOpfMetadataXML = async (xml) => {
description: fetchDescription(metadata), description: fetchDescription(metadata),
genres: fetchGenres(metadata), genres: fetchGenres(metadata),
language: fetchLanguage(metadata), language: fetchLanguage(metadata),
series: fetchSeries(metadata), series: fetchSeries(metadata.meta),
sequence: fetchVolumeNumber(metadata) sequence: fetchVolumeNumber(metadata.meta),
tags: fetchTags(metadata)
} }
return data return data
} }