audiobookshelf/server/Scanner.js

94 lines
3.3 KiB
JavaScript

const Logger = require('./Logger')
const BookFinder = require('./BookFinder')
const Audiobook = require('./Audiobook')
const audioFileScanner = require('./utils/audioFileScanner')
const { getAllAudiobookFiles } = require('./utils/scandir')
const { secondsToTimestamp } = require('./utils/fileUtils')
class Scanner {
constructor(AUDIOBOOK_PATH, METADATA_PATH, db, emitter) {
this.AudiobookPath = AUDIOBOOK_PATH
this.MetadataPath = METADATA_PATH
this.db = db
this.emitter = emitter
this.bookFinder = new BookFinder()
}
get audiobooks() {
return this.db.audiobooks
}
async scan() {
// console.log('Start scan audiobooks', this.audiobooks.map(a => a.fullPath).join(', '))
const scanStart = Date.now()
var audiobookDataFound = await getAllAudiobookFiles(this.AudiobookPath)
for (let i = 0; i < audiobookDataFound.length; i++) {
var audiobookData = audiobookDataFound[i]
if (!audiobookData.parts.length) {
Logger.error('No Valid Parts for Audiobook', audiobookData)
} else {
var existingAudiobook = this.audiobooks.find(a => a.fullPath === audiobookData.fullPath)
if (existingAudiobook) {
Logger.info('Audiobook already added', audiobookData.title)
// Todo: Update Audiobook here
} else {
// console.log('Audiobook not already there... add new audiobook', audiobookData.fullPath)
var audiobook = new Audiobook()
audiobook.setData(audiobookData)
await audioFileScanner.scanParts(audiobook, audiobookData.parts)
if (!audiobook.tracks.length) {
Logger.warn('Invalid audiobook, no valid tracks', audiobook.title)
} else {
Logger.info('Audiobook Scanned', audiobook.title, `(${audiobook.sizePretty}) [${audiobook.durationPretty}]`)
await this.db.insertAudiobook(audiobook)
this.emitter('audiobook_added', audiobook.toJSONMinified())
}
}
var progress = Math.round(100 * (i + 1) / audiobookDataFound.length)
this.emitter('scan_progress', {
total: audiobookDataFound.length,
done: i + 1,
progress
})
}
}
const scanElapsed = Math.floor((Date.now() - scanStart) / 1000)
Logger.info(`[SCANNER] Finished ${secondsToTimestamp(scanElapsed)}`)
}
async fetchMetadata(id, trackIndex = 0) {
var audiobook = this.audiobooks.find(a => a.id === id)
if (!audiobook) {
return false
}
var tracks = audiobook.tracks
var index = isNaN(trackIndex) ? 0 : Number(trackIndex)
var firstTrack = tracks[index]
var firstTrackFullPath = firstTrack.fullPath
var scanResult = await audioFileScanner.scan(firstTrackFullPath)
return scanResult
}
async find(req, res) {
var method = req.params.method
var query = req.query
var result = null
if (method === 'isbn') {
result = await this.bookFinder.findByISBN(query)
} else if (method === 'search') {
result = await this.bookFinder.search(query.provider, query.title, query.author || null)
}
res.json(result)
}
async findCovers(req, res) {
var query = req.query
var result = await this.bookFinder.findCovers(query.provider, query.title, query.author || null)
res.json(result)
}
}
module.exports = Scanner