mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-05 21:10:22 +01:00
Remove NFO metadata and save metadata button
This commit is contained in:
parent
3f6ed6dbf9
commit
79a82df914
@ -9,10 +9,6 @@
|
|||||||
|
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
|
|
||||||
<ui-tooltip v-if="!isMissing && mediaType == 'book'" text="(Root User Only) Save a NFO metadata file in your audiobooks directory" direction="bottom" class="mr-4 hidden sm:block">
|
|
||||||
<ui-btn v-if="isRootUser" :loading="savingMetadata" color="bg" type="button" class="h-full" small @click.stop.prevent="saveMetadata">Save Metadata</ui-btn>
|
|
||||||
</ui-tooltip>
|
|
||||||
|
|
||||||
<ui-tooltip v-if="mediaType == 'book'" :disabled="!!quickMatching" :text="`(Root User Only) Populate empty book details & cover with first book result from '${libraryProvider}'. Does not overwrite details.`" direction="bottom" class="mr-4">
|
<ui-tooltip v-if="mediaType == 'book'" :disabled="!!quickMatching" :text="`(Root User Only) Populate empty book details & cover with first book result from '${libraryProvider}'. Does not overwrite details.`" direction="bottom" class="mr-4">
|
||||||
<ui-btn v-if="isRootUser" :loading="quickMatching" color="bg" type="button" class="h-full" small @click.stop.prevent="quickMatch">Quick Match</ui-btn>
|
<ui-btn v-if="isRootUser" :loading="quickMatching" color="bg" type="button" class="h-full" small @click.stop.prevent="quickMatch">Quick Match</ui-btn>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
@ -40,7 +36,6 @@ export default {
|
|||||||
return {
|
return {
|
||||||
resettingProgress: false,
|
resettingProgress: false,
|
||||||
isScrollable: false,
|
isScrollable: false,
|
||||||
savingMetadata: false,
|
|
||||||
rescanning: false,
|
rescanning: false,
|
||||||
quickMatching: false
|
quickMatching: false
|
||||||
}
|
}
|
||||||
@ -144,24 +139,6 @@ export default {
|
|||||||
this.rescanning = false
|
this.rescanning = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
saveMetadataComplete(result) {
|
|
||||||
this.savingMetadata = false
|
|
||||||
if (result.error) {
|
|
||||||
this.$toast.error(result.error)
|
|
||||||
} else if (result.audiobookId) {
|
|
||||||
var { savedPath } = result
|
|
||||||
if (!savedPath) {
|
|
||||||
this.$toast.error(`Failed to save metadata file (${result.audiobookId})`)
|
|
||||||
} else {
|
|
||||||
this.$toast.success(`Metadata file saved "${result.audiobookTitle}"`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
saveMetadata() {
|
|
||||||
this.savingMetadata = true
|
|
||||||
this.$root.socket.once('save_metadata_complete', this.saveMetadataComplete)
|
|
||||||
this.$root.socket.emit('save_metadata', this.libraryItemId)
|
|
||||||
},
|
|
||||||
submitForm() {
|
submitForm() {
|
||||||
if (this.isProcessing) {
|
if (this.isProcessing) {
|
||||||
return
|
return
|
||||||
|
@ -225,11 +225,6 @@ class Server {
|
|||||||
|
|
||||||
// Scanning
|
// Scanning
|
||||||
socket.on('cancel_scan', this.cancelScan.bind(this))
|
socket.on('cancel_scan', this.cancelScan.bind(this))
|
||||||
socket.on('save_metadata', (libraryItemId) => this.saveMetadata(socket, libraryItemId))
|
|
||||||
|
|
||||||
// Downloading
|
|
||||||
socket.on('download', (payload) => this.downloadManager.downloadSocketRequest(socket, payload))
|
|
||||||
socket.on('remove_download', (downloadId) => this.downloadManager.removeSocketRequest(socket, downloadId))
|
|
||||||
|
|
||||||
// Logs
|
// Logs
|
||||||
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level))
|
||||||
@ -273,14 +268,6 @@ class Server {
|
|||||||
this.scanner.setCancelLibraryScan(id)
|
this.scanner.setCancelLibraryScan(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates an NFO metadata file, if no audiobookId is passed then all audiobooks are done
|
|
||||||
async saveMetadata(socket, audiobookId = null) {
|
|
||||||
Logger.info('[Server] Starting save metadata files')
|
|
||||||
var response = await this.scanner.saveMetadata(audiobookId)
|
|
||||||
Logger.info(`[Server] Finished saving metadata files Successful: ${response.success}, Failed: ${response.failed}`)
|
|
||||||
socket.emit('save_metadata_complete', response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove unused /metadata/items/{id} folders
|
// Remove unused /metadata/items/{id} folders
|
||||||
async purgeMetadata() {
|
async purgeMetadata() {
|
||||||
var itemsMetadata = Path.join(global.MetadataPath, 'items')
|
var itemsMetadata = Path.join(global.MetadataPath, 'items')
|
||||||
|
@ -243,8 +243,6 @@ class LibraryItem {
|
|||||||
this.scanVersion = version
|
this.scanVersion = version
|
||||||
}
|
}
|
||||||
|
|
||||||
saveMetadata() { }
|
|
||||||
|
|
||||||
// Returns null if file not found, true if file was updated, false if up to date
|
// Returns null if file not found, true if file was updated, false if up to date
|
||||||
// updates existing LibraryFile, AudioFile, EBookFile's
|
// updates existing LibraryFile, AudioFile, EBookFile's
|
||||||
checkFileFound(fileFound) {
|
checkFileFound(fileFound) {
|
||||||
|
@ -616,40 +616,6 @@ class Scanner {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Redo metadata
|
|
||||||
async saveMetadata(audiobookId) {
|
|
||||||
// if (audiobookId) {
|
|
||||||
// var audiobook = this.db.audiobooks.find(ab => ab.id === audiobookId)
|
|
||||||
// if (!audiobook) {
|
|
||||||
// return {
|
|
||||||
// error: 'Audiobook not found'
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// var savedPath = await audiobook.writeNfoFile()
|
|
||||||
// return {
|
|
||||||
// audiobookId,
|
|
||||||
// audiobookTitle: audiobook.title,
|
|
||||||
// savedPath
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// var response = {
|
|
||||||
// success: 0,
|
|
||||||
// failed: 0
|
|
||||||
// }
|
|
||||||
// for (let i = 0; i < this.db.audiobooks.length; i++) {
|
|
||||||
// var audiobook = this.db.audiobooks[i]
|
|
||||||
// var savedPath = await audiobook.writeNfoFile()
|
|
||||||
// if (savedPath) {
|
|
||||||
// Logger.info(`[Scanner] Saved metadata nfo ${savedPath}`)
|
|
||||||
// response.success++
|
|
||||||
// } else {
|
|
||||||
// response.failed++
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return response
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
async quickMatchBook(libraryItem, options = {}) {
|
async quickMatchBook(libraryItem, options = {}) {
|
||||||
var provider = options.provider || 'google'
|
var provider = options.provider || 'google'
|
||||||
var searchTitle = options.title || libraryItem.media.metadata.title
|
var searchTitle = options.title || libraryItem.media.metadata.title
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
const fs = require('fs-extra')
|
|
||||||
const Path = require('path')
|
|
||||||
const { bytesPretty } = require('./fileUtils')
|
|
||||||
const Logger = require('../Logger')
|
|
||||||
|
|
||||||
const LEFT_COL_LEN = 25
|
|
||||||
|
|
||||||
function sectionHeaderLines(title) {
|
|
||||||
return [title, ''.padEnd(10, '=')]
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateSection(sectionTitle, sectionData) {
|
|
||||||
var lines = sectionHeaderLines(sectionTitle)
|
|
||||||
for (const key in sectionData) {
|
|
||||||
var line = key.padEnd(LEFT_COL_LEN) + (sectionData[key] || '')
|
|
||||||
lines.push(line)
|
|
||||||
}
|
|
||||||
return lines
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generate(audiobook, nfoFilename = 'metadata.nfo') {
|
|
||||||
var jsonObj = audiobook.toJSON()
|
|
||||||
var book = jsonObj.book
|
|
||||||
|
|
||||||
var generalSectionData = {
|
|
||||||
'Title': book.title,
|
|
||||||
'Subtitle': book.subtitle,
|
|
||||||
'Author': book.author,
|
|
||||||
'Narrator': book.narrator,
|
|
||||||
'Series': book.series,
|
|
||||||
'Volume Number': book.volumeNumber,
|
|
||||||
'Publish Year': book.publishedYear,
|
|
||||||
'Genre': book.genres ? book.genres.join(', ') : '',
|
|
||||||
'Duration': audiobook.durationPretty,
|
|
||||||
'Chapters': jsonObj.chapters.length
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!book.subtitle) {
|
|
||||||
delete generalSectionData['Subtitle']
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!book.series) {
|
|
||||||
delete generalSectionData['Series']
|
|
||||||
delete generalSectionData['Volume Number']
|
|
||||||
}
|
|
||||||
|
|
||||||
var tracks = audiobook.tracks
|
|
||||||
var audioTrack = tracks.length ? audiobook.tracks[0] : {}
|
|
||||||
|
|
||||||
var totalBitrate = 0
|
|
||||||
var numBitrates = 0
|
|
||||||
for (let i = 0; i < tracks.length; i++) {
|
|
||||||
if (tracks[i].bitRate) {
|
|
||||||
totalBitrate += tracks[i].bitRate
|
|
||||||
numBitrates++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var averageBitrate = numBitrates ? totalBitrate / numBitrates : 0
|
|
||||||
|
|
||||||
var mediaSectionData = {
|
|
||||||
'Tracks': jsonObj.tracks.length,
|
|
||||||
'Size': audiobook.sizePretty,
|
|
||||||
'Codec': audioTrack.codec,
|
|
||||||
'Ext': audioTrack.ext,
|
|
||||||
'Channels': audioTrack.channels,
|
|
||||||
'Channel Layout': audioTrack.channelLayout,
|
|
||||||
'Average Bitrate': bytesPretty(averageBitrate)
|
|
||||||
}
|
|
||||||
|
|
||||||
var bookSection = generateSection('Book Info', generalSectionData)
|
|
||||||
|
|
||||||
var descriptionSection = null
|
|
||||||
if (book.description) {
|
|
||||||
descriptionSection = sectionHeaderLines('Book Description')
|
|
||||||
descriptionSection.push(book.description)
|
|
||||||
}
|
|
||||||
|
|
||||||
var mediaSection = generateSection('Media Info', mediaSectionData)
|
|
||||||
|
|
||||||
var fullFile = bookSection.join('\n') + '\n\n'
|
|
||||||
if (descriptionSection) fullFile += descriptionSection.join('\n') + '\n\n'
|
|
||||||
fullFile += mediaSection.join('\n')
|
|
||||||
|
|
||||||
var nfoPath = Path.join(audiobook.fullPath, nfoFilename)
|
|
||||||
var relativePath = Path.join(audiobook.path, nfoFilename)
|
|
||||||
return fs.writeFile(nfoPath, fullFile).then(() => relativePath).catch((error) => {
|
|
||||||
Logger.error(`Failed to write nfo file ${error}`)
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
module.exports = generate
|
|
Loading…
Reference in New Issue
Block a user