Change:Server setting for coverDestination to storeCoverWithBook boolean, Add:abmetadata generator

This commit is contained in:
advplyr 2022-02-27 12:47:56 -06:00
parent 4e7d2ddc58
commit eb109c398f
9 changed files with 33 additions and 51 deletions

View File

@ -57,16 +57,6 @@ export default {
this.$store.commit('setDeveloperMode', value) this.$store.commit('setDeveloperMode', value)
this.$toast.info(`Developer Mode ${value ? 'Enabled' : 'Disabled'}`) this.$toast.info(`Developer Mode ${value ? 'Enabled' : 'Disabled'}`)
} }
// saveMetadataComplete(result) {
// this.savingMetadata = false
// if (!result) return
// this.$toast.success(`Metadata saved for ${result.success} audiobooks`)
// },
// saveMetadataFiles() {
// this.savingMetadata = true
// this.$root.socket.once('save_metadata_complete', this.saveMetadataComplete)
// this.$root.socket.emit('save_metadata')
// }
}, },
mounted() {} mounted() {}
} }

View File

@ -8,8 +8,8 @@
</div> </div>
<div class="flex items-center py-2"> <div class="flex items-center py-2">
<ui-toggle-switch v-model="storeCoversInAudiobookDir" :disabled="updatingServerSettings" @input="updateCoverStorageDestination" /> <ui-toggle-switch v-model="newServerSettings.storeCoverWithBook" :disabled="updatingServerSettings" @input="(val) => updateSettingsKey('storeCoverWithBook', val)" />
<ui-tooltip :text="tooltips.coverDestination"> <ui-tooltip :text="tooltips.storeCoverWithBook">
<p class="pl-4 text-lg"> <p class="pl-4 text-lg">
Store covers with audiobook Store covers with audiobook
<span class="material-icons icon-text">info_outlined</span> <span class="material-icons icon-text">info_outlined</span>
@ -172,7 +172,6 @@ export default {
data() { data() {
return { return {
isResettingAudiobooks: false, isResettingAudiobooks: false,
storeCoversInAudiobookDir: false,
updatingServerSettings: false, updatingServerSettings: false,
useSquareBookCovers: false, useSquareBookCovers: false,
useAlternativeBookshelfView: false, useAlternativeBookshelfView: false,
@ -185,7 +184,7 @@ export default {
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 directory 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', 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', bookshelfView: 'Alternative bookshelf view that shows title & author under book covers',
coverDestination: '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 inside your audiobooks directory. Only one file named "cover" will be kept.',
coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers' coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers'
} }
} }
@ -226,12 +225,6 @@ export default {
scannerCoverProvider: val scannerCoverProvider: val
}) })
}, },
updateCoverStorageDestination(val) {
this.newServerSettings.coverDestination = val ? this.$constants.CoverDestination.AUDIOBOOK : this.$constants.CoverDestination.METADATA
this.updateServerSettings({
coverDestination: this.newServerSettings.coverDestination
})
},
updateBookCoverAspectRatio(val) { updateBookCoverAspectRatio(val) {
this.updateServerSettings({ this.updateServerSettings({
coverAspectRatio: val ? this.$constants.BookCoverAspectRatio.SQUARE : this.$constants.BookCoverAspectRatio.STANDARD coverAspectRatio: val ? this.$constants.BookCoverAspectRatio.SQUARE : this.$constants.BookCoverAspectRatio.STANDARD
@ -263,8 +256,6 @@ export default {
initServerSettings() { initServerSettings() {
this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {} this.newServerSettings = this.serverSettings ? { ...this.serverSettings } : {}
this.storeCoversInAudiobookDir = this.newServerSettings.coverDestination === this.$constants.CoverDestination.AUDIOBOOK
this.useSquareBookCovers = this.newServerSettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE this.useSquareBookCovers = this.newServerSettings.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE
this.useAlternativeBookshelfView = this.newServerSettings.bookshelfView === this.$constants.BookshelfView.TITLES this.useAlternativeBookshelfView = this.newServerSettings.bookshelfView === this.$constants.BookshelfView.TITLES

View File

@ -14,11 +14,6 @@ const DownloadStatus = {
FAILED: 3 FAILED: 3
} }
const CoverDestination = {
METADATA: 0,
AUDIOBOOK: 1
}
const BookCoverAspectRatio = { const BookCoverAspectRatio = {
STANDARD: 0, STANDARD: 0,
SQUARE: 1 SQUARE: 1
@ -32,7 +27,6 @@ const BookshelfView = {
const Constants = { const Constants = {
SupportedFileTypes, SupportedFileTypes,
DownloadStatus, DownloadStatus,
CoverDestination,
BookCoverAspectRatio, BookCoverAspectRatio,
BookshelfView BookshelfView
} }

View File

@ -6,7 +6,6 @@ const readChunk = require('read-chunk')
const imageType = require('image-type') const imageType = require('image-type')
const globals = require('./utils/globals') const globals = require('./utils/globals')
const { CoverDestination } = require('./utils/constants')
const { downloadFile } = require('./utils/fileUtils') const { downloadFile } = require('./utils/fileUtils')
class CoverController { class CoverController {
@ -20,7 +19,7 @@ class CoverController {
} }
getCoverDirectory(audiobook) { getCoverDirectory(audiobook) {
if (this.db.serverSettings.coverDestination === CoverDestination.AUDIOBOOK) { if (this.db.serverSettings.storeCoverWithBook) {
return { return {
fullPath: audiobook.fullPath, fullPath: audiobook.fullPath,
relPath: '/s/book/' + audiobook.id relPath: '/s/book/' + audiobook.id

View File

@ -1,4 +1,4 @@
const { CoverDestination, BookCoverAspectRatio, BookshelfView } = require('../utils/constants') const { BookCoverAspectRatio, BookshelfView } = require('../utils/constants')
const Logger = require('../Logger') const Logger = require('../Logger')
class ServerSettings { class ServerSettings {
@ -18,8 +18,8 @@ class ServerSettings {
this.scannerDisableWatcher = false this.scannerDisableWatcher = false
// Metadata // Metadata
this.coverDestination = CoverDestination.METADATA this.storeCoverWithBook = false
this.saveMetadataFile = false this.storeMetadataWithBook = false
// Security/Rate limits // Security/Rate limits
this.rateLimitLoginRequests = 10 this.rateLimitLoginRequests = 10
@ -59,8 +59,12 @@ class ServerSettings {
this.scannerPreferOpfMetadata = !!settings.scannerPreferOpfMetadata this.scannerPreferOpfMetadata = !!settings.scannerPreferOpfMetadata
this.scannerDisableWatcher = !!settings.scannerDisableWatcher this.scannerDisableWatcher = !!settings.scannerDisableWatcher
this.coverDestination = settings.coverDestination || CoverDestination.METADATA this.storeCoverWithBook = settings.storeCoverWithBook
this.saveMetadataFile = !!settings.saveMetadataFile if (this.storeCoverWithBook == undefined) { // storeCoverWithBook added in 1.7.1 to replace coverDestination
this.storeCoverWithBook = !!settings.coverDestination
}
this.storeMetadataWithBook = !!settings.storeCoverWithBook
this.rateLimitLoginRequests = !isNaN(settings.rateLimitLoginRequests) ? Number(settings.rateLimitLoginRequests) : 10 this.rateLimitLoginRequests = !isNaN(settings.rateLimitLoginRequests) ? Number(settings.rateLimitLoginRequests) : 10
this.rateLimitLoginWindow = !isNaN(settings.rateLimitLoginWindow) ? Number(settings.rateLimitLoginWindow) : 10 * 60 * 1000 // 10 Minutes this.rateLimitLoginWindow = !isNaN(settings.rateLimitLoginWindow) ? Number(settings.rateLimitLoginWindow) : 10 * 60 * 1000 // 10 Minutes
@ -95,8 +99,8 @@ class ServerSettings {
scannerPreferAudioMetadata: this.scannerPreferAudioMetadata, scannerPreferAudioMetadata: this.scannerPreferAudioMetadata,
scannerPreferOpfMetadata: this.scannerPreferOpfMetadata, scannerPreferOpfMetadata: this.scannerPreferOpfMetadata,
scannerDisableWatcher: this.scannerDisableWatcher, scannerDisableWatcher: this.scannerDisableWatcher,
coverDestination: this.coverDestination, storeCoverWithBook: this.storeCoverWithBook,
saveMetadataFile: !!this.saveMetadataFile, storeMetadataWithBook: this.storeMetadataWithBook,
rateLimitLoginRequests: this.rateLimitLoginRequests, rateLimitLoginRequests: this.rateLimitLoginRequests,
rateLimitLoginWindow: this.rateLimitLoginWindow, rateLimitLoginWindow: this.rateLimitLoginWindow,
backupSchedule: this.backupSchedule, backupSchedule: this.backupSchedule,

View File

@ -1,5 +1,3 @@
const { CoverDestination } = require('../utils/constants')
class ScanOptions { class ScanOptions {
constructor(options) { constructor(options) {
this.forceRescan = false this.forceRescan = false
@ -7,7 +5,7 @@ class ScanOptions {
// Server settings // Server settings
this.parseSubtitles = false this.parseSubtitles = false
this.findCovers = false this.findCovers = false
this.coverDestination = CoverDestination.METADATA this.storeCoverWithBook = false
this.preferAudioMetadata = false this.preferAudioMetadata = false
this.preferOpfMetadata = false this.preferOpfMetadata = false
@ -32,7 +30,7 @@ class ScanOptions {
metadataPrecedence: this.metadataPrecedence, metadataPrecedence: this.metadataPrecedence,
parseSubtitles: this.parseSubtitles, parseSubtitles: this.parseSubtitles,
findCovers: this.findCovers, findCovers: this.findCovers,
coverDestination: this.coverDestination, storeCoverWithBook: this.storeCoverWithBook,
preferAudioMetadata: this.preferAudioMetadata, preferAudioMetadata: this.preferAudioMetadata,
preferOpfMetadata: this.preferOpfMetadata preferOpfMetadata: this.preferOpfMetadata
} }
@ -43,7 +41,7 @@ class ScanOptions {
this.parseSubtitles = !!serverSettings.scannerParseSubtitle this.parseSubtitles = !!serverSettings.scannerParseSubtitle
this.findCovers = !!serverSettings.scannerFindCovers this.findCovers = !!serverSettings.scannerFindCovers
this.coverDestination = serverSettings.coverDestination this.storeCoverWithBook = serverSettings.storeCoverWithBook
this.preferAudioMetadata = serverSettings.scannerPreferAudioMetadata this.preferAudioMetadata = serverSettings.scannerPreferAudioMetadata
this.preferOpfMetadata = serverSettings.scannerPreferOpfMetadata this.preferOpfMetadata = serverSettings.scannerPreferOpfMetadata
} }

View File

@ -5,8 +5,8 @@ const Path = require('path')
const Logger = require('../Logger') const Logger = require('../Logger')
const { version } = require('../../package.json') const { version } = require('../../package.json')
const { groupFilesIntoAudiobookPaths, getAudiobookFileData, scanRootDir } = require('../utils/scandir') const { groupFilesIntoAudiobookPaths, getAudiobookFileData, scanRootDir } = require('../utils/scandir')
const { comparePaths, getIno, getId, msToTimestamp } = require('../utils/index') const { comparePaths, getId } = require('../utils/index')
const { ScanResult, CoverDestination, LogLevel } = require('../utils/constants') const { ScanResult, LogLevel } = require('../utils/constants')
const AudioFileScanner = require('./AudioFileScanner') const AudioFileScanner = require('./AudioFileScanner')
const BookFinder = require('../BookFinder') const BookFinder = require('../BookFinder')
@ -33,7 +33,7 @@ class Scanner {
} }
getCoverDirectory(audiobook) { getCoverDirectory(audiobook) {
if (this.db.serverSettings.coverDestination === CoverDestination.AUDIOBOOK) { if (this.db.serverSettings.storeCoverWithBook) {
return { return {
fullPath: audiobook.fullPath, fullPath: audiobook.fullPath,
relPath: '/s/book/' + audiobook.id relPath: '/s/book/' + audiobook.id

View File

@ -20,13 +20,24 @@ const bookKeyMap = {
} }
function generate(audiobook, outputPath, uid, gid) { function generate(audiobook, outputPath, uid, gid) {
var fileString = `[audiobookshelf v${package.version}]\n` var fileString = ';ABMETADATA1\n'
fileString += `#audiobookshelf v${package.version}\n\n`
for (const key in bookKeyMap) { for (const key in bookKeyMap) {
const value = audiobook.book[bookKeyMap[key]] || '' const value = audiobook.book[bookKeyMap[key]] || ''
fileString += `${key}=${value}\n` fileString += `${key}=${value}\n`
} }
if (audiobook.chapters.length) {
fileString += '\n'
audiobook.chapters.forEach((chapter) => {
fileString += `[CHAPTER]\n`
fileString += `start=${chapter.start}\n`
fileString += `end=${chapter.end}\n`
fileString += `title=${chapter.title}\n`
})
}
return fs.writeFile(outputPath, fileString).then(() => { return fs.writeFile(outputPath, fileString).then(() => {
return filePerms(outputPath, 0o774, uid, gid).then(() => true) return filePerms(outputPath, 0o774, uid, gid).then(() => true)
}).catch((error) => { }).catch((error) => {

View File

@ -6,11 +6,6 @@ module.exports.ScanResult = {
UPTODATE: 4 UPTODATE: 4
} }
module.exports.CoverDestination = {
METADATA: 0,
AUDIOBOOK: 1
}
module.exports.BookCoverAspectRatio = { module.exports.BookCoverAspectRatio = {
STANDARD: 0, // 1.6:1 STANDARD: 0, // 1.6:1
SQUARE: 1 SQUARE: 1