Add:metadata.json format #1775 #916

This commit is contained in:
advplyr 2023-05-15 18:23:31 -05:00
parent 32bdae31a8
commit 81d4ac3ed2
8 changed files with 140 additions and 25 deletions

View file

@ -499,14 +499,37 @@ class LibraryItem {
// Make sure metadata book dir exists
await fs.ensureDir(metadataPath)
}
metadataPath = Path.join(metadataPath, 'metadata.abs')
return abmetadataGenerator.generate(this, metadataPath).then((success) => {
this.isSavingMetadata = false
if (!success) Logger.error(`[LibraryItem] Failed saving abmetadata to "${metadataPath}"`)
else Logger.debug(`[LibraryItem] Success saving abmetadata to "${metadataPath}"`)
return success
})
const metadataFileFormat = global.ServerSettings.metadataFileFormat
const metadataFilePath = Path.join(metadataPath, `metadata.${metadataFileFormat}`)
if (metadataFileFormat === 'json') {
// Remove metadata.abs if it exists
if (await fs.pathExists(Path.join(metadataPath, `metadata.abs`))) {
Logger.debug(`[LibraryItem] Removing metadata.abs for item "${this.media.metadata.title}"`)
await fs.remove(Path.join(metadataPath, `metadata.abs`))
}
return fs.writeFile(metadataFilePath, JSON.stringify(this.media.toJSONForMetadataFile(), null, 2)).then(() => {
return true
}).catch((error) => {
Logger.error(`[LibraryItem] Failed to save json file at "${metadataFilePath}"`, error)
return false
})
} else {
// Remove metadata.json if it exists
if (await fs.pathExists(Path.join(metadataPath, `metadata.json`))) {
Logger.debug(`[LibraryItem] Removing metadata.json for item "${this.media.metadata.title}"`)
await fs.remove(Path.join(metadataPath, `metadata.json`))
}
return abmetadataGenerator.generate(this, metadataFilePath).then((success) => {
this.isSavingMetadata = false
if (!success) Logger.error(`[LibraryItem] Failed saving abmetadata to "${metadataFilePath}"`)
else Logger.debug(`[LibraryItem] Success saving abmetadata to "${metadataFilePath}"`)
return success
})
}
}
removeLibraryFile(ino) {

View file

@ -89,6 +89,14 @@ class Book {
}
}
toJSONForMetadataFile() {
return {
tags: [...this.tags],
chapters: this.chapters.map(c => ({ ...c })),
metadata: this.metadata.toJSONForMetadataFile()
}
}
get size() {
var total = 0
this.audioFiles.forEach((af) => total += af.metadata.size)
@ -248,11 +256,12 @@ class Book {
}
}
const metadataAbs = textMetadataFiles.find(lf => lf.metadata.filename === 'metadata.abs')
const metadataAbs = textMetadataFiles.find(lf => lf.metadata.filename === 'metadata.abs' || lf.metadata.filename === 'metadata.json')
if (metadataAbs) {
Logger.debug(`[Book] Found metadata.abs file for "${this.metadata.title}"`)
const isJSON = metadataAbs.metadata.filename === 'metadata.json'
Logger.debug(`[Book] Found ${metadataAbs.metadata.filename} file for "${this.metadata.title}"`)
const metadataText = await readTextFile(metadataAbs.metadata.path)
const abmetadataUpdates = abmetadataGenerator.parseAndCheckForUpdates(metadataText, this, 'book')
const abmetadataUpdates = abmetadataGenerator.parseAndCheckForUpdates(metadataText, this, 'book', isJSON)
if (abmetadataUpdates && Object.keys(abmetadataUpdates).length) {
Logger.debug(`[Book] "${this.metadata.title}" changes found in metadata.abs file`, abmetadataUpdates)

View file

@ -94,6 +94,13 @@ class Podcast {
}
}
toJSONForMetadataFile() {
return {
tags: [...this.tags],
metadata: this.metadata.toJSON()
}
}
get size() {
var total = 0
this.episodes.forEach((ep) => total += ep.size)
@ -199,10 +206,11 @@ class Podcast {
let metadataUpdatePayload = {}
let tagsUpdated = false
const metadataAbs = textMetadataFiles.find(lf => lf.metadata.filename === 'metadata.abs')
const metadataAbs = textMetadataFiles.find(lf => lf.metadata.filename === 'metadata.abs' || lf.metadata.filename === 'metadata.json')
if (metadataAbs) {
const isJSON = metadataAbs.metadata.filename === 'metadata.json'
const metadataText = await readTextFile(metadataAbs.metadata.path)
const abmetadataUpdates = abmetadataGenerator.parseAndCheckForUpdates(metadataText, this, 'podcast')
const abmetadataUpdates = abmetadataGenerator.parseAndCheckForUpdates(metadataText, this, 'podcast', isJSON)
if (abmetadataUpdates && Object.keys(abmetadataUpdates).length) {
Logger.debug(`[Podcast] "${this.metadata.title}" changes found in metadata.abs file`, abmetadataUpdates)

View file

@ -109,6 +109,16 @@ class BookMetadata {
}
}
toJSONForMetadataFile() {
const json = this.toJSON()
json.authors = json.authors.map(au => au.name)
json.series = json.series.map(se => {
if (!se.sequence) return se.name
return `${se.name} #${se.sequence}`
})
return json
}
clone() {
return new BookMetadata(this.toJSON())
}
@ -191,8 +201,9 @@ class BookMetadata {
}
update(payload) {
var json = this.toJSON()
var hasUpdates = false
const json = this.toJSON()
let hasUpdates = false
for (const key in json) {
if (payload[key] !== undefined) {
if (!areEquivalent(payload[key], json[key])) {
@ -373,8 +384,10 @@ class BookMetadata {
const parsed = parseNameString.parse(authorsTag)
if (!parsed) return []
return (parsed.names || []).map((au) => {
const findAuthor = this.authors.find(_au => _au.name == au)
return {
id: `new-${Math.floor(Math.random() * 1000000)}`,
id: findAuthor?.id || `new-${Math.floor(Math.random() * 1000000)}`,
name: au
}
})

View file

@ -1,5 +1,4 @@
const { BookshelfView } = require('../../utils/constants')
const { isNullOrNaN } = require('../../utils')
const Logger = require('../../Logger')
class ServerSettings {
@ -21,6 +20,7 @@ class ServerSettings {
// Metadata - choose to store inside users library item folder
this.storeCoverWithItem = false
this.storeMetadataWithItem = false
this.metadataFileFormat = 'json'
// Security/Rate limits
this.rateLimitLoginRequests = 10
@ -77,6 +77,7 @@ class ServerSettings {
this.storeCoverWithItem = !!settings.storeCoverWithItem
this.storeMetadataWithItem = !!settings.storeMetadataWithItem
this.metadataFileFormat = settings.metadataFileFormat || 'json'
this.rateLimitLoginRequests = !isNaN(settings.rateLimitLoginRequests) ? Number(settings.rateLimitLoginRequests) : 10
this.rateLimitLoginWindow = !isNaN(settings.rateLimitLoginWindow) ? Number(settings.rateLimitLoginWindow) : 10 * 60 * 1000 // 10 Minutes
@ -112,6 +113,16 @@ class ServerSettings {
if (settings.homeBookshelfView == undefined) { // homeBookshelfView was added in 2.1.3
this.homeBookshelfView = settings.bookshelfView
}
if (settings.metadataFileFormat == undefined) { // metadataFileFormat was added in 2.2.21
// All users using old settings will stay abs until changed
this.metadataFileFormat = 'abs'
}
// Validation
if (!['abs', 'json'].includes(this.metadataFileFormat)) {
Logger.error(`[ServerSettings] construct: Invalid metadataFileFormat ${this.metadataFileFormat}`)
this.metadataFileFormat = 'json'
}
if (this.logLevel !== Logger.logLevel) {
Logger.setLogLevel(this.logLevel)
@ -133,6 +144,7 @@ class ServerSettings {
scannerUseTone: this.scannerUseTone,
storeCoverWithItem: this.storeCoverWithItem,
storeMetadataWithItem: this.storeMetadataWithItem,
metadataFileFormat: this.metadataFileFormat,
rateLimitLoginRequests: this.rateLimitLoginRequests,
rateLimitLoginWindow: this.rateLimitLoginWindow,
backupSchedule: this.backupSchedule,