mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-11-03 19:07:00 -05:00 
			
		
		
		
	Scanner update check for mismatched inode and update
This commit is contained in:
		
							parent
							
								
									d753683090
								
							
						
					
					
						commit
						4e45ff83c6
					
				@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "audiobookshelf-client",
 | 
			
		||||
  "version": "1.3.1",
 | 
			
		||||
  "version": "1.3.2",
 | 
			
		||||
  "description": "Audiobook manager and player",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "audiobookshelf",
 | 
			
		||||
  "version": "1.3.1",
 | 
			
		||||
  "version": "1.3.2",
 | 
			
		||||
  "description": "Self-hosted audiobook server for managing and playing audiobooks",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
 | 
			
		||||
@ -60,10 +60,59 @@ class Scanner {
 | 
			
		||||
    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) {
 | 
			
		||||
    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) {
 | 
			
		||||
 | 
			
		||||
      // TEMP: Check if is older audiobook and needs force rescan
 | 
			
		||||
@ -158,7 +207,7 @@ class Scanner {
 | 
			
		||||
        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
 | 
			
		||||
      if (existingAudiobook.checkUpdateMissingParts()) {
 | 
			
		||||
@ -177,12 +226,14 @@ class Scanner {
 | 
			
		||||
        hasUpdates = true
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // If audiobook was missing before, it is now found
 | 
			
		||||
      if (existingAudiobook.isMissing) {
 | 
			
		||||
        existingAudiobook.isMissing = false
 | 
			
		||||
        hasUpdates = true
 | 
			
		||||
        Logger.info(`[Scanner] "${existingAudiobook.title}" was missing but now it is found`)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Save changes and notify users
 | 
			
		||||
      if (hasUpdates) {
 | 
			
		||||
        existingAudiobook.setChapters()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -105,23 +105,26 @@ class Audiobook {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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() {
 | 
			
		||||
    return this.otherFiles.filter(file => file.filetype === 'ebook')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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() {
 | 
			
		||||
    return !!(this.audioFiles || []).find(af => af.embeddedCoverArt)
 | 
			
		||||
    return !!this._audioFiles.find(af => af.embeddedCoverArt)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get hasDescriptionTextFile() {
 | 
			
		||||
    return !!(this.otherFiles || []).find(of => of.filename === 'desc.txt')
 | 
			
		||||
    return !!this._otherFiles.find(of => of.filename === 'desc.txt')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bookToJSON() {
 | 
			
		||||
@ -148,8 +151,8 @@ class Audiobook {
 | 
			
		||||
      tags: this.tags,
 | 
			
		||||
      book: this.bookToJSON(),
 | 
			
		||||
      tracks: this.tracksToJSON(),
 | 
			
		||||
      audioFiles: (this.audioFiles || []).map(audioFile => audioFile.toJSON()),
 | 
			
		||||
      otherFiles: (this.otherFiles || []).map(otherFile => otherFile.toJSON()),
 | 
			
		||||
      audioFiles: this._audioFiles.map(audioFile => audioFile.toJSON()),
 | 
			
		||||
      otherFiles: this._otherFiles.map(otherFile => otherFile.toJSON()),
 | 
			
		||||
      chapters: this.chapters || [],
 | 
			
		||||
      isMissing: !!this.isMissing
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user