add missing podcasts in celery task
[mygpo.git] / mygpo / directory / views.py
blobc410db442add05189cd5a40c936c31949df105b0
1 from __future__ import division
3 from itertools import imap as map
4 from math import ceil
6 from django.http import HttpResponseNotFound, Http404, HttpResponseRedirect
7 from django.core.urlresolvers import reverse
8 from django.shortcuts import render
9 from django.contrib.sites.models import RequestSite
10 from django.views.decorators.cache import cache_control
11 from django.views.decorators.vary import vary_on_cookie
12 from django.utils.decorators import method_decorator
13 from django.views.generic.base import View, TemplateView
14 from django.contrib.auth.decorators import login_required
15 from django.contrib import messages
16 from django.utils.translation import ugettext as _
18 from feedservice.parse.models import ParserException
19 from feedservice.parse import FetchFeedException
21 from mygpo.core.proxy import proxy_object
22 from mygpo.directory.toplist import PodcastToplist, EpisodeToplist, \
23 TrendingPodcasts
24 from mygpo.directory.search import search_podcasts
25 from mygpo.web.utils import process_lang_params, get_language_names, \
26 get_page_list, get_podcast_link_target
27 from mygpo.directory.tags import Topics
28 from mygpo.users.models import User
29 from mygpo.users.settings import FLATTR_TOKEN
30 from mygpo.data.feeddownloader import PodcastUpdater, NoEpisodesException
31 from mygpo.data.tasks import update_podcasts
32 from mygpo.db.couchdb.podcast import get_podcast_languages, podcasts_by_id, \
33 random_podcasts, podcasts_to_dict, podcast_for_url, \
34 get_flattr_podcasts, get_flattr_podcast_count
35 from mygpo.db.couchdb.directory import category_for_tag
36 from mygpo.db.couchdb.podcastlist import random_podcastlists, \
37 podcastlist_count, podcastlists_by_rating
40 @vary_on_cookie
41 @cache_control(private=True)
42 def toplist(request, num=100, lang=None):
44 lang = process_lang_params(request)
46 toplist = PodcastToplist(lang)
47 entries = toplist[:num]
49 max_subscribers = max([p.subscriber_count() for (oldp, p) in entries]) if entries else 0
50 current_site = RequestSite(request)
52 languages = get_podcast_languages()
53 all_langs = get_language_names(languages)
55 return render(request, 'toplist.html', {
56 'entries': entries,
57 'max_subscribers': max_subscribers,
58 'url': current_site,
59 'language': lang,
60 'all_languages': all_langs,
64 class Carousel(View):
65 """ A carousel demo """
67 @method_decorator(cache_control(private=True))
68 @method_decorator(vary_on_cookie)
69 def get(self, request):
71 return render(request, 'carousel.html', {
72 # evaluated lazyly, cached by template
73 'topics': Topics(),
77 class Directory(View):
78 """ The main directory page """
80 @method_decorator(cache_control(private=True))
81 @method_decorator(vary_on_cookie)
82 def get(self, request):
84 return render(request, 'directory.html', {
86 # evaluated lazyly, cached by template
87 'topics': Topics(),
88 'trending_podcasts': TrendingPodcasts(''),
89 'podcastlists': self.get_random_list(),
90 'random_podcasts': self.get_random_podcast(),
94 def get_random_list(self, podcasts_per_list=5):
95 random_list = next(random_podcastlists(), None)
96 list_owner = None
97 if random_list:
98 random_list = proxy_object(random_list)
99 random_list.more_podcasts = max(0, len(random_list.podcasts) - podcasts_per_list)
100 random_list.podcasts = podcasts_by_id(random_list.podcasts[:podcasts_per_list])
101 random_list.user = User.get(random_list.user)
103 yield random_list
105 def get_random_podcast(self):
106 random_podcast = next(random_podcasts(), None)
107 if random_podcast:
108 yield random_podcast.get_podcast()
111 @cache_control(private=True)
112 @vary_on_cookie
113 def category(request, category, page_size=20):
114 category = category_for_tag(category)
115 if not category:
116 return HttpResponseNotFound()
118 # Make sure page request is an int. If not, deliver first page.
119 try:
120 page = int(request.GET.get('page', '1'))
121 except ValueError:
122 page = 1
124 entries = category.get_podcasts( (page-1) * page_size, page*page_size )
125 podcasts = filter(None, entries)
126 num_pages = int(ceil(len(category.podcasts) / page_size))
128 page_list = get_page_list(1, num_pages, page, 15)
130 return render(request, 'category.html', {
131 'entries': podcasts,
132 'category': category.label,
133 'page_list': page_list,
138 RESULTS_PER_PAGE=20
140 @cache_control(private=True)
141 @vary_on_cookie
142 def search(request, template='search.html', args={}):
144 if 'q' in request.GET:
145 q = request.GET.get('q', '').encode('utf-8')
147 try:
148 page = int(request.GET.get('page', 1))
149 except ValueError:
150 page = 1
152 results, total = search_podcasts(q=q, skip=RESULTS_PER_PAGE*(page-1))
153 num_pages = int(ceil(total / RESULTS_PER_PAGE))
155 page_list = get_page_list(1, num_pages, page, 15)
157 else:
158 results = []
159 q = None
160 page_list = []
162 max_subscribers = max([p.subscriber_count() for p in results] + [0])
163 current_site = RequestSite(request)
165 return render(request, template, dict(
166 q= q,
167 results= results,
168 page_list= page_list,
169 max_subscribers= max_subscribers,
170 domain= current_site.domain,
171 **args
175 @cache_control(private=True)
176 @vary_on_cookie
177 def episode_toplist(request, num=100):
178 lang = process_lang_params(request)
180 toplist = EpisodeToplist(language=lang)
181 entries = list(map(proxy_object, toplist[:num]))
183 # load podcast objects
184 podcast_ids = [e.podcast for e in entries]
185 podcasts = podcasts_to_dict(podcast_ids, True)
186 for entry in entries:
187 entry.podcast = podcasts.get(entry.podcast, None)
189 current_site = RequestSite(request)
191 # Determine maximum listener amount (or 0 if no entries exist)
192 max_listeners = max([0]+[e.listeners for e in entries])
194 languages = get_podcast_languages()
195 all_langs = get_language_names(languages)
197 return render(request, 'episode_toplist.html', {
198 'entries': entries,
199 'max_listeners': max_listeners,
200 'url': current_site,
201 'language': lang,
202 'all_languages': all_langs,
206 @cache_control(private=True)
207 @vary_on_cookie
208 def podcast_lists(request, page_size=20):
210 # Make sure page request is an int. If not, deliver first page.
211 try:
212 page = int(request.GET.get('page', '1'))
213 except ValueError:
214 page = 1
216 lists = podcastlists_by_rating(skip=(page-1) * page_size, limit=page_size)
219 def _prepare_list(l):
220 user = User.get(l.user)
221 l = proxy_object(l)
222 l.username = user.username
223 return l
225 lists = map(_prepare_list, lists)
227 num_pages = int(ceil(podcastlist_count() / float(page_size)))
229 page_list = get_page_list(1, num_pages, page, 15)
231 return render(request, 'podcast_lists.html', {
232 'lists': lists,
233 'page_list': page_list,
238 class MissingPodcast(View):
239 """ Check if a podcast is missing """
241 @method_decorator(login_required)
242 def get(self, request):
244 site = RequestSite(request)
246 # check if we're doing a query
247 url = request.GET.get('q', None)
249 if not url:
250 podcast = None
251 can_add = False
253 else:
254 podcast = podcast_for_url(url)
256 # if the podcast does already exist, there's nothing more to do
257 if podcast:
258 can_add = False
260 # check if we could add a podcast for the given URL
261 else:
262 podcast = False
263 updater = PodcastUpdater()
265 try:
266 can_add = updater.verify_podcast_url(url)
268 except (ParserException, FetchFeedException,
269 NoEpisodesException) as ex:
270 can_add = False
271 messages.error(request, str(ex))
273 return render(request, 'missing.html', {
274 'site': site,
275 'q': url,
276 'podcast': podcast,
277 'can_add': can_add,
281 class AddPodcast(View):
282 """ Add a missing podcast"""
284 @method_decorator(login_required)
285 @method_decorator(cache_control(private=True))
286 @method_decorator(vary_on_cookie)
287 def post(self, request):
289 url = request.POST.get('url', None)
291 if not url:
292 raise Http404
294 res = update_podcasts.delay([url])
296 return HttpResponseRedirect(reverse('add-podcast-status',
297 args=[res.task_id]))
300 class AddPodcastStatus(TemplateView):
301 """ Status of adding a podcast """
303 template_name = 'directory/add-podcast-status.html'
305 def get(self, request, task_id):
306 result = update_podcasts.AsyncResult(task_id)
308 if not result.ready():
309 return self.render_to_response({
310 'ready': False,
313 try:
314 podcasts = result.get()
315 messages.success(request, _('%d podcasts added' % len(podcasts)))
317 except (ParserException, FetchFeedException,
318 NoEpisodesException) as ex:
319 messages.error(request, str(ex))
320 podcast = None
322 return self.render_to_response({
323 'ready': True,
324 'podcasts': podcasts,
329 class FlattrPodcastList(View):
330 """ Lists podcasts that have Flattr payment URLs """
332 @method_decorator(cache_control(private=True))
333 @method_decorator(vary_on_cookie)
334 def get(self, request, page_size=20):
336 # Make sure page request is an int. If not, deliver first page.
337 try:
338 page = int(request.GET.get('page', '1'))
339 except ValueError:
340 page = 1
342 podcasts = get_flattr_podcasts( (page-1) * page_size, page_size)
343 podcast_count = get_flattr_podcast_count()
344 num_pages = int(ceil(podcast_count / page_size))
345 page_list = get_page_list(1, num_pages, page, 15)
347 max_subscribers = max([p.subscriber_count() for p in podcasts] + [0])
349 user = request.user
350 flattr_auth = user.is_authenticated() and bool(user.get_wksetting(FLATTR_TOKEN))
352 return render(request, 'flattr-podcasts.html', {
353 'podcasts': podcasts,
354 'page_list': page_list,
355 'current_page': page,
356 'flattr_auth': flattr_auth,
357 'max_subscribers': max_subscribers,