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/>.
19 from collections
import defaultdict
20 from datetime
import datetime
, timedelta
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
, \
43 from mygpo
.users
.tasks
import update_suggestions
44 from mygpo
.web
.utils
import process_lang_params
45 from mygpo
.utils
import parse_range
46 from mygpo
.web
.views
.podcast
import slug_id_decorator
47 from mygpo
.users
.settings
import FLATTR_AUTO
, FLATTR_TOKEN
48 from mygpo
.db
.couchdb
.episode
import favorite_episodes_for_user
49 from mygpo
.db
.couchdb
.podcast
import podcast_by_id
, random_podcasts
50 from mygpo
.db
.couchdb
.user
import suggestions_for_user
51 from mygpo
.db
.couchdb
.directory
import tags_for_user
52 from mygpo
.db
.couchdb
.podcastlist
import podcastlists_for_user
56 @cache_control(private
=True)
58 if request
.user
.is_authenticated():
59 return dashboard(request
)
61 return welcome(request
)
65 @cache_control(private
=True)
67 current_site
= RequestSite(request
)
69 lang
= process_lang_params(request
)
71 toplist
= PodcastToplist(lang
)
73 return render(request
, 'home.html', {
80 @cache_control(private
=True)
82 def dashboard(request
, episode_count
=10):
84 subscribed_podcasts
= list(request
.user
.get_subscribed_podcasts())
85 site
= RequestSite(request
)
89 if request
.user
.devices
:
90 checklist
.append('devices')
92 if subscribed_podcasts
:
93 checklist
.append('subscriptions')
95 if favorite_episodes_for_user(request
.user
):
96 checklist
.append('favorites')
98 if not request
.user
.get_token('subscriptions_token'):
99 checklist
.append('share')
101 if not request
.user
.get_token('favorite_feeds_token'):
102 checklist
.append('share-favorites')
104 if not request
.user
.get_token('userpage_token'):
105 checklist
.append('userpage')
107 if tags_for_user(request
.user
):
108 checklist
.append('tags')
110 # TODO add podcastlist_count_for_user
111 if podcastlists_for_user(request
.user
._id
):
112 checklist
.append('lists')
114 if request
.user
.published_objects
:
115 checklist
.append('publish')
117 if request
.user
.get_wksetting(FLATTR_TOKEN
):
118 checklist
.append('flattr')
120 if request
.user
.get_wksetting(FLATTR_AUTO
):
121 checklist
.append('auto-flattr')
123 tomorrow
= datetime
.today() + timedelta(days
=1)
125 podcasts
= PodcastSet(subscribed_podcasts
)
127 newest_episodes
= podcasts
.get_newest_episodes(tomorrow
, episode_count
)
129 def get_random_podcasts():
130 random_podcast
= next(random_podcasts(), None)
132 yield random_podcast
.get_podcast()
134 # we only show the "install reader" link in firefox, because we don't know
135 # yet how/if this works in other browsers.
136 # hints appreciated at https://bugs.gpodder.org/show_bug.cgi?id=58
137 show_install_reader
= \
138 'firefox' in request
.META
.get('HTTP_USER_AGENT', '').lower()
140 return render(request
, 'dashboard.html', {
141 'user': request
.user
,
142 'subscribed_podcasts': subscribed_podcasts
,
143 'newest_episodes': list(newest_episodes
),
144 'random_podcasts': get_random_podcasts(),
145 'checklist': checklist
,
147 'show_install_reader': show_install_reader
,
152 @cache_control(private
=True)
154 def history(request
, count
=15, uid
=None):
156 page
= parse_range(request
.GET
.get('page', None), 0, sys
.maxint
, 0)
160 device
= request
.user
.get_device_by_uid(uid
, only_active
=False)
161 except DeviceDoesNotExist
as e
:
162 messages
.error(request
, str(e
))
167 history_obj
= History(request
.user
, device
)
171 entries
= history_obj
[start
:end
]
172 HistoryEntry
.fetch_data(request
.user
, entries
)
174 return render(request
, 'history.html', {
184 def blacklist(request
, blacklisted_podcast
):
187 suggestion
= suggestions_for_user(user
)
189 @repeat_on_conflict(['suggestion'])
190 def _update(suggestion
, podcast_id
):
191 suggestion
.blacklist
.append(podcast_id
)
194 _update(suggestion
=suggestion
, podcast_id
=blacklisted_podcast
.get_id())
195 update_suggestions
.delay(user
)
197 return HttpResponseRedirect(reverse('suggestions'))
202 def rate_suggestions(request
):
203 rating_val
= int(request
.GET
.get('rate', None))
205 suggestion
= suggestions_for_user(request
.user
)
206 suggestion
.rate(rating_val
, request
.user
._id
)
209 messages
.success(request
, _('Thanks for rating!'))
211 return HttpResponseRedirect(reverse('suggestions'))
215 @cache_control(private
=True)
217 def suggestions(request
):
218 suggestion_obj
= suggestions_for_user(request
.user
)
219 suggestions
= suggestion_obj
.get_podcasts()
220 current_site
= RequestSite(request
)
221 return render(request
, 'suggestions.html', {
222 'entries': suggestions
,
228 @cache_control(private
=True)
232 tags_tag
= defaultdict(list)
234 for podcast_id
, taglist
in tags_for_user(request
.user
).items():
235 podcast
= podcast_by_id(podcast_id
)
236 tags_podcast
[podcast
] = taglist
239 tags_tag
[ tag
].append(podcast
)
241 return render(request
, 'mytags.html', {
242 'tags_podcast': tags_podcast
,
243 'tags_tag': dict(tags_tag
.items()),
248 class GeventView(View
):
249 """ View that provides parts of the context via gevent coroutines """
251 def get_context(self
, context_funs
):
252 """ returns a dictionary that can be used for a template context
254 context_funs is a context-key => Greenlet object mapping """
258 for key
, fun
in context_funs
.items():
259 jobs
[key
] = gevent
.spawn(fun
)
261 gevent
.joinall(jobs
.values())
263 for key
, gev
in jobs
.items():
264 context_funs
[key
] = gev
.get()
267 for key
, fun
in context_funs
.items():
268 context_funs
[key
] = fun()