move all User and EpisodetUserState db queries into separate module
[mygpo.git] / mygpo / web / views / __init__.py
blobd68de6e46e7872a2f1e14cb529756dccd5291159
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.tags import Tag
41 from mygpo.directory.toplist import PodcastToplist
42 from mygpo.users.models import Suggestions, History, HistoryEntry, DeviceDoesNotExist
43 from mygpo.users.models import PodcastUserState, User
44 from mygpo.web import utils
45 from mygpo.utils import flatten, parse_range
46 from mygpo.share.models import PodcastList
47 from mygpo.db.couchdb.episode import favorite_episodes_for_user
48 from mygpo.db.couchdb.podcast import podcast_by_id, \
49 podcast_for_oldid, random_podcasts
50 from mygpo.db.couchdb.user import suggestions_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 Tag.for_user(request.user):
106 checklist.append('tags')
108 if PodcastList.for_user(request.user._id):
109 checklist.append('lists')
111 if request.user.published_objects:
112 checklist.append('publish')
114 tomorrow = datetime.today() + timedelta(days=1)
116 podcasts = PodcastSet(subscribed_podcasts)
118 newest_episodes = podcasts.get_newest_episodes(tomorrow, episode_count)
120 def get_random_podcasts():
121 random_podcast = next(random_podcasts(), None)
122 if random_podcast:
123 yield random_podcast.get_podcast()
125 # we only show the "install reader" link in firefox, because we don't know
126 # yet how/if this works in other browsers.
127 # hints appreciated at https://bugs.gpodder.org/show_bug.cgi?id=58
128 show_install_reader = \
129 'firefox' in request.META.get('HTTP_USER_AGENT', '').lower()
131 return render(request, 'dashboard.html', {
132 'user': request.user,
133 'subscribed_podcasts': subscribed_podcasts,
134 'newest_episodes': list(newest_episodes),
135 'random_podcasts': get_random_podcasts(),
136 'checklist': checklist,
137 'site': site,
138 'show_install_reader': show_install_reader,
142 @vary_on_cookie
143 @cache_control(private=True)
144 @login_required
145 def history(request, count=15, uid=None):
147 page = parse_range(request.GET.get('page', None), 0, sys.maxint, 0)
149 if uid:
150 try:
151 device = request.user.get_device_by_uid(uid, only_active=False)
152 except DeviceDoesNotExist as e:
153 messages.error(request, str(e))
155 else:
156 device = None
158 history_obj = History(request.user, device)
160 start = page*count
161 end = start+count
162 entries = list(history_obj[start:end])
163 HistoryEntry.fetch_data(request.user, entries)
165 return render(request, 'history.html', {
166 'history': entries,
167 'device': device,
168 'page': page,
172 @never_cache
173 @login_required
174 def blacklist(request, podcast_id):
175 podcast_id = int(podcast_id)
176 blacklisted_podcast = podcast_for_oldid(podcast_id)
178 suggestion = suggestions_for_user(request.user)
180 @repeat_on_conflict(['suggestion'])
181 def _update(suggestion, podcast_id):
182 suggestion.blacklist.append(podcast_id)
183 suggestion.save()
185 @repeat_on_conflict(['user'])
186 def _not_uptodate(user):
187 user.suggestions_up_to_date = False
188 user.save()
190 _update(suggestion=suggestion, podcast_id=blacklisted_podcast.get_id())
191 _not_uptodate(user=request.user)
193 return HttpResponseRedirect(reverse('suggestions'))
196 @never_cache
197 @login_required
198 def rate_suggestions(request):
199 rating_val = int(request.GET.get('rate', None))
201 suggestion = suggestions_for_user(request.user)
202 suggestion.rate(rating_val, request.user._id)
203 suggestion.save()
205 messages.success(request, _('Thanks for rating!'))
207 return HttpResponseRedirect(reverse('suggestions'))
210 @vary_on_cookie
211 @cache_control(private=True)
212 @login_required
213 def suggestions(request):
214 suggestion_obj = suggestions_for_user(request.user)
215 suggestions = suggestion_obj.get_podcasts()
216 current_site = RequestSite(request)
217 return render(request, 'suggestions.html', {
218 'entries': suggestions,
219 'url': current_site
223 @vary_on_cookie
224 @cache_control(private=True)
225 @login_required
226 def mytags(request):
227 tags_podcast = {}
228 tags_tag = defaultdict(list)
230 for podcast_id, taglist in Tag.for_user(request.user).items():
231 podcast = podcast_by_id(podcast_id)
232 tags_podcast[podcast] = taglist
234 for tag in taglist:
235 tags_tag[ tag ].append(podcast)
237 return render(request, 'mytags.html', {
238 'tags_podcast': tags_podcast,
239 'tags_tag': dict(tags_tag.items()),
244 class GeventView(View):
245 """ View that provides parts of the context via gevent coroutines """
247 def get_context(self, context_funs):
248 """ returns a dictionary that can be used for a template context
250 context_funs is a context-key => Greenlet object mapping """
252 gevent.joinall(context_funs.values())
254 for key, gev in context_funs.items():
255 context_funs[key] = gev.get()
257 return context_funs