X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/3d8d1e8e463efe111ed2e2a99861ada52759a1d9..89881ffd8c2da92f115f23b002f48b7e626014d0:/src/catalogue/views.py?ds=inline diff --git a/src/catalogue/views.py b/src/catalogue/views.py index d5b83ab08..8d32e64ee 100644 --- a/src/catalogue/views.py +++ b/src/catalogue/views.py @@ -5,11 +5,13 @@ from collections import OrderedDict import random import re from urllib.parse import quote_plus +from slugify import slugify +from zipstream import ZipStream from django.conf import settings from django.template.loader import render_to_string from django.shortcuts import get_object_or_404, render, redirect -from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect +from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect, StreamingHttpResponse from django.urls import reverse from django.db.models import Q, QuerySet from django.contrib.auth.decorators import login_required, user_passes_test @@ -23,6 +25,7 @@ from club.forms import DonationStep1Form from club.models import Club from annoy.models import DynamicTextInsert from pdcounter import views as pdcounter_views +from social.models import UserList from wolnelektury.utils import is_ajax from catalogue import constants from catalogue import forms @@ -211,26 +214,45 @@ class AudiobooksView(LiteratureView): class TaggedObjectList(BookList): def analyse(self): super().analyse() + self.ctx['tags'] = analyse_tags(self.request, self.kwargs['tags']) - self.ctx['fragment_tags'] = [t for t in self.ctx['tags'] if t.category in ('theme', 'object')] - self.ctx['work_tags'] = [t for t in self.ctx['tags'] if t not in self.ctx['fragment_tags']] + if len(self.ctx['tags']) > 4: + raise Http404 + self.ctx.update({ + 'fragment_tags': [], + 'work_tags': [], + 'user_lists': [], + }) + for tag in self.ctx['tags']: + if isinstance(tag, UserList): + self.ctx['user_lists'].append(tag) + elif tag.category == 'theme': + self.ctx['fragment_tags'].append(tag) + else: + self.ctx['work_tags'].append(tag) + self.is_themed = self.ctx['has_theme'] = bool(self.ctx['fragment_tags']) if self.is_themed: self.ctx['main_tag'] = self.ctx['fragment_tags'][0] - elif self.ctx['tags']: - self.ctx['main_tag'] = self.ctx['tags'][0] + elif self.ctx['work_tags']: + self.ctx['main_tag'] = self.ctx['work_tags'][0] else: self.ctx['main_tag'] = None self.ctx['filtering_tags'] = [ t for t in self.ctx['tags'] if t is not self.ctx['main_tag'] ] - if len(self.ctx['tags']) == 1 and self.ctx['main_tag'].category == 'author': + if len(self.ctx['tags']) == 1 and self.ctx['main_tag'] is not None and self.ctx['main_tag'].category == 'author': self.ctx['translation_list'] = self.ctx['main_tag'].book_set.all() self.ctx['narrated'] = self.ctx['main_tag'].narrated.all() def get_queryset(self): - qs = Book.tagged.with_all(self.ctx['work_tags']).filter(findable=True) + if self.ctx['work_tags']: + qs = Book.tagged.with_all(self.ctx['work_tags']).filter(findable=True) + else: + qs = Book.objects.filter(findable=True) + for ul in self.ctx['user_lists']: + qs = qs.filter(id__in=[i.id for i in ul.get_books()]) qs = qs.exclude(ancestor__in=qs) if self.is_themed: fqs = Fragment.tagged.with_all(self.ctx['fragment_tags']) @@ -242,6 +264,9 @@ class TaggedObjectList(BookList): return qs def get_suggested_tags(self, queryset): + if self.ctx['user_lists']: + # TODO + return [] tag_ids = [t.id for t in self.ctx['tags']] if self.is_themed: related_tags = [] @@ -253,6 +278,7 @@ class TaggedObjectList(BookList): containing_books, ).exclude(category='set').exclude(pk__in=tag_ids) )) + ### FIXME: These won't be tags if self.request.user.is_authenticated: related_tags.extend(list( Tag.objects.usage_for_queryset( @@ -293,6 +319,7 @@ def object_list(request, objects, list_type='books'): Tag.objects.usage_for_queryset( objects, counts=True ).exclude(category='set')) + ### FIXME: these won't be tags if request.user.is_authenticated: related_tag_lists.append( Tag.objects.usage_for_queryset( @@ -310,7 +337,7 @@ def object_list(request, objects, list_type='books'): .only('name', 'sort_key', 'category', 'slug')) if isinstance(objects, QuerySet): objects = prefetch_relations(objects, 'author') - + categories = split_tags(*related_tag_lists) suggest = [] for c in ['set', 'author', 'epoch', 'kind', 'genre']: @@ -325,7 +352,7 @@ def object_list(request, objects, list_type='books'): } template = 'catalogue/author_detail.html' - + return render( request, template, result, ) @@ -493,6 +520,49 @@ def download_zip(request, file_format=None, media_format=None, slug=None): return HttpResponseRedirect(quote_plus(settings.MEDIA_URL + url, safe='/?=')) +def stream_zip(request, media_format=None, slug=None): + book = get_object_or_404(Book, slug=slug) + def iterate_audiobooks(book, names): + for bm in book.media.filter(type=media_format).order_by('index'): + yield ( + bm.file.path, + bm.get_extra_info_json().get('license'), + names + (slugify(bm.part_name),) if bm.part_name else names + ) + for child in book.get_children(): + yield from iterate_audiobooks(child, names + (slugify(child.title),)) + + zs = ZipStream() + + audiobook_list = list(iterate_audiobooks(book, ())) + + licenses = set() + for i, (file_path, lic, names) in enumerate(audiobook_list): + index = i + 1 + part_name = '_'.join(names) + if part_name: + part_name = '_' + part_name + ext = file_path.rsplit('.', 1)[-1] + if len(audiobook_list) > 1: + zip_name = f'{book.slug}_{index:03d}{part_name}'[:240] + '.' + ext + else: + zip_name = book.slug[:240] + '.' + ext + zs.add_path(file_path, zip_name) + + lic_name = constants.LICENSES.get(lic, {}).get('locative') + if lic_name: + licenses.add(lic_name) + + readme = render_to_string('catalogue/audiobook_zip_readme.txt', { + 'licenses': licenses, + }) + zs.add(readme, 'informacje.txt') + + response = StreamingHttpResponse(zs, content_type='application/zip') + response['Content-Disposition'] = f'attachment; filename={slug}_{media_format}.zip' + return response + + class CustomPDFFormView(AjaxableFormView): form_class = forms.CustomPDFForm title = gettext_lazy('Stwórz własny PDF')