mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-08-04 10:14:36 +02:00
Update:Remove scanner settings, add library scanner settings tab, add order of precedence
This commit is contained in:
parent
5ad9f507ba
commit
347b49f564
35 changed files with 764 additions and 809 deletions
|
@ -1,13 +1,6 @@
|
|||
const xml2js = require('xml2js')
|
||||
const Logger = require('../../Logger')
|
||||
|
||||
// given a list of audio files, extract all of the Overdrive Media Markers metaTags, and return an array of them as XML
|
||||
function extractOverdriveMediaMarkers(includedAudioFiles) {
|
||||
Logger.debug('[parseOverdriveMediaMarkers] Extracting overdrive media markers')
|
||||
var markers = includedAudioFiles.map((af) => af.metaTags.tagOverdriveMediaMarker).filter(af => af) || []
|
||||
|
||||
return markers
|
||||
}
|
||||
|
||||
// given the array of Overdrive Media Markers from generateOverdriveMediaMarkers()
|
||||
// parse and clean them in to something a bit more usable
|
||||
function cleanOverdriveMediaMarkers(overdriveMediaMarkers) {
|
||||
|
@ -29,12 +22,11 @@ function cleanOverdriveMediaMarkers(overdriveMediaMarkers) {
|
|||
]
|
||||
*/
|
||||
|
||||
var parseString = require('xml2js').parseString // function to convert xml to JSON
|
||||
var parsedOverdriveMediaMarkers = []
|
||||
|
||||
const parsedOverdriveMediaMarkers = []
|
||||
overdriveMediaMarkers.forEach((item, index) => {
|
||||
var parsed_result = null
|
||||
parseString(item, function (err, result) {
|
||||
let parsed_result = null
|
||||
// convert xml to JSON
|
||||
xml2js.parseString(item, function (err, result) {
|
||||
/*
|
||||
result.Markers.Marker is the result of parsing the XML for the MediaMarker tags for the MP3 file (Part##.mp3)
|
||||
it is shaped like this, and needs further cleaning below:
|
||||
|
@ -54,7 +46,7 @@ function cleanOverdriveMediaMarkers(overdriveMediaMarkers) {
|
|||
*/
|
||||
|
||||
// The values for Name and Time in results.Markers.Marker are returned as Arrays from parseString and should be strings
|
||||
if (result && result.Markers && result.Markers.Marker) {
|
||||
if (result?.Markers?.Marker) {
|
||||
parsed_result = objectValuesArrayToString(result.Markers.Marker)
|
||||
}
|
||||
})
|
||||
|
@ -138,22 +130,13 @@ function generateParsedChapters(includedAudioFiles, cleanedOverdriveMediaMarkers
|
|||
return parsedChapters
|
||||
}
|
||||
|
||||
module.exports.overdriveMediaMarkersExist = (includedAudioFiles) => {
|
||||
return extractOverdriveMediaMarkers(includedAudioFiles).length > 1
|
||||
}
|
||||
|
||||
module.exports.parseOverdriveMediaMarkersAsChapters = (includedAudioFiles) => {
|
||||
Logger.info('[parseOverdriveMediaMarkers] Parsing of Overdrive Media Markers started')
|
||||
|
||||
var overdriveMediaMarkers = extractOverdriveMediaMarkers(includedAudioFiles)
|
||||
const overdriveMediaMarkers = includedAudioFiles.map((af) => af.metaTags.tagOverdriveMediaMarker).filter(af => af) || []
|
||||
if (!overdriveMediaMarkers.length) return null
|
||||
|
||||
var cleanedOverdriveMediaMarkers = cleanOverdriveMediaMarkers(overdriveMediaMarkers)
|
||||
// TODO: generateParsedChapters requires overdrive media markers and included audio files length to be the same
|
||||
// so if not equal then we must exit
|
||||
if (cleanedOverdriveMediaMarkers.length !== includedAudioFiles.length) return null
|
||||
|
||||
var parsedChapters = generateParsedChapters(includedAudioFiles, cleanedOverdriveMediaMarkers)
|
||||
|
||||
return parsedChapters
|
||||
return generateParsedChapters(includedAudioFiles, cleanedOverdriveMediaMarkers)
|
||||
}
|
|
@ -2,6 +2,18 @@ const Path = require('path')
|
|||
const { filePathToPOSIX } = require('./fileUtils')
|
||||
const globals = require('./globals')
|
||||
const LibraryFile = require('../objects/files/LibraryFile')
|
||||
const parseNameString = require('./parsers/parseNameString')
|
||||
|
||||
/**
|
||||
* @typedef LibraryItemFilenameMetadata
|
||||
* @property {string} title
|
||||
* @property {string} subtitle Book mediaType only
|
||||
* @property {string[]} authors Book mediaType only
|
||||
* @property {string[]} narrators Book mediaType only
|
||||
* @property {string} seriesName Book mediaType only
|
||||
* @property {string} seriesSequence Book mediaType only
|
||||
* @property {string} publishedYear Book mediaType only
|
||||
*/
|
||||
|
||||
function isMediaFile(mediaType, ext, audiobooksOnly = false) {
|
||||
if (!ext) return false
|
||||
|
@ -210,10 +222,15 @@ function buildLibraryFile(libraryItemPath, files) {
|
|||
}
|
||||
module.exports.buildLibraryFile = buildLibraryFile
|
||||
|
||||
// Input relative filepath, output all details that can be parsed
|
||||
function getBookDataFromDir(folderPath, relPath, parseSubtitle = false) {
|
||||
relPath = filePathToPOSIX(relPath)
|
||||
var splitDir = relPath.split('/')
|
||||
/**
|
||||
* Get details parsed from filenames
|
||||
*
|
||||
* @param {string} relPath
|
||||
* @param {boolean} parseSubtitle
|
||||
* @returns {LibraryItemFilenameMetadata}
|
||||
*/
|
||||
function getBookDataFromDir(relPath, parseSubtitle = false) {
|
||||
const splitDir = relPath.split('/')
|
||||
|
||||
var folder = splitDir.pop() // Audio files will always be in the directory named for the title
|
||||
series = (splitDir.length > 1) ? splitDir.pop() : null // If there are at least 2 more directories, next furthest will be the series
|
||||
|
@ -226,17 +243,13 @@ function getBookDataFromDir(folderPath, relPath, parseSubtitle = false) {
|
|||
var [title, subtitle] = parseSubtitle ? getSubtitle(folder) : [folder, null]
|
||||
|
||||
return {
|
||||
mediaMetadata: {
|
||||
author,
|
||||
title,
|
||||
subtitle,
|
||||
series,
|
||||
sequence,
|
||||
publishedYear,
|
||||
narrators,
|
||||
},
|
||||
relPath: relPath, // relative audiobook path i.e. /Author Name/Book Name/..
|
||||
path: Path.posix.join(folderPath, relPath) // i.e. /audiobook/Author Name/Book Name/..
|
||||
title,
|
||||
subtitle,
|
||||
authors: parseNameString.parse(author)?.names || [],
|
||||
narrators: parseNameString.parse(narrators)?.names || [],
|
||||
seriesName: series,
|
||||
seriesSequence: sequence,
|
||||
publishedYear
|
||||
}
|
||||
}
|
||||
module.exports.getBookDataFromDir = getBookDataFromDir
|
||||
|
@ -301,28 +314,43 @@ function getSubtitle(folder) {
|
|||
return [splitTitle.shift(), splitTitle.join(' - ')]
|
||||
}
|
||||
|
||||
function getPodcastDataFromDir(folderPath, relPath) {
|
||||
relPath = filePathToPOSIX(relPath)
|
||||
/**
|
||||
*
|
||||
* @param {string} relPath
|
||||
* @returns {LibraryItemFilenameMetadata}
|
||||
*/
|
||||
function getPodcastDataFromDir(relPath) {
|
||||
const splitDir = relPath.split('/')
|
||||
|
||||
// Audio files will always be in the directory named for the title
|
||||
const title = splitDir.pop()
|
||||
return {
|
||||
mediaMetadata: {
|
||||
title
|
||||
},
|
||||
relPath: relPath, // relative podcast path i.e. /Podcast Name/..
|
||||
path: Path.posix.join(folderPath, relPath) // i.e. /podcasts/Podcast Name/..
|
||||
title
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} libraryMediaType
|
||||
* @param {string} folderPath
|
||||
* @param {string} relPath
|
||||
* @returns {{ mediaMetadata: LibraryItemFilenameMetadata, relPath: string, path: string}}
|
||||
*/
|
||||
function getDataFromMediaDir(libraryMediaType, folderPath, relPath) {
|
||||
relPath = filePathToPOSIX(relPath)
|
||||
let fullPath = Path.posix.join(folderPath, relPath)
|
||||
let mediaMetadata = null
|
||||
|
||||
if (libraryMediaType === 'podcast') {
|
||||
return getPodcastDataFromDir(folderPath, relPath)
|
||||
} else if (libraryMediaType === 'book') {
|
||||
return getBookDataFromDir(folderPath, relPath, !!global.ServerSettings.scannerParseSubtitle)
|
||||
} else {
|
||||
return getPodcastDataFromDir(folderPath, relPath)
|
||||
mediaMetadata = getPodcastDataFromDir(relPath)
|
||||
} else { // book
|
||||
mediaMetadata = getBookDataFromDir(relPath, !!global.ServerSettings.scannerParseSubtitle)
|
||||
}
|
||||
|
||||
return {
|
||||
mediaMetadata,
|
||||
relPath,
|
||||
path: fullPath
|
||||
}
|
||||
}
|
||||
module.exports.getDataFromMediaDir = getDataFromMediaDir
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue