From 95f0307be1c55fc90aad852c300006e4a4ddab0b Mon Sep 17 00:00:00 2001 From: JB Date: Tue, 11 Nov 2025 07:56:51 -0800 Subject: [PATCH] feat: Add handling for author-series name collisions in Audiobookshelf metadata --- abogen/web/service.py | 29 +++++++++++++++++++++++++++++ tests/test_service.py | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/abogen/web/service.py b/abogen/web/service.py index 6f7af49..f2e89f0 100644 --- a/abogen/web/service.py +++ b/abogen/web/service.py @@ -359,6 +359,33 @@ def _build_audiobookshelf_metadata(job: Job) -> Dict[str, Any]: tags.get("series_title"), tags.get("seriestitle"), ) + if series_name: + normalized_series = series_name.strip() + if normalized_series: + author_candidates: set[str] = set() + for name in authors: + author_name = name.strip() + if author_name: + author_candidates.add(author_name.casefold()) + raw_author_fields = ( + tags.get("authors"), + tags.get("author"), + tags.get("album_artist"), + tags.get("artist"), + tags.get("writer"), + tags.get("composer"), + ) + for raw_author in raw_author_fields: + if not raw_author: + continue + author_text = str(raw_author).strip() + if author_text: + author_candidates.add(author_text.casefold()) + joined_authors = ", ".join(authors) + if joined_authors: + author_candidates.add(joined_authors.casefold()) + if normalized_series.casefold() in author_candidates: + series_name = None series_sequence = None for key in _SERIES_SEQUENCE_TAG_KEYS: raw_value = tags.get(key) @@ -366,6 +393,8 @@ def _build_audiobookshelf_metadata(job: Job) -> Dict[str, Any]: if normalized_sequence: series_sequence = normalized_sequence break + if not series_name: + series_sequence = None data: Dict[str, Any] = { "title": title, "authors": authors, diff --git a/tests/test_service.py b/tests/test_service.py index 652679b..18d68f5 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -248,4 +248,36 @@ def test_audiobookshelf_metadata_allows_decimal_sequence(tmp_path): metadata = _build_audiobookshelf_metadata(job) - assert metadata["seriesSequence"] == "4.5" \ No newline at end of file + assert metadata["seriesSequence"] == "4.5" + + +def test_audiobookshelf_metadata_ignores_author_series_collision(tmp_path): + source = tmp_path / "book.txt" + source.write_text("content", encoding="utf-8") + + job = Job( + id="job-abs-author-series", + original_filename="book.txt", + stored_path=source, + language="en", + voice="af_alloy", + speed=1.0, + use_gpu=False, + subtitle_mode="Sentence", + output_format="mp3", + save_mode="Save next to input file", + output_folder=tmp_path, + replace_single_newlines=False, + subtitle_format="srt", + created_at=time.time(), + metadata_tags={ + "series": "Jane Doe", + "series_index": "1", + "authors": "Jane Doe", + }, + ) + + metadata = _build_audiobookshelf_metadata(job) + + assert "seriesName" not in metadata + assert "seriesSequence" not in metadata \ No newline at end of file