move all PodcastList db queries into separate module
[mygpo.git] / mygpo / web / views / __init__.py
blobaebe63dc9681a45aeaf0ebf230964971d934fd80
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 import sys
19 from collections import defaultdict
20 from datetime import datetime, timedelta
21 from itertools import islice
23 import gevent
25 from django.core.urlresolvers import reverse
26 from django.http import HttpResponseRedirect
27 from django.contrib import messages
28 from django.utils.translation import ugettext as _
29 from django.contrib.auth.decorators import login_required
30 from django.shortcuts import render
31 from django.contrib.sites.models import RequestSite
32 from django.views.generic.base import View
33 from django.views.decorators.vary import vary_on_cookie
34 from django.views.decorators.cache import never_cache, cache_control
36 from mygpo.decorators import repeat_on_conflict
37 from mygpo.core import models
38 from mygpo.core.models import Podcast
39 from mygpo.core.podcasts import PodcastSet
40 from mygpo.directory.toplist import PodcastToplist
41 from mygpo.users.models import Suggestions, History, HistoryEntry, DeviceDoesNotExist
42 from mygpo.users.models import PodcastUserState, User
43 from mygpo.web import utils
44 from mygpo.utils import flatten, parse_range
45 from mygpo.db.couchdb.episode import favorite_episodes_for_user
46 from mygpo.db.couchdb.podcast import podcast_by_id, \
47 podcast_for_oldid, random_podcasts
48 from mygpo.db.couchdb.user import suggestions_for_user
49 from mygpo.db.couchdb.directory import tags_for_user
50 from mygpo.db.couchdb.podcastlist import podcastlists_for_user
53 @vary_on_cookie
54 @cache_control(private=True)
55 def home(request):
56 if request.user.is_authenticated():
57 return dashboard(request)
58 else:
59 return welcome(request)
62 @vary_on_cookie
63 @cache_control(private=True)
64 def welcome(request):
65 current_site = RequestSite(request)
67 lang = utils.process_lang_params(request)
69 toplist = PodcastToplist(lang)
71 return render(request, 'home.html', {
72 'url': current_site,
73 'toplist': toplist,
77 @vary_on_cookie
78 @cache_control(private=True)
79 @login_required
80 def dashboard(request, episode_count=10):
82 subscribed_podcasts = list(request.user.get_subscribed_podcasts())
83 site = RequestSite(request)
85 checklist = []
87 if request.user.devices:
88 checklist.append('devices')
90 if subscribed_podcasts:
91 checklist.append('subscriptions')
93 if favorite_episodes_for_user(request.user):
94 checklist.append('favorites')
96 if not request.user.get_token('subscriptions_token'):
97 checklist.append('share')
99 if not request.user.get_token('favorite_feeds_token'):
100 checklist.append('share-favorites')
102 if not request.user.get_token('userpage_token'):
103 checklist.append('userpage')
105 if tags_for_user(request.user):
106 checklist.append('tags')
108 # TODO add podcastlist_count_for_user
109 if podcastlists_for_user(request.user._id):
110 checklist.append('lists')
112 if request.user.published_objects:
113 checklist.append('publish')
115 tomorrow = datetime.today() + timedelta(days=1)
117 podcasts = PodcastSet(subscribed_podcasts)
119 newest_episodes = podcasts.get_newest_episodes(tomorrow, episode_count)
121 def get_random_podcasts():
122 random_podcast = next(random_podcasts(), None)
123 if random_podcast:
124 yield random_podcast.get_podcast()
126 # we only show the "install reader" link in firefox, because we don't know
127 # yet how/if this works in other browsers.
128 # hints appreciated at https://bugs.gpodder.org/show_bug.cgi?id=58
129 show_install_reader = \
130 'firefox' in request.META.get('HTTP_USER_AGENT', '').lower()
132 return render(request, 'dashboard.html', {
133 'user': request.user,
134 'subscribed_podcasts': subscribed_podcasts,
135 'newest_episodes': list(newest_episodes),
136 'random_podcasts': get_random_podcasts(),
137 'checklist': checklist,
138 'site': site,
139 'show_install_reader': show_install_reader,
143 @vary_on_cookie
144 @cache_control(private=True)
145 @login_required
146 def history(request, count=15, uid=None):
148 page = parse_range(request.GET.get('page', None), 0, sys.maxint, 0)
150 if uid:
151 try:
152 device = request.user.get_device_by_uid(uid, only_active=False)
153 except DeviceDoesNotExist as e:
154 messages.error(request, str(e))
156 else:
157 device = None
159 history_obj = History(request.user, device)
161 start = page*count
162 end = start+count
163 entries = list(history_obj[start:end])
164 HistoryEntry.fetch_data(request.user, entries)
166 return render(request, 'history.html', {
167 'history': entries,
168 'device': device,
169 'page': page,
173 @never_cache
174 @login_required
175 def blacklist(request, podcast_id):
176 podcast_id = int(podcast_id)
177 blacklisted_podcast = podcast_for_oldid(podcast_id)
179 suggestion = suggestions_for_user(request.user)
181 @repeat_on_conflict(['suggestion'])
182 def _update(suggestion, podcast_id):
183 suggestion.blacklist.append(podcast_id)
184 suggestion.save()
186 @repeat_on_conflict(['user'])
187 def _not_uptodate(user):
188 user.suggestions_up_to_date = False
189 user.save()
191 _update(suggestion=suggestion, podcast_id=blacklisted_podcast.get_id())
192 _not_uptodate(user=request.user)
194 return HttpResponseRedirect(reverse('suggestions'))
197 @never_cache
198 @login_required
199 def rate_suggestions(request):
200 rating_val = int(request.GET.get('rate', None))
202 suggestion = suggestions_for_user(request.user)
203 suggestion.rate(rating_val, request.user._id)
204 suggestion.save()
206 messages.success(request, _('Thanks for rating!'))
208 return HttpResponseRedirect(reverse('suggestions'))
211 @vary_on_cookie
212 @cache_control(private=True)
213 @login_required
214 def suggestions(request):
215 suggestion_obj = suggestions_for_user(request.user)
216 suggestions = suggestion_obj.get_podcasts()
217 current_site = RequestSite(request)
218 return render(request, 'suggestions.html', {
219 'entries': suggestions,
220 'url': current_site
224 @vary_on_cookie
225 @cache_control(private=True)
226 @login_required
227 def mytags(request):
228 tags_podcast = {}
229 tags_tag = defaultdict(list)
231 for podcast_id, taglist in tags_for_user(request.user).items():
232 podcast = podcast_by_id(podcast_id)
233 tags_podcast[podcast] = taglist
235 for tag in taglist:
236 tags_tag[ tag ].append(podcast)
238 return render(request, 'mytags.html', {
239 'tags_podcast': tags_podcast,
240 'tags_tag': dict(tags_tag.items()),
245 class GeventView(View):
246 """ View that provides parts of the context via gevent coroutines """
248 def get_context(self, context_funs):
249 """ returns a dictionary that can be used for a template context
251 context_funs is a context-key => Greenlet object mapping """
253 gevent.joinall(context_funs.values())
255 for key, gev in context_funs.items():
256 context_funs[key] = gev.get()
258 return context_funs