diff --git a/abogen/web/routes/api.py b/abogen/web/routes/api.py index 4057a3e..938e15d 100644 --- a/abogen/web/routes/api.py +++ b/abogen/web/routes/api.py @@ -225,6 +225,7 @@ def api_calibre_opds_import() -> ResponseReturnValue: raw_series = metadata_payload.get("series") or metadata_payload.get("series_name") series_name = str(raw_series or "").strip() + if series_name: metadata_overrides["series"] = series_name metadata_overrides.setdefault("series_name", series_name) @@ -258,6 +259,18 @@ def api_calibre_opds_import() -> ResponseReturnValue: metadata_overrides.setdefault("description", description_text) metadata_overrides.setdefault("summary", description_text) + subtitle_value = metadata_payload.get("subtitle") + if subtitle_value: + subtitle_text = _stringify_metadata_value(subtitle_value) + if subtitle_text: + metadata_overrides.setdefault("subtitle", subtitle_text) + + publisher_value = metadata_payload.get("publisher") + if publisher_value: + publisher_text = _stringify_metadata_value(publisher_value) + if publisher_text: + metadata_overrides.setdefault("publisher", publisher_text) + settings = load_settings() integrations = load_integration_settings() calibre_settings = integrations.get("calibre_opds", {}) diff --git a/abogen/web/routes/utils/form.py b/abogen/web/routes/utils/form.py index 16c3f8c..c8cb724 100644 --- a/abogen/web/routes/utils/form.py +++ b/abogen/web/routes/utils/form.py @@ -600,6 +600,46 @@ def apply_book_step_form( pending.applied_speaker_config = (form.get("speaker_config") or "").strip() or None + # Metadata updates + if "meta_title" in form: + pending.metadata_tags["title"] = str(form.get("meta_title", "")).strip() + + if "meta_subtitle" in form: + pending.metadata_tags["subtitle"] = str(form.get("meta_subtitle", "")).strip() + + if "meta_author" in form: + authors = str(form.get("meta_author", "")).strip() + pending.metadata_tags["authors"] = authors + pending.metadata_tags["author"] = authors + + if "meta_series" in form: + series = str(form.get("meta_series", "")).strip() + pending.metadata_tags["series"] = series + pending.metadata_tags["series_name"] = series + pending.metadata_tags["seriesname"] = series + pending.metadata_tags["series_title"] = series + pending.metadata_tags["seriestitle"] = series + # If user manually edits series, update opds_series too so it persists + if "opds_series" in pending.metadata_tags: + pending.metadata_tags["opds_series"] = series + + if "meta_series_index" in form: + idx = str(form.get("meta_series_index", "")).strip() + pending.metadata_tags["series_index"] = idx + pending.metadata_tags["series_sequence"] = idx + + if "meta_publisher" in form: + pending.metadata_tags["publisher"] = str(form.get("meta_publisher", "")).strip() + + if "meta_description" in form: + desc = str(form.get("meta_description", "")).strip() + pending.metadata_tags["description"] = desc + pending.metadata_tags["summary"] = desc + + if coerce_bool(form.get("remove_cover"), False): + pending.cover_image_path = None + pending.cover_image_mime = None + def persist_cover_image(extraction_result: Any, stored_path: Path) -> tuple[Optional[Path], Optional[str]]: cover_bytes = getattr(extraction_result, "cover_image", None) if not cover_bytes: diff --git a/abogen/web/service.py b/abogen/web/service.py index 3e053e4..3b47995 100644 --- a/abogen/web/service.py +++ b/abogen/web/service.py @@ -389,33 +389,7 @@ 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) @@ -427,9 +401,11 @@ def build_audiobookshelf_metadata(job: Job) -> Dict[str, Any]: series_sequence = None data: Dict[str, Any] = { "title": title, + "subtitle": tags.get("subtitle"), "authors": authors, "narrators": narrators, "description": description, + "publisher": tags.get("publisher"), "genres": genres, "tags": keywords, "language": language, diff --git a/abogen/web/templates/partials/new_job_step_book.html b/abogen/web/templates/partials/new_job_step_book.html index c4b2879..13b46d3 100644 --- a/abogen/web/templates/partials/new_job_step_book.html +++ b/abogen/web/templates/partials/new_job_step_book.html @@ -220,6 +220,53 @@ + + Book Metadata + + + Title + + + + Subtitle + + + + Author(s) + + Comma separated for multiple authors + + + Series + + + + Series Index + + + + Publisher + + + + Description + {{ pending.metadata_tags.get('description', '') or pending.metadata_tags.get('summary', '') }} + + + + + + Remove Cover Image + + {% if pending.cover_image_path %} + Cover image currently exists. + {% else %} + No cover image found. + {% endif %} + + + + Narrator defaults
Comma separated for multiple authors
Cover image currently exists.
No cover image found.