From 6ac0a8a678bdfd702e53cabd9a09cfcf44aabc82 Mon Sep 17 00:00:00 2001 From: Cutch Date: Mon, 24 Nov 2025 22:46:57 -0500 Subject: [PATCH] Add id to the metadata json and use it when moving files if ino cannot be matched --- server/models/LibraryItem.js | 2 ++ server/scanner/BookScanner.js | 1 + server/scanner/LibraryScanner.js | 14 +++++++++++++- server/scanner/PodcastScanner.js | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/server/models/LibraryItem.js b/server/models/LibraryItem.js index 16a52161..3051aacc 100644 --- a/server/models/LibraryItem.js +++ b/server/models/LibraryItem.js @@ -574,6 +574,7 @@ class LibraryItem extends Model { let jsonObject = {} if (this.mediaType === 'book') { jsonObject = { + absId: this.id, tags: mediaExpanded.tags || [], chapters: mediaExpanded.chapters?.map((c) => ({ ...c })) || [], title: mediaExpanded.title, @@ -598,6 +599,7 @@ class LibraryItem extends Model { } } else { jsonObject = { + absId: this.id, tags: mediaExpanded.tags || [], title: mediaExpanded.title, author: mediaExpanded.author, diff --git a/server/scanner/BookScanner.js b/server/scanner/BookScanner.js index a1e7ff50..fa3695fe 100644 --- a/server/scanner/BookScanner.js +++ b/server/scanner/BookScanner.js @@ -821,6 +821,7 @@ class BookScanner { const metadataFilePath = Path.join(metadataPath, `metadata.${global.ServerSettings.metadataFileFormat}`) const jsonObject = { + absId: libraryItem.id, tags: libraryItem.media.tags || [], chapters: libraryItem.media.chapters?.map((c) => ({ ...c })) || [], title: libraryItem.media.title, diff --git a/server/scanner/LibraryScanner.js b/server/scanner/LibraryScanner.js index 640c82d7..79cc194f 100644 --- a/server/scanner/LibraryScanner.js +++ b/server/scanner/LibraryScanner.js @@ -14,6 +14,7 @@ const LibraryItemScanner = require('./LibraryItemScanner') const LibraryScan = require('./LibraryScan') const LibraryItemScanData = require('./LibraryItemScanData') const Task = require('../objects/Task') +const abmetadataGenerator = require('../utils/generators/abmetadataGenerator') class LibraryScanner { constructor() { @@ -574,7 +575,7 @@ class LibraryScanner { let updatedLibraryItemDetails = {} if (!existingLibraryItem) { const isSingleMedia = isSingleMediaFile(fileUpdateGroup, itemDir) - existingLibraryItem = (await findLibraryItemByItemToItemInoMatch(library.id, fullPath)) || (await findLibraryItemByItemToFileInoMatch(library.id, fullPath, isSingleMedia)) || (await findLibraryItemByFileToItemInoMatch(library.id, fullPath, isSingleMedia, fileUpdateGroup[itemDir])) + existingLibraryItem = (await findLibraryItemByItemToItemInoMatch(library.id, fullPath)) || (await findLibraryItemByItemToFileInoMatch(library.id, fullPath, isSingleMedia)) || (await findLibraryItemByFileToItemInoMatch(library.id, fullPath, isSingleMedia, fileUpdateGroup[itemDir])) || (await findLibraryItemByItemToMetadata(fullPath, isSingleMedia)) if (existingLibraryItem) { // Update library item paths for scan existingLibraryItem.path = fullPath @@ -709,3 +710,14 @@ async function findLibraryItemByFileToItemInoMatch(libraryId, fullPath, isSingle if (existingLibraryItem) Logger.debug(`[LibraryScanner] Found library item with inode matching one of "${itemFileInos.join(',')}" at path "${existingLibraryItem.path}"`) return existingLibraryItem } + +async function findLibraryItemByItemToMetadata(fullPath, isSingleMedia) { + if (isSingleMedia) return null + const metadataText = await fileUtils.readTextFile(Path.join(fullPath, 'metadata.json')) + if (!metadataText) return null + const abMetadata = abmetadataGenerator.parseJson(metadataText) || {} + // check if metadata id exists in the database + const existingLibraryItem = await Database.libraryItemModel.getExpandedById(abMetadata.absId) + if (existingLibraryItem) Logger.debug(`[LibraryScanner] Found library item with metadata id matching one of "${abMetadata.absId}" at path "${existingLibraryItem.path}"`) + return existingLibraryItem +} diff --git a/server/scanner/PodcastScanner.js b/server/scanner/PodcastScanner.js index c9569c3a..d2ccf334 100644 --- a/server/scanner/PodcastScanner.js +++ b/server/scanner/PodcastScanner.js @@ -421,6 +421,7 @@ class PodcastScanner { const metadataFilePath = Path.join(metadataPath, `metadata.${global.ServerSettings.metadataFileFormat}`) const jsonObject = { + absId: libraryItem.id, tags: libraryItem.media.tags || [], title: libraryItem.media.title, author: libraryItem.media.author,