Add:Generate book metadata file when book details are changed,Add:Server setting for storing book metadata in book folder

This commit is contained in:
advplyr 2022-02-27 14:28:18 -06:00
parent aa50cc2d81
commit 295c6b0c74
5 changed files with 58 additions and 6 deletions

View File

@ -11,7 +11,17 @@
<ui-toggle-switch v-model="newServerSettings.storeCoverWithBook" :disabled="updatingServerSettings" @input="(val) => updateSettingsKey('storeCoverWithBook', val)" />
<ui-tooltip :text="tooltips.storeCoverWithBook">
<p class="pl-4 text-lg">
Store covers with audiobook
Store covers with book
<span class="material-icons icon-text">info_outlined</span>
</p>
</ui-tooltip>
</div>
<div class="flex items-center py-2">
<ui-toggle-switch v-model="newServerSettings.storeMetadataWithBook" :disabled="updatingServerSettings" @input="(val) => updateSettingsKey('storeMetadataWithBook', val)" />
<ui-tooltip :text="tooltips.storeMetadataWithBook">
<p class="pl-4 text-lg">
Store metadata with book
<span class="material-icons icon-text">info_outlined</span>
</p>
</ui-tooltip>
@ -181,10 +191,11 @@ export default {
scannerDisableWatcher: 'Disables the automatic adding/updating of audiobooks when file changes are detected. *Requires server restart',
scannerPreferOpfMetadata: 'OPF file metadata will be used for book details over folder names',
scannerPreferAudioMetadata: 'Audio file ID3 meta tags will be used for book details over folder names',
scannerParseSubtitle: 'Extract subtitles from audiobook directory names.<br>Subtitle must be seperated by " - "<br>i.e. "Book Title - A Subtitle Here" has the subtitle "A Subtitle Here"',
scannerParseSubtitle: 'Extract subtitles from audiobook folder names.<br>Subtitle must be seperated by " - "<br>i.e. "Book Title - A Subtitle Here" has the subtitle "A Subtitle Here"',
scannerFindCovers: 'If your audiobook does not have an embedded cover or a cover image inside the folder, the scanner will attempt to find a cover.<br>Note: This will extend scan time',
bookshelfView: 'Alternative bookshelf view that shows title & author under book covers',
storeCoverWithBook: 'By default covers are stored in /metadata/books, enabling this setting will store covers inside your audiobooks directory. Only one file named "cover" will be kept.',
storeCoverWithBook: 'By default covers are stored in /metadata/books, enabling this setting will store covers in the books folder. Only one file named "cover" will be kept',
storeMetadataWithBook: 'By default metadata files are stored in /metadata/books, enabling this setting will store metadata files in the books folder. Uses .abs file extension',
coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers'
}
}

View File

@ -124,8 +124,8 @@ class Db {
if (!this.serverSettings) {
this.serverSettings = new ServerSettings()
await this.insertEntity('settings', this.serverSettings)
global.ServerSettings = this.serverSettings.toJSON()
}
global.ServerSettings = this.serverSettings.toJSON()
}
async load() {
@ -311,5 +311,12 @@ class Db {
return []
})
}
// Check if server was updated and previous version was earlier than param
checkPreviousVersionIsBefore(version) {
if (!this.previousVersion) return false
// true if version > previousVersion
return version.localeCompare(this.previousVersion) >= 0
}
}
module.exports = Db

View File

@ -35,6 +35,8 @@ class Server {
this.Uid = isNaN(UID) ? 0 : Number(UID)
this.Gid = isNaN(GID) ? 0 : Number(GID)
this.Host = '0.0.0.0'
global.Uid = this.Uid
global.Gid = this.Gid
global.ConfigPath = Path.normalize(CONFIG_PATH)
global.AudiobookPath = Path.normalize(AUDIOBOOK_PATH)
global.MetadataPath = Path.normalize(METADATA_PATH)
@ -132,6 +134,10 @@ class Server {
Logger.info(`[Server] Running scan for duplicate book IDs`)
await this.scanner.fixDuplicateIds()
}
// If server upgrade and last version was 1.7.0 or earlier - add abmetadata files
// if (this.db.checkPreviousVersionIsBefore('1.7.1')) {
// TODO: wait until stable
// }
if (this.db.serverSettings.scannerDisableWatcher) {
Logger.info(`[Server] Watcher is disabled`)

View File

@ -5,6 +5,7 @@ const { comparePaths, getIno, getId, elapsedPretty } = require('../utils/index')
const { parseOpfMetadataXML } = require('../utils/parseOpfMetadata')
const { extractCoverArt } = require('../utils/ffmpegHelpers')
const nfoGenerator = require('../utils/nfoGenerator')
const abmetadataGenerator = require('../utils/abmetadataGenerator')
const Logger = require('../Logger')
const Book = require('./Book')
const AudioTrack = require('./AudioTrack')
@ -44,6 +45,9 @@ class Audiobook {
if (audiobook) {
this.construct(audiobook)
}
// Temp flags
this.isSavingMetadata = false
}
construct(audiobook) {
@ -424,6 +428,10 @@ class Audiobook {
if (payload.book && this.book.update(payload.book)) {
hasUpdates = true
// TODO: Book may have updates where this save is not necessary
// add check first if metadata update is needed
this.saveAbMetadata()
}
if (hasUpdates) {
@ -1025,5 +1033,25 @@ class Audiobook {
}
return false
}
async saveAbMetadata() {
if (this.isSavingMetadata) return
this.isSavingMetadata = true
var metadataPath = Path.join(global.MetadataPath, 'books', this.id)
if (global.ServerSettings.storeMetadataWithBook) {
metadataPath = this.fullPath
} else {
// Make sure metadata book dir exists
await fs.ensureDir(metadataPath)
}
metadataPath = Path.join(metadataPath, 'metadata.abs')
return abmetadataGenerator.generate(this, metadataPath).then((success) => {
if (!success) Logger.error(`[Audiobook] Failed saving abmetadata to "${metadataPath}"`)
else Logger.debug(`[Audiobook] Success saving abmetadata to "${metadataPath}"`)
return success
})
}
}
module.exports = Audiobook

View File

@ -19,7 +19,7 @@ const bookKeyMap = {
genres: 'genresCommaSeparated'
}
function generate(audiobook, outputPath, uid, gid) {
function generate(audiobook, outputPath) {
var fileString = ';ABMETADATA1\n'
fileString += `#audiobookshelf v${package.version}\n\n`
@ -39,7 +39,7 @@ function generate(audiobook, outputPath, uid, gid) {
}
return fs.writeFile(outputPath, fileString).then(() => {
return filePerms(outputPath, 0o774, uid, gid).then(() => true)
return filePerms(outputPath, 0o774, global.Uid, global.Gid).then(() => true)
}).catch((error) => {
Logger.error(`[absMetaFileGenerator] Failed to save abs file`, error)
return false