From 1f06d1a1d8386fcf6aa09441d09b6f2d0dd4941b Mon Sep 17 00:00:00 2001
From: Mouse Reeve
Date: Tue, 14 Sep 2021 15:26:18 -0700
Subject: [PATCH] Removes local connector
---
bookwyrm/connectors/__init__.py | 2 +-
bookwyrm/connectors/abstract_connector.py | 1 -
bookwyrm/connectors/connector_manager.py | 16 +-
bookwyrm/connectors/self_connector.py | 164 ------------------
bookwyrm/management/commands/initdb.py | 13 --
.../migrations/0097_remove_connector_local.py | 17 ++
bookwyrm/models/connector.py | 1 -
bookwyrm/templates/search/book.html | 19 +-
.../snippets/search_result_text.html | 22 +--
bookwyrm/views/search.py | 19 +-
10 files changed, 55 insertions(+), 219 deletions(-)
delete mode 100644 bookwyrm/connectors/self_connector.py
create mode 100644 bookwyrm/migrations/0097_remove_connector_local.py
diff --git a/bookwyrm/connectors/__init__.py b/bookwyrm/connectors/__init__.py
index 689f2701..efbdb166 100644
--- a/bookwyrm/connectors/__init__.py
+++ b/bookwyrm/connectors/__init__.py
@@ -3,4 +3,4 @@ from .settings import CONNECTORS
from .abstract_connector import ConnectorException
from .abstract_connector import get_data, get_image
-from .connector_manager import search, local_search, first_search_result
+from .connector_manager import search, first_search_result
diff --git a/bookwyrm/connectors/abstract_connector.py b/bookwyrm/connectors/abstract_connector.py
index ffacffdf..9f20a6c3 100644
--- a/bookwyrm/connectors/abstract_connector.py
+++ b/bookwyrm/connectors/abstract_connector.py
@@ -31,7 +31,6 @@ class AbstractMinimalConnector(ABC):
"isbn_search_url",
"name",
"identifier",
- "local",
]
for field in self_fields:
setattr(self, field, getattr(info, field))
diff --git a/bookwyrm/connectors/connector_manager.py b/bookwyrm/connectors/connector_manager.py
index 1d9588d6..6f62b59a 100644
--- a/bookwyrm/connectors/connector_manager.py
+++ b/bookwyrm/connectors/connector_manager.py
@@ -55,7 +55,7 @@ def search(query, min_confidence=0.1, return_first=False):
# if we found anything, return it
return result_set[0]
- if result_set or connector.local:
+ if result_set:
results.append(
{
"connector": connector,
@@ -71,20 +71,6 @@ def search(query, min_confidence=0.1, return_first=False):
return results
-def local_search(query, min_confidence=0.1, raw=False, filters=None):
- """only look at local search results"""
- connector = load_connector(models.Connector.objects.get(local=True))
- return connector.search(
- query, min_confidence=min_confidence, raw=raw, filters=filters
- )
-
-
-def isbn_local_search(query, raw=False):
- """only look at local search results"""
- connector = load_connector(models.Connector.objects.get(local=True))
- return connector.isbn_search(query, raw=raw)
-
-
def first_search_result(query, min_confidence=0.1):
"""search until you find a result that fits"""
return search(query, min_confidence=min_confidence, return_first=True) or None
diff --git a/bookwyrm/connectors/self_connector.py b/bookwyrm/connectors/self_connector.py
deleted file mode 100644
index 8d5a7614..00000000
--- a/bookwyrm/connectors/self_connector.py
+++ /dev/null
@@ -1,164 +0,0 @@
-""" using a bookwyrm instance as a source of book data """
-from functools import reduce
-import operator
-
-from django.contrib.postgres.search import SearchRank, SearchQuery
-from django.db.models import OuterRef, Subquery, F, Q
-
-from bookwyrm import models
-from .abstract_connector import AbstractConnector, SearchResult
-
-
-class Connector(AbstractConnector):
- """instantiate a connector"""
-
- # pylint: disable=arguments-differ
- def search(self, query, min_confidence=0, raw=False, filters=None):
- """search your local database"""
- filters = filters or []
- if not query:
- return []
- # first, try searching unqiue identifiers
- results = search_identifiers(query, *filters)
- if not results:
- # then try searching title/author
- results = search_title_author(query, min_confidence, *filters)
- search_results = []
- for result in results:
- if raw:
- search_results.append(result)
- else:
- search_results.append(self.format_search_result(result))
- if len(search_results) >= 10:
- break
- if not raw:
- search_results.sort(key=lambda r: r.confidence, reverse=True)
- return search_results
-
- def isbn_search(self, query, raw=False):
- """search your local database"""
- if not query:
- return []
-
- filters = [{f: query} for f in ["isbn_10", "isbn_13"]]
- results = models.Edition.objects.filter(
- reduce(operator.or_, (Q(**f) for f in filters))
- ).distinct()
-
- # when there are multiple editions of the same work, pick the default.
- # it would be odd for this to happen.
-
- default_editions = models.Edition.objects.filter(
- parent_work=OuterRef("parent_work")
- ).order_by("-edition_rank")
- results = (
- results.annotate(
- default_id=Subquery(default_editions.values("id")[:1])
- ).filter(default_id=F("id"))
- or results
- )
-
- search_results = []
- for result in results:
- if raw:
- search_results.append(result)
- else:
- search_results.append(self.format_search_result(result))
- if len(search_results) >= 10:
- break
- return search_results
-
- def format_search_result(self, search_result):
- cover = None
- if search_result.cover:
- cover = "%s%s" % (self.covers_url, search_result.cover)
-
- return SearchResult(
- title=search_result.title,
- key=search_result.remote_id,
- author=search_result.author_text,
- year=search_result.published_date.year
- if search_result.published_date
- else None,
- connector=self,
- cover=cover,
- confidence=search_result.rank if hasattr(search_result, "rank") else 1,
- )
-
- def format_isbn_search_result(self, search_result):
- return self.format_search_result(search_result)
-
- def is_work_data(self, data):
- pass
-
- def get_edition_from_work_data(self, data):
- pass
-
- def get_work_from_edition_data(self, data):
- pass
-
- def get_authors_from_data(self, data):
- return None
-
- def parse_isbn_search_data(self, data):
- """it's already in the right format, don't even worry about it"""
- return data
-
- def parse_search_data(self, data):
- """it's already in the right format, don't even worry about it"""
- return data
-
- def expand_book_data(self, book):
- pass
-
-
-def search_identifiers(query, *filters):
- """tries remote_id, isbn; defined as dedupe fields on the model"""
- # pylint: disable=W0212
- or_filters = [
- {f.name: query}
- for f in models.Edition._meta.get_fields()
- if hasattr(f, "deduplication_field") and f.deduplication_field
- ]
- results = models.Edition.objects.filter(
- *filters, reduce(operator.or_, (Q(**f) for f in or_filters))
- ).distinct()
- if results.count() <= 1:
- return results
-
- # when there are multiple editions of the same work, pick the default.
- # it would be odd for this to happen.
- default_editions = models.Edition.objects.filter(
- parent_work=OuterRef("parent_work")
- ).order_by("-edition_rank")
- return (
- results.annotate(default_id=Subquery(default_editions.values("id")[:1])).filter(
- default_id=F("id")
- )
- or results
- )
-
-
-def search_title_author(query, min_confidence, *filters):
- """searches for title and author"""
- query = SearchQuery(query, config="simple") | SearchQuery(query, config="english")
- results = (
- models.Edition.objects.filter(*filters, search_vector=query)
- .annotate(rank=SearchRank(F("search_vector"), query))
- .filter(rank__gt=min_confidence)
- .order_by("-rank")
- )
-
- # when there are multiple editions of the same work, pick the closest
- editions_of_work = results.values("parent_work__id").values_list("parent_work__id")
-
- # filter out multiple editions of the same work
- for work_id in set(editions_of_work):
- editions = results.filter(parent_work=work_id)
- default = editions.order_by("-edition_rank").first()
- default_rank = default.rank if default else 0
- # if mutliple books have the top rank, pick the default edition
- if default_rank == editions.first().rank:
- yield default
- else:
- yield editions.first()
diff --git a/bookwyrm/management/commands/initdb.py b/bookwyrm/management/commands/initdb.py
index 71ac511a..9f2f29cd 100644
--- a/bookwyrm/management/commands/initdb.py
+++ b/bookwyrm/management/commands/initdb.py
@@ -73,19 +73,6 @@ def init_permissions():
def init_connectors():
"""access book data sources"""
- Connector.objects.create(
- identifier=DOMAIN,
- name="Local",
- local=True,
- connector_file="self_connector",
- base_url="https://%s" % DOMAIN,
- books_url="https://%s/book" % DOMAIN,
- covers_url="https://%s/images/" % DOMAIN,
- search_url="https://%s/search?q=" % DOMAIN,
- isbn_search_url="https://%s/isbn/" % DOMAIN,
- priority=1,
- )
-
Connector.objects.create(
identifier="bookwyrm.social",
name="BookWyrm dot Social",
diff --git a/bookwyrm/migrations/0097_remove_connector_local.py b/bookwyrm/migrations/0097_remove_connector_local.py
new file mode 100644
index 00000000..fc04bcce
--- /dev/null
+++ b/bookwyrm/migrations/0097_remove_connector_local.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.4 on 2021-09-14 22:10
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("bookwyrm", "0096_merge_20210912_0044"),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name="connector",
+ name="local",
+ ),
+ ]
diff --git a/bookwyrm/models/connector.py b/bookwyrm/models/connector.py
index 17ba3148..b982c0ff 100644
--- a/bookwyrm/models/connector.py
+++ b/bookwyrm/models/connector.py
@@ -14,7 +14,6 @@ class Connector(BookWyrmModel):
identifier = models.CharField(max_length=255, unique=True)
priority = models.IntegerField(default=2)
name = models.CharField(max_length=255, null=True, blank=True)
- local = models.BooleanField(default=False)
connector_file = models.CharField(max_length=255, choices=ConnectorFiles.choices)
api_key = models.CharField(max_length=255, null=True, blank=True)
active = models.BooleanField(default=True)
diff --git a/bookwyrm/templates/search/book.html b/bookwyrm/templates/search/book.html
index 39f83732..12164bb3 100644
--- a/bookwyrm/templates/search/book.html
+++ b/bookwyrm/templates/search/book.html
@@ -8,7 +8,24 @@
{% for result in local_results.results %}
- {% include 'snippets/search_result_text.html' with result=result %}
+
+
+ {% include 'snippets/book_cover.html' with book=result cover_class='is-w-xs is-h-xs' %}
+
+
+
+
+
+ {% include "snippets/book_titleby.html" with book=result %}
+
+
+
+ {% if result.first_published_date or result.published_date %}
+ ({% firstof result.first_published_date.year result.published_date.year %})
+ {% endif %}
+
+
+
{% endfor %}
diff --git a/bookwyrm/templates/snippets/search_result_text.html b/bookwyrm/templates/snippets/search_result_text.html
index 40fa5a3d..973f1f5b 100644
--- a/bookwyrm/templates/snippets/search_result_text.html
+++ b/bookwyrm/templates/snippets/search_result_text.html
@@ -9,10 +9,8 @@
{{ result.title }}
@@ -26,16 +24,14 @@
{% endif %}
- {% if remote_result %}
-
- {% endif %}
+
+ {% trans "Import book" %}
+
+
diff --git a/bookwyrm/views/search.py b/bookwyrm/views/search.py
index cdea8663..6c9593a1 100644
--- a/bookwyrm/views/search.py
+++ b/bookwyrm/views/search.py
@@ -10,6 +10,7 @@ from django.views import View
from bookwyrm import models
from bookwyrm.connectors import connector_manager
+from bookwyrm.book_search import search
from bookwyrm.settings import PAGE_LENGTH
from bookwyrm.utils import regex
from .helpers import is_api_request, privacy_filter
@@ -31,9 +32,7 @@ class Search(View):
if is_api_request(request):
# only return local book results via json so we don't cascade
- book_results = connector_manager.local_search(
- query, min_confidence=min_confidence
- )
+ book_results = search(query, min_confidence=min_confidence)
return JsonResponse([r.json() for r in book_results], safe=False)
if query and not search_type:
@@ -69,13 +68,13 @@ class Search(View):
def book_search(query, _, min_confidence, search_remote=False):
"""the real business is elsewhere"""
# try a local-only search
- if not search_remote:
- results = connector_manager.local_search(query, min_confidence=min_confidence)
- if results:
- # gret, we found something
- return [{"results": results}], False
- # if there weere no local results, or the request was for remote, search all sources
- return connector_manager.search(query, min_confidence=min_confidence), True
+ results = [{"results": search(query, min_confidence=min_confidence)}]
+ if results and not search_remote:
+ return results, False
+
+ # if there were no local results, or the request was for remote, search all sources
+ results += connector_manager.search(query, min_confidence=min_confidence)
+ return results, True
def user_search(query, viewer, *_):