]> git.0d.be Git - django-panik-emissions.git/blob - emissions/views.py
de183ab29836bb969df6914fbb8700468264ba1c
[django-panik-emissions.git] / emissions / views.py
1 import datetime
2 import json
3 import os
4 import time
5
6 from django.conf import settings
7 from django.core.exceptions import PermissionDenied
8 from django.core.files.storage import DefaultStorage
9 from django.core.urlresolvers import reverse_lazy
10 from django.http import HttpResponse, Http404, HttpResponseRedirect
11 from django.core.urlresolvers import reverse, reverse_lazy
12 from django.shortcuts import redirect
13 from django.utils.translation import ugettext as _, ugettext_lazy
14
15 from django.views.decorators.csrf import csrf_exempt
16 from django.views.generic.base import View, TemplateView, RedirectView
17 from django.views.generic.edit import CreateView, UpdateView, DeleteView
18 from django.views.generic.list import ListView
19 from django.views.generic.detail import DetailView
20
21 from django.contrib import messages
22
23 import haystack.views
24
25 from .models import Emission, Episode, Diffusion, Category, Schedule, \
26                     SoundFile, NewsItem, NewsCategory, Absence, \
27                     PlaylistElement
28 from .forms import EmissionForm, EpisodeForm, EpisodeNewForm, ScheduleForm, \
29                    DiffusionForm, SoundFileForm, NewsItemForm, \
30                    SoundFileEditForm, AbsenceForm, PlaylistElementForm
31
32
33 __all__ = ['EmissionListView', 'EmissionDetailView', 'EmissionCreateView',
34            'EmissionUpdateView', 'EmissionDeleteView',
35            'EpisodeCreateView', 'EpisodeDetailView', 'EpisodeUpdateView',
36            'EpisodeDeleteView', 'EmissionAddScheduleView',
37            'ScheduleDeleteView', 'CategoryListView', 'DaysView',
38            'UploadView', 'EpisodeAddSoundFileView',
39            'EpisodeAddDiffusionView', 'DiffusionDeleteView',
40            'EmissionNewsItemAdd', 'NewsItemDetailView',
41            'NewsItemUpdateView', 'CategoryNewsItemAddView',
42            'NewsItemDeleteView', 'NewsItemAddView',
43            'SoundFileDeleteView', 'SoundFileUpdateView',
44            'EmissionAddAbsenceView', 'AbsenceDeleteView',
45            'EmissionOpenChatView', 'EmissionCloseChatView',
46            'EpisodeRegieView',
47            'EpisodeRegieUpdateOrderView',
48            'EpisodeRegieMarks', 'EpisodeRegieDeleteElementView',
49            'EpisodeStartView', 'EpisodeStopView',
50            ]
51
52
53 SUCCESS_MESSAGE = ugettext_lazy('Your changes will appear online in a few minutes.')
54
55
56 class EmissionListView(ListView):
57     model = Emission
58
59     def get_queryset(self):
60         return Emission.objects.order_by('title')
61
62
63 class CategoryListView(ListView):
64     model = Category
65
66     def get_queryset(self):
67         return Category.objects.order_by('title')
68
69
70 class EmissionDetailView(DetailView):
71     model = Emission
72
73     def get_context_data(self, **kwargs):
74         context = super(EmissionDetailView, self).get_context_data(**kwargs)
75         context['add_schedule_form'] = ScheduleForm(initial={'emission': self.object})
76         context['add_absence_form'] = AbsenceForm(
77                 initial={'emission': self.object, 'user': self.request.user})
78         context['schedules'] = Schedule.objects.select_related().filter(
79                 emission=self.object).order_by('datetime')
80
81         # get all episodes, with an additional attribute to get the date of
82         # their first diffusion
83         context['episodes'] = \
84                 Episode.objects.select_related().filter(emission=self.object
85                     ).extra(select={
86                         'first_diffusion': 'emissions_diffusion.datetime',
87                         },
88                         select_params=(False, True),
89                         where=['''datetime = (SELECT MIN(datetime)
90                                                 FROM emissions_diffusion
91                                                WHERE episode_id = emissions_episode.id)'''],
92                         tables=['emissions_diffusion'],
93                     ).order_by('-first_diffusion').distinct()
94
95         # get all related soundfiles in a single query
96         soundfiles = {}
97         for soundfile in SoundFile.objects.filter(podcastable=True,
98                 fragment=False, episode__emission=self.object):
99             soundfiles[soundfile.episode_id] = soundfile
100
101         Episode.set_prefetched_soundfiles(soundfiles)
102
103         context['newsitems'] = self.object.get_sorted_newsitems()
104         context['absences'] = self.object.absence_set.select_related(
105                 ).filter(datetime__gte=datetime.date.today()).order_by('datetime')
106
107         if not 'all' in self.request.GET:
108             context['episodes'] = context['episodes'][:10]
109             if context['absences']:
110                 context['newsitems'] = context['newsitems'][:5]
111             else:
112                 context['newsitems'] = context['newsitems'][:10]
113
114         try:
115             context['can_manage'] = self.request.user.can_manage(self.object)
116         except AttributeError:
117             pass
118
119         return context
120
121
122 class EmissionCreateView(CreateView):
123     form_class = EmissionForm
124     model = Emission
125
126     success_url = reverse_lazy('emission-list')
127
128     def get_form(self, *args, **kwargs):
129         if not self.request.user.has_perm('emissions.add_emission'):
130             raise PermissionDenied()
131         return super(EmissionCreateView, self).get_form(*args, **kwargs)
132
133     def get_success_url(self):
134         messages.success(self.request, SUCCESS_MESSAGE)
135         return super(EmissionCreateView, self).get_success_url()
136
137
138 class EmissionUpdateView(UpdateView):
139     form_class = EmissionForm
140     model = Emission
141
142     def get_form(self, *args, **kwargs):
143         if not self.request.user.can_manage(self.object):
144             raise PermissionDenied()
145         return super(EmissionUpdateView, self).get_form(*args, **kwargs)
146
147     def get_success_url(self):
148         messages.success(self.request, SUCCESS_MESSAGE)
149         return super(EmissionUpdateView, self).get_success_url()
150
151
152 class EmissionDeleteView(DeleteView):
153     model = Emission
154     success_url = reverse_lazy('home')
155
156     def get_form(self, *args, **kwargs):
157         if not self.request.user.can_manage(self.object):
158             raise PermissionDenied()
159         return super(EmissionDeleteView, self).get_form(*args, **kwargs)
160
161     def get_success_url(self):
162         messages.success(self.request, SUCCESS_MESSAGE)
163         return super(EmissionDeleteView, self).get_success_url()
164
165
166 class EpisodeCreateView(CreateView):
167     model = Episode
168     form_class = EpisodeNewForm
169
170     def get_form(self, *args, **kwargs):
171         emission = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
172         if not self.request.user.can_manage(emission):
173             raise PermissionDenied()
174         return super(EpisodeCreateView, self).get_form(*args, **kwargs)
175
176     def get_initial(self):
177         initial = super(EpisodeCreateView, self).get_initial()
178         initial['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
179         initial['duration'] = initial['emission'].duration
180         initial['first_diffusion'] = initial['emission'].get_next_planned_date()
181         for i, schedule in enumerate(
182                 Schedule.objects.filter(emission=initial['emission'],
183                     rerun=True).order_by('datetime')):
184             rerun_date = schedule.get_next_planned_date(initial['first_diffusion'])
185             if i == 0:
186                 initial['second_diffusion'] = rerun_date
187             elif i == 1:
188                 initial['third_diffusion'] = rerun_date
189             elif i == 2:
190                 initial['fourth_diffusion'] = rerun_date
191         return initial
192
193     def get_context_data(self, **kwargs):
194         context = super(EpisodeCreateView, self).get_context_data(**kwargs)
195         context['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
196         return context
197
198     def get_success_url(self):
199         messages.success(self.request, SUCCESS_MESSAGE)
200         return self.object.get_absolute_url()
201
202
203 class EmissionEpisodeMixin(object):
204     def get_queryset(self):
205         return self.model.objects.filter(emission__slug=self.kwargs['emission_slug'])
206
207
208 class EpisodeDetailView(EmissionEpisodeMixin, DetailView):
209     model = Episode
210
211     def get_context_data(self, **kwargs):
212         context = super(EpisodeDetailView, self).get_context_data(**kwargs)
213         context['diffusions'] = Diffusion.objects.filter(episode=self.object.id)
214         context['soundfiles'] = SoundFile.objects.filter(episode=self.object.id)
215
216         try:
217             context['can_manage'] = self.request.user.can_manage(self.object.emission)
218         except AttributeError:
219             pass
220
221         return context
222
223
224 class EpisodeUpdateView(EmissionEpisodeMixin, UpdateView):
225     form_class = EpisodeForm
226     model = Episode
227
228     def get_form(self, *args, **kwargs):
229         if not self.request.user.can_manage(self.object.emission):
230             raise PermissionDenied()
231         return super(EpisodeUpdateView, self).get_form(*args, **kwargs)
232
233     def get_success_url(self):
234         messages.success(self.request, SUCCESS_MESSAGE)
235         return super(EpisodeUpdateView, self).get_success_url()
236
237
238 class EpisodeDeleteView(EmissionEpisodeMixin, DeleteView):
239     model = Episode
240
241     def get_form(self, *args, **kwargs):
242         if not self.request.user.can_manage(self.object.emission):
243             raise PermissionDenied()
244         return super(EpisodeDeleteView, self).get_form(*args, **kwargs)
245
246     def get_success_url(self):
247         messages.success(self.request, SUCCESS_MESSAGE)
248         return reverse('emission-view', kwargs={
249             'slug': self.object.emission.slug})
250
251
252 class EmissionAddScheduleView(CreateView):
253     form_class = ScheduleForm
254     model = Schedule
255
256     def get_form(self, *args, **kwargs):
257         if not self.request.user.has_perm('emissions.add_schedule'):
258             raise PermissionDenied()
259         return super(EmissionAddScheduleView, self).get_form(*args, **kwargs)
260
261     def get_success_url(self):
262         messages.success(self.request, SUCCESS_MESSAGE)
263         return self.object.emission.get_absolute_url()
264
265
266 class ScheduleDeleteView(RedirectView):
267     def get_redirect_url(self, emission_slug, pk):
268         if not self.request.user.has_perm('emissions.delete_schedule'):
269             raise PermissionDenied()
270         Schedule.objects.filter(id=pk).delete()
271         messages.success(self.request, SUCCESS_MESSAGE)
272         return reverse('emission-view', kwargs={'slug': str(emission_slug)})
273
274
275 class EmissionAddAbsenceView(CreateView):
276     form_class = AbsenceForm
277     model = Absence
278
279     def get_initial(self):
280         initial = super(EmissionAddAbsenceView, self).get_initial()
281         initial['emission'] = Emission.objects.get(slug=self.kwargs.get('slug'))
282         initial['user'] = self.request.user
283         return initial
284
285     def get_success_url(self):
286         messages.success(self.request, SUCCESS_MESSAGE)
287         return self.object.emission.get_absolute_url()
288
289     def get_form(self, *args, **kwargs):
290         emission = Emission.objects.get(slug=self.kwargs.get('slug'))
291         if not self.request.user.can_manage(emission):
292             raise PermissionDenied()
293         return super(EmissionAddAbsenceView, self).get_form(*args, **kwargs)
294
295
296 class AbsenceDeleteView(RedirectView):
297     def get_redirect_url(self, emission_slug, pk):
298         if not self.request.user.has_perm('emissions.delete_absence'):
299             raise PermissionDenied()
300         Absence.objects.filter(id=pk).delete()
301         messages.success(self.request, SUCCESS_MESSAGE)
302         return reverse('emission-view', kwargs={'slug': str(emission_slug)})
303
304
305 class DaysView(TemplateView):
306     template_name = 'emissions/days.html'
307
308     def get_context_data(self, **kwargs):
309         context = super(DaysView, self).get_context_data(**kwargs)
310         schedules = Schedule.objects.all().order_by('datetime')
311         days = []
312         for day in range(7):
313             days.append({'schedules': [x for x in schedules if x.is_on_weekday(day+1)],
314                          'datetime': datetime.datetime(2007, 1, day+1)})
315         context['days'] = days
316         return context
317
318 class JSONResponse(HttpResponse):
319     """JSON response class."""
320     def __init__(self, obj='', json_opts={}, mimetype='application/json', *args, **kwargs):
321         content = json.dumps(obj, **json_opts)
322         super(JSONResponse,self).__init__(content, mimetype, *args, **kwargs)
323
324
325 class UploadView(View):
326
327     def response_mimetype(self, request):
328         if 'application/json' in request.META['HTTP_ACCEPT']:
329             return 'application/json'
330         else:
331             return 'text/plain'
332
333     @csrf_exempt
334     def post(self, request, transaction_id):
335         storage = DefaultStorage()
336         max_filename_length = 256
337         url = reverse('upload', kwargs={'transaction_id': transaction_id})
338         if request.FILES is None:
339             response = JSONResponse({}, {}, self.response_mimetype(request))
340             response['Content-Disposition'] = 'inline; filename=files.json'
341             return response
342         data = []
343         for uploaded_file in request.FILES.values():
344             path = os.path.join('upload', str(transaction_id), uploaded_file.name)
345             filename = storage.save(path, uploaded_file)
346             url = '%s%s' % (url, os.path.basename(filename))
347             data.append({'name': uploaded_file.name, 'size': uploaded_file.size, 'url': url})
348         response = JSONResponse(data, {}, self.response_mimetype(request))
349         response['Content-Disposition'] = 'inline; filename=files.json'
350         return response
351
352
353 class EpisodeAddSoundFileView(CreateView):
354     form_class = SoundFileForm
355     model = SoundFile
356
357     def get_initial(self):
358         context = {
359             'episode': Episode.objects.get(
360                 slug=self.kwargs.get('slug'),
361                 emission__slug=self.kwargs.get('emission_slug')),
362             'title': _('Record'),
363         }
364         context['license'] = context['episode'].emission.default_license
365         return context
366
367     def get_form(self, *args, **kwargs):
368         emission = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
369         if not self.request.user.can_manage(emission):
370             raise PermissionDenied()
371         return super(EpisodeAddSoundFileView, self).get_form(*args, **kwargs)
372
373     def get_success_url(self):
374         messages.success(self.request, SUCCESS_MESSAGE)
375         return self.object.episode.get_absolute_url()
376
377
378 class EpisodeAddDiffusionView(CreateView):
379     form_class = DiffusionForm
380     model = Diffusion
381
382     def get_initial(self):
383         return {
384             'episode': Episode.objects.get(
385                 slug=self.kwargs.get('slug'),
386                 emission__slug=self.kwargs.get('emission_slug')),
387         }
388
389     def get_form(self, *args, **kwargs):
390         if not self.request.user.has_perm('emissions.add_diffusion'):
391             raise PermissionDenied()
392         episode = Episode.objects.get(slug=self.kwargs.get('slug'),
393                 emission__slug=self.kwargs.get('emission_slug'))
394         if not self.request.user.can_manage(episode):
395             raise PermissionDenied()
396         return super(EpisodeAddDiffusionView, self).get_form(*args, **kwargs)
397
398     def get_success_url(self):
399         messages.success(self.request, SUCCESS_MESSAGE)
400         return self.object.episode.get_absolute_url()
401
402
403 class DiffusionDeleteView(RedirectView):
404     def get_redirect_url(self, emission_slug, slug, pk):
405         if not self.request.user.has_perm('emissions.delete_diffusion'):
406             raise PermissionDenied()
407         episode = Episode.objects.get(slug=slug, emission__slug=emission_slug)
408         if not self.request.user.can_manage(episode):
409             raise PermissionDenied()
410         Diffusion.objects.filter(id=pk).delete()
411         messages.success(self.request, SUCCESS_MESSAGE)
412         return reverse('episode-view', kwargs={'emission_slug': str(emission_slug),
413                                                'slug': str(slug)})
414
415
416 class FacetedSearchView(haystack.views.FacetedSearchView):
417     def extra_context(self):
418         context = super(FacetedSearchView, self).extra_context()
419         context['selected_categories'] = [
420                 x.split(':', 1)[1] for x in self.request.GET.getlist('selected_facets')
421                 if x.startswith('categories_exact')]
422         context['selected_tags'] = [
423                 x.split(':', 1)[1] for x in self.request.GET.getlist('selected_facets')
424                 if x.startswith('tags_exact')]
425         return context
426
427
428 class EmissionNewsItemAdd(CreateView):
429     model = NewsItem
430     form_class = NewsItemForm
431
432     def get_form(self, *args, **kwargs):
433         emission = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
434         if not self.request.user.can_manage(emission):
435             raise PermissionDenied()
436         return super(EmissionNewsItemAdd, self).get_form(*args, **kwargs)
437
438     def get_initial(self):
439         initial = super(EmissionNewsItemAdd, self).get_initial()
440         initial['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
441         initial['date'] = datetime.datetime.today()
442         initial['user'] = self.request.user
443         return initial
444
445     def get_context_data(self, **kwargs):
446         context = super(EmissionNewsItemAdd, self).get_context_data(**kwargs)
447         context['emission'] = Emission.objects.get(slug=self.kwargs.get('emission_slug'))
448         return context
449
450     def get_success_url(self):
451         messages.success(self.request, SUCCESS_MESSAGE)
452         return self.object.get_absolute_url()
453
454
455 class NewsItemDetailView(DetailView):
456     model = NewsItem
457
458     def get_context_data(self, **kwargs):
459         context = super(NewsItemDetailView, self).get_context_data(**kwargs)
460         context['can_manage'] = self.request.user.can_manage(self.object)
461         return context
462
463
464 class NewsItemUpdateView(UpdateView):
465     form_class = NewsItemForm
466     model = NewsItem
467
468     def get_form(self, *args, **kwargs):
469         if not self.request.user.can_manage(self.object):
470             raise PermissionDenied()
471         return super(NewsItemUpdateView, self).get_form(*args, **kwargs)
472
473     def get_initial(self):
474         initial = super(NewsItemUpdateView, self).get_initial()
475         initial['user'] = self.request.user
476         return initial
477
478     def get_success_url(self):
479         messages.success(self.request, SUCCESS_MESSAGE)
480         return super(NewsItemUpdateView, self).get_success_url()
481
482
483 class CategoryNewsItemAddView(CreateView):
484     model = NewsItem
485     form_class = NewsItemForm
486
487     def get_form(self, *args, **kwargs):
488         if not self.request.user.has_perm('emissions.add_newsitem'):
489             raise PermissionDenied()
490         return super(CategoryNewsItemAddView, self).get_form(*args, **kwargs)
491
492     def get_initial(self):
493         initial = super(CategoryNewsItemAddView, self).get_initial()
494         initial['category'] = NewsCategory.objects.get(slug=self.kwargs.get('slug'))
495         initial['date'] = datetime.datetime.today()
496         initial['user'] = self.request.user
497         return initial
498
499     def get_success_url(self):
500         messages.success(self.request, SUCCESS_MESSAGE)
501         return self.object.get_absolute_url()
502
503
504 class NewsItemAddView(CreateView):
505     model = NewsItem
506     form_class = NewsItemForm
507
508     def get_form(self, *args, **kwargs):
509         if not self.request.user.has_perm('emissions.add_newsitem'):
510             raise PermissionDenied()
511         return super(NewsItemAddView, self).get_form(*args, **kwargs)
512
513     def get_initial(self):
514         initial = super(NewsItemAddView, self).get_initial()
515         initial['date'] = datetime.datetime.today()
516         initial['user'] = self.request.user
517         return initial
518
519     def get_success_url(self):
520         messages.success(self.request, SUCCESS_MESSAGE)
521         return self.object.get_absolute_url()
522
523
524 class NewsItemDeleteView(DeleteView):
525     model = NewsItem
526     success_url = reverse_lazy('home')
527
528     def get_form(self, *args, **kwargs):
529         if not self.request.user.can_manage(self.object):
530             raise PermissionDenied()
531         return super(NewsItemDeleteView, self).get_form(*args, **kwargs)
532
533     def get_success_url(self):
534         messages.success(self.request, SUCCESS_MESSAGE)
535         return super(NewsItemDeleteView, self).get_success_url()
536
537
538 class SoundFileDeleteView(DeleteView):
539     model = SoundFile
540
541     def get_form(self, *args, **kwargs):
542         if not self.request.user.can_manage(self.object):
543             raise PermissionDenied()
544         return super(SoundFileDeleteView, self).get_form(*args, **kwargs)
545
546     def get_success_url(self):
547         messages.success(self.request, SUCCESS_MESSAGE)
548         return reverse('episode-view', kwargs={
549             'emission_slug': self.object.episode.emission.slug,
550             'slug': self.object.episode.slug})
551
552
553 class SoundFileUpdateView(UpdateView):
554     template_name_suffix = '_form_update'
555     form_class = SoundFileEditForm
556     model = SoundFile
557
558     def get_form(self, *args, **kwargs):
559         if not self.request.user.can_manage(self.object.episode.emission):
560             raise PermissionDenied()
561         return super(SoundFileUpdateView, self).get_form(*args, **kwargs)
562
563     def get_success_url(self):
564         messages.success(self.request, SUCCESS_MESSAGE)
565         return '../../'
566
567
568 class EmissionOpenChatView(DetailView):
569     model = Emission
570
571     def render_to_response(self, context):
572         self.object.chat_open = datetime.datetime.now()
573         self.object.save()
574         return redirect(self.object.get_absolute_url())
575
576
577 class EmissionCloseChatView(DetailView):
578     model = Emission
579
580     def render_to_response(self, context):
581         self.object.chat_open = None
582         self.object.save()
583         return redirect(self.object.get_absolute_url())
584
585
586 class EpisodeRegieView(EmissionEpisodeMixin, DetailView):
587     model = Episode
588     template_name = 'emissions/episode_regie.html'
589
590     def get_object(self, queryset=None):
591         try:
592             return Episode.objects.get(slug=self.kwargs.get('slug'),
593                     emission__slug=self.kwargs.get('emission_slug'))
594         except Episode.DoesNotExist:
595             raise Http404()
596
597     def post(self, request, *args, **kwargs):
598         episode = self.get_object()
599         form = PlaylistElementForm(request.POST, request.FILES)
600         if not form.is_valid():
601             messages.error(request, _('Error adding file'))
602             return HttpResponseRedirect('.')
603         i = PlaylistElement.objects.filter(episode=episode).count()
604         playlist_element = PlaylistElement(
605                 episode=episode,
606                 title=os.path.basename(form.cleaned_data['sound'].name),
607                 sound=form.cleaned_data['sound'],
608                 order=i+1)
609         playlist_element.save()
610         messages.info(request, _('File uploaded successfully.'))
611         return HttpResponseRedirect('.')
612
613     def get_context_data(self, **kwargs):
614         context = super(EpisodeRegieView, self).get_context_data(**kwargs)
615         context['playlist'] = PlaylistElement.objects.filter(episode=self.object.id)
616         context['start_time'] = ''
617         context['end_time'] = ''
618         if self.object.effective_start:
619             context['ready'] = 'ready'
620             context['start_time'] = int(time.mktime(self.object.effective_start.timetuple())*1000
621                     + self.object.effective_start.microsecond/1000)
622         if self.object.effective_end:
623             context['end_time'] = int(time.mktime(self.object.effective_end.timetuple())*1000
624                     + self.object.effective_end.microsecond/1000)
625             context['download_url'] = self.object.get_pige_download_url()
626
627         try:
628             context['can_manage'] = self.request.user.can_manage(self.object)
629         except AttributeError:
630             pass
631
632         context['upload_file_form'] = PlaylistElementForm(initial={'episode': self.object})
633
634         return context
635
636
637 class EpisodeRegieUpdateOrderView(View):
638     def get(self, request, *args, **kwargs):
639         new_order = request.GET.getlist('new-order[]')
640         for element in PlaylistElement.objects.filter(id__in=new_order):
641             element.order = new_order.index(str(element.id)) + 1
642             element.save()
643         return HttpResponse('ok')
644
645
646 class EpisodeRegieDeleteElementView(EpisodeRegieView):
647     def get(self, request, *args, **kwargs):
648         element_id = request.GET.get('id')
649         element = PlaylistElement.objects.get(id=element_id)
650         if not self.request.user.can_manage(element.episode):
651             return JSONResponse({'err': 1})
652         element.delete()
653         return HttpResponseRedirect('..')
654
655
656 class EpisodeRegieMarks(EpisodeRegieView):
657     def get(self, request, *args, **kwargs):
658         episode = self.get_object()
659         start = self.request.GET['start']
660         end = self.request.GET['end']
661         if start:
662             episode.effective_start = datetime.datetime.fromtimestamp(float(start)/1000)
663         else:
664             episode.effective_start = None
665         if end:
666             episode.effective_end = datetime.datetime.fromtimestamp(float(end)/1000)
667         else:
668             episode.effective_end = None
669         episode.save()
670         obj = {'err': 0}
671         if end:
672             obj['pige_download_url'] = episode.get_pige_download_url()
673         return JSONResponse(obj)
674
675
676 class EpisodeStartView(EmissionEpisodeMixin, RedirectView):
677     def get_redirect_url(self, emission_slug, slug):
678         episode = Episode.objects.get(slug=slug, emission__slug=emission_slug)
679         episode.effective_start = datetime.datetime.now()
680         episode.save()
681         messages.success(self.request, _('Started recording'))
682         return reverse('episode-view',
683                 kwargs={'emission_slug': emission_slug,
684                         'slug': slug})
685
686
687 class EpisodeStopView(EmissionEpisodeMixin, RedirectView):
688     def get_redirect_url(self, emission_slug, slug):
689         episode = Episode.objects.get(slug=slug, emission__slug=emission_slug)
690         episode.effective_end = datetime.datetime.now()
691         episode.save()
692         messages.success(self.request, _('Stopped recording'))
693         return reverse('episode-view',
694                 kwargs={'emission_slug': emission_slug,
695                         'slug': slug})