2021-04-06 18:58:07 +00:00
|
|
|
""" inventaire data connector """
|
2021-04-07 01:34:55 +00:00
|
|
|
from bookwyrm import models
|
2021-04-06 18:58:07 +00:00
|
|
|
from .abstract_connector import AbstractConnector, SearchResult, Mapping
|
|
|
|
from .abstract_connector import get_data
|
2021-04-06 20:39:10 +00:00
|
|
|
from .connector_manager import ConnectorException
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Connector(AbstractConnector):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""instantiate a connector for OL"""
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def __init__(self, identifier):
|
|
|
|
super().__init__(identifier)
|
|
|
|
|
2021-04-07 00:46:06 +00:00
|
|
|
get_first = lambda a: a[0]
|
|
|
|
shared_mappings = [
|
|
|
|
Mapping("id", remote_field="uri", formatter=self.get_remote_id),
|
|
|
|
Mapping("bnfId", remote_field="wdt:P268", formatter=get_first),
|
|
|
|
Mapping("openlibraryKey", remote_field="wdt:P648", formatter=get_first),
|
|
|
|
]
|
2021-04-06 18:58:07 +00:00
|
|
|
self.book_mappings = [
|
2021-04-06 20:53:58 +00:00
|
|
|
Mapping("title", remote_field="wdt:P1476", formatter=get_first),
|
|
|
|
Mapping("subtitle", remote_field="wdt:P1680", formatter=get_first),
|
2021-04-06 20:03:22 +00:00
|
|
|
Mapping("inventaireId", remote_field="uri"),
|
2021-04-06 18:58:07 +00:00
|
|
|
Mapping("cover", remote_field="image", formatter=self.get_cover_url),
|
2021-04-06 20:53:58 +00:00
|
|
|
Mapping("isbn13", remote_field="wdt:P212", formatter=get_first),
|
|
|
|
Mapping("isbn10", remote_field="wdt:P957", formatter=get_first),
|
2021-04-07 01:00:54 +00:00
|
|
|
Mapping("oclcNumber", remote_field="wdt:P5331", formatter=get_first),
|
2021-04-07 00:46:06 +00:00
|
|
|
Mapping("goodreadsKey", remote_field="wdt:P2969", formatter=get_first),
|
|
|
|
Mapping("librarythingKey", remote_field="wdt:P1085", formatter=get_first),
|
2021-04-07 01:10:42 +00:00
|
|
|
Mapping("languages", remote_field="wdt:P407", formatter=self.resolve_keys),
|
|
|
|
Mapping("publishers", remote_field="wdt:P123", formatter=self.resolve_keys),
|
2021-04-06 20:53:58 +00:00
|
|
|
Mapping("publishedDate", remote_field="wdt:P577", formatter=get_first),
|
|
|
|
Mapping("pages", remote_field="wdt:P1104", formatter=get_first),
|
2021-04-07 01:10:42 +00:00
|
|
|
Mapping(
|
|
|
|
"subjectPlaces", remote_field="wdt:P840", formatter=self.resolve_keys
|
|
|
|
),
|
|
|
|
Mapping("subjects", remote_field="wdt:P921", formatter=self.resolve_keys),
|
2021-04-06 20:53:58 +00:00
|
|
|
Mapping("asin", remote_field="wdt:P5749", formatter=get_first),
|
2021-04-07 00:46:06 +00:00
|
|
|
] + shared_mappings
|
|
|
|
# TODO: P136: genre, P674 characters, P950 bne
|
2021-04-06 18:58:07 +00:00
|
|
|
|
2021-04-07 00:46:06 +00:00
|
|
|
self.author_mappings = [
|
|
|
|
Mapping("id", remote_field="uri", formatter=self.get_remote_id),
|
2021-04-07 01:00:54 +00:00
|
|
|
Mapping("name", remote_field="labels", formatter=get_language_code),
|
2021-04-07 00:46:06 +00:00
|
|
|
Mapping("goodreadsKey", remote_field="wdt:P2963", formatter=get_first),
|
|
|
|
Mapping("isni", remote_field="wdt:P213", formatter=get_first),
|
|
|
|
Mapping("viafId", remote_field="wdt:P214", formatter=get_first),
|
|
|
|
Mapping("gutenberg_id", remote_field="wdt:P1938", formatter=get_first),
|
|
|
|
Mapping("born", remote_field="wdt:P569", formatter=get_first),
|
|
|
|
Mapping("died", remote_field="wdt:P570", formatter=get_first),
|
|
|
|
] + shared_mappings
|
|
|
|
|
|
|
|
def get_remote_id(self, value):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""convert an id/uri into a url"""
|
2021-04-06 20:53:58 +00:00
|
|
|
return "{:s}?action=by-uris&uris={:s}".format(self.books_url, value)
|
2021-04-06 20:39:10 +00:00
|
|
|
|
2021-04-06 19:29:06 +00:00
|
|
|
def get_book_data(self, remote_id):
|
|
|
|
data = get_data(remote_id)
|
|
|
|
extracted = list(data.get("entities").values())
|
2021-04-06 20:53:58 +00:00
|
|
|
try:
|
|
|
|
data = extracted[0]
|
|
|
|
except KeyError:
|
|
|
|
raise ConnectorException("Invalid book data")
|
|
|
|
# flatten the data so that images, uri, and claims are on the same level
|
|
|
|
return {
|
|
|
|
**data.get("claims"),
|
2021-04-07 01:00:54 +00:00
|
|
|
**{k: data.get(k) for k in ["uri", "image", "labels"]},
|
2021-04-06 20:53:58 +00:00
|
|
|
}
|
2021-04-06 19:29:06 +00:00
|
|
|
|
2021-04-06 18:58:07 +00:00
|
|
|
def parse_search_data(self, data):
|
2021-04-06 20:53:58 +00:00
|
|
|
return data.get("results")
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def format_search_result(self, search_result):
|
|
|
|
images = search_result.get("image")
|
2021-04-06 20:53:58 +00:00
|
|
|
cover = (
|
|
|
|
"{:s}/img/entities/{:s}".format(self.covers_url, images[0])
|
|
|
|
if images
|
|
|
|
else None
|
|
|
|
)
|
2021-04-06 18:58:07 +00:00
|
|
|
return SearchResult(
|
|
|
|
title=search_result.get("label"),
|
2021-04-06 20:39:10 +00:00
|
|
|
key="{:s}?action=by-uris&uris={:s}".format(
|
|
|
|
self.books_url, search_result.get("uri")
|
|
|
|
),
|
2021-04-06 19:17:58 +00:00
|
|
|
view_link="{:s}{:s}".format(self.base_url, search_result.get("uri")),
|
2021-04-06 18:58:07 +00:00
|
|
|
cover=cover,
|
|
|
|
connector=self,
|
|
|
|
)
|
|
|
|
|
|
|
|
def parse_isbn_search_data(self, data):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""boop doop"""
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def format_isbn_search_result(self, search_result):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""beep bloop"""
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def is_work_data(self, data):
|
2021-04-06 19:29:06 +00:00
|
|
|
return data.get("type") == "work"
|
2021-04-06 18:58:07 +00:00
|
|
|
|
2021-04-07 01:34:55 +00:00
|
|
|
def load_edition_data(self, work_uri):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""get a list of editions for a work"""
|
2021-04-07 01:51:43 +00:00
|
|
|
url = "{:s}?action=reverse-claims&property=wdt:P629&value={:s}".format(
|
2021-04-07 01:34:55 +00:00
|
|
|
self.books_url, work_uri
|
2021-04-06 20:39:10 +00:00
|
|
|
)
|
2021-04-07 01:34:55 +00:00
|
|
|
return get_data(url)
|
|
|
|
|
|
|
|
def get_edition_from_work_data(self, data):
|
|
|
|
data = self.load_edition_data(data.get("uri"))
|
2021-04-06 20:39:10 +00:00
|
|
|
try:
|
|
|
|
uri = data["uris"][0]
|
|
|
|
except KeyError:
|
|
|
|
raise ConnectorException("Invalid book data")
|
|
|
|
return self.get_book_data(self.get_remote_id(uri))
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def get_work_from_edition_data(self, data):
|
2021-04-06 20:39:10 +00:00
|
|
|
try:
|
|
|
|
uri = data["claims"]["wdt:P629"]
|
|
|
|
except KeyError:
|
|
|
|
raise ConnectorException("Invalid book data")
|
|
|
|
return self.get_book_data(self.get_remote_id(uri))
|
|
|
|
|
2021-04-06 18:58:07 +00:00
|
|
|
def get_authors_from_data(self, data):
|
2021-04-07 01:51:43 +00:00
|
|
|
authors = data.get("wdt:P50", [])
|
2021-04-07 00:46:06 +00:00
|
|
|
for author in authors:
|
|
|
|
yield self.get_or_create_author(self.get_remote_id(author))
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def expand_book_data(self, book):
|
2021-04-07 01:34:55 +00:00
|
|
|
work = book
|
|
|
|
# go from the edition to the work, if necessary
|
|
|
|
if isinstance(book, models.Edition):
|
|
|
|
work = book.parent_work
|
|
|
|
|
|
|
|
try:
|
|
|
|
edition_options = self.load_edition_data(work.inventaire_id)
|
|
|
|
except ConnectorException:
|
|
|
|
# who knows, man
|
|
|
|
return
|
|
|
|
|
|
|
|
for edition_uri in edition_options.get("uris"):
|
|
|
|
remote_id = self.get_remote_id(edition_uri)
|
|
|
|
self.get_or_create_book(remote_id)
|
2021-04-06 18:58:07 +00:00
|
|
|
|
|
|
|
def get_cover_url(self, cover_blob, *_):
|
2021-04-06 20:53:58 +00:00
|
|
|
"""format the relative cover url into an absolute one:
|
2021-04-06 18:58:07 +00:00
|
|
|
{"url": "/img/entities/e794783f01b9d4f897a1ea9820b96e00d346994f"}
|
|
|
|
"""
|
|
|
|
cover_id = cover_blob[0].get("url")
|
|
|
|
if not cover_id:
|
|
|
|
return None
|
|
|
|
return "%s%s" % (self.covers_url, cover_id)
|
|
|
|
|
2021-04-07 01:10:42 +00:00
|
|
|
def resolve_keys(self, keys):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""cool, it's "wd:Q3156592" now what the heck does that mean"""
|
2021-04-07 01:10:42 +00:00
|
|
|
results = []
|
|
|
|
for uri in keys:
|
|
|
|
try:
|
|
|
|
data = self.get_book_data(self.get_remote_id(uri))
|
|
|
|
except ConnectorException:
|
|
|
|
continue
|
|
|
|
results.append(get_language_code(data.get("labels")))
|
|
|
|
return results
|
2021-04-06 18:58:07 +00:00
|
|
|
|
2021-04-07 00:46:06 +00:00
|
|
|
|
|
|
|
def get_language_code(options, code="en"):
|
2021-04-26 21:43:29 +00:00
|
|
|
"""when there are a bunch of translation but we need a single field"""
|
2021-04-07 00:46:06 +00:00
|
|
|
return options.get(code)
|