Fix:Update metadata.json when using item metadata utils #2837

This commit is contained in:
advplyr 2024-04-12 17:34:10 -05:00
parent 29fc503503
commit c4fd4ff9de
3 changed files with 154 additions and 1 deletions

View File

@ -329,6 +329,7 @@ class MiscController {
await libraryItem.media.update({
tags: libraryItem.media.tags
})
await libraryItem.saveMetadataFile()
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
numItemsUpdated++
@ -370,6 +371,7 @@ class MiscController {
await libraryItem.media.update({
tags: libraryItem.media.tags
})
await libraryItem.saveMetadataFile()
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
numItemsUpdated++
@ -462,6 +464,7 @@ class MiscController {
await libraryItem.media.update({
genres: libraryItem.media.genres
})
await libraryItem.saveMetadataFile()
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
numItemsUpdated++
@ -503,6 +506,7 @@ class MiscController {
await libraryItem.media.update({
genres: libraryItem.media.genres
})
await libraryItem.saveMetadataFile()
const oldLibraryItem = Database.libraryItemModel.getOldLibraryItem(libraryItem)
SocketAuthority.emitter('item_updated', oldLibraryItem.toJSONExpanded())
numItemsUpdated++

View File

@ -1,8 +1,12 @@
const Path = require('path')
const { DataTypes, Model } = require('sequelize')
const fsExtra = require('../libs/fsExtra')
const Logger = require('../Logger')
const oldLibraryItem = require('../objects/LibraryItem')
const libraryFilters = require('../utils/queries/libraryFilters')
const { areEquivalent } = require('../utils/index')
const { filePathToPOSIX, getFileTimestampsWithIno } = require('../utils/fileUtils')
const LibraryFile = require('../objects/files/LibraryFile')
const Book = require('./Book')
const Podcast = require('./Podcast')
@ -828,6 +832,147 @@ class LibraryItem extends Model {
return this[mixinMethodName](options)
}
/**
*
* @returns {Promise<Book|Podcast>}
*/
getMediaExpanded() {
if (this.mediaType === 'podcast') {
return this.getMedia({
include: [
{
model: this.sequelize.models.podcastEpisode
}
]
})
} else {
return this.getMedia({
include: [
{
model: this.sequelize.models.author,
through: {
attributes: []
}
},
{
model: this.sequelize.models.series,
through: {
attributes: ['sequence']
}
}
],
order: [
[this.sequelize.models.author, this.sequelize.models.bookAuthor, 'createdAt', 'ASC'],
[this.sequelize.models.series, 'bookSeries', 'createdAt', 'ASC']
]
})
}
}
/**
*
* @returns {Promise}
*/
async saveMetadataFile() {
let metadataPath = Path.join(global.MetadataPath, 'items', this.id)
let storeMetadataWithItem = global.ServerSettings.storeMetadataWithItem
if (storeMetadataWithItem && !this.isFile) {
metadataPath = this.path
} else {
// Make sure metadata book dir exists
storeMetadataWithItem = false
await fsExtra.ensureDir(metadataPath)
}
const metadataFilePath = Path.join(metadataPath, `metadata.${global.ServerSettings.metadataFileFormat}`)
// Expanded with series, authors, podcastEpisodes
const mediaExpanded = this.media || await this.getMediaExpanded()
let jsonObject = {}
if (this.mediaType === 'book') {
jsonObject = {
tags: mediaExpanded.tags || [],
chapters: mediaExpanded.chapters?.map(c => ({ ...c })) || [],
title: mediaExpanded.title,
subtitle: mediaExpanded.subtitle,
authors: mediaExpanded.authors.map(a => a.name),
narrators: mediaExpanded.narrators,
series: mediaExpanded.series.map(se => {
const sequence = se.bookSeries?.sequence || ''
if (!sequence) return se.name
return `${se.name} #${sequence}`
}),
genres: mediaExpanded.genres || [],
publishedYear: mediaExpanded.publishedYear,
publishedDate: mediaExpanded.publishedDate,
publisher: mediaExpanded.publisher,
description: mediaExpanded.description,
isbn: mediaExpanded.isbn,
asin: mediaExpanded.asin,
language: mediaExpanded.language,
explicit: !!mediaExpanded.explicit,
abridged: !!mediaExpanded.abridged
}
} else {
jsonObject = {
tags: mediaExpanded.tags || [],
title: mediaExpanded.title,
author: mediaExpanded.author,
description: mediaExpanded.description,
releaseDate: mediaExpanded.releaseDate,
genres: mediaExpanded.genres || [],
feedURL: mediaExpanded.feedURL,
imageURL: mediaExpanded.imageURL,
itunesPageURL: mediaExpanded.itunesPageURL,
itunesId: mediaExpanded.itunesId,
itunesArtistId: mediaExpanded.itunesArtistId,
asin: mediaExpanded.asin,
language: mediaExpanded.language,
explicit: !!mediaExpanded.explicit,
podcastType: mediaExpanded.podcastType
}
}
return fsExtra.writeFile(metadataFilePath, JSON.stringify(jsonObject, null, 2)).then(async () => {
// Add metadata.json to libraryFiles array if it is new
let metadataLibraryFile = this.libraryFiles.find(lf => lf.metadata.path === filePathToPOSIX(metadataFilePath))
if (storeMetadataWithItem) {
if (!metadataLibraryFile) {
const newLibraryFile = new LibraryFile()
await newLibraryFile.setDataFromPath(metadataFilePath, `metadata.json`)
metadataLibraryFile = newLibraryFile.toJSON()
this.libraryFiles.push(metadataLibraryFile)
} else {
const fileTimestamps = await getFileTimestampsWithIno(metadataFilePath)
if (fileTimestamps) {
metadataLibraryFile.metadata.mtimeMs = fileTimestamps.mtimeMs
metadataLibraryFile.metadata.ctimeMs = fileTimestamps.ctimeMs
metadataLibraryFile.metadata.size = fileTimestamps.size
metadataLibraryFile.ino = fileTimestamps.ino
}
}
const libraryItemDirTimestamps = await getFileTimestampsWithIno(this.path)
if (libraryItemDirTimestamps) {
this.mtime = libraryItemDirTimestamps.mtimeMs
this.ctime = libraryItemDirTimestamps.ctimeMs
let size = 0
this.libraryFiles.forEach((lf) => size += (!isNaN(lf.metadata.size) ? Number(lf.metadata.size) : 0))
this.size = size
await this.save()
}
}
Logger.debug(`Success saving abmetadata to "${metadataFilePath}"`)
return metadataLibraryFile
}).catch((error) => {
Logger.error(`Failed to save json file at "${metadataFilePath}"`, error)
return null
})
}
/**
* Initialize model
* @param {import('../Database').sequelize} sequelize

View File

@ -34,6 +34,10 @@ module.exports = {
attributes: ['sequence']
}
}
],
order: [
[Database.authorModel, Database.bookAuthorModel, 'createdAt', 'ASC'],
[Database.seriesModel, 'bookSeries', 'createdAt', 'ASC']
]
})
for (const book of booksWithTag) {
@ -68,7 +72,7 @@ module.exports = {
/**
* Get all library items that have genres
* @param {string[]} genres
* @returns {Promise<LibraryItem[]>}
* @returns {Promise<import('../../models/LibraryItem')[]>}
*/
async getAllLibraryItemsWithGenres(genres) {
const libraryItems = []