replace Http404 with more appropriate methods
[mygpo.git] / mygpo / web / views / podcast.py
blob47f65b36ed435789f823abf0f0f0b29fae1d92e9
1 from datetime import date, timedelta, datetime
3 from django.http import HttpResponseBadRequest, HttpResponseRedirect, Http404
4 from django.db import IntegrityError
5 from django.shortcuts import get_object_or_404, render_to_response
6 from django.template import RequestContext
7 from django.contrib.auth.decorators import login_required
8 from django.contrib.sites.models import Site
9 from django.utils.translation import ugettext as _
11 from mygpo.api.models import Podcast, Episode, EpisodeAction, Device, SubscriptionAction, Subscription, SUBSCRIBE_ACTION, UNSUBSCRIBE_ACTION, SyncGroup
12 from mygpo.web.forms import PrivacyForm, SyncForm
13 from mygpo.data.models import Listener, PodcastTag
14 from mygpo.decorators import manual_gc, allowed_methods
15 from mygpo.utils import daterange
18 MAX_TAGS_ON_PAGE=50
21 @allowed_methods(['GET', 'POST'])
22 def show(request, pid):
23 podcast = get_object_or_404(Podcast, pk=pid)
24 episodes = episode_list(podcast, request.user)
25 max_listeners = max([x.listeners for x in episodes]) if len(episodes) else 0
26 related_podcasts = [x for x in podcast.group.podcasts() if x != podcast] if podcast.group else []
28 tags = get_tags(podcast, request.user)
30 if request.user.is_authenticated():
31 devices = Device.objects.filter(user=request.user)
32 history = SubscriptionAction.objects.filter(podcast=podcast,device__in=devices).order_by('-timestamp')
33 subscribed_devices = [s.device for s in Subscription.objects.filter(podcast=podcast,user=request.user)]
34 subscribe_targets = podcast.subscribe_targets(request.user)
35 success = False
38 qs = Subscription.objects.filter(podcast=podcast, user=request.user)
39 if qs.count()>0 and request.user.get_profile().public_profile:
40 # subscription meta is valid for all subscriptions, so we get one - doesn't matter which
41 subscription = qs[0]
42 subscriptionmeta = subscription.get_meta()
43 if request.method == 'POST':
44 privacy_form = PrivacyForm(request.POST)
45 if privacy_form.is_valid():
46 subscriptionmeta.settings['public_subscription'] = privacy_form.cleaned_data['public']
47 try:
48 subscriptionmeta.save()
49 success = True
50 except IntegrityError, ie:
51 error_message = _('You can\'t use the same Device ID for two devices.')
52 else:
53 privacy_form = PrivacyForm({
54 'public': subscriptionmeta.public
57 else:
58 privacy_form = None
60 subscribe_form = SyncForm()
61 subscribe_form.set_targets(subscribe_targets, '')
63 timeline_data = listener_data(podcast)
64 return render_to_response('podcast.html', {
65 'tags': tags,
66 'history': history,
67 'timeline_data': timeline_data,
68 'podcast': podcast,
69 'privacy_form': privacy_form,
70 'devices': subscribed_devices,
71 'related_podcasts': related_podcasts,
72 'can_subscribe': len(subscribe_targets) > 0,
73 'subscribe_form': subscribe_form,
74 'episodes': episodes,
75 'max_listeners': max_listeners,
76 'success': success
77 }, context_instance=RequestContext(request))
78 else:
79 current_site = Site.objects.get_current()
80 return render_to_response('podcast.html', {
81 'podcast': podcast,
82 'related_podcasts': related_podcasts,
83 'tags': tags,
84 'url': current_site,
85 'episodes': episodes,
86 'max_listeners': max_listeners,
87 }, context_instance=RequestContext(request))
90 def get_tags(podcast, user):
91 tags = {}
92 for t in PodcastTag.objects.filter(podcast=podcast).values('tag').distinct():
93 tag_str = t['tag'].lower()
94 tags[tag_str] = False
96 if not user.is_anonymous():
97 for t in PodcastTag.objects.filter(podcast=podcast, user=user).values('tag').distinct():
98 tag_str = t['tag'].lower()
99 tags[tag_str] = True
101 tag_list = [{'tag': key, 'is_own': value} for key, value in tags.iteritems()]
102 tag_list.sort(key=lambda x: x['tag'])
104 if len(tag_list) > MAX_TAGS_ON_PAGE:
105 tag_list = filter(lambda x: x['is_own'], tag_list)
106 tag_list.append({'tag': '...', 'is_own': False})
108 return tag_list
111 def listener_data(podcast):
112 d = date(2010, 1, 1)
113 day = timedelta(1)
114 episodes = EpisodeAction.objects.filter(episode__podcast=podcast, timestamp__gte=d).order_by('timestamp').values('timestamp')
115 if len(episodes) == 0:
116 return []
118 start = episodes[0]['timestamp']
120 days = []
121 for d in daterange(start):
122 next = d + timedelta(days=1)
123 listeners = EpisodeAction.objects.filter(episode__podcast=podcast, timestamp__gte=d, timestamp__lt=next).values('user_id').distinct().count()
124 e = Episode.objects.filter(podcast=podcast, timestamp__gte=d, timestamp__lt=next)
125 episode = e[0] if e.count() > 0 else None
126 days.append({
127 'date': d,
128 'listeners': listeners,
129 'episode': episode})
131 return days
134 def episode_list(podcast, user):
136 Returns a list of episodes, with their action-attribute set to the latest
137 action. The attribute is unsert if there is no episode-action for
138 the episode.
140 episodes = Episode.objects.filter(podcast=podcast).order_by('-timestamp')
141 for e in episodes:
142 listeners = Listener.objects.filter(episode=e).values('user').distinct()
143 e.listeners = listeners.count()
145 if user.is_authenticated():
146 actions = EpisodeAction.objects.filter(episode=e, user=user).order_by('-timestamp')
147 if actions.count() > 0:
148 e.action = actions[0]
150 return episodes
153 @login_required
154 def add_tag(request, pid):
155 podcast = get_object_or_404(Podcast, id=pid)
156 tag_str = request.GET.get('tag', '')
157 if not tag_str:
158 return HttpResponseBadRequest()
160 tags = tag_str.split(',')
161 for t in tags:
162 t = t.strip()
163 tag = PodcastTag.objects.get_or_create(podcast=podcast, tag=t, source='user', user=request.user)
165 if request.GET.get('next', '') == 'mytags':
166 return HttpResponseRedirect('/tags/')
168 return HttpResponseRedirect('/podcast/%s' % pid)
171 @login_required
172 def remove_tag(request, pid):
173 podcast = get_object_or_404(Podcast, id=pid)
174 tag_str = request.GET.get('tag', '')
175 if not tag_str:
176 return HttpResponseBadRequest()
178 PodcastTag.objects.filter(podcast=podcast, tag=tag_str, source='user', user=request.user).delete()
180 if request.GET.get('next', '') == 'mytags':
181 return HttpResponseRedirect('/tags/')
183 return HttpResponseRedirect('/podcast/%s' % pid)
186 @manual_gc
187 @login_required
188 @allowed_methods(['GET', 'POST'])
189 def subscribe(request, pid):
190 podcast = get_object_or_404(Podcast, pk=pid)
191 error_message = None
193 if request.method == 'POST':
194 form = SyncForm(request.POST)
196 try:
197 target = form.get_target()
199 if isinstance(target, SyncGroup):
200 device = target.devices()[0]
201 else:
202 device = target
204 try:
205 SubscriptionAction.objects.create(podcast=podcast, device=device, action=SUBSCRIBE_ACTION)
206 except IntegrityError, e:
207 log('error while subscribing to podcast (device %s, podcast %s)' % (device.id, podcast.id))
209 return HttpResponseRedirect('/podcast/%s' % podcast.id)
211 except ValueError, e:
212 error_message = _('Could not subscribe to the podcast: %s' % e)
214 targets = podcast.subscribe_targets(request.user)
216 form = SyncForm()
217 form.set_targets(targets, _('Choose a device:'))
219 return render_to_response('subscribe.html', {
220 'error_message': error_message,
221 'podcast': podcast,
222 'can_subscribe': len(targets) > 0,
223 'form': form
224 }, context_instance=RequestContext(request))
227 @manual_gc
228 @login_required
229 def unsubscribe(request, pid, device_id):
231 return_to = request.GET.get('return_to', None)
233 if not return_to:
234 raise Http404('Wrong URL')
236 podcast = get_object_or_404(Podcast, pk=pid)
237 device = Device.objects.get(pk=device_id)
238 try:
239 SubscriptionAction.objects.create(podcast=podcast, device=device, action=UNSUBSCRIBE_ACTION, timestamp=datetime.now())
240 except IntegrityError, e:
241 log('error while unsubscribing from podcast (device %s, podcast %s)' % (device.id, podcast.id))
243 return HttpResponseRedirect(return_to)
246 @manual_gc
247 @login_required
248 def subscribe_url(request):
249 url = request.GET.get('url', None)
251 if not url:
252 raise Http404('http://my.gpodder.org/subscribe?url=http://www.example.com/podcast.xml')
254 url = sanitize_url(url)
256 if url == '':
257 raise Http404('Please specify a valid url')
259 podcast, created = Podcast.objects.get_or_create(url=url)
261 return HttpResponseRedirect('/podcast/%d/subscribe' % podcast.pk)