99from infogami .utils .delegate import register_exception
1010from openlibrary .core import helpers as h
1111from openlibrary .core import ia
12+ from openlibrary .core import lending
1213from openlibrary .core .imports import ImportItem
1314from openlibrary .core .models import Edition
1415from openlibrary .plugins .openlibrary .processors import urlsafe
@@ -182,6 +183,18 @@ def process(self, result):
182183 for a in w .get ('authors' , [])
183184 ]
184185 self .authors = get_many_as_dict (author_keys )
186+
187+ # Collect all ocaids for bulk availability request
188+ ocaids = [doc .get ('ocaid' ) for doc in result .values () if doc .get ('ocaid' )]
189+
190+ # Make bulk availability request if we have ocaids
191+ self .availability_map = {}
192+ if ocaids :
193+ try :
194+ self .availability_map = lending .get_availability ('identifier' , ocaids )
195+ except Exception :
196+ # Fall back to individual calls if bulk API fails
197+ self .availability_map = {}
185198
186199 return {k : self .process_doc (doc ) for k , doc in result .items ()}
187200
@@ -313,7 +326,12 @@ def row(r):
313326
314327 def ebook (doc ):
315328 itemid = doc ['ocaid' ]
316- availability = get_ia_availability (itemid )
329+ # Use bulk availability data if available, otherwise fall back to individual call
330+ availability_data = self .availability_map .get (itemid )
331+ if availability_data :
332+ availability = map_availability_to_legacy_contract (availability_data )
333+ else :
334+ availability = get_ia_availability (itemid )
317335
318336 d = {
319337 "preview_url" : "https://archive.org/details/" + itemid ,
@@ -378,8 +396,11 @@ def get_authors(docs):
378396
379397
380398def process_result_for_details (result ):
381- def f (bib_key , doc ):
382- d = process_doc_for_viewapi (bib_key , doc )
399+ def f (bib_key , doc , availability_map ):
400+ # Get availability for this document's ocaid
401+ ocaid = doc .get ('ocaid' )
402+ availability = availability_map .get (ocaid ) if ocaid else None
403+ d = process_doc_for_viewapi (bib_key , doc , availability )
383404
384405 if 'authors' in doc :
385406 doc ['authors' ] = [author_dict [a ['key' ]] for a in doc ['authors' ]]
@@ -388,11 +409,41 @@ def f(bib_key, doc):
388409 return d
389410
390411 author_dict = get_authors (result .values ())
391- return {k : f (k , doc ) for k , doc in result .items ()}
412+
413+ # Collect all ocaids for bulk availability request
414+ ocaids = [doc .get ('ocaid' ) for doc in result .values () if doc .get ('ocaid' )]
415+
416+ # Make bulk availability request if we have ocaids
417+ availability_map = {}
418+ if ocaids :
419+ try :
420+ availability_map = lending .get_availability ('identifier' , ocaids )
421+ except Exception :
422+ # Fall back to individual calls if bulk API fails
423+ availability_map = {}
424+
425+ return {k : f (k , doc , availability_map ) for k , doc in result .items ()}
392426
393427
394428def process_result_for_viewapi (result ):
395- return {k : process_doc_for_viewapi (k , doc ) for k , doc in result .items ()}
429+ # Collect all ocaids for bulk availability request
430+ ocaids = [doc .get ('ocaid' ) for doc in result .values () if doc .get ('ocaid' )]
431+
432+ # Make bulk availability request if we have ocaids
433+ availability_map = {}
434+ if ocaids :
435+ try :
436+ availability_map = lending .get_availability ('identifier' , ocaids )
437+ except Exception :
438+ # Fall back to individual calls if bulk API fails
439+ availability_map = {}
440+
441+ return {
442+ k : process_doc_for_viewapi (
443+ k , doc , availability_map .get (doc .get ('ocaid' ))
444+ )
445+ for k , doc in result .items ()
446+ }
396447
397448
398449def get_ia_availability (itemid ):
@@ -406,11 +457,38 @@ def get_ia_availability(itemid):
406457 return 'full'
407458
408459
409- def process_doc_for_viewapi (bib_key , page ):
460+ def map_availability_to_legacy_contract (availability_data ):
461+ """
462+ Map bulk availability API response to legacy contract values.
463+
464+ Args:
465+ availability_data: AvailabilityStatusV2 dict from bulk API
466+
467+ Returns:
468+ str: One of 'borrow', 'restricted', 'full', or 'noview' for missing data
469+ """
470+ if not availability_data :
471+ return 'noview'
472+
473+ # Apply the same logic as get_ia_availability but using bulk API fields
474+ if availability_data .get ('is_lendable' ):
475+ return 'borrow'
476+ elif availability_data .get ('is_printdisabled' ):
477+ return 'restricted'
478+ else :
479+ return 'full'
480+
481+
482+ def process_doc_for_viewapi (bib_key , page , availability = None ):
410483 url = get_url (page )
411484
412485 if 'ocaid' in page :
413- preview = get_ia_availability (page ['ocaid' ])
486+ if availability is not None :
487+ # Use provided availability data from bulk API
488+ preview = map_availability_to_legacy_contract (availability )
489+ else :
490+ # Fallback to individual API call for backward compatibility
491+ preview = get_ia_availability (page ['ocaid' ])
414492 preview_url = 'https://archive.org/details/' + page ['ocaid' ]
415493 else :
416494 preview = 'noview'
0 commit comments