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
.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
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 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)
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
,
138 'show_install_reader': show_install_reader
,
143 @cache_control(private
=True)
145 def history(request
, count
=15, uid
=None):
147 page
= parse_range(request
.GET
.get('page', None), 0, sys
.maxint
, 0)
151 device
= request
.user
.get_device_by_uid(uid
, only_active
=False)
152 except DeviceDoesNotExist
as e
:
153 messages
.error(request
, str(e
))
158 history_obj
= History(request
.user
, device
)
162 entries
= list(history_obj
[start
:end
])
163 HistoryEntry
.fetch_data(request
.user
, entries
)
165 return render(request
, 'history.html', {
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
)
185 @repeat_on_conflict(['user'])
186 def _not_uptodate(user
):
187 user
.suggestions_up_to_date
= False
190 _update(suggestion
=suggestion
, podcast_id
=blacklisted_podcast
.get_id())
191 _not_uptodate(user
=request
.user
)
193 return HttpResponseRedirect(reverse('suggestions'))
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
)
205 messages
.success(request
, _('Thanks for rating!'))
207 return HttpResponseRedirect(reverse('suggestions'))
211 @cache_control(private
=True)
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
,
224 @cache_control(private
=True)
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
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()