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
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
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'])
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 = []
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(
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(
.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']:
}
template = 'catalogue/author_detail.html'
-
+
return render(
request, template, result,
)
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,
+ 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()
+
+ for i, (file_path, names) in enumerate(iterate_audiobooks(book, ())):
+ index = i + 1
+ part_name = '_'.join(names)
+ ext = file_path.rsplit('.', 1)[-1]
+ zip_name = f'{book.slug}_{index:03d}_{part_name}'[:240] + '.' + ext
+ zs.add_path(file_path, zip_name)
+
+ 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')