paths
[audio.git] / src / archive / views.py
index b5850a0..6ae2927 100644 (file)
@@ -1,18 +1,18 @@
-# Create your views here.
-
 from datetime import datetime
 import os
 import os.path
 from datetime import datetime
 import os
 import os.path
-from urllib import quote
+from urllib.parse import quote
 
 from archive import settings
 
 from archive import settings
-from django.contrib.auth import logout
 from django.contrib.auth.decorators import permission_required
 from django.contrib.auth.decorators import permission_required
-from django.core.urlresolvers import reverse
+from django.contrib.postgres.search import SearchVector
+from django.urls import reverse
 from django.db.models import Q, Max
 from django.http import Http404, HttpResponse
 from django.shortcuts import render, redirect, get_object_or_404
 from django.db.models import Q, Max
 from django.http import Http404, HttpResponse
 from django.shortcuts import render, redirect, get_object_or_404
+from django.utils.translation import gettext as _
 from django.views.decorators.http import require_POST
 from django.views.decorators.http import require_POST
+from django.views.generic import ListView
 
 import mutagen
 
 
 import mutagen
 
@@ -24,8 +24,6 @@ from archive.utils import all_files
 
 
 def list_new(request):
 
 
 def list_new(request):
-    division = 'new'
-
     path = settings.NEW_PATH
     objects = sorted(all_files(path))
     return render(request, "archive/list_new.html", locals())
     path = settings.NEW_PATH
     objects = sorted(all_files(path))
     return render(request, "archive/list_new.html", locals())
@@ -33,10 +31,8 @@ def list_new(request):
 
 @permission_required('archive.change_audiobook')
 def file_new(request, filename):
 
 @permission_required('archive.change_audiobook')
 def file_new(request, filename):
-    division = 'new'
-
-    filepath = filename.encode('utf-8')
-    root_filepath = os.path.join(settings.NEW_PATH, filename.encode('utf-8'))
+    filepath = filename
+    root_filepath = os.path.join(settings.NEW_PATH, filename)
     if request.POST:
         form = AudiobookForm(request.POST)
         if form.is_valid():
     if request.POST:
         form = AudiobookForm(request.POST)
         if form.is_valid():
@@ -65,7 +61,7 @@ def file_new(request, filename):
                     d[tag] = None
 
     if not request.POST:
                     d[tag] = None
 
     if not request.POST:
-        form = AudiobookForm(d)
+        form = AudiobookForm(initial=d)
     return render(request, "archive/file_new.html", locals())
 
 
     return render(request, "archive/file_new.html", locals())
 
 
@@ -74,9 +70,8 @@ def file_new(request, filename):
 def move_to_archive(request, filename):
     """ move a new file to the unmanaged files dir """
 
 def move_to_archive(request, filename):
     """ move a new file to the unmanaged files dir """
 
-    filename_str = filename.encode('utf-8')
-    old_path = os.path.join(settings.NEW_PATH, filename_str)
-    new_path = os.path.join(settings.UNMANAGED_PATH, filename_str)
+    old_path = os.path.join(settings.NEW_PATH, filename)
+    new_path = os.path.join(settings.UNMANAGED_PATH, filename)
     new_dir = os.path.split(new_path)[0]
     if not os.path.isdir(new_dir):
         os.makedirs(new_dir)
     new_dir = os.path.split(new_path)[0]
     if not os.path.isdir(new_dir):
         os.makedirs(new_dir)
@@ -135,9 +130,8 @@ def remove_to_archive(request, aid):
 def move_to_new(request, filename):
     """ move a unmanaged file to new files dir """
 
 def move_to_new(request, filename):
     """ move a unmanaged file to new files dir """
 
-    filename_str = filename.encode('utf-8')
-    old_path = os.path.join(settings.UNMANAGED_PATH, filename_str)
-    new_path = os.path.join(settings.NEW_PATH, filename_str)
+    old_path = os.path.join(settings.UNMANAGED_PATH, filename)
+    new_path = os.path.join(settings.NEW_PATH, filename)
     new_dir = os.path.split(new_path)[0]
     if not os.path.isdir(new_dir):
         os.makedirs(new_dir)
     new_dir = os.path.split(new_path)[0]
     if not os.path.isdir(new_dir):
         os.makedirs(new_dir)
@@ -161,20 +155,7 @@ def move_to_new(request, filename):
 def publish(request, aid, publish=True):
     """ mark file for publishing """
     audiobook = get_object_or_404(models.Audiobook, id=aid)
 def publish(request, aid, publish=True):
     """ mark file for publishing """
     audiobook = get_object_or_404(models.Audiobook, id=aid)
-    tags = {
-        'name': audiobook.title,
-        'url': audiobook.url,
-        'tags': audiobook.new_publish_tags(),
-        }
-    audiobook.mp3_tags = tags
-    audiobook.ogg_tags = tags
-    audiobook.mp3_status = audiobook.ogg_status = status.WAITING
-    audiobook.save()
-    # isn't there a race here?
-    audiobook.mp3_task = tasks.Mp3Task.delay(aid, publish).task_id
-    audiobook.ogg_task = tasks.OggTask.delay(aid, publish).task_id
-    audiobook.save()
-
+    audiobook.publish(request.user, publish=publish)
     return redirect(file_managed, aid)
 
 
     return redirect(file_managed, aid)
 
 
@@ -186,55 +167,59 @@ def cancel_publishing(request, aid):
     # TODO: cancel tasks
     audiobook.mp3_status = None
     audiobook.ogg_status = None
     # TODO: cancel tasks
     audiobook.mp3_status = None
     audiobook.ogg_status = None
+    audiobook.youtube_status = None
+    audiobook.youtube_queued = None
     audiobook.save()
     return redirect(file_managed, aid)
 
 
 def download(request, aid, which="source"):
     audiobook.save()
     return redirect(file_managed, aid)
 
 
 def download(request, aid, which="source"):
-    if which not in ("source", "mp3", "ogg"):
+    if which not in ("source", "mp3", "ogg", 'mkv'):
         raise Http404
     audiobook = get_object_or_404(models.Audiobook, id=aid)
         raise Http404
     audiobook = get_object_or_404(models.Audiobook, id=aid)
-    file_ = getattr(audiobook, "%s_file" % which)
+    field = which
+    if which == 'mkv':
+        field = 'youtube'
+    file_ = getattr(audiobook, "%s_file" % field)
     if not file_:
         raise Http404
     ext = file_.path.rsplit('.', 1)[-1]
     if not file_:
         raise Http404
     ext = file_.path.rsplit('.', 1)[-1]
-    response = HttpResponse(mimetype='application/force-download')
+    response = HttpResponse(content_type='application/force-download')
     
     response['Content-Disposition'] = "attachment; filename*=UTF-8''%s.%s" % (
         quote(audiobook.title.encode('utf-8'), safe=''), ext)
     
     response['Content-Disposition'] = "attachment; filename*=UTF-8''%s.%s" % (
         quote(audiobook.title.encode('utf-8'), safe=''), ext)
-    response['X-Sendfile'] = file_.path.encode('utf-8')
+    with open(file_.path, 'rb') as f:
+        response.write(f.read())
+    #response['X-Sendfile'] = file_.path.encode('utf-8')
     return response
 
 
     return response
 
 
-def list_unpublished(request):
-    division = 'unpublished'
-
-    objects = models.Audiobook.objects.filter(Q(mp3_published=None) | Q(ogg_published=None))
-    return render(request, "archive/list_unpublished.html", locals())
-
-
 def list_publishing(request):
 def list_publishing(request):
-    division = 'publishing'
-
-    objects = models.Audiobook.objects.exclude(mp3_status=None, ogg_status=None)
+    objects = models.Audiobook.objects.exclude(
+        mp3_status=None, ogg_status=None, youtube_status=None
+    ).order_by("youtube_queued", "title")
     objects_by_status = {}
     for o in objects:
     objects_by_status = {}
     for o in objects:
+        statuses = set()
         if o.mp3_status:
         if o.mp3_status:
-            k = o.mp3_status, o.get_mp3_status_display()
-            objects_by_status.setdefault(k, []).append(o)
-        if o.ogg_status and o.ogg_status != o.mp3_status:
-            k = o.ogg_status, o.get_ogg_status_display()
-            objects_by_status.setdefault(k, []).append(o)
+            statuses.add((o.mp3_status, o.get_mp3_status_display()))
+        if o.ogg_status:
+            statuses.add((o.ogg_status, o.get_ogg_status_display()))
+        if o.youtube_status:
+            statuses.add((o.youtube_status, o.get_youtube_status_display()))
+        for status in statuses:
+            objects_by_status.setdefault(status, []).append(o)
     status_objects = sorted(objects_by_status.items(), reverse=True)
 
     return render(request, "archive/list_publishing.html", locals())
 
 
     status_objects = sorted(objects_by_status.items(), reverse=True)
 
     return render(request, "archive/list_publishing.html", locals())
 
 
-def list_published(request):
-    division = 'published'
-
-    objects = models.Audiobook.objects.exclude(Q(mp3_published=None) | Q(ogg_published=None))
-    return render(request, "archive/list_published.html", locals())
+class AudiobookList(ListView):
+    def get_queryset(self):
+        qs = models.Audiobook.objects.all()
+        if 's' in self.request.GET:
+            qs = qs.annotate(s=SearchVector('title', 'slug')).filter(s=self.request.GET['s'])
+        return qs
 
 
 @permission_required('archive.change_audiobook')
 
 
 @permission_required('archive.change_audiobook')
@@ -249,31 +234,89 @@ def file_managed(request, id):
             except IOError:
                 raise Http404
 
             except IOError:
                 raise Http404
 
-    division = 'published' if audiobook.published() else 'unpublished'
-    path = audiobook.source_file.path[len(settings.FILES_PATH):].lstrip('/')
+    tags = {}
+    if audiobook.source_file:
+        path = audiobook.source_file.path[len(settings.FILES_PATH):].lstrip('/')
 
 
-    # for tags update
-    tags = mutagen.File(audiobook.source_file.path.encode('utf-8'))
-    if not tags:
-        tags = {}
+        # for tags update
+        tags = mutagen.File(audiobook.source_file.path.encode('utf-8'))
+        if not tags:
+            tags = {}
     form = AudiobookForm(instance=audiobook)
 
     form = AudiobookForm(instance=audiobook)
 
+    user_can_publish = (
+        request.user.is_authenticated and
+        request.user.oauthconnection_set.filter(access=True).exists())
+
+    alerts = []
+    parts_count = audiobook.parts_count
+    if parts_count > 1:
+        series = models.Audiobook.objects.filter(slug=audiobook.slug)
+        if not audiobook.index:
+            alerts.append(_('There is more than one part, but index is not set.'))
+        if set(series.values_list('index', flat=True)) != set(range(1, parts_count + 1)):
+            alerts.append(_('Part indexes are not 1..%(parts_count)d.') % {"parts_count": parts_count})
+
+    from youtube.models import YouTube
+    youtube = YouTube.objects.first()
+    youtube_title = youtube.get_title(audiobook)
+    youtube_description = youtube.get_description(audiobook)
+
+            
     return render(request, "archive/file_managed.html", locals())
 
 
 def list_unmanaged(request):
     return render(request, "archive/file_managed.html", locals())
 
 
 def list_unmanaged(request):
-    division = 'unmanaged'
-
     objects = sorted(all_files(settings.UNMANAGED_PATH))
     return render(request, "archive/list_unmanaged.html", locals())
 
 
 def file_unmanaged(request, filename):
     objects = sorted(all_files(settings.UNMANAGED_PATH))
     return render(request, "archive/list_unmanaged.html", locals())
 
 
 def file_unmanaged(request, filename):
-    division = 'unmanaged'
-
-    tags = mutagen.File(os.path.join(settings.UNMANAGED_PATH, filename.encode('utf-8')))
+    tags = mutagen.File(os.path.join(settings.UNMANAGED_PATH, filename))
     if not tags:
         tags = {}
     
     err_exists = request.GET.get('exists')
     return render(request, "archive/file_unmanaged.html", locals())
     if not tags:
         tags = {}
     
     err_exists = request.GET.get('exists')
     return render(request, "archive/file_unmanaged.html", locals())
+
+
+class BookView(ListView):
+    template_name = 'archive/book.html'
+
+    def get_queryset(self):
+        qs = models.Audiobook.objects.filter(slug=self.kwargs["slug"]).order_by(
+            "index"
+        )
+        last_vol = None
+        last_vol_sub = None
+        for b in qs:
+            if last_vol is None or last_vol.youtube_volume_index != b.youtube_volume_index:
+                last_vol = b
+                b.total = 0
+                if last_vol_sub is None or b.youtube_volume:
+                    last_vol_sub = last_vol
+                    last_vol_sub.total_for_sub = 0
+            last_vol.total += b.duration
+            last_vol_sub.total_for_sub += b.duration
+            b.subtotal = last_vol_sub.total_for_sub
+        return list(qs)
+
+
+@permission_required('archive.change_audiobook')
+def book_youtube_volume(request, aid):
+    audiobook = get_object_or_404(models.Audiobook, id=aid)
+    slug = audiobook.slug
+    cur_vol = audiobook.youtube_volume
+    new_vol = request.POST.get('volume', '')
+
+    audiobook.youtube_volume = new_vol
+    audiobook.save()
+    
+    for a in models.Audiobook.objects.filter(slug=slug, youtube_volume=cur_vol, index__gt=audiobook.index).order_by('index'):
+        if a.youtube_volume != cur_vol:
+            break
+        a.youtube_volume = new_vol
+        a.save()
+    
+    return redirect('book', audiobook.slug)
+