From 3b617a910ae3a600956c6dffff6e66b65e48d5e9 Mon Sep 17 00:00:00 2001 From: Steppenstreuner Date: Fri, 28 Aug 2026 13:12:26 +0200 Subject: [PATCH] fix(metadata): use audible.de api for german audiobooks --- wordarr/metadata/audible.py | 53 ++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/wordarr/metadata/audible.py b/wordarr/metadata/audible.py index 699ae04..7bd3781 100644 --- a/wordarr/metadata/audible.py +++ b/wordarr/metadata/audible.py @@ -1,32 +1,53 @@ +import asyncio +import os + import httpx from .base import MetadataResult +# Comma-separated marketplace TLDs, first entries rank first in the results. +REGIONS = [r.strip() for r in os.environ.get("WORDARR_AUDIBLE_REGIONS", "de,com").split(",")] -async def search(query: str) -> list[MetadataResult]: + +async def _search_region(client: httpx.AsyncClient, tld: str, query: str) -> list[dict]: params = { "keywords": query, "num_results": 10, "response_groups": "media,contributors,product_desc,product_attrs", "products_sort_by": "Relevance", } - async with httpx.AsyncClient(timeout=15) as client: - resp = await client.get("https://api.audible.com/1.0/catalog/products", params=params) + try: + resp = await client.get(f"https://api.audible.{tld}/1.0/catalog/products", params=params) resp.raise_for_status() - products = resp.json().get("products", []) + return resp.json().get("products", []) + except httpx.HTTPError: + return [] + + +async def search(query: str) -> list[MetadataResult]: + async with httpx.AsyncClient(timeout=15) as client: + region_results = await asyncio.gather( + *(_search_region(client, tld, query) for tld in REGIONS) + ) results = [] - for p in products: - images = p.get("product_images") or {} - release = p.get("release_date") or "" - results.append( - MetadataResult( - media_type="audiobook", - title=p.get("title", ""), - authors=", ".join(a.get("name", "") for a in p.get("authors") or []), - external_id=p.get("asin", ""), - year=int(release[:4]) if release[:4].isdigit() else None, - cover_url=next(iter(images.values()), ""), + seen_asins = set() + for products in region_results: + for p in products: + asin = p.get("asin", "") + if asin in seen_asins: + continue + seen_asins.add(asin) + images = p.get("product_images") or {} + release = p.get("release_date") or "" + results.append( + MetadataResult( + media_type="audiobook", + title=p.get("title", ""), + authors=", ".join(a.get("name", "") for a in p.get("authors") or []), + external_id=asin, + year=int(release[:4]) if release[:4].isdigit() else None, + cover_url=next(iter(images.values()), ""), + ) ) - ) return results