b0cb5a14c7d71feab52bd6a7a52449e119a668f1
[mygpo.git] / mygpo / web / views / __init__.py
blobb0cb5a14c7d71feab52bd6a7a52449e119a668f1
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
22 try:
23 import gevent
24 except ImportError:
25 gevent = None
27 from django.core.urlresolvers import reverse
28 from django.http import HttpResponseRedirect
29 from django.contrib import messages
30 from django.utils.translation import ugettext as _
31 from django.contrib.auth.decorators import login_required
32 from django.shortcuts import render
33 from django.contrib.sites.models import RequestSite
34 from django.views.generic.base import View
35 from django.views.decorators.vary import vary_on_cookie
36 from django.views.decorators.cache import never_cache, cache_control
38 from mygpo.decorators import repeat_on_conflict
39 from mygpo.core.podcasts import PodcastSet
40 from mygpo.directory.toplist import PodcastToplist
41 from mygpo.users.models import Suggestions, History, HistoryEntry, \
42 DeviceDoesNotExist
43 from mygpo.web.utils import process_lang_params
44 from mygpo.utils import parse_range
45 from mygpo.web.views.podcast import slug_id_decorator
46 from mygpo.users.settings import FLATTR_AUTO, FLATTR_TOKEN
47 from mygpo.db.couchdb.episode import favorite_episodes_for_user
48 from mygpo.db.couchdb.podcast import podcast_by_id, random_podcasts
49 from mygpo.db.couchdb.user import suggestions_for_user
50 from mygpo.db.couchdb.directory import tags_for_user
51 from mygpo.db.couchdb.podcastlist import podcastlists_for_user
54 @vary_on_cookie
55 @cache_control(private=True)
56 def home(request):
57 if request.user.is_authenticated():
58 return dashboard(request)
59 else:
60 return welcome(request)
63 @vary_on_cookie
64 @cache_control(private=True)
65 def welcome(request):
66 current_site = RequestSite(request)
68 lang = process_lang_params(request)
70 toplist = PodcastToplist(lang)
72 return render(request, 'home.html', {
73 'url': current_site,
74 'toplist': toplist,
78 @vary_on_cookie
79 @cache_control(private=True)
80 @login_required
81 def dashboard(request, episode_count=10):
83 subscribed_podcasts = list(request.user.get_subscribed_podcasts())
84 site = RequestSite(request)
86 checklist = []
88 if request.user.devices:
89 checklist.append('devices')
91 if subscribed_podcasts:
92 checklist.append('subscriptions')
94 if favorite_episodes_for_user(request.user):
95 checklist.append('favorites')
97 if not request.user.get_token('subscriptions_token'):
98 checklist.append('share')
100 if not request.user.get_token('favorite_feeds_token'):
101 checklist.append('share-favorites')
103 if not request.user.get_token('userpage_token'):
104 checklist.append('userpage')
106 if tags_for_user(request.user):
107 checklist.append('tags')
109 # TODO add podcastlist_count_for_user
110 if podcastlists_for_user(request.user._id):
111 checklist.append('lists')
113 if request.user.published_objects:
114 checklist.append('publish')
116 if request.user.get_wksetting(FLATTR_TOKEN):
117 checklist.append('flattr')
119 if request.user.get_wksetting(FLATTR_AUTO):
120 checklist.append('auto-flattr')
122 tomorrow = datetime.today() + timedelta(days=1)
124 podcasts = PodcastSet(subscribed_podcasts)
126 newest_episodes = podcasts.get_newest_episodes(tomorrow, episode_count)
128 def get_random_podcasts():
129 random_podcast = next(random_podcasts(), None)
130 if random_podcast:
131 yield random_podcast.get_podcast()
133 # we only show the "install reader" link in firefox, because we don't know
134 # yet how/if this works in other browsers.
135 # hints appreciated at https://bugs.gpodder.org/show_bug.cgi?id=58
136 show_install_reader = \
137 'firefox' in request.META.get('HTTP_USER_AGENT', '').lower()
139 return render(request, 'dashboard.html', {
140 'user': request.user,
141 'subscribed_podcasts': subscribed_podcasts,
142 'newest_episodes': list(newest_episodes),
143 'random_podcasts': get_random_podcasts(),
144 'checklist': checklist,
145 'site': site,
146 'show_install_reader': show_install_reader,
150 @vary_on_cookie
151 @cache_control(private=True)
152 @login_required
153 def history(request, count=15, uid=None):
155 page = parse_range(request.GET.get('page', None), 0, sys.maxint, 0)
157 if uid:
158 try:
159 device = request.user.get_device_by_uid(uid, only_active=False)
160 except DeviceDoesNotExist as e:
161 messages.error(request, str(e))
163 else:
164 device = None
166 history_obj = History(request.user, device)
168 start = page*count
169 end = start+count
170 entries = history_obj[start:end]
171 HistoryEntry.fetch_data(request.user, entries)
173 return render(request, 'history.html', {
174 'history': entries,
175 'device': device,
176 'page': page,
180 @never_cache
181 @login_required
182 @slug_id_decorator
183 def blacklist(request, blacklisted_podcast):
184 suggestion = suggestions_for_user(request.user)
186 @repeat_on_conflict(['suggestion'])
187 def _update(suggestion, podcast_id):
188 suggestion.blacklist.append(podcast_id)
189 suggestion.save()
191 @repeat_on_conflict(['user'])
192 def _not_uptodate(user):
193 user.suggestions_up_to_date = False
194 user.save()
196 _update(suggestion=suggestion, podcast_id=blacklisted_podcast.get_id())
197 _not_uptodate(user=request.user)
199 return HttpResponseRedirect(reverse('suggestions'))
202 @never_cache
203 @login_required
204 def rate_suggestions(request):
205 rating_val = int(request.GET.get('rate', None))
207 suggestion = suggestions_for_user(request.user)
208 suggestion.rate(rating_val, request.user._id)
209 suggestion.save()
211 messages.success(request, _('Thanks for rating!'))
213 return HttpResponseRedirect(reverse('suggestions'))
216 @vary_on_cookie
217 @cache_control(private=True)
218 @login_required
219 def suggestions(request):
220 suggestion_obj = suggestions_for_user(request.user)
221 suggestions = suggestion_obj.get_podcasts()
222 current_site = RequestSite(request)
223 return render(request, 'suggestions.html', {
224 'entries': suggestions,
225 'url': current_site
229 @vary_on_cookie
230 @cache_control(private=True)
231 @login_required
232 def mytags(request):
233 tags_podcast = {}
234 tags_tag = defaultdict(list)
236 for podcast_id, taglist in tags_for_user(request.user).items():
237 podcast = podcast_by_id(podcast_id)
238 tags_podcast[podcast] = taglist
240 for tag in taglist:
241 tags_tag[ tag ].append(podcast)
243 return render(request, 'mytags.html', {
244 'tags_podcast': tags_podcast,
245 'tags_tag': dict(tags_tag.items()),
250 class GeventView(View):
251 """ View that provides parts of the context via gevent coroutines """
253 def get_context(self, context_funs):
254 """ returns a dictionary that can be used for a template context
256 context_funs is a context-key => Greenlet object mapping """
258 if gevent:
259 jobs = {}
260 for key, fun in context_funs.items():
261 jobs[key] = gevent.spawn(fun)
263 gevent.joinall(jobs.values())
265 for key, gev in jobs.items():
266 context_funs[key] = gev.get()
268 else:
269 for key, fun in context_funs.items():
270 context_funs[key] = fun()
272 return context_funs