Commit d9f7be8a authored by ale's avatar ale

add OpenLibrary metadata lookup (unused for now)

parent a56704d4
package liber
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"regexp"
"strings"
)
type openLibraryRefiner struct{}
func (r *openLibraryRefiner) Name() string {
return "openlibrary"
}
type olSearchResults struct {
Docs []olSearchResult `json:"docs"`
}
type olSearchResult struct {
Title string `json:"title"`
Author string `json:"author_name"`
Date string `json:"first_publish_year"`
OLKey string `json:"key"`
}
type olAuthor struct {
Name string `json:"name"`
}
type olPublisher olAuthor
type olExcerpt struct {
Text string `json:"text"`
}
type olMetadata struct {
Key string `json:"key"`
Title string `json:"title"`
Identifiers map[string][]string `json:"identifiers"`
Authors []*olAuthor `json:"authors"`
Excerpts []*olExcerpt `json:"excerpts"`
Publishers []*olPublisher `json:"publishers"`
PublishDate string `json:"publish_date"`
Cover map[string]string `json:"cover"`
Language []string
}
var dateRx = regexp.MustCompile(`(\d{4})`)
func (m *olMetadata) toMetadata() *Metadata {
out := &Metadata{
Title: m.Title,
Language: m.Language,
}
for _, a := range m.Authors {
out.Creator = append(out.Creator, a.Name)
}
for _, p := range m.Publishers {
out.Publisher = append(out.Publisher, p.Name)
}
for _, attr := range []string{"isbn_10", "isbn_13"} {
if isbn, ok := m.Identifiers[attr]; ok {
out.ISBN = append(out.ISBN, isbn...)
}
}
if match := dateRx.FindString(m.PublishDate); match != "" {
out.Date = match
}
for _, e := range m.Excerpts {
out.Description = e.Text
break
}
return out
}
var olSemaphore = make(chan bool, 3)
func openlibraryQuery(uri string, out interface{}) error {
olSemaphore <- true
defer func() {
<-olSemaphore
}()
resp, err := http.Get(uri)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("HTTP status %s", resp.Status)
}
if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
return err
}
return nil
}
// Return book information given an ID.
func (r *openLibraryRefiner) queryBibKeys(bibkeys []string) ([]*Metadata, error) {
values := make(url.Values)
values.Set("bibkeys", strings.Join(bibkeys, ","))
values.Set("jscmd", "data")
values.Set("format", "json")
uri := fmt.Sprintf("https://openlibrary.org/api/books?%s", values.Encode())
var result map[string]*olMetadata
if err := openlibraryQuery(uri, &result); err != nil {
return nil, err
}
var out []*Metadata
for _, m := range result {
out = append(out, m.toMetadata())
}
return out, nil
}
// Find a book given one or more ISBN numbers.
func (r *openLibraryRefiner) queryISBN(isbn []string) ([]*Metadata, error) {
var bibkeys []string
for _, i := range isbn {
bibkeys = append(bibkeys, fmt.Sprintf("ISBN:%s", i))
}
return r.queryBibKeys(bibkeys)
}
// Find a book using title/author.
func (r *openLibraryRefiner) queryTitleAuthor(m *Metadata) ([]*Metadata, error) {
values := make(url.Values)
values.Set("title", m.Title)
if len(m.Creator) > 0 {
values.Set("author", m.Creator[0])
}
uri := fmt.Sprintf("https://openlibrary.org/search.json?%s", values.Encode())
var result olSearchResults
if err := openlibraryQuery(uri, &result); err != nil {
return nil, err
}
var bibkeys []string
for _, doc := range result.Docs {
bibkeys = append(bibkeys, fmt.Sprintf("OLID:%s", doc.OLKey))
}
return r.queryBibKeys(bibkeys)
}
func (r *openLibraryRefiner) Lookup(m *Metadata) ([]*Metadata, error) {
if len(m.ISBN) > 0 {
return r.queryISBN(m.ISBN)
}
return r.queryTitleAuthor(m)
}
func (r *openLibraryRefiner) GetBookCover(m *Metadata) ([]byte, error) {
return nil, nil
}
......@@ -306,6 +306,7 @@ func (db *Database) Update(dir string, chooser MetadataChooserFunc) {
// Check Google Books when the metadata is not
// sufficient to fully describe the book.
refiners: []MetadataRefiner{
//&openLibraryRefiner{},
&googleBooksRefiner{},
},
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment