Add: track manager sort by filename #128, Add: Support publish year wrapped in parenthesis, Change: Parse out CD Num from filename, Change: Show First Last author everywhere when Last, First is used in folder name, Fix: Re-Scan updates parsed track nums

This commit is contained in:
advplyr 2021-10-23 20:31:48 -05:00
parent b32b99418a
commit 92c2c53c09
10 changed files with 115 additions and 23 deletions

View file

@ -109,7 +109,7 @@ class Scanner {
titleDistance: 2,
authorDistance: 2
}
var results = await this.bookFinder.findCovers('openlibrary', audiobook.title, audiobook.author, options)
var results = await this.bookFinder.findCovers('openlibrary', audiobook.title, audiobook.authorFL, options)
if (results.length) {
Logger.debug(`[Scanner] Found best cover for "${audiobook.title}"`)

View file

@ -13,6 +13,7 @@ class AudioFile {
this.trackNumFromMeta = null
this.trackNumFromFilename = null
this.cdNumFromFilename = null
this.format = null
this.duration = null
@ -39,6 +40,16 @@ class AudioFile {
}
}
// Sort number takes cd num into account
// get sortNumber() {
// if (this.manuallyVerified) return this.index
// var num = this.index
// if (this.cdNumFromFilename && !isNaN(this.cdNumFromFilename)) {
// num += (Number(this.cdNumFromFilename) * 1000)
// }
// return num
// }
toJSON() {
return {
index: this.index,
@ -50,6 +61,7 @@ class AudioFile {
addedAt: this.addedAt,
trackNumFromMeta: this.trackNumFromMeta,
trackNumFromFilename: this.trackNumFromFilename,
cdNumFromFilename: this.cdNumFromFilename,
manuallyVerified: !!this.manuallyVerified,
invalid: !!this.invalid,
exclude: !!this.exclude,
@ -84,6 +96,7 @@ class AudioFile {
this.trackNumFromMeta = data.trackNumFromMeta || null
this.trackNumFromFilename = data.trackNumFromFilename || null
this.cdNumFromFilename = data.cdNumFromFilename || null
this.format = data.format
this.duration = data.duration
@ -117,6 +130,7 @@ class AudioFile {
this.trackNumFromMeta = data.trackNumFromMeta || null
this.trackNumFromFilename = data.trackNumFromFilename || null
this.cdNumFromFilename = data.cdNumFromFilename || null
this.manuallyVerified = !!data.manuallyVerified
this.invalid = !!data.invalid
@ -178,7 +192,10 @@ class AudioFile {
channels: data.channels,
channelLayout: data.channel_layout,
chapters: data.chapters || [],
embeddedCoverArt: data.embedded_cover_art || null
embeddedCoverArt: data.embedded_cover_art || null,
trackNumFromMeta: data.trackNumFromMeta,
trackNumFromFilename: data.trackNumFromFilename,
cdNumFromFilename: data.cdNumFromFilename
}
var hasUpdates = false

View file

@ -35,11 +35,11 @@ class Book {
get _title() { return this.title || '' }
get _subtitle() { return this.subtitle || '' }
get _narrator() { return this.narrator || '' }
get _author() { return this.author || '' }
get _author() { return this.authorFL || '' }
get _series() { return this.series || '' }
get shouldSearchForCover() {
if (this.author !== this.lastCoverSearchAuthor || this.title !== this.lastCoverSearchTitle || !this.lastCoverSearch) return true
if (this.authorFL !== this.lastCoverSearchAuthor || this.title !== this.lastCoverSearchTitle || !this.lastCoverSearch) return true
var timeSinceLastSearch = Date.now() - this.lastCoverSearch
return timeSinceLastSearch > 1000 * 60 * 60 * 24 * 7 // every 7 days do another lookup
}
@ -180,7 +180,7 @@ class Book {
updateLastCoverSearch(coverWasFound) {
this.lastCoverSearch = coverWasFound ? null : Date.now()
this.lastCoverSearchAuthor = coverWasFound ? null : this.author
this.lastCoverSearchAuthor = coverWasFound ? null : this.authorFL
this.lastCoverSearchTitle = coverWasFound ? null : this.title
}
@ -225,7 +225,7 @@ class Book {
var authorMatch = this._author.toLowerCase().includes(search)
var seriesMatch = this._series.toLowerCase().includes(search)
var bookMatchKey = titleMatch ? 'title' : subtitleMatch ? 'subtitle' : authorMatch ? 'author' : seriesMatch ? 'series' : false
var bookMatchKey = titleMatch ? 'title' : subtitleMatch ? 'subtitle' : authorMatch ? 'authorFL' : seriesMatch ? 'series' : false
var bookMatchText = bookMatchKey ? this[bookMatchKey] : ''
return {
book: bookMatchKey,

View file

@ -89,7 +89,10 @@ function getTrackNumberFromFilename(title, author, series, publishYear, filename
if (publishYear) partbasename = partbasename.replace(publishYear)
// Remove eg. "disc 1" from path
partbasename = partbasename.replace(/ disc \d\d? /i, '')
partbasename = partbasename.replace(/\bdisc \d\d?\b/i, '')
// Remove "cd01" or "cd 01" from path
partbasename = partbasename.replace(/\bcd ?\d\d?\b/i, '')
var numbersinpath = partbasename.match(/\d{1,4}/g)
if (!numbersinpath) return null
@ -98,6 +101,27 @@ function getTrackNumberFromFilename(title, author, series, publishYear, filename
return number
}
function getCdNumberFromFilename(title, author, series, publishYear, filename) {
var partbasename = Path.basename(filename, Path.extname(filename))
// Remove title, author, series, and publishYear from filename if there
if (title) partbasename = partbasename.replace(title, '')
if (author) partbasename = partbasename.replace(author, '')
if (series) partbasename = partbasename.replace(series, '')
if (publishYear) partbasename = partbasename.replace(publishYear)
var cdNumber = null
var cdmatch = partbasename.match(/\b(disc|cd) ?(\d\d?)\b/i)
if (cdmatch && cdmatch.length > 2 && cdmatch[2]) {
if (!isNaN(cdmatch[2])) {
cdNumber = Number(cdmatch[2])
}
}
return cdNumber
}
async function scanAudioFiles(audiobook, newAudioFiles) {
if (!newAudioFiles || !newAudioFiles.length) {
Logger.error('[AudioFileScanner] Scan Audio Files no new files', audiobook.title)
@ -123,6 +147,14 @@ async function scanAudioFiles(audiobook, newAudioFiles) {
var trackNumFromFilename = getTrackNumberFromFilename(book.title, book.author, book.series, book.publishYear, audioFile.filename)
var cdNumFromFilename = getCdNumberFromFilename(book.title, book.author, book.series, book.publishYear, audioFile.filename)
// IF CD num was found but no track num - USE cd num as track num
if (!trackNumFromFilename && cdNumFromFilename) {
trackNumFromFilename = cdNumFromFilename
cdNumFromFilename = null
}
var audioFileObj = {
ino: audioFile.ino,
filename: audioFile.filename,
@ -131,7 +163,8 @@ async function scanAudioFiles(audiobook, newAudioFiles) {
ext: audioFile.ext,
...scanData,
trackNumFromMeta,
trackNumFromFilename
trackNumFromFilename,
cdNumFromFilename
}
var audioFile = audiobook.addAudioFile(audioFileObj)
@ -172,6 +205,7 @@ async function scanAudioFiles(audiobook, newAudioFiles) {
}
tracks.sort((a, b) => a.index - b.index)
audiobook.audioFiles.sort((a, b) => {
var aNum = isNumber(a.trackNumFromMeta) ? a.trackNumFromMeta : isNumber(a.trackNumFromFilename) ? a.trackNumFromFilename : 0
var bNum = isNumber(b.trackNumFromMeta) ? b.trackNumFromMeta : isNumber(b.trackNumFromFilename) ? b.trackNumFromFilename : 0
@ -209,7 +243,27 @@ async function rescanAudioFiles(audiobook) {
// audiobook.invalidAudioFiles.push(parts[i])
continue;
}
var hasUpdates = audioFile.updateMetadata(scanData)
var trackNumFromMeta = getTrackNumberFromMeta(scanData)
var book = audiobook.book || {}
var trackNumFromFilename = getTrackNumberFromFilename(book.title, book.author, book.series, book.publishYear, audioFile.filename)
var cdNumFromFilename = getCdNumberFromFilename(book.title, book.author, book.series, book.publishYear, audioFile.filename)
// IF CD num was found but no track num - USE cd num as track num
if (!trackNumFromFilename && cdNumFromFilename) {
trackNumFromFilename = cdNumFromFilename
cdNumFromFilename = null
}
var metadataUpdate = {
...scanData,
trackNumFromMeta,
trackNumFromFilename,
cdNumFromFilename
}
var hasUpdates = audioFile.updateMetadata(metadataUpdate)
if (hasUpdates) {
// Sync audio track with audio file
var matchingAudioTrack = audiobook.tracks.find(t => t.ino === audioFile.ino)

View file

@ -206,9 +206,16 @@ function getAudiobookDataFromDir(folderPath, dir, parseSubtitle = false) {
var publishYear = null
// If Title is of format 1999 - Title, then use 1999 as publish year
var publishYearMatch = title.match(/^([0-9]{4}) - (.+)/)
if (publishYearMatch && publishYearMatch.length > 2) {
// OLD regex (not matching parentheses)
// var publishYearMatch = title.match(/^([0-9]{4}) - (.+)/)
// If Title is of format 1999 OR (1999) - Title, then use 1999 as publish year
var publishYearMatch = title.match(/^(\(?[0-9]{4}\)?) - (.+)/)
if (publishYearMatch && publishYearMatch.length > 2 && publishYearMatch[1]) {
// Strip parentheses
if (publishYearMatch[1].startsWith('(') && publishYearMatch[1].endsWith(')')) {
publishYearMatch[1] = publishYearMatch[1].slice(1, -1)
}
if (!isNaN(publishYearMatch[1])) {
publishYear = publishYearMatch[1]
title = publishYearMatch[2]