1077e5bbaeb898d4237f738fbebcdfa03aa88dd6
[mygpo.git] / mygpo / web / views / podcast.py
blob1077e5bbaeb898d4237f738fbebcdfa03aa88dd6
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.listener_count() 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 = podcast.get_episodes().order_by('-timestamp')
141 for e in episodes:
142 if user.is_authenticated():
143 actions = EpisodeAction.objects.filter(episode=e, user=user).order_by('-timestamp')
144 if actions.count() > 0:
145 e.action = actions[0]
147 return episodes
150 @login_required
151 def add_tag(request, pid):
152 podcast = get_object_or_404(Podcast, id=pid)
153 tag_str = request.GET.get('tag', '')
154 if not tag_str:
155 return HttpResponseBadRequest()
157 tags = tag_str.split(',')
158 for t in tags:
159 t = t.strip()
160 tag = PodcastTag.objects.get_or_create(podcast=podcast, tag=t, source='user', user=request.user)
162 if request.GET.get('next', '') == 'mytags':
163 return HttpResponseRedirect('/tags/')
165 return HttpResponseRedirect('/podcast/%s' % pid)
168 @login_required
169 def remove_tag(request, pid):
170 podcast = get_object_or_404(Podcast, id=pid)
171 tag_str = request.GET.get('tag', '')
172 if not tag_str:
173 return HttpResponseBadRequest()
175 PodcastTag.objects.filter(podcast=podcast, tag=tag_str, source='user', user=request.user).delete()
177 if request.GET.get('next', '') == 'mytags':
178 return HttpResponseRedirect('/tags/')
180 return HttpResponseRedirect('/podcast/%s' % pid)
183 @manual_gc
184 @login_required
185 @allowed_methods(['GET', 'POST'])
186 def subscribe(request, pid):
187 podcast = get_object_or_404(Podcast, pk=pid)
188 error_message = None
190 if request.method == 'POST':
191 form = SyncForm(request.POST)
193 try:
194 target = form.get_target()
196 if isinstance(target, SyncGroup):
197 device = target.devices()[0]
198 else:
199 device = target
201 try:
202 SubscriptionAction.objects.create(podcast=podcast, device=device, action=SUBSCRIBE_ACTION)
203 except IntegrityError, e:
204 log('error while subscribing to podcast (device %s, podcast %s)' % (device.id, podcast.id))
206 return HttpResponseRedirect('/podcast/%s' % podcast.id)
208 except ValueError, e:
209 error_message = _('Could not subscribe to the podcast: %s' % e)
211 targets = podcast.subscribe_targets(request.user)
213 form = SyncForm()
214 form.set_targets(targets, _('Choose a device:'))
216 return render_to_response('subscribe.html', {
217 'error_message': error_message,
218 'podcast': podcast,
219 'can_subscribe': len(targets) > 0,
220 'form': form
221 }, context_instance=RequestContext(request))
224 @manual_gc
225 @login_required
226 def unsubscribe(request, pid, device_id):
228 return_to = request.GET.get('return_to', None)
230 if not return_to:
231 raise Http404('Wrong URL')
233 podcast = get_object_or_404(Podcast, pk=pid)
234 device = Device.objects.get(pk=device_id)
235 try:
236 SubscriptionAction.objects.create(podcast=podcast, device=device, action=UNSUBSCRIBE_ACTION, timestamp=datetime.now())
237 except IntegrityError, e:
238 log('error while unsubscribing from podcast (device %s, podcast %s)' % (device.id, podcast.id))
240 return HttpResponseRedirect(return_to)
243 @manual_gc
244 @login_required
245 def subscribe_url(request):
246 url = request.GET.get('url', None)
248 if not url:
249 raise Http404('http://my.gpodder.org/subscribe?url=http://www.example.com/podcast.xml')
251 url = sanitize_url(url)
253 if url == '':
254 raise Http404('Please specify a valid url')
256 podcast, created = Podcast.objects.get_or_create(url=url)
258 return HttpResponseRedirect('/podcast/%d/subscribe' % podcast.pk)