mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Scanner update check for mismatched inode and update
This commit is contained in:
		
							parent
							
								
									47c6c1aaad
								
							
						
					
					
						commit
						0db34dcab5
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "audiobookshelf-client",
 | 
					  "name": "audiobookshelf-client",
 | 
				
			||||||
  "version": "1.3.1",
 | 
					  "version": "1.3.2",
 | 
				
			||||||
  "description": "Audiobook manager and player",
 | 
					  "description": "Audiobook manager and player",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "audiobookshelf",
 | 
					  "name": "audiobookshelf",
 | 
				
			||||||
  "version": "1.3.1",
 | 
					  "version": "1.3.2",
 | 
				
			||||||
  "description": "Self-hosted audiobook server for managing and playing audiobooks",
 | 
					  "description": "Self-hosted audiobook server for managing and playing audiobooks",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 | 
				
			|||||||
@ -60,10 +60,59 @@ class Scanner {
 | 
				
			|||||||
    return audiobookDataAudioFiles.filter(abdFile => !!abdFile.ino)
 | 
					    return audiobookDataAudioFiles.filter(abdFile => !!abdFile.ino)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Only updates audio files with matching paths
 | 
				
			||||||
 | 
					  syncAudiobookInodeValues(audiobook, { audioFiles, otherFiles }) {
 | 
				
			||||||
 | 
					    var filesUpdated = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Sync audio files & audio tracks with updated inodes
 | 
				
			||||||
 | 
					    audiobook._audioFiles.forEach((audioFile) => {
 | 
				
			||||||
 | 
					      var matchingAudioFile = audioFiles.find(af => af.ino !== audioFile.ino && af.path === audioFile.path)
 | 
				
			||||||
 | 
					      if (matchingAudioFile) {
 | 
				
			||||||
 | 
					        // Audio Track should always have the same ino as the equivalent audio file (not all audio files have a track)
 | 
				
			||||||
 | 
					        var audioTrack = audiobook.tracks.find(t => t.ino === audioFile.ino)
 | 
				
			||||||
 | 
					        if (audioTrack) {
 | 
				
			||||||
 | 
					          Logger.debug(`[Scanner] Found audio file & track with mismatched inode "${audioFile.filename}" - updating it`)
 | 
				
			||||||
 | 
					          audioTrack.ino = matchingAudioFile.ino
 | 
				
			||||||
 | 
					          filesUpdated++
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          Logger.debug(`[Scanner] Found audio file with mismatched inode "${audioFile.filename}" - updating it`)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        audioFile.ino = matchingAudioFile.ino
 | 
				
			||||||
 | 
					        filesUpdated++
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Sync other files with updated inodes
 | 
				
			||||||
 | 
					    audiobook._otherFiles.forEach((otherFile) => {
 | 
				
			||||||
 | 
					      var matchingOtherFile = otherFiles.find(of => of.ino !== otherFile.ino && of.path === otherFile.path)
 | 
				
			||||||
 | 
					      if (matchingOtherFile) {
 | 
				
			||||||
 | 
					        Logger.debug(`[Scanner] Found other file with mismatched inode "${otherFile.filename}" - updating it`)
 | 
				
			||||||
 | 
					        otherFile.ino = matchingOtherFile.ino
 | 
				
			||||||
 | 
					        filesUpdated++
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return filesUpdated
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async scanAudiobookData(audiobookData, forceAudioFileScan = false) {
 | 
					  async scanAudiobookData(audiobookData, forceAudioFileScan = false) {
 | 
				
			||||||
    var existingAudiobook = this.audiobooks.find(a => a.ino === audiobookData.ino)
 | 
					    var existingAudiobook = this.audiobooks.find(a => a.ino === audiobookData.ino)
 | 
				
			||||||
    // Logger.debug(`[Scanner] Scanning "${audiobookData.title}" (${audiobookData.ino}) - ${!!existingAudiobook ? 'Exists' : 'New'}`)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // inode value may change when using shared drives, update inode if matching path is found
 | 
				
			||||||
 | 
					    // Note: inode will not change on rename
 | 
				
			||||||
 | 
					    var hasUpdatedIno = false
 | 
				
			||||||
 | 
					    if (!existingAudiobook) {
 | 
				
			||||||
 | 
					      // check an audiobook exists with matching path, then update inodes
 | 
				
			||||||
 | 
					      existingAudiobook = this.audiobooks.find(a => a.path === audiobookData.path)
 | 
				
			||||||
 | 
					      if (existingAudiobook) {
 | 
				
			||||||
 | 
					        hasUpdatedIno = true
 | 
				
			||||||
 | 
					        var filesUpdated = this.syncAudiobookInodeValues(existingAudiobook, audiobookData)
 | 
				
			||||||
 | 
					        Logger.info(`[Scanner] Updating inode value for "${existingAudiobook.title}" - ${filesUpdated} files updated`)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Logger.debug(`[Scanner] Scanning "${audiobookData.title}" (${audiobookData.ino}) - ${!!existingAudiobook ? 'Exists' : 'New'}`)
 | 
				
			||||||
    if (existingAudiobook) {
 | 
					    if (existingAudiobook) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // TEMP: Check if is older audiobook and needs force rescan
 | 
					      // TEMP: Check if is older audiobook and needs force rescan
 | 
				
			||||||
@ -158,7 +207,7 @@ class Scanner {
 | 
				
			|||||||
        return ScanResult.REMOVED
 | 
					        return ScanResult.REMOVED
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      var hasUpdates = removedAudioFiles.length || removedAudioTracks.length || newAudioFiles.length || hasUpdatedAudioFiles
 | 
					      var hasUpdates = hasUpdatedIno || removedAudioFiles.length || removedAudioTracks.length || newAudioFiles.length || hasUpdatedAudioFiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Check that audio tracks are in sequential order with no gaps
 | 
					      // Check that audio tracks are in sequential order with no gaps
 | 
				
			||||||
      if (existingAudiobook.checkUpdateMissingParts()) {
 | 
					      if (existingAudiobook.checkUpdateMissingParts()) {
 | 
				
			||||||
@ -177,12 +226,14 @@ class Scanner {
 | 
				
			|||||||
        hasUpdates = true
 | 
					        hasUpdates = true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // If audiobook was missing before, it is now found
 | 
				
			||||||
      if (existingAudiobook.isMissing) {
 | 
					      if (existingAudiobook.isMissing) {
 | 
				
			||||||
        existingAudiobook.isMissing = false
 | 
					        existingAudiobook.isMissing = false
 | 
				
			||||||
        hasUpdates = true
 | 
					        hasUpdates = true
 | 
				
			||||||
        Logger.info(`[Scanner] "${existingAudiobook.title}" was missing but now it is found`)
 | 
					        Logger.info(`[Scanner] "${existingAudiobook.title}" was missing but now it is found`)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Save changes and notify users
 | 
				
			||||||
      if (hasUpdates) {
 | 
					      if (hasUpdates) {
 | 
				
			||||||
        existingAudiobook.setChapters()
 | 
					        existingAudiobook.setChapters()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -105,23 +105,26 @@ class Audiobook {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get invalidParts() {
 | 
					  get invalidParts() {
 | 
				
			||||||
    return (this.audioFiles || []).filter(af => af.invalid).map(af => ({ filename: af.filename, error: af.error || 'Unknown Error' }))
 | 
					    return this._audioFiles.filter(af => af.invalid).map(af => ({ filename: af.filename, error: af.error || 'Unknown Error' }))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get _audioFiles() { return this.audioFiles || [] }
 | 
				
			||||||
 | 
					  get _otherFiles() { return this.otherFiles || [] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get ebooks() {
 | 
					  get ebooks() {
 | 
				
			||||||
    return this.otherFiles.filter(file => file.filetype === 'ebook')
 | 
					    return this.otherFiles.filter(file => file.filetype === 'ebook')
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get hasMissingIno() {
 | 
					  get hasMissingIno() {
 | 
				
			||||||
    return !this.ino || (this.audioFiles || []).find(abf => !abf.ino) || (this.otherFiles || []).find(f => !f.ino) || (this.tracks || []).find(t => !t.ino)
 | 
					    return !this.ino || this._audioFiles.find(abf => !abf.ino) || this._otherFiles.find(f => !f.ino) || (this.tracks || []).find(t => !t.ino)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get hasEmbeddedCoverArt() {
 | 
					  get hasEmbeddedCoverArt() {
 | 
				
			||||||
    return !!(this.audioFiles || []).find(af => af.embeddedCoverArt)
 | 
					    return !!this._audioFiles.find(af => af.embeddedCoverArt)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get hasDescriptionTextFile() {
 | 
					  get hasDescriptionTextFile() {
 | 
				
			||||||
    return !!(this.otherFiles || []).find(of => of.filename === 'desc.txt')
 | 
					    return !!this._otherFiles.find(of => of.filename === 'desc.txt')
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bookToJSON() {
 | 
					  bookToJSON() {
 | 
				
			||||||
@ -148,8 +151,8 @@ class Audiobook {
 | 
				
			|||||||
      tags: this.tags,
 | 
					      tags: this.tags,
 | 
				
			||||||
      book: this.bookToJSON(),
 | 
					      book: this.bookToJSON(),
 | 
				
			||||||
      tracks: this.tracksToJSON(),
 | 
					      tracks: this.tracksToJSON(),
 | 
				
			||||||
      audioFiles: (this.audioFiles || []).map(audioFile => audioFile.toJSON()),
 | 
					      audioFiles: this._audioFiles.map(audioFile => audioFile.toJSON()),
 | 
				
			||||||
      otherFiles: (this.otherFiles || []).map(otherFile => otherFile.toJSON()),
 | 
					      otherFiles: this._otherFiles.map(otherFile => otherFile.toJSON()),
 | 
				
			||||||
      chapters: this.chapters || [],
 | 
					      chapters: this.chapters || [],
 | 
				
			||||||
      isMissing: !!this.isMissing
 | 
					      isMissing: !!this.isMissing
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user