Skip to content

Commit

Permalink
Update:Book series embeds in grouping meta tag as semicolon deliminat…
Browse files Browse the repository at this point in the history
…ed, book meta tag parser falls back to using grouping tag for series if set #3473
  • Loading branch information
advplyr committed Oct 20, 2024
1 parent 72e59e7 commit 953ffe8
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 27 deletions.
4 changes: 4 additions & 0 deletions server/objects/metadata/AudioMetaTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class AudioMetaTags {
this.tagTitleSort = null
this.tagSeries = null
this.tagSeriesPart = null
this.tagGrouping = null
this.tagTrack = null
this.tagDisc = null
this.tagSubtitle = null
Expand Down Expand Up @@ -116,6 +117,7 @@ class AudioMetaTags {
this.tagTitleSort = metadata.tagTitleSort || null
this.tagSeries = metadata.tagSeries || null
this.tagSeriesPart = metadata.tagSeriesPart || null
this.tagGrouping = metadata.tagGrouping || null
this.tagTrack = metadata.tagTrack || null
this.tagDisc = metadata.tagDisc || null
this.tagSubtitle = metadata.tagSubtitle || null
Expand Down Expand Up @@ -156,6 +158,7 @@ class AudioMetaTags {
this.tagTitleSort = payload.file_tag_titlesort || null
this.tagSeries = payload.file_tag_series || null
this.tagSeriesPart = payload.file_tag_seriespart || null
this.tagGrouping = payload.file_tag_grouping || null
this.tagTrack = payload.file_tag_track || null
this.tagDisc = payload.file_tag_disc || null
this.tagSubtitle = payload.file_tag_subtitle || null
Expand Down Expand Up @@ -196,6 +199,7 @@ class AudioMetaTags {
tagTitleSort: payload.file_tag_titlesort || null,
tagSeries: payload.file_tag_series || null,
tagSeriesPart: payload.file_tag_seriespart || null,
tagGrouping: payload.file_tag_grouping || null,
tagTrack: payload.file_tag_track || null,
tagDisc: payload.file_tag_disc || null,
tagSubtitle: payload.file_tag_subtitle || null,
Expand Down
30 changes: 25 additions & 5 deletions server/scanner/AudioFileScanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const prober = require('../utils/prober')
const { LogLevel } = require('../utils/constants')
const { parseOverdriveMediaMarkersAsChapters } = require('../utils/parsers/parseOverdriveMediaMarkers')
const parseNameString = require('../utils/parsers/parseNameString')
const parseSeriesString = require('../utils/parsers/parseSeriesString')
const LibraryItem = require('../models/LibraryItem')
const AudioFile = require('../objects/files/AudioFile')

Expand Down Expand Up @@ -256,6 +257,7 @@ class AudioFileScanner {
},
{
tag: 'tagSeries',
altTag: 'tagGrouping',
key: 'series'
},
{
Expand All @@ -276,8 +278,10 @@ class AudioFileScanner {
const audioFileMetaTags = firstScannedFile.metaTags
MetadataMapArray.forEach((mapping) => {
let value = audioFileMetaTags[mapping.tag]
let isAltTag = false
if (!value && mapping.altTag) {
value = audioFileMetaTags[mapping.altTag]
isAltTag = true
}

if (value && typeof value === 'string') {
Expand All @@ -290,12 +294,28 @@ class AudioFileScanner {
} else if (mapping.key === 'genres') {
bookMetadata.genres = this.parseGenresString(value)
} else if (mapping.key === 'series') {
bookMetadata.series = [
{
name: value,
sequence: audioFileMetaTags.tagSeriesPart || null
// If series was embedded in the grouping tag, then parse it with semicolon separator and sequence in the same string
// e.g. "Test Series; Series Name #1; Other Series #2"
if (isAltTag) {
const series = value
.split(';')
.map((seriesWithPart) => {
seriesWithPart = seriesWithPart.trim()
return parseSeriesString.parse(seriesWithPart)
})
.filter(Boolean)
if (series.length) {
bookMetadata.series = series
}
]
} else {
// Original embed used "series" and "series-part" tags
bookMetadata.series = [
{
name: value,
sequence: audioFileMetaTags.tagSeriesPart || null
}
]
}
} else {
bookMetadata[mapping.key] = value
}
Expand Down
3 changes: 1 addition & 2 deletions server/utils/ffmpegHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,8 @@ function getFFMetadataObject(libraryItem, audioFilesLength) {
copyright: metadata.publisher,
publisher: metadata.publisher, // mp3 only
TRACKTOTAL: `${audioFilesLength}`, // mp3 only
grouping: metadata.series?.map((s) => s.name + (s.sequence ? ` #${s.sequence}` : '')).join(', ')
grouping: metadata.series?.map((s) => s.name + (s.sequence ? ` #${s.sequence}` : '')).join('; ')
}

Object.keys(ffmetadata).forEach((key) => {
if (!ffmetadata[key]) {
delete ffmetadata[key]
Expand Down
27 changes: 7 additions & 20 deletions server/utils/generators/abmetadataGenerator.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const Logger = require('../../Logger')
const parseSeriesString = require('../parsers/parseSeriesString')

function parseJsonMetadataText(text) {
try {
Expand All @@ -19,39 +20,25 @@ function parseJsonMetadataText(text) {
delete abmetadataData.metadata

if (abmetadataData.series?.length) {
abmetadataData.series = [...new Set(abmetadataData.series.map(t => t?.trim()).filter(t => t))]
abmetadataData.series = abmetadataData.series.map(series => {
let sequence = null
let name = series
// Series sequence match any characters after " #" other than whitespace and another #
// e.g. "Name #1a" is valid. "Name #1#a" or "Name #1 a" is not valid.
const matchResults = series.match(/ #([^#\s]+)$/) // Pull out sequence #
if (matchResults && matchResults.length && matchResults.length > 1) {
sequence = matchResults[1] // Group 1
name = series.replace(matchResults[0], '')
}
return {
name,
sequence
}
})
abmetadataData.series = [...new Set(abmetadataData.series.map((t) => t?.trim()).filter((t) => t))]
abmetadataData.series = abmetadataData.series.map((series) => parseSeriesString.parse(series))
}
// clean tags & remove dupes
if (abmetadataData.tags?.length) {
abmetadataData.tags = [...new Set(abmetadataData.tags.map(t => t?.trim()).filter(t => t))]
abmetadataData.tags = [...new Set(abmetadataData.tags.map((t) => t?.trim()).filter((t) => t))]
}
if (abmetadataData.chapters?.length) {
abmetadataData.chapters = cleanChaptersArray(abmetadataData.chapters, abmetadataData.title)
}
// clean remove dupes
if (abmetadataData.authors?.length) {
abmetadataData.authors = [...new Set(abmetadataData.authors.map(t => t?.trim()).filter(t => t))]
abmetadataData.authors = [...new Set(abmetadataData.authors.map((t) => t?.trim()).filter((t) => t))]
}
if (abmetadataData.narrators?.length) {
abmetadataData.narrators = [...new Set(abmetadataData.narrators.map(t => t?.trim()).filter(t => t))]
abmetadataData.narrators = [...new Set(abmetadataData.narrators.map((t) => t?.trim()).filter((t) => t))]
}
if (abmetadataData.genres?.length) {
abmetadataData.genres = [...new Set(abmetadataData.genres.map(t => t?.trim()).filter(t => t))]
abmetadataData.genres = [...new Set(abmetadataData.genres.map((t) => t?.trim()).filter((t) => t))]
}
return abmetadataData
} catch (error) {
Expand Down
27 changes: 27 additions & 0 deletions server/utils/parsers/parseSeriesString.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Parse a series string into a name and sequence
*
* @example
* Name #1a => { name: 'Name', sequence: '1a' }
* Name #1 => { name: 'Name', sequence: '1' }
*
* @param {string} seriesString
* @returns {{name: string, sequence: string}|null}
*/
module.exports.parse = (seriesString) => {
if (!seriesString || typeof seriesString !== 'string') return null

let sequence = null
let name = seriesString
// Series sequence match any characters after " #" other than whitespace and another #
// e.g. "Name #1a" is valid. "Name #1#a" or "Name #1 a" is not valid.
const matchResults = seriesString.match(/ #([^#\s]+)$/) // Pull out sequence #
if (matchResults && matchResults.length && matchResults.length > 1) {
sequence = matchResults[1] // Group 1
name = seriesString.replace(matchResults[0], '')
}
return {
name,
sequence
}
}
1 change: 1 addition & 0 deletions server/utils/prober.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ function parseTags(format, verbose) {
file_tag_genre: tryGrabTags(format, 'genre', 'tcon', 'tco'),
file_tag_series: tryGrabTags(format, 'series', 'show', 'mvnm'),
file_tag_seriespart: tryGrabTags(format, 'series-part', 'episode_id', 'mvin', 'part'),
file_tag_grouping: tryGrabTags(format, 'grouping'),
file_tag_isbn: tryGrabTags(format, 'isbn'), // custom
file_tag_language: tryGrabTags(format, 'language', 'lang'),
file_tag_asin: tryGrabTags(format, 'asin', 'audible_asin'), // custom
Expand Down

0 comments on commit 953ffe8

Please sign in to comment.