Skip to content

Commit

Permalink
Remove force re-scan and old scanner logic
Browse files Browse the repository at this point in the history
  • Loading branch information
advplyr committed Sep 4, 2023
1 parent b9da3fa commit b1c0783
Show file tree
Hide file tree
Showing 14 changed files with 146 additions and 689 deletions.
4 changes: 0 additions & 4 deletions client/components/tables/library/LibrariesTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
<ui-btn @click="clickAddLibrary">{{ $strings.ButtonAddYourFirstLibrary }}</ui-btn>
</div>

<p v-if="libraries.length" class="text-xs mt-4 text-gray-200">
*<strong>{{ $strings.ButtonForceReScan }}</strong> {{ $strings.MessageForceReScanDescription }}
</p>

<p v-if="libraries.length && libraries.some((li) => li.mediaType === 'book')" class="text-xs mt-4 text-gray-200">
**<strong>{{ $strings.ButtonMatchBooks }}</strong> {{ $strings.MessageMatchBooksDescription }}
</p>
Expand Down
25 changes: 0 additions & 25 deletions client/components/tables/library/LibraryItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,6 @@ export default {
text: this.$strings.ButtonScan,
action: 'scan',
value: 'scan'
},
{
text: this.$strings.ButtonForceReScan,
action: 'force-scan',
value: 'force-scan'
}
]
if (this.isBookLibrary) {
Expand Down Expand Up @@ -137,26 +132,6 @@ export default {
this.$toast.error(this.$strings.ToastLibraryScanFailedToStart)
})
},
forceScan() {
const payload = {
message: this.$strings.MessageConfirmForceReScan,
callback: (confirmed) => {
if (confirmed) {
this.$store
.dispatch('libraries/requestLibraryScan', { libraryId: this.library.id, force: 1 })
.then(() => {
this.$toast.success(this.$strings.ToastLibraryScanStarted)
})
.catch((error) => {
console.error('Failed to start scan', error)
this.$toast.error(this.$strings.ToastLibraryScanFailedToStart)
})
}
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
deleteClick() {
const payload = {
message: this.$getString('MessageConfirmDeleteLibrary', [this.library.name]),
Expand Down
5 changes: 1 addition & 4 deletions server/controllers/LibraryController.js
Original file line number Diff line number Diff line change
Expand Up @@ -974,12 +974,9 @@ class LibraryController {
Logger.error(`[LibraryController] Non-root user attempted to scan library`, req.user)
return res.sendStatus(403)
}
const options = {
forceRescan: req.query.force == 1
}
res.sendStatus(200)

await LibraryScanner.scan(req.library, options)
await LibraryScanner.scan(req.library)

await Database.resetLibraryIssuesFilterData(req.library.id)
Logger.info('[LibraryController] Scan complete')
Expand Down
3 changes: 2 additions & 1 deletion server/controllers/LibraryItemController.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const { reqSupportsWebp } = require('../utils/index')
const { ScanResult } = require('../utils/constants')
const { getAudioMimeTypeFromExtname } = require('../utils/fileUtils')
const LibraryItemScanner = require('../scanner/LibraryItemScanner')
const AudioFileScanner = require('../scanner/AudioFileScanner')

class LibraryItemController {
constructor() { }
Expand Down Expand Up @@ -555,7 +556,7 @@ class LibraryItemController {
return res.sendStatus(404)
}

const ffprobeData = await this.scanner.probeAudioFile(audioFile)
const ffprobeData = await AudioFileScanner.probeAudioFile(audioFile)
res.json(ffprobeData)
}

Expand Down
236 changes: 37 additions & 199 deletions server/objects/LibraryItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,183 +338,6 @@ class LibraryItem {
return hasUpdated
}

// Data pulled from scandir during a scan, check it with current data
checkScanData(dataFound) {
let hasUpdated = false

if (this.isMissing) {
// Item no longer missing
this.isMissing = false
hasUpdated = true
}

if (dataFound.isFile !== this.isFile && dataFound.isFile !== undefined) {
Logger.info(`[LibraryItem] Check scan item isFile toggled from ${this.isFile} => ${dataFound.isFile}`)
this.isFile = dataFound.isFile
hasUpdated = true
}

if (dataFound.ino !== this.ino) {
Logger.warn(`[LibraryItem] Check scan item changed inode "${this.ino}" -> "${dataFound.ino}"`)
this.ino = dataFound.ino
hasUpdated = true
}

if (dataFound.folderId !== this.folderId) {
Logger.warn(`[LibraryItem] Check scan item changed folder ${this.folderId} -> ${dataFound.folderId}`)
this.folderId = dataFound.folderId
hasUpdated = true
}

if (dataFound.path !== this.path) {
Logger.warn(`[LibraryItem] Check scan item changed path "${this.path}" -> "${dataFound.path}" (inode ${this.ino})`)
this.path = dataFound.path
this.relPath = dataFound.relPath
hasUpdated = true
}

['mtimeMs', 'ctimeMs', 'birthtimeMs'].forEach((key) => {
if (dataFound[key] != this[key]) {
this[key] = dataFound[key] || 0
hasUpdated = true
}
})

const newLibraryFiles = []
const existingLibraryFiles = []

dataFound.libraryFiles.forEach((lf) => {
const fileFoundCheck = this.checkFileFound(lf, true)
if (fileFoundCheck === null) {
newLibraryFiles.push(lf)
} else if (fileFoundCheck && lf.metadata.format !== 'abs' && lf.metadata.filename !== 'metadata.json') { // Ignore abs file updates
hasUpdated = true
existingLibraryFiles.push(lf)
} else {
existingLibraryFiles.push(lf)
}
})

const filesRemoved = []

// Remove files not found (inodes will all be up to date at this point)
this.libraryFiles = this.libraryFiles.filter(lf => {
if (!dataFound.libraryFiles.find(_lf => _lf.ino === lf.ino)) {
// Check if removing cover path
if (lf.metadata.path === this.media.coverPath) {
Logger.debug(`[LibraryItem] "${this.media.metadata.title}" check scan cover removed`)
this.media.updateCover('')
}
filesRemoved.push(lf.toJSON())
this.media.removeFileWithInode(lf.ino)
return false
}
return true
})
if (filesRemoved.length) {
if (this.media.mediaType === 'book') {
this.media.checkUpdateMissingTracks()
}
hasUpdated = true
}

// Add library files to library item
if (newLibraryFiles.length) {
newLibraryFiles.forEach((lf) => this.libraryFiles.push(lf.clone()))
hasUpdated = true
}

// Check if invalid
this.isInvalid = !this.media.hasMediaEntities

// If cover path is in item folder, make sure libraryFile exists for it
if (this.media.coverPath && this.media.coverPath.startsWith(this.path)) {
const lf = this.libraryFiles.find(lf => lf.metadata.path === this.media.coverPath)
if (!lf) {
Logger.warn(`[LibraryItem] Invalid cover path - library file dne "${this.media.coverPath}"`)
this.media.updateCover('')
hasUpdated = true
}
}

if (hasUpdated) {
this.setLastScan()
}

return {
updated: hasUpdated,
newLibraryFiles,
filesRemoved,
existingLibraryFiles // Existing file data may get re-scanned if forceRescan is set
}
}

// Set metadata from files
async syncFiles(preferOpfMetadata, librarySettings) {
let hasUpdated = false

if (this.isBook) {
// Add/update ebook files (ebooks that were removed are removed in checkScanData)
if (librarySettings.audiobooksOnly) {
hasUpdated = this.media.ebookFile
if (hasUpdated) {
// If library was set to audiobooks only then set primary ebook as supplementary
Logger.info(`[LibraryItem] Library is audiobooks only so setting ebook "${this.media.ebookFile.metadata.filename}" as supplementary`)
}
this.setPrimaryEbook(null)
} else if (this.media.ebookFile) {
const matchingLibraryFile = this.libraryFiles.find(lf => lf.ino === this.media.ebookFile.ino)
if (matchingLibraryFile && this.media.ebookFile.updateFromLibraryFile(matchingLibraryFile)) {
hasUpdated = true
}
// Set any other ebook files as supplementary
const suppEbookLibraryFiles = this.libraryFiles.filter(lf => lf.isEBookFile && !lf.isSupplementary && this.media.ebookFile.ino !== lf.ino)
if (suppEbookLibraryFiles.length) {
for (const libraryFile of suppEbookLibraryFiles) {
libraryFile.isSupplementary = true
}
hasUpdated = true
}
} else {
const ebookLibraryFiles = this.libraryFiles.filter(lf => lf.isEBookFile && !lf.isSupplementary)

// Prefer epub ebook then fallback to first other ebook file
const ebookLibraryFile = ebookLibraryFiles.find(lf => lf.metadata.format === 'epub') || ebookLibraryFiles[0]
if (ebookLibraryFile) {
this.setPrimaryEbook(ebookLibraryFile)
hasUpdated = true
}
}
}

// Set cover image if not set
const imageFiles = this.libraryFiles.filter(lf => lf.fileType === 'image')
if (imageFiles.length && !this.media.coverPath) {
// attempt to find a file called cover.<ext> otherwise just fall back to the first image found
const coverMatch = imageFiles.find(iFile => /\/cover\.[^.\/]*$/.test(iFile.metadata.path))
if (coverMatch) {
this.media.coverPath = coverMatch.metadata.path
} else {
this.media.coverPath = imageFiles[0].metadata.path
}
Logger.info('[LibraryItem] Set media cover path', this.media.coverPath)
hasUpdated = true
}

// Parse metadata files
const textMetadataFiles = this.libraryFiles.filter(lf => lf.fileType === 'metadata' || lf.fileType === 'text')
if (textMetadataFiles.length) {
if (await this.media.syncMetadataFiles(textMetadataFiles, preferOpfMetadata)) {
hasUpdated = true
}
}

if (hasUpdated) {
this.updatedAt = Date.now()
}
return hasUpdated
}

searchQuery(query) {
query = cleanStringForSearch(query)
return this.media.searchQuery(query)
Expand Down Expand Up @@ -556,19 +379,27 @@ class LibraryItem {
return fs.writeFile(metadataFilePath, JSON.stringify(this.media.toJSONForMetadataFile(), null, 2)).then(async () => {
// Add metadata.json to libraryFiles array if it is new
let metadataLibraryFile = this.libraryFiles.find(lf => lf.metadata.path === filePathToPOSIX(metadataFilePath))
if (storeMetadataWithItem && !metadataLibraryFile) {
metadataLibraryFile = new LibraryFile()
await metadataLibraryFile.setDataFromPath(metadataFilePath, `metadata.json`)
this.libraryFiles.push(metadataLibraryFile)
} else if (storeMetadataWithItem) {
const fileTimestamps = await getFileTimestampsWithIno(metadataFilePath)
if (fileTimestamps) {
metadataLibraryFile.metadata.mtimeMs = fileTimestamps.mtimeMs
metadataLibraryFile.metadata.ctimeMs = fileTimestamps.ctimeMs
metadataLibraryFile.metadata.size = fileTimestamps.size
metadataLibraryFile.ino = fileTimestamps.ino
if (storeMetadataWithItem) {
if (!metadataLibraryFile) {
metadataLibraryFile = new LibraryFile()
await metadataLibraryFile.setDataFromPath(metadataFilePath, `metadata.json`)
this.libraryFiles.push(metadataLibraryFile)
} else {
const fileTimestamps = await getFileTimestampsWithIno(metadataFilePath)
if (fileTimestamps) {
metadataLibraryFile.metadata.mtimeMs = fileTimestamps.mtimeMs
metadataLibraryFile.metadata.ctimeMs = fileTimestamps.ctimeMs
metadataLibraryFile.metadata.size = fileTimestamps.size
metadataLibraryFile.ino = fileTimestamps.ino
}
}
const libraryItemDirTimestamps = await getFileTimestampsWithIno(this.path)
if (libraryItemDirTimestamps) {
this.mtimeMs = libraryItemDirTimestamps.mtimeMs
this.ctimeMs = libraryItemDirTimestamps.ctimeMs
}
}

Logger.debug(`[LibraryItem] Success saving abmetadata to "${metadataFilePath}"`)

return metadataLibraryFile
Expand All @@ -593,17 +424,24 @@ class LibraryItem {
}
// Add metadata.abs to libraryFiles array if it is new
let metadataLibraryFile = this.libraryFiles.find(lf => lf.metadata.path === filePathToPOSIX(metadataFilePath))
if (storeMetadataWithItem && !metadataLibraryFile) {
metadataLibraryFile = new LibraryFile()
await metadataLibraryFile.setDataFromPath(metadataFilePath, `metadata.abs`)
this.libraryFiles.push(metadataLibraryFile)
} else if (storeMetadataWithItem) {
const fileTimestamps = await getFileTimestampsWithIno(metadataFilePath)
if (fileTimestamps) {
metadataLibraryFile.metadata.mtimeMs = fileTimestamps.mtimeMs
metadataLibraryFile.metadata.ctimeMs = fileTimestamps.ctimeMs
metadataLibraryFile.metadata.size = fileTimestamps.size
metadataLibraryFile.ino = fileTimestamps.ino
if (storeMetadataWithItem) {
if (!metadataLibraryFile) {
metadataLibraryFile = new LibraryFile()
await metadataLibraryFile.setDataFromPath(metadataFilePath, `metadata.abs`)
this.libraryFiles.push(metadataLibraryFile)
} else {
const fileTimestamps = await getFileTimestampsWithIno(metadataFilePath)
if (fileTimestamps) {
metadataLibraryFile.metadata.mtimeMs = fileTimestamps.mtimeMs
metadataLibraryFile.metadata.ctimeMs = fileTimestamps.ctimeMs
metadataLibraryFile.metadata.size = fileTimestamps.size
metadataLibraryFile.ino = fileTimestamps.ino
}
}
const libraryItemDirTimestamps = await getFileTimestampsWithIno(this.path)
if (libraryItemDirTimestamps) {
this.mtimeMs = libraryItemDirTimestamps.mtimeMs
this.ctimeMs = libraryItemDirTimestamps.ctimeMs
}
}

Expand Down
2 changes: 1 addition & 1 deletion server/objects/files/AudioFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class AudioFile {
return !this.invalid && !this.exclude
}

// New scanner creates AudioFile from MediaFileScanner
// New scanner creates AudioFile from AudioFileScanner
setDataFromProbe(libraryFile, probeData) {
this.ino = libraryFile.ino || null

Expand Down
14 changes: 12 additions & 2 deletions server/scanner/AudioFileScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@ class AudioFileScanner {
const probeData = await prober.probe(libraryFile.metadata.path)

if (probeData.error) {
Logger.error(`[MediaFileScanner] ${probeData.error} : "${libraryFile.metadata.path}"`)
Logger.error(`[AudioFileScanner] ${probeData.error} : "${libraryFile.metadata.path}"`)
return null
}

if (!probeData.audioStream) {
Logger.error('[MediaFileScanner] Invalid audio file no audio stream')
Logger.error('[AudioFileScanner] Invalid audio file no audio stream')
return null
}

Expand Down Expand Up @@ -195,5 +195,15 @@ class AudioFileScanner {

return results
}

/**
*
* @param {AudioFile} audioFile
* @returns {object}
*/
probeAudioFile(audioFile) {
Logger.debug(`[AudioFileScanner] Running ffprobe for audio file at "${audioFile.metadata.path}"`)
return prober.rawProbe(audioFile.metadata.path)
}
}
module.exports = new AudioFileScanner()
Loading

0 comments on commit b1c0783

Please sign in to comment.