Skip to content

Commit

Permalink
Update new library scanner to check for cover images and ebooks
Browse files Browse the repository at this point in the history
  • Loading branch information
advplyr committed Aug 28, 2023
1 parent 2c8448d commit f8f94f2
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 6 deletions.
3 changes: 3 additions & 0 deletions server/Database.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ class Database {
// Cached library filter data
this.libraryFilterData = {}

/** @type {import('./objects/settings/ServerSettings')} */
this.serverSettings = null
/** @type {import('./objects/settings/NotificationSettings')} */
this.notificationSettings = null
/** @type {import('./objects/settings/EmailSettings')} */
this.emailSettings = null
}

Expand Down
38 changes: 34 additions & 4 deletions server/scanner/LibraryItemScanData.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ class LibraryItemScanData {
return this.libraryFiles.filter(lf => globals.SupportedAudioTypes.includes(lf.metadata.ext?.slice(1).toLowerCase() || ''))
}

/** @type {LibraryItem.LibraryFileObject[]} */
get imageLibraryFiles() {
return this.libraryFiles.filter(lf => globals.SupportedImageTypes.includes(lf.metadata.ext?.slice(1).toLowerCase() || ''))
}

/** @type {LibraryItem.LibraryFileObject[]} */
get ebookLibraryFiles() {
return this.libraryFiles.filter(lf => globals.SupportedEbookTypes.includes(lf.metadata.ext?.slice(1).toLowerCase() || ''))
}

/**
*
* @param {LibraryItem} existingLibraryItem
Expand Down Expand Up @@ -124,7 +134,7 @@ class LibraryItemScanData {
}

if (!matchingLibraryFile) { // Library file removed
libraryScan.addLog(LogLevel.INFO, `Library file "${existingLibraryFile.metadata.path}" was removed from library item "${existingLibraryItem.path}"`)
libraryScan.addLog(LogLevel.INFO, `Library file "${existingLibraryFile.metadata.path}" was removed from library item "${existingLibraryItem.relPath}"`)
this.libraryFilesRemoved.push(existingLibraryFile)
existingLibraryItem.libraryFiles = existingLibraryItem.libraryFiles.filter(lf => lf !== existingLibraryFile)
this.hasChanges = true
Expand All @@ -141,7 +151,11 @@ class LibraryItemScanData {
if (libraryFilesAdded.length) {
this.hasChanges = true
for (const libraryFile of libraryFilesAdded) {
libraryScan.addLog(LogLevel.INFO, `New library file found with path "${libraryFile.metadata.path}" for library item "${existingLibraryItem.path}"`)
libraryScan.addLog(LogLevel.INFO, `New library file found with path "${libraryFile.metadata.path}" for library item "${existingLibraryItem.relPath}"`)
if (libraryFile.isEBookFile) {
// Set all new ebook files as supplementary
libraryFile.isSupplementary = true
}
existingLibraryItem.libraryFiles.push(libraryFile.toJSON())
}
}
Expand All @@ -155,14 +169,15 @@ class LibraryItemScanData {
existingLibraryItem.lastScan = Date.now()
existingLibraryItem.lastScanVersion = packageJson.version

libraryScan.addLog(LogLevel.DEBUG, `Library item "${existingLibraryItem.path}" changed: [${existingLibraryItem.changed()?.join(',') || ''}]`)
libraryScan.addLog(LogLevel.DEBUG, `Library item "${existingLibraryItem.relPath}" changed: [${existingLibraryItem.changed()?.join(',') || ''}]`)
libraryScan.resultsUpdated++

if (this.hasLibraryFileChanges) {
existingLibraryItem.changed('libraryFiles', true)
}
await existingLibraryItem.save()
} else {
libraryScan.addLog(LogLevel.DEBUG, `Library item "${existingLibraryItem.path}" is up-to-date`)
libraryScan.addLog(LogLevel.DEBUG, `Library item "${existingLibraryItem.relPath}" is up-to-date`)
}
}

Expand Down Expand Up @@ -219,5 +234,20 @@ class LibraryItemScanData {
// Fallback to check inode value
return this.audioLibraryFilesRemoved.some(af => af.ino === existingAudioFile.ino)
}

/**
* Check if existing ebook file on Book was removed
* @param {import('../models/Book').EBookFileObject} ebookFile
* @returns {boolean} true if ebook file was removed
*/
checkEbookFileRemoved(ebookFile) {
if (!this.ebookLibraryFiles.length) return true

if (this.ebookLibraryFiles.some(lf => lf.metadata.path === ebookFile.metadata.path)) {
return false
}

return !this.ebookLibraryFiles.some(lf => lf.ino === ebookFile.ino)
}
}
module.exports = LibraryItemScanData
3 changes: 2 additions & 1 deletion server/scanner/LibraryScan.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class LibraryScan {
constructor() {
this.id = null
this.type = null
/** @type {import('../objects/Library')} */
this.library = null
this.verbose = false

Expand Down Expand Up @@ -117,7 +118,7 @@ class LibraryScan {
}

if (this.verbose) {
Logger.debug(`[LibraryScan] "${this.libraryName}":`, args)
Logger.debug(`[LibraryScan] "${this.libraryName}":`, ...args)
}
this.logs.push(logObj)
}
Expand Down
76 changes: 75 additions & 1 deletion server/scanner/LibraryScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const fs = require('../libs/fsExtra')
const fileUtils = require('../utils/fileUtils')
const scanUtils = require('../utils/scandir')
const { ScanResult, LogLevel } = require('../utils/constants')
const globals = require('../utils/globals')
const AudioFileScanner = require('./AudioFileScanner')
const ScanOptions = require('./ScanOptions')
const LibraryScan = require('./LibraryScan')
Expand Down Expand Up @@ -128,11 +129,13 @@ class LibraryScanner {
libraryScan.addLog(LogLevel.INFO, `Library item "${existingLibraryItem.relPath}" folder exists but has no episodes`)
} else {
libraryScan.addLog(LogLevel.WARN, `Library Item "${existingLibraryItem.path}" (inode: ${existingLibraryItem.ino}) is missing`)
libraryScan.resultsMissing++
if (!existingLibraryItem.isMissing) {
libraryItemIdsMissing.push(existingLibraryItem.id)
}
}
} else {
libraryItemDataFound = libraryItemDataFound.filter(lidf => lidf !== libraryItemData)
await libraryItemData.checkLibraryItemData(existingLibraryItem, libraryScan)
if (libraryItemData.hasLibraryFileChanges || libraryItemData.hasPathChange) {
await this.rescanLibraryItem(existingLibraryItem, libraryItemData, libraryScan)
Expand All @@ -153,6 +156,11 @@ class LibraryScanner {
}
})
}

// Add new library items
if (libraryItemDataFound.length) {

}
}

/**
Expand Down Expand Up @@ -230,7 +238,6 @@ class LibraryScanner {
* @param {LibraryScan} libraryScan
*/
async rescanLibraryItem(existingLibraryItem, libraryItemData, libraryScan) {

if (existingLibraryItem.mediaType === 'book') {
/** @type {Book} */
const media = await existingLibraryItem.getMedia({
Expand Down Expand Up @@ -309,10 +316,77 @@ class LibraryScanner {
media.changed('audioFiles', true)
}

// Check if cover was removed
if (media.coverPath && !libraryItemData.imageLibraryFiles.some(lf => lf.metadata.path === media.coverPath)) {
media.coverPath = null
hasMediaChanges = true
}

// Check if cover is not set and image files were found
if (!media.coverPath && libraryItemData.imageLibraryFiles.length) {
// Prefer using a cover image with the name "cover" otherwise use the first image
const coverMatch = libraryItemData.imageLibraryFiles.find(iFile => /\/cover\.[^.\/]*$/.test(iFile.metadata.path))
media.coverPath = coverMatch?.metadata.path || libraryItemData.imageLibraryFiles[0].metadata.path
hasMediaChanges = true
}

// Check if ebook was removed
if (media.ebookFile && (libraryScan.library.settings.audiobooksOnly || libraryItemData.checkEbookFileRemoved(media.ebookFile))) {
media.ebookFile = null
hasMediaChanges = true
}

// Check if ebook is not set and ebooks were found
if (!media.ebookFile && !libraryScan.library.settings.audiobooksOnly && libraryItemData.ebookLibraryFiles.length) {
// Prefer to use an epub ebook then fallback to the first ebook found
let ebookLibraryFile = libraryItemData.ebookLibraryFiles.find(lf => lf.metadata.ext.slice(1).toLowerCase() === 'epub')
if (!ebookLibraryFile) ebookLibraryFile = libraryItemData.ebookLibraryFiles[0]
// Ebook file is the same as library file except for additional `ebookFormat`
ebookLibraryFile.ebookFormat = ebookLibraryFile.metadata.ext.slice(1).toLowerCase()
media.ebookFile = ebookLibraryFile
media.changed('ebookFile', true)
hasMediaChanges = true
}

// Check/update the isSupplementary flag on libraryFiles for the LibraryItem
let libraryItemUpdated = false
for (const libraryFile of existingLibraryItem.libraryFiles) {
if (globals.SupportedEbookTypes.includes(libraryFile.metadata.ext.slice(1).toLowerCase())) {
if (media.ebookFile && libraryFile.ino === media.ebookFile.ino) {
if (libraryFile.isSupplementary !== false) {
libraryFile.isSupplementary = false
libraryItemUpdated = true
}
} else if (libraryFile.isSupplementary !== true) {
libraryFile.isSupplementary = true
libraryItemUpdated = true
}
}
}
if (libraryItemUpdated) {
existingLibraryItem.changed('libraryFiles', true)
await existingLibraryItem.save()
}

// TODO: Update chapters & metadata

if (hasMediaChanges) {
await media.save()
}
}
}

/**
*
* @param {LibraryItemScanData} libraryItemData
* @param {LibraryScan} libraryScan
*/
async scanNewLibraryItem(libraryItemData, libraryScan) {

if (libraryScan.libraryMediaType === 'book') {
let scannedAudioFiles = await AudioFileScanner.executeMediaFileScans(libraryScan.libraryMediaType, libraryItemData, libraryItemData.audioLibraryFiles)
// TODO: Create new book
}
}
}
module.exports = LibraryScanner

0 comments on commit f8f94f2

Please sign in to comment.