369e7e49e762e5c0d8c1df71e5db50805ab064bf
[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, permission_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 @permission_required('archive.change_audiobook')
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 @permission_required('archive.change_audiobook')
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 @permission_required('archive.change_audiobook')
100 def remove_to_archive(request, aid):
101     """ move a managed file to the unmanaged files dir """
102
103     audiobook = get_object_or_404(models.Audiobook, id=aid)
104     old_path = audiobook.source_file.path
105     new_path = os.path.join(settings.UNMANAGED_PATH,
106         str(audiobook.source_file)[len(settings.FILES_SAVE_PATH):].lstrip('/'))
107     new_dir = os.path.split(new_path)[0]
108     if not os.path.isdir(new_dir):
109         os.makedirs(new_dir)
110
111     if not os.path.isfile(old_path):
112         raise Http404
113
114     try:
115         os.link(old_path, new_path)
116     except OSError:
117         # destination file exists, don't overwrite it
118         # TODO: this should probably be more informative
119         return redirect(file_new, filename)
120     else:
121         os.unlink(old_path)
122         audiobook.delete()
123
124     return redirect(list_unmanaged)
125
126 @require_POST
127 @permission_required('archive.change_audiobook')
128 def move_to_new(request, filename):
129     """ move a unmanaged file to new files dir """
130
131     filename_str = filename.encode('utf-8')
132     old_path = os.path.join(settings.UNMANAGED_PATH, filename_str)
133     new_path = os.path.join(settings.NEW_PATH, filename_str)
134     new_dir = os.path.split(new_path)[0]
135     if not os.path.isdir(new_dir):
136         os.makedirs(new_dir)
137
138     if not os.path.isfile(old_path):
139         raise Http404
140
141     try:
142         os.link(old_path, new_path)
143         os.unlink(old_path)
144     except OSError:
145         # destination file exists, don't overwrite it
146         # TODO: this should probably be more informative
147         return redirect(reverse(file_unmanaged, args=[filename]) + "?exists=1")
148
149     return redirect(list_unmanaged)
150
151
152 @require_POST
153 @permission_required('archive.change_audiobook')
154 def publish(request, aid, publish=True):
155     """ mark file for publishing """
156     audiobook = get_object_or_404(models.Audiobook, id=aid)
157     tags = {
158         'name': audiobook.title,
159         'url': audiobook.url,
160         'tags': audiobook.new_publish_tags(),
161         }
162     audiobook.mp3_tags = tags
163     audiobook.ogg_tags = tags
164     audiobook.mp3_status = audiobook.ogg_status = status.WAITING
165     audiobook.save()
166     # isn't there a race here?
167     audiobook.mp3_task = tasks.Mp3Task.delay(aid, publish).task_id
168     audiobook.ogg_task = tasks.OggTask.delay(aid, publish).task_id
169     audiobook.save()
170
171     return redirect(file_managed, aid)
172
173
174 @require_POST
175 @permission_required('archive.change_audiobook')
176 def cancel_publishing(request, aid):
177     """ cancel scheduled publishing """
178     audiobook = get_object_or_404(models.Audiobook, id=aid)
179     # TODO: cancel tasks
180     audiobook.mp3_status = None
181     audiobook.ogg_status = None
182     audiobook.save()
183     return redirect(file_managed, aid)
184
185
186 @login_required
187 def list_unpublished(request):
188     division = 'unpublished'
189
190     objects = models.Audiobook.objects.filter(Q(mp3_published=None) | Q(ogg_published=None))
191     return render(request, "archive/list_unpublished.html", locals())
192
193
194 @login_required
195 def list_publishing(request):
196     division = 'publishing'
197
198     objects = models.Audiobook.objects.exclude(mp3_status=None, ogg_status=None)
199     objects_by_status = {}
200     for o in objects:
201         if o.mp3_status:
202             k = o.mp3_status, o.get_mp3_status_display()
203             objects_by_status.setdefault(k, []).append(o)
204         if o.ogg_status and o.ogg_status != o.mp3_status:
205             k = o.ogg_status, o.get_ogg_status_display()
206             objects_by_status.setdefault(k, []).append(o)
207     status_objects = sorted(objects_by_status.items(), reverse=True)
208
209     return render(request, "archive/list_publishing.html", locals())
210
211
212 @login_required
213 def list_published(request):
214     division = 'published'
215
216     objects = models.Audiobook.objects.exclude(Q(mp3_published=None) | Q(ogg_published=None))
217     return render(request, "archive/list_published.html", locals())
218
219
220 @permission_required('archive.change_audiobook')
221 def file_managed(request, id):
222     audiobook = get_object_or_404(models.Audiobook, id=id)
223
224     if request.POST:
225         form = AudiobookForm(request.POST, instance=audiobook)
226         if form.is_valid():
227             try:
228                 form.save()
229             except IOError:
230                 raise Http404
231
232     division = 'published' if audiobook.published() else 'unpublished'
233     path = audiobook.source_file.path[len(settings.FILES_PATH):].lstrip('/')
234
235     # for tags update
236     tags = mutagen.File(audiobook.source_file.path)
237     if not tags:
238         tags = {}
239     form = AudiobookForm(instance=audiobook)
240
241     return render(request, "archive/file_managed.html", locals())
242
243
244 @login_required
245 def list_unmanaged(request):
246     division = 'unmanaged'
247
248     objects = sorted(all_files(settings.UNMANAGED_PATH))
249     return render(request, "archive/list_unmanaged.html", locals())
250
251
252 @login_required
253 def file_unmanaged(request, filename):
254     division = 'unmanaged'
255
256     tags = mutagen.File(os.path.join(settings.UNMANAGED_PATH, filename.encode('utf-8')))
257     if not tags:
258         tags = {}
259     
260     err_exists = request.GET.get('exists')
261     return render(request, "archive/file_unmanaged.html", locals())