X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/6d42bc478e3d1bd90eb294464748c21e4de0fc63..ca8f4e8fef80cb603117ed579da8554f503698e5:/src/opds/views.py diff --git a/src/opds/views.py b/src/opds/views.py index 6d04c6c2a..38f34efd5 100644 --- a/src/opds/views.py +++ b/src/opds/views.py @@ -1,5 +1,5 @@ -# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. -# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Wolne Lektury. See NOTICE for more information. # from functools import reduce import os.path @@ -8,7 +8,7 @@ from urllib.parse import urljoin from django.contrib.syndication.views import Feed from django.shortcuts import get_object_or_404 from django.urls import reverse -from django.utils.feedgenerator import Atom1Feed +from django.utils.feedgenerator import Atom1Feed, Enclosure from django.conf import settings from django.http import Http404 from django.contrib.sites.models import Site @@ -16,8 +16,8 @@ from django.utils.functional import lazy from basicauth import logged_in_or_basicauth, factory_decorator from catalogue.models import Book, Tag +from search.utils import UnaccentSearchQuery, UnaccentSearchVector -from search.views import Search import operator import logging import re @@ -145,23 +145,32 @@ class OPDSFeed(Atom1Feed): # Enclosure as OPDS Acquisition Link for enc in item.get('enclosures', []): - handler.addQuickElement( - "link", '', + handler.startElement( + "link", { "rel": "http://opds-spec.org/acquisition", "href": enc.url, - "length": enc.length, + "length": str(enc.length), "type": enc.mime_type, }) - # add a "red book" icon - handler.addQuickElement( - "link", '', - { - "rel": "http://opds-spec.org/thumbnail", - "href": self._book_img, - "length": self._book_img_size, - "type": "image/png", + if hasattr(enc, 'indirect'): + NS = 'http://opds-spec.org/2010/catalog' + handler.startPrefixMapping('opds', NS) + handler.startElementNS((NS, 'indirectAcquisition'), 'opds:indirectAcquisition', { + (None, 'type'): enc.indirect, }) + handler.endElementNS((NS, 'indirectAcquisition'), 'opds:indirectAcquisition') + handler.endPrefixMapping('opds') + handler.endElement('link') + # add a "red book" icon + handler.addQuickElement( + "link", '', + { + "rel": "http://opds-spec.org/thumbnail", + "href": self._book_img, + "length": self._book_img_size, + "type": "image/png", + }) # Categories. for cat in item['categories']: @@ -175,7 +184,6 @@ class OPDSFeed(Atom1Feed): class AcquisitionFeed(Feed): feed_type = OPDSFeed link = 'http://www.wolnelektury.pl/' - item_enclosure_mime_type = "application/epub+zip" author_name = "Wolne Lektury" author_link = "http://www.wolnelektury.pl/" @@ -200,11 +208,23 @@ class AcquisitionFeed(Feed): except AttributeError: return '' - def item_enclosure_url(self, book): - return full_url(book.epub_url()) if book.epub_file else None - - def item_enclosure_length(self, book): - return book.epub_file.size if book.epub_file else None + def item_enclosures(self, book): + enc = [] + if book.epub_file: + enc.append(Enclosure( + url=full_url(book.epub_url()), + length=book.epub_file.size, + mime_type="application/epub+zip" + )) + if book.has_mp3_file(): + e = Enclosure( + url=full_url(reverse('download_zip_mp3', args=[book.slug])), + length=sum(bm.file.size for bm in book.get_media('mp3')), + mime_type="application/zip" + ) + e.indirect = 'audio/mpeg' + enc.append(e) + return enc @piwik_track @@ -277,7 +297,9 @@ class ByTagFeed(AcquisitionFeed): return get_object_or_404(Tag, category=category, slug=slug) def items(self, tag): - return Book.tagged_top_level([tag]) + qs = Book.tagged_top_level([tag]) + qs = qs.filter(preview=False, findable=True) + return qs @factory_decorator(logged_in_or_basicauth()) @@ -350,15 +372,6 @@ class SearchFeed(AcquisitionFeed): 'text': (10, 11), } - PARAMS_TO_FIELDS = { - 'author': 'authors', - 'translator': 'translators', - # 'title': 'title', - 'categories': 'tag_name_pl', - 'description': 'text', - # 'text': 'text', - } - ATOM_PLACEHOLDER = re.compile(r"^{(atom|opds):\w+}$") def get_object(self, request): @@ -413,30 +426,33 @@ class SearchFeed(AcquisitionFeed): # query is set above. log.debug("Inline query = [%s], criteria: %s" % (query, criteria)) - srch = Search() - - book_hit_filter = srch.index.Q(book_id__any=True) - filters = [book_hit_filter] + [srch.index.Q( - **{self.PARAMS_TO_FIELDS.get(cn, cn): criteria[cn]} - ) for cn in self.MATCHES.keys() if cn in criteria - if criteria[cn]] - + books = Book.objects.filter(findable=True, preview=False).annotate( + search_vector=UnaccentSearchVector('title') + ) if query: - q = srch.index.query( - reduce( - operator.or_, - [srch.index.Q(**{self.PARAMS_TO_FIELDS.get(cn, cn): query}) for cn in self.MATCHES.keys()], - srch.index.Q())) - else: - q = srch.index.query(srch.index.Q()) - - q = srch.apply_filters(q, filters).field_limit(score=True, fields=['book_id']) - results = q.execute() - - book_scores = dict([(r['book_id'], r['score']) for r in results]) - books = Book.objects.filter(id__in=set([r['book_id'] for r in results])) - books = list(books) - books.sort(reverse=True, key=lambda book: book_scores[book.id]) + squery = UnaccentSearchQuery(query, config=settings.SEARCH_CONFIG) + books = books.filter(search_vector=squery) + if criteria['author']: + authors = Tag.objects.filter(category='author').annotate( + search_vector=UnaccentSearchVector('name_pl') + ).filter(search_vector=UnaccentSearchQuery(criteria['author'], config=settings.SEARCH_CONFIG)) + books = books.filter(tag_relations__tag__in=authors) + if criteria['categories']: + tags = Tag.objects.filter(category__in=('genre', 'kind', 'epoch')).annotate( + search_vector=UnaccentSearchVector('name_pl') + ).filter(search_vector=UnaccentSearchQuery(criteria['categories'], config=settings.SEARCH_CONFIG)) + books = books.filter(tag_relations__tag__in=tags) + if criteria['translator']: + # TODO + pass + if criteria['title']: + books = books.filter( + search_vector=UnaccentSearchQuery(criteria['title'], config=settings.SEARCH_CONFIG) + ) + + books = books.exclude(ancestor__in=books) + + books = books.order_by('popularity__count') return books def get_link(self, query):