Begin cutting AddedContent over to the OpenLibrary Read API
authorDan Scott <dan@coffeecode.net>
Thu, 2 Jun 2011 13:46:24 +0000 (09:46 -0400)
committerDan Scott <dan@coffeecode.net>
Fri, 3 Jun 2011 15:39:55 +0000 (11:39 -0400)
Use the all-in-one Read API request to get results; this should
cut our requests in half and improve our caching results.

Signed-off-by: Dan Scott <dscott@laurentian.ca>
Open-ILS/src/perlmods/lib/OpenILS/WWW/AddedContent/OpenLibrary.pm

index 41f8ee8..7d3ae81 100644 (file)
@@ -28,10 +28,10 @@ use Data::Dumper;
 
 my $AC = 'OpenILS::WWW::AddedContent';
 
-# These URLs are always the same for OpenLibrary, so there's no advantage to
-# pulling from opensrf.xml; we hardcode them here
-my $base_url = 'http://openlibrary.org/api/books?details=true&bibkeys=ISBN:';
-my $cover_base_url = 'http://covers.openlibrary.org/b/isbn/';
+# This URL is always the same for OpenLibrary, so there's no advantage to
+# pulling from opensrf.xml
+
+my $read_api = 'http://openlibrary.org/api/volumes/brief/json/';
 
 sub new {
     my( $class, $args ) = @_;
@@ -60,17 +60,16 @@ sub jacket_large {
 
 # --------------------------------------------------------------------------
 
-
-sub excerpt_html {
+sub ebooks_html {
     my( $self, $key ) = @_;
-    my $book_details_json = $self->fetch_details_response($key)->content();
+    my $book_data_json = $self->fetch_response($key)->content();
 
-    $logger->debug("$key: $book_details_json");
+    $logger->debug("$key: " . $book_data_json);
 
-    my $excerpt_html;
+    my $ebook_html;
     
-    my $book_details = OpenSRF::Utils::JSON->JSON2perl($book_details_json);
-    my $book_key = (keys %$book_details)[0];
+    my $book_data = OpenSRF::Utils::JSON->JSON2perl($book_data_json);
+    my $book_key = (keys %$book_data)[0];
 
     # We didn't find a matching book; short-circuit our response
     if (!$book_key) {
@@ -78,12 +77,59 @@ sub excerpt_html {
         return 0;
     }
 
-    my $first_sentence = $book_details->{$book_key}->{first_sentence};
+    my $ebooks_json = $book_data->{$book_key}->{ebooks};
+
+    # No ebooks are available for this book; short-circuit
+    if (!$ebooks_json or !scalar(@$ebooks_json)) {
+        $logger->debug("$key: no ebooks");
+        return 0;
+    }
+
+    # Check the availability of the ebooks
+    my $available = $ebooks_json->[0]->{'availability'} || '';
+    if (!$available) {
+        $logger->debug("$key: no available ebooks");
+        return 0;
+    }
+
+    # Build a basic list of available ebook types and their URLs
+    # ebooks appears to be an array containing one element - a hash
+
+    # First element of the hash is 'read_url' which is a URL to
+    # Internet Archive online reader
+    my $stream_url = $ebooks_json->[0]->{'read_url'} || '';
+    if ($stream_url) {
+        $ebook_html .= "<li class='ebook_stream'><a href='$stream_url'>Read online</a></li>\n";
+        $logger->debug("$key: stream URL = $stream_url");
+    }
+
+    my $ebook_formats = $ebooks_json->[0]->{'formats'} || '';
+    # Next elements are various ebook formats that are available
+    foreach my $ebook (keys %{$ebook_formats}) {
+        if ($ebook_formats->{$ebook} eq 'read_url') {
+            next;
+        }
+        $ebook_html .= "<li class='ebook_$ebook'><a href='" . 
+            $ebook_formats->{$ebook}->{'url'} . "'>" . uc($ebook) . "</a></li>\n";
+    }
+
+    $logger->debug("$key: $ebook_html");
+    $self->send_html("<ul class='ebooks'>$ebook_html</ul>");
+}
+
+sub excerpt_html {
+    my( $self, $key ) = @_;
+
+    my $excerpt_html;
+
+    my $content = $self->fetch_details_response($key)->content();
+
+    my $first_sentence = $content->{details}->{first_sentence};
     if ($first_sentence) {
         $excerpt_html .= "<div class='sentence1'>$first_sentence</div>\n";
     }
 
-    my $excerpts_json = $book_details->{$book_key}->{excerpts};
+    my $excerpts_json = $content->{details}->{$book_key}->{excerpts};
     if ($excerpts_json && scalar(@$excerpts_json)) {
         # Load up excerpt text with comments in tooltip
         foreach my $excerpt (@$excerpts_json) {
@@ -115,27 +161,12 @@ HTML table.
 
 sub toc_html {
     my( $self, $key ) = @_;
-    my $book_details_json = $self->fetch_response($key)->content();
-
-
-    # Trim the "var _OlBookInfo = " declaration that makes this
-    # invalid JSON
-    $book_details_json =~ s/^.+?({.*?});$/$1/s;
-
-    $logger->debug("$key: " . $book_details_json);
 
     my $toc_html;
     
-    my $book_details = OpenSRF::Utils::JSON->JSON2perl($book_details_json);
-    my $book_key = (keys %$book_details)[0];
-
-    # We didn't find a matching book; short-circuit our response
-    if (!$book_key) {
-        $logger->debug("$key: no found book");
-        return 0;
-    }
+    my $details = $self->fetch_details_response($key) || return 0;
 
-    my $toc_json = $book_details->{$book_key}->{details}->{table_of_contents};
+    my $toc_json = $details->{table_of_contents};
 
     # No table of contents is available for this book; short-circuit
     if (!$toc_json or !scalar(@$toc_json)) {
@@ -210,16 +241,49 @@ sub send_html {
 # returns the HTTP response object from the URL fetch
 sub fetch_response {
     my( $self, $key ) = @_;
-    my $url = $base_url . "$key";
+
+    # TODO: OpenLibrary can also accept lccn, oclc, olid...
+    # Hardcoded to only accept ISBNs for now.
+    $key = "isbn:$key";
+
+    my $url = $read_api . $key;
     my $response = $AC->get_url($url);
-    return $response;
+
+    my $book_results = OpenSRF::Utils::JSON->JSON2perl($response);
+    my $record = $book_results->{$key};
+
+    # We didn't find a matching book; short-circuit our response
+    if (!$record) {
+        $logger->debug("$key: no found record");
+        return 0;
+    }
+
+    return $record;
+}
+
+sub fetch_details_response {
+    my ($self, $key) = @_;
+
+    my $book_results = $self->fetch_response($key)->content();
+
+    $logger->debug("$key: $book_results");
+    
+    my $book_key = (keys %$book_results)[0];
+
+    # We didn't find a matching book; short-circuit our response
+    if (!$book_key) {
+        $logger->debug("$key: no found book");
+        return 0;
+    }
+
+    return $book_results->{$book_key}->{details};
 }
 
 # returns the HTTP response object from the URL fetch
 sub fetch_cover_response {
     my( $self, $size, $key ) = @_;
 
-    my $response = $self->fetch_data_response($key)->content();
+    my $response = $self->fetch_response($key)->content();
 
     my $book_data = OpenSRF::Utils::JSON->JSON2perl($response);
     my $book_key = (keys %$book_data)[0];
@@ -240,5 +304,4 @@ sub fetch_cover_response {
     return $AC->get_url($covers_json->{$size}) || 0;
 }
 
-
 1;