mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-11-13 12:23:34 +01:00
Add one name dedupe function and use it for parsed names and metadata.json
This commit is contained in:
1 parent
616c8ba152
commit
f1f57d6595
3 files changed
+41
-5
No files matched your search
@@ -1,5 +1,6 @@
|
||||
const Logger = require('../../Logger')
|
||||
const parseSeriesString = require('../parsers/parseSeriesString')
|
||||
const { dedupeNames } = require('../parsers/parseNameString')
|
||||
|
||||
const mediaTypeKeys = {
|
||||
book: {
|
||||
@@ -140,8 +141,7 @@ function validateMetadataValue(key, value, expectedType) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const cleanedArray = value.filter((t) => typeof t === 'string')
|
||||
return [...new Set(cleanedArray.map((t) => t.trim()).filter((t) => t))]
|
||||
return dedupeNames(value)
|
||||
}
|
||||
|
||||
Logger.warn(`[abmetadataGenerator] Unknown expected type "${expectedType}" for key "${key}"`)
|
||||
|
||||
@@ -35,6 +35,28 @@ module.exports.nameToLastFirst = (firstLast) => {
|
||||
return `${nameObj.last_name}, ${nameObj.first_name}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim names, drop blanks, and drop exact repeats. The first spelling is kept.
|
||||
* Callers that build bookAuthors rows should use this instead of deduping per metadata source.
|
||||
*
|
||||
* @param {string[]} names
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function dedupeNames(names) {
|
||||
if (!Array.isArray(names)) return []
|
||||
const seen = new Set()
|
||||
const deduped = []
|
||||
for (const name of names) {
|
||||
if (typeof name !== 'string') continue
|
||||
const trimmed = name.trim()
|
||||
if (!trimmed || seen.has(trimmed)) continue
|
||||
seen.add(trimmed)
|
||||
deduped.push(trimmed)
|
||||
}
|
||||
return deduped
|
||||
}
|
||||
module.exports.dedupeNames = dedupeNames
|
||||
|
||||
/**
|
||||
* Parses a name string into an array of names
|
||||
*
|
||||
@@ -62,7 +84,7 @@ module.exports.parse = (nameString) => {
|
||||
// If names are in Chinese,Japanese and Korean languages, return as is.
|
||||
if (/[\u4e00-\u9fff\u3040-\u30ff\u31f0-\u31ff]/.test(splitNames[0])) {
|
||||
return {
|
||||
names: splitNames
|
||||
names: dedupeNames(splitNames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +124,7 @@ module.exports.parse = (nameString) => {
|
||||
names = names.filter((n) => n.first_name || n.last_name)
|
||||
|
||||
// Set name strings and remove duplicates
|
||||
const namesArray = [...new Set(names.map((a) => (a.first_name ? `${a.first_name} ${a.last_name}` : a.last_name)))]
|
||||
const namesArray = dedupeNames(names.map((a) => (a.first_name ? `${a.first_name} ${a.last_name}` : a.last_name)))
|
||||
|
||||
return {
|
||||
names: namesArray // Array of first last
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const chai = require('chai')
|
||||
const expect = chai.expect
|
||||
const { parse, nameToLastFirst } = require('../../../../server/utils/parsers/parseNameString')
|
||||
const { parse, nameToLastFirst, dedupeNames } = require('../../../../server/utils/parsers/parseNameString')
|
||||
|
||||
describe('parseNameString', () => {
|
||||
describe('parse', () => {
|
||||
@@ -80,6 +80,20 @@ describe('parseNameString', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('dedupeNames', () => {
|
||||
it('trims, drops blanks, and keeps the first spelling of an exact repeat', () => {
|
||||
expect(dedupeNames([' Stephen King ', 'Stephen King', '', ' ', 'stephen king'])).to.deep.equal(['Stephen King', 'stephen king'])
|
||||
})
|
||||
|
||||
it('preserves order and ignores non-strings', () => {
|
||||
expect(dedupeNames(['Amy Yao', null, 'Amy Yao', 3, 'Raymond Chandler'])).to.deep.equal(['Amy Yao', 'Raymond Chandler'])
|
||||
})
|
||||
|
||||
it('returns an empty array for non-arrays', () => {
|
||||
expect(dedupeNames(null)).to.deep.equal([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('nameToLastFirst', () => {
|
||||
it('converts First Last to Last, First format', () => {
|
||||
const result = nameToLastFirst('John Smith')
|
||||
|
||||
Reference in new issue
Block a user