1 from functools
import wraps
3 from django
.core
.urlresolvers
import reverse
4 from django
.http
import Http404
, HttpResponseRedirect
, HttpResponseForbidden
5 from django
.shortcuts
import render
6 from django
.template
.defaultfilters
import slugify
7 from django
.contrib
.sites
.models
import RequestSite
8 from django
.contrib
.auth
.decorators
import login_required
9 from django
.contrib
import messages
10 from django
.utils
.translation
import ugettext
as _
11 from django
.views
.decorators
.vary
import vary_on_cookie
12 from django
.views
.decorators
.cache
import cache_control
13 from django
.views
.generic
.base
import View
14 from django
.utils
.decorators
import method_decorator
16 from mygpo
.core
.proxy
import proxy_object
17 from mygpo
.api
.simple
import format_podcast_list
18 from mygpo
.share
.models
import PodcastList
19 from mygpo
.users
.models
import User
20 from mygpo
.directory
.views
import search
as directory_search
21 from mygpo
.decorators
import repeat_on_conflict
22 from mygpo
.flattr
import Flattr
23 from mygpo
.userfeeds
.feeds
import FavoriteFeed
24 from mygpo
.db
.couchdb
.podcast
import podcasts_by_id
, podcast_for_url
25 from mygpo
.db
.couchdb
.podcastlist
import podcastlist_for_user_slug
, \
27 from mygpo
.data
.feeddownloader
import PodcastUpdater
31 def list_decorator(must_own
=False):
34 def _decorator(request
, username
, listname
, *args
, **kwargs
):
36 user
= User
.get_user(username
)
40 if must_own
and request
.user
!= user
:
41 return HttpResponseForbidden()
43 plist
= podcastlist_for_user_slug(user
._id
, listname
)
48 return f(request
, plist
, user
, *args
, **kwargs
)
56 def search(request
, username
, listname
):
57 return directory_search(request
, 'list_search.html',
58 {'listname': listname
})
62 def lists_own(request
):
64 lists
= podcastlists_for_user(request
.user
._id
)
66 return render(request
, 'lists.html', {
71 def lists_user(request
, username
):
73 user
= User
.get_user(username
)
77 lists
= podcastlists_for_user(user
._id
)
79 return render(request
, 'lists_user.html', {
85 @list_decorator(must_own
=False)
86 def list_show(request
, plist
, owner
):
88 is_own
= owner
== request
.user
89 site
= RequestSite(request
)
91 plist
= proxy_object(plist
)
93 podcasts
= podcasts_by_id(plist
.podcasts
)
94 plist
.podcasts
= podcasts
96 max_subscribers
= max([p
.subscriber_count() for p
in podcasts
] + [0])
98 thing
= plist
.get_flattr_thing(site
.domain
, owner
.username
)
99 flattr
= Flattr(owner
, site
.domain
)
100 flattr_autosubmit
= flattr
.get_autosubmit_url(thing
)
102 return render(request
, 'list.html', {
103 'podcastlist': plist
,
104 'max_subscribers': max_subscribers
,
106 'flattr_autosubmit': flattr_autosubmit
,
107 'domain': site
.domain
,
112 @list_decorator(must_own
=False)
113 def list_opml(request
, plist
, owner
):
114 podcasts
= podcasts_by_id(plist
.podcasts
)
115 return format_podcast_list(podcasts
, 'opml', plist
.title
)
119 def create_list(request
):
120 title
= request
.POST
.get('title', None)
123 messages
.error(request
, _('You have to specify a title.'))
124 return HttpResponseRedirect(reverse('lists-overview'))
126 slug
= slugify(title
)
129 messages
.error(request
, _('"{title}" is not a valid title').format(
131 return HttpResponseRedirect(reverse('lists-overview'))
133 plist
= podcastlist_for_user_slug(request
.user
._id
, slug
)
136 plist
= PodcastList()
139 plist
.user
= request
.user
._id
142 list_url
= reverse('list-show', args
=[request
.user
.username
, slug
])
143 return HttpResponseRedirect(list_url
)
147 @list_decorator(must_own
=True)
148 def add_podcast(request
, plist
, owner
, podcast_id
):
150 @repeat_on_conflict(['plist'])
151 def _add(plist
, podcast_id
):
152 plist
.podcasts
.append(podcast_id
)
155 _add(plist
=plist
, podcast_id
=podcast_id
)
157 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
158 return HttpResponseRedirect(list_url
)
162 @list_decorator(must_own
=True)
163 def remove_podcast(request
, plist
, owner
, podcast_id
):
165 @repeat_on_conflict(['plist'])
166 def _remove(plist
, podcast_id
):
167 plist
.podcasts
.remove(podcast_id
)
170 _remove(plist
=plist
, podcast_id
=podcast_id
)
172 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
173 return HttpResponseRedirect(list_url
)
177 @list_decorator(must_own
=True)
178 def delete_list(request
, plist
, owner
):
180 return HttpResponseRedirect(reverse('lists-overview'))
184 @list_decorator(must_own
=False)
185 def rate_list(request
, plist
, owner
):
186 rating_val
= int(request
.GET
.get('rate', None))
188 @repeat_on_conflict(['plist'])
189 def _rate(plist
, rating_val
, user
):
190 plist
.rate(rating_val
, user
._id
)
193 _rate(plist
, rating_val
, request
.user
)
195 messages
.success(request
, _('Thanks for rating!'))
197 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
198 return HttpResponseRedirect(list_url
)
201 class FavoritesPublic(View
):
205 @method_decorator(vary_on_cookie
)
206 @method_decorator(cache_control(private
=True))
207 @method_decorator(login_required
)
208 def post(self
, request
):
211 request
.user
.favorite_feeds_token
= ''
215 request
.user
.create_new_token('favorite_feeds_token', 8)
218 token
= request
.user
.favorite_feeds_token
220 return HttpResponseRedirect(reverse('share-favorites'))
224 class ShareFavorites(View
):
226 @method_decorator(vary_on_cookie
)
227 @method_decorator(cache_control(private
=True))
228 @method_decorator(login_required
)
229 def get(self
, request
):
232 favfeed
= FavoriteFeed(user
)
233 site
= RequestSite(request
)
234 feed_url
= favfeed
.get_public_url(site
.domain
)
236 podcast
= podcast_for_url(feed_url
)
238 token
= request
.user
.favorite_feeds_token
240 return render(request
, 'share/favorites.html', {
247 class PublicSubscriptions(View
):
251 @method_decorator(vary_on_cookie
)
252 @method_decorator(cache_control(private
=True))
253 @method_decorator(login_required
)
254 def post(self
, request
):
256 self
.update(request
.user
)
258 return HttpResponseRedirect(reverse('share'))
261 @repeat_on_conflict(['user'])
262 def update(self
, user
):
264 user
.subscriptions_token
= ''
266 user
.create_new_token('subscriptions_token')
271 class FavoritesFeedCreateEntry(View
):
272 """ Creates a Podcast object for the user's favorites feed """
274 @method_decorator(vary_on_cookie
)
275 @method_decorator(cache_control(private
=True))
276 @method_decorator(login_required
)
277 def post(self
, request
):
280 feed
= FavoriteFeed(user
)
281 site
= RequestSite(request
)
282 feed_url
= feed
.get_public_url(site
.domain
)
284 podcast
= podcast_for_url(feed_url
, create
=True)
286 if not podcast
.get_id() in user
.published_objects
:
287 user
.published_objects
.append(podcast
.get_id())
290 updater
= PodcastUpdater()
291 updater
.update(feed_url
)
293 return HttpResponseRedirect(reverse('share-favorites'))
297 def overview(request
):
299 site
= RequestSite(request
)
301 subscriptions_token
= user
.get_token('subscriptions_token')
302 userpage_token
= user
.get_token('userpage_token')
303 favfeed_token
= user
.get_token('favorite_feeds_token')
305 favfeed
= FavoriteFeed(user
)
306 favfeed_url
= favfeed
.get_public_url(site
.domain
)
307 favfeed_podcast
= podcast_for_url(favfeed_url
)
309 return render(request
, 'share/overview.html', {
311 'subscriptions_token': subscriptions_token
,
312 'userpage_token': userpage_token
,
313 'favfeed_token': favfeed_token
,
314 'favfeed_podcast': favfeed_podcast
,
319 def set_token_public(request
, token_name
, public
):
322 @repeat_on_conflict(['user'])
324 setattr(user
, token_name
, '')
328 @repeat_on_conflict(['user'])
330 user
.create_new_token(token_name
)
333 _update(user
=request
.user
)
335 return HttpResponseRedirect(reverse('share'))