use directories and allow filetypes other than FLAC
[audio.git] / apps / archive / views.py
1 # Create your views here.
2
3 from datetime import datetime
4 import os
5 import os.path
6
7 from archive import settings
8 from django.contrib.auth import logout
9 from django.contrib.auth.decorators import login_required
10 from django.core.urlresolvers import reverse
11 from django.db.models import Q, Max
12 from django.http import Http404
13 from django.shortcuts import render, redirect, get_object_or_404
14 from django.views.decorators.http import require_POST
15
16 import mutagen
17
18 from archive.constants import status
19 from archive import models
20 from archive.forms import AudiobookForm
21 from archive import tasks
22 from archive.utils import all_files
23
24
25 @login_required
26 def list_new(request):
27     division = 'new'
28
29     path = settings.NEW_PATH
30     objects = sorted(all_files(path))
31     return render(request, "archive/list_new.html", locals())
32
33
34 @login_required
35 def file_new(request, filename):
36     division = 'new'
37
38     filepath = filename.encode('utf-8')
39     root_filepath = os.path.join(settings.NEW_PATH, filename.encode('utf-8'))
40     if request.POST:
41         form = AudiobookForm(request.POST)
42         if form.is_valid():
43             try:
44                 form.save(path=filepath)
45             except IOError:
46                 raise Http404
47             return redirect(list_new)
48
49     try:
50         tags = mutagen.File(root_filepath)
51     except IOError:
52         raise Http404
53     d = {}
54     if tags:
55         for tag in tags:
56             value = tags[tag]
57             if isinstance(value, list):
58                 d[tag] = value[0]
59             else:
60                 d[tag] = value
61             if tag == 'project':
62                 try:
63                     d[tag] = models.Project.objects.get(name=d[tag]).pk
64                 except models.Project.DoesNotExist:
65                     d[tag] = None
66
67     if not request.POST:
68         form = AudiobookForm(d)
69     return render(request, "archive/file_new.html", locals())
70
71
72 @require_POST
73 @login_required
74 def move_to_archive(request, filename):
75     """ move a new file to the unmanaged files dir """
76
77     filename_str = filename.encode('utf-8')
78     old_path = os.path.join(settings.NEW_PATH, filename_str)
79     new_path = os.path.join(settings.UNMANAGED_PATH, filename_str)
80     new_dir = os.path.split(new_path)[0]
81     if not os.path.isdir(new_dir):
82         os.makedirs(new_dir)
83
84     if not os.path.isfile(old_path):
85         raise Http404
86
87     try:
88         os.link(old_path, new_path)
89         os.unlink(old_path)
90     except OSError:
91         # destination file exists, don't overwrite it
92         # TODO: this should probably be more informative
93         return redirect(file_new, filename)
94
95     return redirect(list_new)
96
97
98 @require_POST
99 @login_required
100 def move_to_new(request, filename):
101     """ move a unmanaged file to new files dir """
102
103     filename_str = filename.encode('utf-8')
104     old_path = os.path.join(settings.UNMANAGED_PATH, filename_str)
105     new_path = os.path.join(settings.NEW_PATH, filename_str)
106     new_dir = os.path.split(new_path)[0]
107     if not os.path.isdir(new_dir):
108         os.makedirs(new_dir)
109
110     if not os.path.isfile(old_path):
111         raise Http404
112
113     try:
114         os.link(old_path, new_path)
115         os.unlink(old_path)
116     except OSError:
117         # destination file exists, don't overwrite it
118         # TODO: this should probably be more informative
119         return redirect(reverse(file_unmanaged, args=[filename]) + "?exists=1")
120
121     return redirect(list_unmanaged)
122
123
124 @require_POST
125 @login_required
126 def publish(request, aid):
127     """ mark file for publishing """
128     audiobook = get_object_or_404(models.Audiobook, id=aid)
129     tags = {
130         'name': audiobook.title,
131         'url': audiobook.url,
132         'tags': audiobook.new_publish_tags(),
133         }
134     audiobook.mp3_tags = tags
135     audiobook.ogg_tags = tags
136     audiobook.mp3_status = audiobook.ogg_status = status.WAITING
137     audiobook.save()
138     # isn't there a race here?
139     audiobook.mp3_task = tasks.Mp3Task.delay(aid).task_id
140     audiobook.ogg_task = tasks.OggTask.delay(aid).task_id
141     audiobook.save()
142
143     return redirect(file_managed, aid)
144
145
146 @require_POST
147 @login_required
148 def cancel_publishing(request, aid):
149     """ cancel scheduled publishing """
150     audiobook = get_object_or_404(models.Audiobook, id=aid)
151     # TODO: cancel tasks
152     audiobook.mp3_status = None
153     audiobook.ogg_status = None
154     audiobook.save()
155     return redirect(file_managed, aid)
156
157
158 @login_required
159 def list_unpublished(request):
160     division = 'unpublished'
161
162     objects = models.Audiobook.objects.filter(Q(mp3_published=None) | Q(ogg_published=None))
163     return render(request, "archive/list_unpublished.html", locals())
164
165
166 @login_required
167 def list_publishing(request):
168     division = 'publishing'
169
170     objects = models.Audiobook.objects.exclude(mp3_status=None, ogg_status=None)
171     objects_by_status = {}
172     for o in objects:
173         if o.mp3_status:
174             k = o.mp3_status, o.get_mp3_status_display()
175             objects_by_status.setdefault(k, []).append(o)
176         if o.ogg_status and o.ogg_status != o.mp3_status:
177             k = o.ogg_status, o.get_ogg_status_display()
178             objects_by_status.setdefault(k, []).append(o)
179     status_objects = sorted(objects_by_status.items(), reverse=True)
180
181     return render(request, "archive/list_publishing.html", locals())
182
183
184 @login_required
185 def list_published(request):
186     division = 'published'
187
188     objects = models.Audiobook.objects.exclude(Q(mp3_published=None) | Q(ogg_published=None))
189     return render(request, "archive/list_published.html", locals())
190
191
192 @login_required
193 def file_managed(request, id):
194     audiobook = get_object_or_404(models.Audiobook, id=id)
195
196     if request.POST:
197         form = AudiobookForm(request.POST, instance=audiobook)
198         if form.is_valid():
199             try:
200                 form.save()
201             except IOError:
202                 raise Http404
203
204     division = 'published' if audiobook.published() else 'unpublished'
205     path = audiobook.source_file.path[len(settings.FILES_PATH):].lstrip('/')
206
207     # for tags update
208     tags = mutagen.File(audiobook.source_file.path)
209     if not tags:
210         tags = {}
211     form = AudiobookForm(instance=audiobook)
212
213     return render(request, "archive/file_managed.html", locals())
214
215
216 @login_required
217 def list_unmanaged(request):
218     division = 'unmanaged'
219
220     objects = sorted(all_files(settings.UNMANAGED_PATH))
221     return render(request, "archive/list_unmanaged.html", locals())
222
223
224 @login_required
225 def file_unmanaged(request, filename):
226     division = 'unmanaged'
227
228     tags = mutagen.File(os.path.join(settings.UNMANAGED_PATH, filename.encode('utf-8')))
229     if not tags:
230         tags = {}
231     
232     err_exists = request.GET.get('exists')
233     return render(request, "archive/file_unmanaged.html", locals())
234
235
236 @login_required
237 def logout_view(request):
238     logout(request)
239     return redirect(list_new)