from __future__ import annotations import logging from datetime import datetime, timezone from django.core.files.base import ContentFile from apps.books.models import EBook from apps.books.services.openlibrary import ( HIGH_CONFIDENCE, download_cover, fetch_metadata, ) logger = logging.getLogger(__name__) def enrich_ebook_metadata(ebook: EBook) -> EBook: """Fetch Open Library metadata and update the ebook. Never raises to callers.""" user_title = ebook.title user_author = ebook.author or "" try: result = fetch_metadata(user_title, user_author) except Exception: logger.exception("Open Library metadata fetch failed for ebook %s", ebook.pk) return ebook if result is None: return ebook now = datetime.now(timezone.utc).isoformat() metadata = { "source": "openlibrary", "matched_at": now, "match_language": result.match_language, "match_score": result.match_score, "match_status": result.match_status, "user_input": {"title": user_title, "author": user_author}, "openlibrary": result.openlibrary, } ebook.metadata_json = metadata update_fields = ["metadata_json", "updated_at"] if result.match_status == "not_found": ebook.save(update_fields=update_fields) return ebook ol = result.openlibrary cover_id = ol.get("cover_id") cover_missing = ( not ebook.cover_image or not ebook.cover_image.name or not ebook.cover_image.storage.exists(ebook.cover_image.name) ) if cover_id and cover_missing: if ebook.cover_image: ebook.cover_image.delete(save=False) cover_bytes = download_cover(int(cover_id)) if cover_bytes: filename = f"ol_cover_{ebook.pk}_{cover_id}.jpg" ebook.cover_image.save(filename, ContentFile(cover_bytes), save=False) update_fields.append("cover_image") if result.match_score >= HIGH_CONFIDENCE: ol_title = ol.get("title") ol_authors = ol.get("authors") or [] if ol_title: ebook.title = ol_title[:512] update_fields.append("title") if ol_authors: ebook.author = ol_authors[0][:256] update_fields.append("author") ebook.save(update_fields=list(dict.fromkeys(update_fields))) return ebook