diff --git a/vrobbler/apps/books/sources/openlibrary.py b/vrobbler/apps/books/sources/openlibrary.py index aecf4b5..92a2b75 100644 --- a/vrobbler/apps/books/sources/openlibrary.py +++ b/vrobbler/apps/books/sources/openlibrary.py @@ -1,129 +1,153 @@ import logging +import requests + logger = logging.getLogger(__name__) +OPENLIBRARY_BASE_URL = "https://openlibrary.org" + def lookup_book_from_openlibrary(title: str, author: str | None = None) -> dict: try: - from olclient import OpenLibrary - except ImportError: - logger.warning("openlibrary-client not installed") - return {} - - ol = OpenLibrary() - - try: - work_obj = ol.Work.search(title) + response = requests.get( + f"{OPENLIBRARY_BASE_URL}/search.json", + params={"title": title, "limit": 1}, + timeout=10, + ) + response.raise_for_status() + search_results = response.json() except Exception as e: - logger.warning(f"Could not find work for {title}: {e}") + logger.warning(f"Could not search for {title}: {e}") return {} - if not work_obj: + docs = search_results.get("docs", []) + if not docs: return {} - olid = work_obj.identifiers.get("olid", [None])[0] + work_doc = docs[0] + olid = work_doc.get("key", "").replace("/works/", "") if not olid: return {} try: - work_json = ol.Work.get(olid) + work_response = requests.get( + f"{OPENLIBRARY_BASE_URL}/works/{olid}.json", timeout=10 + ) + work_response.raise_for_status() + work_json = work_response.json() except Exception as e: logger.warning(f"Could not get work JSON for {olid}: {e}") return {} - book_dict: dict = {"title": work_json.title, "openlibrary_id": olid} + book_dict: dict = {"title": work_json.get("title"), "openlibrary_id": olid} - if description := getattr(work_json, "description", None): + description = work_json.get("description") + if description: if isinstance(description, dict): book_dict["summary"] = description.get("value", "") else: book_dict["summary"] = str(description) - if subjects := getattr(work_json, "subjects", None): + subjects = work_json.get("subjects", []) + if subjects: book_dict["genres"] = subjects[:10] - covers = getattr(work_json, "covers", None) + covers = work_json.get("covers", []) if covers: book_dict["cover_url"] = ( f"https://covers.openlibrary.org/b/id/{covers[0]}-L.jpg" ) try: - editions_data = ol.get(f"{olid}/editions.json") - if editions_data and (entries := editions_data.get("entries")): + editions_response = requests.get( + f"{OPENLIBRARY_BASE_URL}/works/{olid}/editions.json", timeout=10 + ) + if editions_response.status_code == 200: + editions_data = editions_response.json() + entries = editions_data.get("entries", []) if entries: edition = entries[0] - if isbn_list := edition.get("isbn_10"): + isbn_list = edition.get("isbn_10", []) + if isbn_list: book_dict["isbn_10"] = isbn_list[0] - if isbn_list := edition.get("isbn_13"): + isbn_list = edition.get("isbn_13", []) + if isbn_list: book_dict["isbn_13"] = isbn_list[0] - if publishers := edition.get("publishers"): + publishers = edition.get("publishers", []) + if publishers: book_dict["publisher"] = publishers[0] - if pub_date := edition.get("publish_date"): + pub_date = edition.get("publish_date") + if pub_date: book_dict["publish_date"] = pub_date if len(pub_date) >= 4: try: book_dict["first_publish_year"] = int(pub_date[:4]) except ValueError: pass - if pages := edition.get("number_of_pages_median"): + pages = edition.get("number_of_pages_median") + if pages: book_dict["pages"] = pages - if edition_covers := edition.get("covers"): - if edition_covers and not book_dict.get("cover_url"): - book_dict["cover_url"] = ( - f"https://covers.openlibrary.org/b/id/{edition_covers[0]}-L.jpg" - ) + edition_covers = edition.get("covers", []) + if edition_covers and not book_dict.get("cover_url"): + book_dict["cover_url"] = ( + f"https://covers.openlibrary.org/b/id/{edition_covers[0]}-L.jpg" + ) except Exception as e: logger.warning(f"Could not get editions for {olid}: {e}") if author: book_dict["authors"] = [author] - elif work_obj.authors: - book_dict["authors"] = [ - a.get("name", "") for a in work_obj.authors if a.get("name") - ] + elif work_doc.get("author_name"): + book_dict["authors"] = work_doc.get("author_name", []) return book_dict def lookup_author_from_openlibrary(name: str) -> dict: try: - from olclient import OpenLibrary - except ImportError: - logger.warning("openlibrary-client not installed") - return {} - - ol = OpenLibrary() - - try: - author_list = ol.Author.search(name) + response = requests.get( + f"{OPENLIBRARY_BASE_URL}/search.json", + params={"author": name, "limit": 1}, + timeout=10, + ) + response.raise_for_status() + search_results = response.json() except Exception as e: - logger.warning(f"Could not find author {name}: {e}") + logger.warning(f"Could not search for author {name}: {e}") return {} - if not author_list or not isinstance(author_list, list): + docs = search_results.get("docs", []) + if not docs: return {} - author_json = author_list[0] - author_olid = author_json.get("key", "").replace("/authors/", "") - + author_doc = docs[0] + author_olid = author_doc.get("key", "").replace("/authors/", "") if not author_olid: return {} author_dict: dict = { - "name": author_json.get("name", name), + "name": author_doc.get("name", name), "openlibrary_id": author_olid, } - if author_json.get("bio"): - bio = author_json.get("bio") - if isinstance(bio, dict): - author_dict["bio"] = bio.get("value", "") - else: - author_dict["bio"] = str(bio) + try: + author_response = requests.get( + f"{OPENLIBRARY_BASE_URL}/authors/{author_olid}.json", timeout=10 + ) + if author_response.status_code == 200: + author_json = author_response.json() + bio = author_json.get("bio") + if bio: + if isinstance(bio, dict): + author_dict["bio"] = bio.get("value", "") + else: + author_dict["bio"] = str(bio) - if wikipedia := author_json.get("wikipedia"): - author_dict["wikipedia_url"] = wikipedia + wikipedia = author_json.get("wikipedia") + if wikipedia: + author_dict["wikipedia_url"] = wikipedia + except Exception as e: + logger.warning(f"Could not get author JSON for {author_olid}: {e}") author_dict["author_headshot_url"] = ( f"https://covers.openlibrary.org/a/olid/{author_olid}-L.jpg"