Source code for api.admin.controller.metadata_services
import flask
from flask import Response
from flask_babel import lazy_gettext as _
from api.admin.problem_details import *
from api.nyt import NYTBestSellerAPI
from api.novelist import NoveListAPI
from core.opds_import import MetadataWranglerOPDSLookup
from core.model import (
ExternalIntegration,
get_one,
)
from core.util.http import HTTP
from core.util.problem_detail import ProblemDetail
from . import SitewideRegistrationController
[docs]class MetadataServicesController(SitewideRegistrationController):
def __init__(self, manager):
super(MetadataServicesController, self).__init__(manager)
self.provider_apis = [
NYTBestSellerAPI,
NoveListAPI,
MetadataWranglerOPDSLookup,
]
self.protocols = self._get_integration_protocols(self.provider_apis, protocol_name_attr="PROTOCOL")
self.goal = ExternalIntegration.METADATA_GOAL
self.type = _("metadata service")
[docs] def process_metadata_services(self):
self.require_system_admin()
if flask.request.method == 'GET':
return self.process_get()
else:
return self.process_post()
[docs] def process_get(self):
metadata_services = self._get_integration_info(self.goal, self.protocols)
for service in metadata_services:
service_object = get_one(self._db, ExternalIntegration, id=service.get("id"), goal=ExternalIntegration.METADATA_GOAL)
protocol_class, tuple = self.find_protocol_class(service_object)
service["self_test_results"] = self._get_prior_test_results(service_object, protocol_class, *tuple)
return dict(
metadata_services=metadata_services,
protocols=self.protocols,
)
[docs] def find_protocol_class(self, integration):
if integration.protocol == ExternalIntegration.METADATA_WRANGLER:
return (
MetadataWranglerOPDSLookup,
(MetadataWranglerOPDSLookup.from_config, self._db)
)
elif integration.protocol == ExternalIntegration.NYT:
return (
NYTBestSellerAPI,
(NYTBestSellerAPI.from_config, self._db)
)
elif integration.protocol == ExternalIntegration.NOVELIST:
return (
NoveListAPI,
(NoveListAPI.from_config, self._db)
)
raise NotImplementedError(
"No metadata self-test class for protocol %s" % integration.protocol
)
[docs] def process_post(self, do_get=HTTP.debuggable_get, do_post=HTTP.debuggable_post):
name = flask.request.form.get("name")
protocol = flask.request.form.get("protocol")
url = flask.request.form.get("url")
fields = {"name": name, "protocol": protocol, "url": url}
form_field_error = self.validate_form_fields(**fields)
if form_field_error:
return form_field_error
id = flask.request.form.get("id")
is_new = False
if id:
# Find an existing service in order to edit it
service = self.look_up_service_by_id(id, protocol)
else:
service, is_new = self._create_integration(
self.protocols, protocol, self.goal
)
if isinstance(service, ProblemDetail):
self._db.rollback()
return service
name_error = self.check_name_unique(service, name)
if name_error:
self._db.rollback()
return name_error
protocol_error = self.set_protocols(service, protocol)
if protocol_error:
self._db.rollback()
return protocol_error
wrangler_error = self.register_with_metadata_wrangler(
do_get, do_post, is_new, service
)
if isinstance(wrangler_error, ProblemDetail):
self._db.rollback()
return wrangler_error
service.name = name
if is_new:
return Response(str(service.id), 201)
else:
return Response(str(service.id), 200)
[docs] def validate_form_fields(self, **fields):
"""The 'name' and 'protocol' fields cannot be blank, and the protocol must
be selected from the list of recognized protocols. The URL must be valid."""
name = fields.get("name")
protocol = fields.get("protocol")
url = fields.get("url")
if not name:
return INCOMPLETE_CONFIGURATION
if not protocol:
return NO_PROTOCOL_FOR_NEW_SERVICE
error = self.validate_protocol()
if error:
return error
wrong_format = self.validate_formats()
if wrong_format:
return wrong_format
[docs] def register_with_metadata_wrangler(self, do_get, do_post, is_new, service):
"""Register this site with the Metadata Wrangler."""
if ((is_new or not service.password) and
service.protocol == ExternalIntegration.METADATA_WRANGLER):
return self.process_sitewide_registration(
integration=service, do_get=do_get, do_post=do_post
)
[docs] def process_delete(self, service_id):
return self._delete_integration(
service_id, self.goal
)