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
.userfeeds
.feeds
import FavoriteFeed
23 from mygpo
.db
.couchdb
.podcast
import podcasts_by_id
, podcast_for_url
24 from mygpo
.db
.couchdb
.podcastlist
import podcastlist_for_user_slug
, \
26 from mygpo
.data
.feeddownloader
import PodcastUpdater
30 def list_decorator(must_own
=False):
33 def _decorator(request
, username
, listname
, *args
, **kwargs
):
35 user
= User
.get_user(username
)
39 if must_own
and request
.user
!= user
:
40 return HttpResponseForbidden()
42 plist
= podcastlist_for_user_slug(user
._id
, listname
)
47 return f(request
, plist
, user
, *args
, **kwargs
)
55 def search(request
, username
, listname
):
56 return directory_search(request
, 'list_search.html',
57 {'listname': listname
})
61 def lists_own(request
):
63 lists
= podcastlists_for_user(request
.user
._id
)
65 return render(request
, 'lists.html', {
70 def lists_user(request
, username
):
72 user
= User
.get_user(username
)
76 lists
= podcastlists_for_user(user
._id
)
78 return render(request
, 'lists_user.html', {
84 @list_decorator(must_own
=False)
85 def list_show(request
, plist
, owner
):
87 is_own
= owner
== request
.user
89 plist
= proxy_object(plist
)
91 podcasts
= podcasts_by_id(plist
.podcasts
)
92 plist
.podcasts
= podcasts
94 max_subscribers
= max([p
.subscriber_count() for p
in podcasts
] + [0])
96 site
= RequestSite(request
)
98 return render(request
, 'list.html', {
100 'max_subscribers': max_subscribers
,
102 'domain': site
.domain
,
107 @list_decorator(must_own
=False)
108 def list_opml(request
, plist
, owner
):
109 podcasts
= podcasts_by_id(plist
.podcasts
)
110 return format_podcast_list(podcasts
, 'opml', plist
.title
)
114 def create_list(request
):
115 title
= request
.POST
.get('title', None)
118 messages
.error(request
, _('You have to specify a title.'))
119 return HttpResponseRedirect(reverse('lists-overview'))
121 slug
= slugify(title
)
124 messages
.error(request
, _('"{title}" is not a valid title').format(
126 return HttpResponseRedirect(reverse('lists-overview'))
128 plist
= podcastlist_for_user_slug(request
.user
._id
, slug
)
131 plist
= PodcastList()
134 plist
.user
= request
.user
._id
137 list_url
= reverse('list-show', args
=[request
.user
.username
, slug
])
138 return HttpResponseRedirect(list_url
)
142 @list_decorator(must_own
=True)
143 def add_podcast(request
, plist
, owner
, podcast_id
):
145 @repeat_on_conflict(['plist'])
146 def _add(plist
, podcast_id
):
147 plist
.podcasts
.append(podcast_id
)
150 _add(plist
=plist
, podcast_id
=podcast_id
)
152 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
153 return HttpResponseRedirect(list_url
)
157 @list_decorator(must_own
=True)
158 def remove_podcast(request
, plist
, owner
, podcast_id
):
160 @repeat_on_conflict(['plist'])
161 def _remove(plist
, podcast_id
):
162 plist
.podcasts
.remove(podcast_id
)
165 _remove(plist
=plist
, podcast_id
=podcast_id
)
167 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
168 return HttpResponseRedirect(list_url
)
172 @list_decorator(must_own
=True)
173 def delete_list(request
, plist
, owner
):
175 return HttpResponseRedirect(reverse('lists-overview'))
179 @list_decorator(must_own
=False)
180 def rate_list(request
, plist
, owner
):
181 rating_val
= int(request
.GET
.get('rate', None))
183 plist
.rate(rating_val
, request
.user
._id
)
186 messages
.success(request
, _('Thanks for rating!'))
188 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
189 return HttpResponseRedirect(list_url
)
192 class FavoritesPublic(View
):
196 @method_decorator(vary_on_cookie
)
197 @method_decorator(cache_control(private
=True))
198 @method_decorator(login_required
)
199 def post(self
, request
):
202 request
.user
.favorite_feeds_token
= ''
206 request
.user
.create_new_token('favorite_feeds_token', 8)
209 token
= request
.user
.favorite_feeds_token
211 return HttpResponseRedirect(reverse('share-favorites'))
215 class ShareFavorites(View
):
217 @method_decorator(vary_on_cookie
)
218 @method_decorator(cache_control(private
=True))
219 @method_decorator(login_required
)
220 def get(self
, request
):
223 favfeed
= FavoriteFeed(user
)
224 site
= RequestSite(request
)
225 feed_url
= favfeed
.get_public_url(site
.domain
)
227 podcast
= podcast_for_url(feed_url
)
229 token
= request
.user
.favorite_feeds_token
231 return render(request
, 'share/favorites.html', {
238 class PublicSubscriptions(View
):
242 @method_decorator(vary_on_cookie
)
243 @method_decorator(cache_control(private
=True))
244 @method_decorator(login_required
)
245 def post(self
, request
):
247 self
.update(request
.user
)
249 return HttpResponseRedirect(reverse('share'))
252 @repeat_on_conflict(['user'])
253 def update(self
, user
):
255 user
.subscriptions_token
= ''
257 user
.create_new_token('subscriptions_token')
262 class FavoritesFeedCreateEntry(View
):
263 """ Creates a Podcast object for the user's favorites feed """
265 @method_decorator(vary_on_cookie
)
266 @method_decorator(cache_control(private
=True))
267 @method_decorator(login_required
)
268 def post(self
, request
):
271 feed
= FavoriteFeed(user
)
272 site
= RequestSite(request
)
273 feed_url
= feed
.get_public_url(site
.domain
)
275 podcast
= podcast_for_url(feed_url
, create
=True)
277 if not podcast
.get_id() in user
.published_objects
:
278 user
.published_objects
.append(podcast
.get_id())
281 updater
= PodcastUpdater([podcast
])
284 return HttpResponseRedirect(reverse('share-favorites'))
288 def overview(request
):
290 site
= RequestSite(request
)
292 subscriptions_token
= user
.get_token('subscriptions_token')
293 userpage_token
= user
.get_token('userpage_token')
294 favfeed_token
= user
.get_token('favorite_feeds_token')
296 favfeed
= FavoriteFeed(user
)
297 favfeed_url
= favfeed
.get_public_url(site
.domain
)
298 favfeed_podcast
= podcast_for_url(favfeed_url
)
300 return render(request
, 'share/overview.html', {
302 'subscriptions_token': subscriptions_token
,
303 'userpage_token': userpage_token
,
304 'favfeed_token': favfeed_token
,
305 'favfeed_podcast': favfeed_podcast
,
310 def set_token_public(request
, token_name
, public
):
313 @repeat_on_conflict(['user'])
315 setattr(user
, token_name
, '')
319 @repeat_on_conflict(['user'])
321 user
.create_new_token(token_name
)
324 _update(user
=request
.user
)
326 return HttpResponseRedirect(reverse('share'))