[Migration] remove podcasts_by_id
[mygpo.git] / mygpo / publisher / views.py
blob032a6f8cf1906c5eb65320e410d5aa1bede37d42
1 from functools import wraps
2 import urllib
4 from django.shortcuts import render
5 from django.http import HttpResponse, HttpResponseRedirect, \
6 HttpResponseForbidden, Http404
7 from django.core.cache import cache
8 from django.views.decorators.cache import never_cache, cache_control
9 from django.views.decorators.vary import vary_on_cookie
10 from django.core.urlresolvers import reverse
11 from django.utils.translation import ugettext as _
12 from django.contrib import messages
13 from django.shortcuts import get_object_or_404
15 from mygpo.podcasts.models import PodcastGroup, Podcast
16 from mygpo.core.proxy import proxy_object
17 from mygpo.publisher.auth import require_publisher, is_publisher
18 from mygpo.publisher.forms import SearchPodcastForm
19 from mygpo.publisher.utils import listener_data, episode_listener_data, \
20 check_publisher_permission, subscriber_data
21 from mygpo.web.heatmap import EpisodeHeatmap
22 from mygpo.web.views.episode import slug_decorator as episode_slug_decorator
23 from mygpo.web.views.podcast import slug_decorator as podcast_slug_decorator
24 from mygpo.web.utils import get_podcast_link_target, normalize_twitter, \
25 get_episode_link_target
26 from django.contrib.sites.models import RequestSite
27 from mygpo.data.tasks import update_podcasts
28 from mygpo.decorators import requires_token, allowed_methods
29 from mygpo.users.models import User
30 from mygpo.db.couchdb.episode import episodes_for_podcast, \
31 set_episode_slug, remove_episode_slug
32 from mygpo.db.couchdb.podcast import update_additional_data
33 from mygpo.db.couchdb.episode_state import episode_listener_counts
34 from mygpo.db.couchdb.pubsub import subscription_for_topic
37 @vary_on_cookie
38 @cache_control(private=True)
39 def home(request):
40 if is_publisher(request.user):
41 podcasts = Podcasts.objects.filter(id__in=request.user.published_objects)
42 site = RequestSite(request)
43 update_token = request.user.get_token('publisher_update_token')
44 form = SearchPodcastForm()
45 return render(request, 'publisher/home.html', {
46 'update_token': update_token,
47 'podcasts': podcasts,
48 'form': form,
49 'site': site,
52 else:
53 site = RequestSite(request)
54 return render(request, 'publisher/info.html', {
55 'site': site
59 @vary_on_cookie
60 @cache_control(private=True)
61 @require_publisher
62 def search_podcast(request):
63 form = SearchPodcastForm(request.POST)
64 if form.is_valid():
65 podcast_url = form.cleaned_data['url']
66 podcast = get_objet_or_404(Podcast, urls__url=podcast_url)
67 url = get_podcast_link_target(podcast, 'podcast-publisher-detail')
68 else:
69 url = reverse('publisher')
71 return HttpResponseRedirect(url)
74 @vary_on_cookie
75 @cache_control(private=True)
76 @require_publisher
77 @allowed_methods(['GET', 'POST'])
78 def podcast(request, podcast):
80 if not check_publisher_permission(request.user, podcast):
81 return HttpResponseForbidden()
83 timeline_data = listener_data([podcast])
84 subscription_data = subscriber_data([podcast])[-20:]
86 update_token = request.user.publisher_update_token
88 heatmap = EpisodeHeatmap(podcast.get_id())
90 pubsubscription = subscription_for_topic(podcast.url)
92 site = RequestSite(request)
93 feedurl_quoted = urllib.quote(podcast.url)
95 return render(request, 'publisher/podcast.html', {
96 'site': site,
97 'podcast': podcast,
98 'group': podcast.group,
99 'form': None,
100 'timeline_data': timeline_data,
101 'subscriber_data': subscription_data,
102 'update_token': update_token,
103 'heatmap': heatmap,
104 'feedurl_quoted': feedurl_quoted,
105 'pubsubscription': pubsubscription,
109 @vary_on_cookie
110 @cache_control(private=True)
111 @require_publisher
112 def group(request, group):
114 podcasts = group.podcasts
116 # users need to have publisher access for at least one of the group's podcasts
117 if not any([check_publisher_permission(request.user, p) for p in podcasts]):
118 return HttpResponseForbidden()
120 timeline_data = listener_data(podcasts)
121 subscription_data = list(subscriber_data(podcasts))[-20:]
123 return render(request, 'publisher/group.html', {
124 'group': group,
125 'timeline_data': timeline_data,
126 'subscriber_data': subscription_data,
130 @vary_on_cookie
131 @cache_control(private=True)
132 @require_publisher
133 def update_podcast(request, podcast):
135 if not check_publisher_permission(request.user, podcast):
136 return HttpResponseForbidden()
138 update_podcasts.delay([podcast.url])
139 messages.success(request, _('The update has been scheduled. It might take some time until the results are visible.'))
141 url = get_podcast_link_target(podcast, 'podcast-publisher-detail')
142 return HttpResponseRedirect(url)
145 @vary_on_cookie
146 @cache_control(private=True)
147 @require_publisher
148 def save_podcast(request, podcast):
149 twitter = normalize_twitter(request.POST.get('twitter', ''))
150 update_additional_data(podcast, twitter)
151 messages.success(request, _('Data updated'))
152 url = get_podcast_link_target(podcast, 'podcast-publisher-detail')
153 return HttpResponseRedirect(url)
157 @never_cache
158 @require_publisher
159 def new_update_token(request, username):
160 request.user.create_new_token('publisher_update_token')
161 request.user.save()
162 messages.success(request, _('Publisher token updated'))
163 return HttpResponseRedirect(reverse('publisher'))
166 @never_cache
167 @requires_token(token_name='publisher_update_token')
168 def update_published_podcasts(request, username):
169 user = User.get_user(username)
170 if not user:
171 raise Http404
173 published_podcasts = Podcast.objects.filter(id__in=user.published_objects)
174 update_podcasts.delay([podcast.url for podcast in published_podcasts])
175 return HttpResponse('Updated:\n' + '\n'.join([p.url for p in published_podcasts]), mimetype='text/plain')
178 @vary_on_cookie
179 @cache_control(private=True)
180 @require_publisher
181 def episodes(request, podcast):
183 if not check_publisher_permission(request.user, podcast):
184 return HttpResponseForbidden()
186 episodes = episodes_for_podcast(podcast, descending=True)
187 listeners = dict(episode_listener_counts(podcast))
189 max_listeners = max(listeners.values() + [0])
191 def annotate_episode(episode):
192 listener_count = listeners.get(episode._id, None)
193 return proxy_object(episode, listeners=listener_count)
195 episodes = map(annotate_episode, episodes)
197 return render(request, 'publisher/episodes.html', {
198 'podcast': podcast,
199 'episodes': episodes,
200 'max_listeners': max_listeners
204 @require_publisher
205 @vary_on_cookie
206 @cache_control(private=True)
207 @allowed_methods(['GET', 'POST'])
208 def episode(request, episode):
210 site = RequestSite(request)
211 podcast = episode.podcast
213 if not check_publisher_permission(request.user, podcast):
214 return HttpResponseForbidden()
216 if request.method == 'POST':
217 form = None # EpisodeForm(request.POST, instance=e)
218 # if form.is_valid():
219 # form.save()
221 elif request.method == 'GET':
222 form = None # EpisodeForm(instance=e)
224 timeline_data = list(episode_listener_data(episode))
226 heatmap = EpisodeHeatmap(episode.podcast, episode._id,
227 duration=episode.duration)
229 return render(request, 'publisher/episode.html', {
230 'is_secure': request.is_secure(),
231 'domain': site.domain,
232 'episode': episode,
233 'podcast': podcast,
234 'form': form,
235 'timeline_data': timeline_data,
236 'heatmap': heatmap,
240 @require_publisher
241 @never_cache
242 @allowed_methods(['POST'])
243 def update_episode_slug(request, episode):
244 """ sets a new "main" slug, and moves the existing to the merged slugs """
246 new_slug = request.POST.get('slug')
247 podcast = episode.podcast
249 if new_slug:
250 # remove the new slug from other episodes (of the same podcast)
251 other_episodes = Episode.objects.filter(podcast=podcast,
252 slugs__slug=new_slug)
254 for other_episode in other_episodes:
256 if other_episode == episode:
257 continue
259 remove_episode_slug(other_episode, new_slug)
260 messages.warning(request,
261 _(u'Removed slug {slug} from {episode}'.format(
262 slug=new_slug, episode=other_episode.title))
265 set_episode_slug(episode, new_slug)
267 # TODO: we should use better cache invalidation
268 cache.clear()
270 return HttpResponseRedirect(
271 get_episode_link_target(episode, podcast, 'episode-publisher-detail')
275 @vary_on_cookie
276 @cache_control(private=True)
277 def link(request):
278 current_site = RequestSite(request)
279 return render(request, 'link.html', {
280 'url': current_site
284 @vary_on_cookie
285 @cache_control(private=True)
286 def advertise(request):
287 site = RequestSite(request)
288 return render(request, 'publisher/advertise.html', {
289 'site': site
293 def group_id_decorator(f):
294 @wraps(f)
295 def _decorator(request, slug_id, *args, **kwargs):
296 group = get_object_or_404(PodcastGroup, pk=slug_id)
297 return f(request, group, *args, **kwargs)
299 return _decorator
302 episode_slug = episode_slug_decorator(episode)
303 update_episode_slug_slug = episode_slug_decorator(update_episode_slug)
304 podcast_slug = podcast_slug_decorator(podcast)
305 episodes_slug = podcast_slug_decorator(episodes)
306 update_podcast_slug = podcast_slug_decorator(update_podcast)
307 save_podcast_slug = podcast_slug_decorator(save_podcast)
308 group_slug = group_id_decorator(group)