mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Fix:Scanner smart re-order
This commit is contained in:
parent
411183e4b4
commit
e5f8be5b24
@ -120,6 +120,7 @@ class FolderWatcher extends EventEmitter {
|
||||
|
||||
onRename(libraryId, pathFrom, pathTo) {
|
||||
Logger.debug(`[Watcher] Rename ${pathFrom} => ${pathTo}`)
|
||||
this.addFileUpdate(libraryId, pathFrom, 'renamed')
|
||||
this.addFileUpdate(libraryId, pathTo, 'renamed')
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,6 @@ class AudioFileScanner {
|
||||
return nodupes
|
||||
}
|
||||
|
||||
// Must be all audiofiles in audiobook
|
||||
runSmartTrackOrder(audiobook, audioFiles) {
|
||||
var discsFromFilename = []
|
||||
var tracksFromFilename = []
|
||||
@ -159,7 +158,12 @@ class AudioFileScanner {
|
||||
|
||||
for (let i = 0; i < audioFiles.length; i++) {
|
||||
audioFiles[i].index = i + 1
|
||||
audiobook.addAudioFile(audioFiles[i])
|
||||
var existingAF = audiobook.getAudioFileByIno(audioFiles[i].ino)
|
||||
if (existingAF) {
|
||||
audiobook.updateAudioFile(audioFiles[i])
|
||||
} else {
|
||||
audiobook.addAudioFile(audioFiles[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,43 +176,34 @@ class AudioFileScanner {
|
||||
libraryScan.addLog(LogLevel.DEBUG, `Book "${bookScanData.path}" Audio file scan took ${audioScanResult.elapsed}ms for ${audioScanResult.audioFiles.length} with average time of ${audioScanResult.averageScanDuration}ms`)
|
||||
}
|
||||
|
||||
var numExistingAudioFilesToInclude = audiobook.audioFilesToInclude.filter(af => !audioScanResult.audioFiles.find(_af => _af.ino === af.ino)).length
|
||||
var totalAudioFilesToInclude = numExistingAudioFilesToInclude + audioScanResult.audioFiles.length
|
||||
var totalAudioFilesToInclude = audioScanResult.audioFiles.length
|
||||
var newAudioFiles = audioScanResult.audioFiles.filter(af => {
|
||||
return !audiobook.audioFilesToInclude.find(_af => _af.ino === af.ino)
|
||||
})
|
||||
|
||||
if (numExistingAudioFilesToInclude <= 0) { // SMART TRACK ORDER for New or empty audiobooks
|
||||
this.runSmartTrackOrder(audiobook, audioScanResult.audioFiles)
|
||||
hasUpdated = true
|
||||
if (newAudioFiles.length) {
|
||||
// Single Track Audiobooks
|
||||
if (totalAudioFilesToInclude === 1) {
|
||||
var af = audioScanResult.audioFiles[0]
|
||||
af.index = 1
|
||||
audiobook.addAudioFile(af)
|
||||
hasUpdated = true
|
||||
} else {
|
||||
this.runSmartTrackOrder(audiobook, audioScanResult.audioFiles)
|
||||
hasUpdated = true
|
||||
}
|
||||
} else {
|
||||
// validate & add/update audio files to existing audiobook
|
||||
for (let i = 0; i < audioScanResult.audioFiles.length; i++) {
|
||||
var newAF = audioScanResult.audioFiles[i]
|
||||
var existingAF = audiobook.getAudioFileByIno(newAF.ino)
|
||||
|
||||
var trackIndex = null
|
||||
if (totalAudioFilesToInclude === 1) { // Single track audiobooks
|
||||
trackIndex = 1
|
||||
} else if (existingAF && existingAF.manuallyVerified) { // manually verified audio files use existing index
|
||||
trackIndex = existingAF.index
|
||||
} else {
|
||||
trackIndex = newAF.validateTrackIndex()
|
||||
}
|
||||
|
||||
if (trackIndex !== null) {
|
||||
if (audiobook.checkHasTrackNum(trackIndex, newAF.ino)) {
|
||||
newAF.setDuplicateTrackNumber(trackIndex)
|
||||
} else {
|
||||
newAF.index = trackIndex
|
||||
}
|
||||
}
|
||||
Logger.debug(`[AudioFileScanner] No audio track re-order required`)
|
||||
// Only update metadata not index
|
||||
audioScanResult.audioFiles.forEach((af) => {
|
||||
var existingAF = audiobook.getAudioFileByIno(af.ino)
|
||||
if (existingAF) {
|
||||
if (audiobook.updateAudioFile(newAF)) {
|
||||
af.index = existingAF.index
|
||||
if (audiobook.updateAudioFile(af)) {
|
||||
hasUpdated = true
|
||||
}
|
||||
} else {
|
||||
audiobook.addAudioFile(newAF)
|
||||
hasUpdated = true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Set book details from audio file ID3 tags, optional prefer
|
||||
|
@ -322,7 +322,7 @@ class Scanner {
|
||||
}
|
||||
|
||||
async rescanAudiobook(audiobookCheckData, libraryScan) {
|
||||
const { newAudioFileData, newOtherFileData, audiobook, bookScanData, updated, existingAudioFileData, existingOtherFileData } = audiobookCheckData
|
||||
const { newAudioFileData, audioFilesRemoved, newOtherFileData, audiobook, bookScanData, updated, existingAudioFileData, existingOtherFileData } = audiobookCheckData
|
||||
libraryScan.addLog(LogLevel.DEBUG, `Library "${libraryScan.libraryName}" Re-scanning "${audiobook.path}"`)
|
||||
var hasUpdated = updated
|
||||
|
||||
@ -342,7 +342,7 @@ class Scanner {
|
||||
}
|
||||
}
|
||||
// Scan new audio files
|
||||
if (newAudioFileData.length) {
|
||||
if (newAudioFileData.length || audioFilesRemoved.length) {
|
||||
if (await AudioFileScanner.scanAudioFiles(newAudioFileData, bookScanData, audiobook, libraryScan.preferAudioMetadata, libraryScan)) {
|
||||
hasUpdated = true
|
||||
}
|
||||
@ -459,11 +459,38 @@ class Scanner {
|
||||
async scanFolderUpdates(library, folder, fileUpdateBookGroup) {
|
||||
Logger.debug(`[Scanner] Scanning file update groups in folder "${folder.id}" of library "${library.name}"`)
|
||||
|
||||
// First pass - Remove files in parent dirs of audiobooks and remap the fileupdate group
|
||||
// Test Case: Moving audio files from audiobook folder to author folder should trigger a re-scan of audiobook
|
||||
var updateGroup = { ...fileUpdateBookGroup }
|
||||
for (const bookDir in updateGroup) {
|
||||
var bookDirNestedFiles = fileUpdateBookGroup[bookDir].filter(b => b.includes('/'))
|
||||
if (!bookDirNestedFiles.length) continue;
|
||||
|
||||
var firstNest = bookDirNestedFiles[0].split('/').shift()
|
||||
var altDir = `${bookDir}/${firstNest}`
|
||||
|
||||
var fullPath = Path.posix.join(folder.fullPath.replace(/\\/g, '/'), bookDir)
|
||||
var childAudiobook = this.db.audiobooks.find(ab => ab.fullPath !== fullPath && ab.fullPath.startsWith(fullPath))
|
||||
if (!childAudiobook) {
|
||||
continue;
|
||||
}
|
||||
var altFullPath = Path.posix.join(folder.fullPath.replace(/\\/g, '/'), altDir)
|
||||
var altChildAudiobook = this.db.audiobooks.find(ab => ab.fullPath !== altFullPath && ab.fullPath.startsWith(altFullPath))
|
||||
if (altChildAudiobook) {
|
||||
continue;
|
||||
}
|
||||
|
||||
delete fileUpdateBookGroup[bookDir]
|
||||
fileUpdateBookGroup[altDir] = bookDirNestedFiles.map((f) => f.split('/').slice(1).join('/'))
|
||||
Logger.warn(`[Scanner] Some files were modified in a parent directory of an audiobook "${childAudiobook.title}" - ignoring`)
|
||||
}
|
||||
|
||||
// Second pass: Check for new/updated/removed audiobooks
|
||||
var bookGroupingResults = {}
|
||||
for (const bookDir in fileUpdateBookGroup) {
|
||||
var fullPath = Path.posix.join(folder.fullPath.replace(/\\/g, '/'), bookDir)
|
||||
|
||||
// Check if book dir group is already an audiobook or in a subdir of an audiobook
|
||||
// Check if book dir group is already an audiobook
|
||||
var existingAudiobook = this.db.audiobooks.find(ab => fullPath.startsWith(ab.fullPath))
|
||||
if (existingAudiobook) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user