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
21 from itertools
import islice
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
54 @cache_control(private
=True)
56 if request
.user
.is_authenticated():
57 return dashboard(request
)
59 return welcome(request
)
63 @cache_control(private
=True)
65 current_site
= RequestSite(request
)
67 lang
= utils
.process_lang_params(request
)
69 toplist
= PodcastToplist(lang
)
71 return render(request
, 'home.html', {
78 @cache_control(private
=True)
80 def dashboard(request
, episode_count
=10):
82 subscribed_podcasts
= list(request
.user
.get_subscribed_podcasts())
83 site
= RequestSite(request
)
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)
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
,
139 'show_install_reader': show_install_reader
,
144 @cache_control(private
=True)
146 def history(request
, count
=15, uid
=None):
148 page
= parse_range(request
.GET
.get('page', None), 0, sys
.maxint
, 0)
152 device
= request
.user
.get_device_by_uid(uid
, only_active
=False)
153 except DeviceDoesNotExist
as e
:
154 messages
.error(request
, str(e
))
159 history_obj
= History(request
.user
, device
)
163 entries
= list(history_obj
[start
:end
])
164 HistoryEntry
.fetch_data(request
.user
, entries
)
166 return render(request
, 'history.html', {
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
)
186 @repeat_on_conflict(['user'])
187 def _not_uptodate(user
):
188 user
.suggestions_up_to_date
= False
191 _update(suggestion
=suggestion
, podcast_id
=blacklisted_podcast
.get_id())
192 _not_uptodate(user
=request
.user
)
194 return HttpResponseRedirect(reverse('suggestions'))
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
)
206 messages
.success(request
, _('Thanks for rating!'))
208 return HttpResponseRedirect(reverse('suggestions'))
212 @cache_control(private
=True)
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
,
225 @cache_control(private
=True)
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
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()