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
.podcasts
.models
import Podcast
41 from mygpo
.directory
.toplist
import PodcastToplist
42 from mygpo
.users
.models
import History
, HistoryEntry
, DeviceDoesNotExist
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_episode_ids_for_user
49 from mygpo
.db
.couchdb
.podcast
import podcast_by_id
50 from mygpo
.db
.couchdb
.user
import (suggestions_for_user
,
51 blacklist_suggested_podcast
)
52 from mygpo
.db
.couchdb
.directory
import tags_for_user
53 from mygpo
.db
.couchdb
.podcastlist
import podcastlists_for_user
57 @cache_control(private
=True)
59 if request
.user
.is_authenticated():
60 return dashboard(request
)
62 return welcome(request
)
66 @cache_control(private
=True)
68 current_site
= RequestSite(request
)
70 lang
= process_lang_params(request
)
72 toplist
= PodcastToplist(lang
)
74 return render(request
, 'home.html', {
81 @cache_control(private
=True)
83 def dashboard(request
, episode_count
=10):
85 subscribed_podcasts
= list(request
.user
.get_subscribed_podcasts())
86 site
= RequestSite(request
)
90 if request
.user
.devices
:
91 checklist
.append('devices')
93 if subscribed_podcasts
:
94 checklist
.append('subscriptions')
96 if favorite_episode_ids_for_user(request
.user
):
97 checklist
.append('favorites')
99 if not request
.user
.get_token('subscriptions_token'):
100 checklist
.append('share')
102 if not request
.user
.get_token('favorite_feeds_token'):
103 checklist
.append('share-favorites')
105 if not request
.user
.get_token('userpage_token'):
106 checklist
.append('userpage')
108 if tags_for_user(request
.user
):
109 checklist
.append('tags')
111 # TODO add podcastlist_count_for_user
112 if podcastlists_for_user(request
.user
._id
):
113 checklist
.append('lists')
115 if request
.user
.published_objects
:
116 checklist
.append('publish')
118 if request
.user
.get_wksetting(FLATTR_TOKEN
):
119 checklist
.append('flattr')
121 if request
.user
.get_wksetting(FLATTR_AUTO
):
122 checklist
.append('auto-flattr')
124 tomorrow
= datetime
.today() + timedelta(days
=1)
126 podcasts
= PodcastSet(subscribed_podcasts
)
128 newest_episodes
= podcasts
.get_newest_episodes(tomorrow
, episode_count
)
130 # we only show the "install reader" link in firefox, because we don't know
131 # yet how/if this works in other browsers.
132 # hints appreciated at https://bugs.gpodder.org/show_bug.cgi?id=58
133 show_install_reader
= \
134 'firefox' in request
.META
.get('HTTP_USER_AGENT', '').lower()
136 return render(request
, 'dashboard.html', {
137 'user': request
.user
,
138 'subscribed_podcasts': subscribed_podcasts
,
139 'newest_episodes': list(newest_episodes
),
140 'random_podcast': Podcast
.objects
.random().first(),
141 'checklist': checklist
,
143 'show_install_reader': show_install_reader
,
148 @cache_control(private
=True)
150 def history(request
, count
=15, uid
=None):
152 page
= parse_range(request
.GET
.get('page', None), 0, sys
.maxint
, 0)
156 device
= request
.user
.get_device_by_uid(uid
, only_active
=False)
157 except DeviceDoesNotExist
as e
:
158 messages
.error(request
, str(e
))
163 history_obj
= History(request
.user
, device
)
167 entries
= history_obj
[start
:end
]
168 HistoryEntry
.fetch_data(request
.user
, entries
)
170 return render(request
, 'history.html', {
180 def blacklist(request
, blacklisted_podcast
):
182 suggestion
= suggestions_for_user(user
)
183 blacklist_suggested_podcast(suggestion
, blacklisted_podcast
.get_id())
184 update_suggestions
.delay(user
)
185 return HttpResponseRedirect(reverse('suggestions'))
190 def rate_suggestions(request
):
191 rating_val
= int(request
.GET
.get('rate', None))
193 suggestion
= suggestions_for_user(request
.user
)
194 suggestion
.rate(rating_val
, request
.user
._id
)
197 messages
.success(request
, _('Thanks for rating!'))
199 return HttpResponseRedirect(reverse('suggestions'))
203 @cache_control(private
=True)
205 def suggestions(request
):
206 suggestion_obj
= suggestions_for_user(request
.user
)
207 suggestions
= suggestion_obj
.get_podcasts()
208 current_site
= RequestSite(request
)
209 return render(request
, 'suggestions.html', {
210 'entries': suggestions
,
216 @cache_control(private
=True)
220 tags_tag
= defaultdict(list)
222 for podcast_id
, taglist
in tags_for_user(request
.user
).items():
223 podcast
= podcast_by_id(podcast_id
)
224 tags_podcast
[podcast
] = taglist
227 tags_tag
[ tag
].append(podcast
)
229 return render(request
, 'mytags.html', {
230 'tags_podcast': tags_podcast
,
231 'tags_tag': dict(tags_tag
.items()),
236 class GeventView(View
):
237 """ View that provides parts of the context via gevent coroutines """
239 def get_context(self
, context_funs
):
240 """ returns a dictionary that can be used for a template context
242 context_funs is a context-key => Greenlet object mapping """
246 for key
, fun
in context_funs
.items():
247 jobs
[key
] = gevent
.spawn(fun
)
249 gevent
.joinall(jobs
.values())
251 for key
, gev
in jobs
.items():
252 context_funs
[key
] = gev
.get()
255 for key
, fun
in context_funs
.items():
256 context_funs
[key
] = fun()