[Migration] Get Episodes from PostgreSQL
[mygpo.git] / mygpo / publisher / views.py
blobcceb06f29b17646a076ee0bbf60f527d1119cf00
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 set_episode_slug, remove_episode_slug
31 from mygpo.db.couchdb.episode_state import episode_listener_counts
32 from mygpo.db.couchdb.pubsub import subscription_for_topic
35 @vary_on_cookie
36 @cache_control(private=True)
37 def home(request):
38 if is_publisher(request.user):
39 podcasts = Podcasts.objects.filter(id__in=request.user.published_objects)
40 site = RequestSite(request)
41 update_token = request.user.get_token('publisher_update_token')
42 form = SearchPodcastForm()
43 return render(request, 'publisher/home.html', {
44 'update_token': update_token,
45 'podcasts': podcasts,
46 'form': form,
47 'site': site,
50 else:
51 site = RequestSite(request)
52 return render(request, 'publisher/info.html', {
53 'site': site
57 @vary_on_cookie
58 @cache_control(private=True)
59 @require_publisher
60 def search_podcast(request):
61 form = SearchPodcastForm(request.POST)
62 if form.is_valid():
63 podcast_url = form.cleaned_data['url']
64 podcast = get_objet_or_404(Podcast, urls__url=podcast_url)
65 url = get_podcast_link_target(podcast, 'podcast-publisher-detail')
66 else:
67 url = reverse('publisher')
69 return HttpResponseRedirect(url)
72 @vary_on_cookie
73 @cache_control(private=True)
74 @require_publisher
75 @allowed_methods(['GET', 'POST'])
76 def podcast(request, podcast):
78 if not check_publisher_permission(request.user, podcast):
79 return HttpResponseForbidden()
81 timeline_data = listener_data([podcast])
82 subscription_data = subscriber_data([podcast])[-20:]
84 update_token = request.user.publisher_update_token
86 heatmap = EpisodeHeatmap(podcast.get_id())
88 pubsubscription = subscription_for_topic(podcast.url)
90 site = RequestSite(request)
91 feedurl_quoted = urllib.quote(podcast.url)
93 return render(request, 'publisher/podcast.html', {
94 'site': site,
95 'podcast': podcast,
96 'group': podcast.group,
97 'form': None,
98 'timeline_data': timeline_data,
99 'subscriber_data': subscription_data,
100 'update_token': update_token,
101 'heatmap': heatmap,
102 'feedurl_quoted': feedurl_quoted,
103 'pubsubscription': pubsubscription,
107 @vary_on_cookie
108 @cache_control(private=True)
109 @require_publisher
110 def group(request, group):
112 podcasts = group.podcasts
114 # users need to have publisher access for at least one of the group's podcasts
115 if not any([check_publisher_permission(request.user, p) for p in podcasts]):
116 return HttpResponseForbidden()
118 timeline_data = listener_data(podcasts)
119 subscription_data = list(subscriber_data(podcasts))[-20:]
121 return render(request, 'publisher/group.html', {
122 'group': group,
123 'timeline_data': timeline_data,
124 'subscriber_data': subscription_data,
128 @vary_on_cookie
129 @cache_control(private=True)
130 @require_publisher
131 def update_podcast(request, podcast):
133 if not check_publisher_permission(request.user, podcast):
134 return HttpResponseForbidden()
136 update_podcasts.delay([podcast.url])
137 messages.success(request, _('The update has been scheduled. It might take some time until the results are visible.'))
139 url = get_podcast_link_target(podcast, 'podcast-publisher-detail')
140 return HttpResponseRedirect(url)
143 @vary_on_cookie
144 @cache_control(private=True)
145 @require_publisher
146 def save_podcast(request, podcast):
147 twitter = normalize_twitter(request.POST.get('twitter', ''))
148 podcast.twitter = twitter
149 podcast.save()
150 messages.success(request, _('Data updated'))
151 url = get_podcast_link_target(podcast, 'podcast-publisher-detail')
152 return HttpResponseRedirect(url)
156 @never_cache
157 @require_publisher
158 def new_update_token(request, username):
159 request.user.create_new_token('publisher_update_token')
160 request.user.save()
161 messages.success(request, _('Publisher token updated'))
162 return HttpResponseRedirect(reverse('publisher'))
165 @never_cache
166 @requires_token(token_name='publisher_update_token')
167 def update_published_podcasts(request, username):
168 user = User.get_user(username)
169 if not user:
170 raise Http404
172 published_podcasts = Podcast.objects.filter(id__in=user.published_objects)
173 update_podcasts.delay([podcast.url for podcast in published_podcasts])
174 return HttpResponse('Updated:\n' + '\n'.join([p.url for p in published_podcasts]), mimetype='text/plain')
177 @vary_on_cookie
178 @cache_control(private=True)
179 @require_publisher
180 def episodes(request, podcast):
182 if not check_publisher_permission(request.user, podcast):
183 return HttpResponseForbidden()
185 episodes = podcast.episode_set().all()
186 listeners = dict(episode_listener_counts(podcast))
188 max_listeners = max(listeners.values() + [0])
190 def annotate_episode(episode):
191 listener_count = listeners.get(episode._id, None)
192 return proxy_object(episode, listeners=listener_count)
194 episodes = map(annotate_episode, episodes)
196 return render(request, 'publisher/episodes.html', {
197 'podcast': podcast,
198 'episodes': episodes,
199 'max_listeners': max_listeners
203 @require_publisher
204 @vary_on_cookie
205 @cache_control(private=True)
206 @allowed_methods(['GET', 'POST'])
207 def episode(request, episode):
209 site = RequestSite(request)
210 podcast = episode.podcast
212 if not check_publisher_permission(request.user, podcast):
213 return HttpResponseForbidden()
215 if request.method == 'POST':
216 form = None # EpisodeForm(request.POST, instance=e)
217 # if form.is_valid():
218 # form.save()
220 elif request.method == 'GET':
221 form = None # EpisodeForm(instance=e)
223 timeline_data = list(episode_listener_data(episode))
225 heatmap = EpisodeHeatmap(episode.podcast, episode._id,
226 duration=episode.duration)
228 return render(request, 'publisher/episode.html', {
229 'is_secure': request.is_secure(),
230 'domain': site.domain,
231 'episode': episode,
232 'podcast': podcast,
233 'form': form,
234 'timeline_data': timeline_data,
235 'heatmap': heatmap,
239 @require_publisher
240 @never_cache
241 @allowed_methods(['POST'])
242 def update_episode_slug(request, episode):
243 """ sets a new "main" slug, and moves the existing to the merged slugs """
245 new_slug = request.POST.get('slug')
246 podcast = episode.podcast
248 if new_slug:
249 # remove the new slug from other episodes (of the same podcast)
250 other_episodes = Episode.objects.filter(podcast=podcast,
251 slugs__slug=new_slug)
253 for other_episode in other_episodes:
255 if other_episode == episode:
256 continue
258 remove_episode_slug(other_episode, new_slug)
259 messages.warning(request,
260 _(u'Removed slug {slug} from {episode}'.format(
261 slug=new_slug, episode=other_episode.title))
264 set_episode_slug(episode, new_slug)
266 # TODO: we should use better cache invalidation
267 cache.clear()
269 return HttpResponseRedirect(
270 get_episode_link_target(episode, podcast, 'episode-publisher-detail')
274 @vary_on_cookie
275 @cache_control(private=True)
276 def link(request):
277 current_site = RequestSite(request)
278 return render(request, 'link.html', {
279 'url': current_site
283 @vary_on_cookie
284 @cache_control(private=True)
285 def advertise(request):
286 site = RequestSite(request)
287 return render(request, 'publisher/advertise.html', {
288 'site': site
292 def group_id_decorator(f):
293 @wraps(f)
294 def _decorator(request, slug_id, *args, **kwargs):
295 group = get_object_or_404(PodcastGroup, pk=slug_id)
296 return f(request, group, *args, **kwargs)
298 return _decorator
301 episode_slug = episode_slug_decorator(episode)
302 update_episode_slug_slug = episode_slug_decorator(update_episode_slug)
303 podcast_slug = podcast_slug_decorator(podcast)
304 episodes_slug = podcast_slug_decorator(episodes)
305 update_podcast_slug = podcast_slug_decorator(update_podcast)
306 save_podcast_slug = podcast_slug_decorator(save_podcast)
307 group_slug = group_id_decorator(group)