1 from functools
import wraps
2 from datetime
import datetime
4 from django
.core
.urlresolvers
import reverse
5 from django
.http
import Http404
, HttpResponseRedirect
, HttpResponseForbidden
6 from django
.shortcuts
import render
7 from django
.utils
.text
import slugify
8 from django
.contrib
.sites
.models
import RequestSite
9 from django
.contrib
.auth
.decorators
import login_required
10 from django
.contrib
import messages
11 from django
.utils
.translation
import ugettext
as _
12 from django
.views
.decorators
.vary
import vary_on_cookie
13 from django
.views
.decorators
.cache
import cache_control
14 from django
.views
.generic
.base
import View
15 from django
.utils
.decorators
import method_decorator
17 from mygpo
.utils
import get_timestamp
18 from mygpo
.core
.proxy
import proxy_object
19 from mygpo
.api
.simple
import format_podcast_list
20 from mygpo
.share
.models
import PodcastList
21 from mygpo
.users
.models
import User
22 from mygpo
.directory
.views
import search
as directory_search
23 from mygpo
.decorators
import repeat_on_conflict
24 from mygpo
.flattr
import Flattr
25 from mygpo
.userfeeds
.feeds
import FavoriteFeed
26 from mygpo
.db
.couchdb
.podcast
import podcasts_by_id
, podcast_for_url
27 from mygpo
.db
.couchdb
.podcastlist
import podcastlist_for_user_slug
, \
29 from mygpo
.data
.feeddownloader
import PodcastUpdater
33 def list_decorator(must_own
=False):
36 def _decorator(request
, username
, listname
, *args
, **kwargs
):
38 user
= User
.get_user(username
)
42 if must_own
and request
.user
!= user
:
43 return HttpResponseForbidden()
45 plist
= podcastlist_for_user_slug(user
._id
, listname
)
50 return f(request
, plist
, user
, *args
, **kwargs
)
58 def search(request
, username
, listname
):
59 return directory_search(request
, 'list_search.html',
60 {'listname': listname
})
64 def lists_own(request
):
66 lists
= podcastlists_for_user(request
.user
._id
)
68 return render(request
, 'lists.html', {
73 def lists_user(request
, username
):
75 user
= User
.get_user(username
)
79 lists
= podcastlists_for_user(user
._id
)
81 return render(request
, 'lists_user.html', {
87 @list_decorator(must_own
=False)
88 def list_show(request
, plist
, owner
):
90 is_own
= owner
== request
.user
91 site
= RequestSite(request
)
93 plist
= proxy_object(plist
)
95 podcasts
= podcasts_by_id(plist
.podcasts
)
96 plist
.podcasts
= podcasts
98 max_subscribers
= max([p
.subscriber_count() for p
in podcasts
] + [0])
100 thing
= plist
.get_flattr_thing(site
.domain
, owner
.username
)
101 flattr
= Flattr(owner
, site
.domain
, request
.is_secure())
102 flattr_autosubmit
= flattr
.get_autosubmit_url(thing
)
104 return render(request
, 'list.html', {
105 'podcastlist': plist
,
106 'max_subscribers': max_subscribers
,
108 'flattr_autosubmit': flattr_autosubmit
,
109 'domain': site
.domain
,
114 @list_decorator(must_own
=False)
115 def list_opml(request
, plist
, owner
):
116 podcasts
= podcasts_by_id(plist
.podcasts
)
117 return format_podcast_list(podcasts
, 'opml', plist
.title
)
121 def create_list(request
):
122 title
= request
.POST
.get('title', None)
125 messages
.error(request
, _('You have to specify a title.'))
126 return HttpResponseRedirect(reverse('lists-overview'))
128 slug
= slugify(title
)
131 messages
.error(request
, _('"{title}" is not a valid title').format(
133 return HttpResponseRedirect(reverse('lists-overview'))
135 plist
= podcastlist_for_user_slug(request
.user
._id
, slug
)
138 plist
= PodcastList()
139 plist
.created_timestamp
= get_timestamp(datetime
.utcnow())
142 plist
.user
= request
.user
._id
145 list_url
= reverse('list-show', args
=[request
.user
.username
, slug
])
146 return HttpResponseRedirect(list_url
)
150 @list_decorator(must_own
=True)
151 def add_podcast(request
, plist
, owner
, podcast_id
):
153 @repeat_on_conflict(['plist'])
154 def _add(plist
, podcast_id
):
155 plist
.podcasts
.append(podcast_id
)
158 _add(plist
=plist
, podcast_id
=podcast_id
)
160 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
161 return HttpResponseRedirect(list_url
)
165 @list_decorator(must_own
=True)
166 def remove_podcast(request
, plist
, owner
, podcast_id
):
168 @repeat_on_conflict(['plist'])
169 def _remove(plist
, podcast_id
):
170 plist
.podcasts
.remove(podcast_id
)
173 _remove(plist
=plist
, podcast_id
=podcast_id
)
175 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
176 return HttpResponseRedirect(list_url
)
180 @list_decorator(must_own
=True)
181 def delete_list(request
, plist
, owner
):
183 return HttpResponseRedirect(reverse('lists-overview'))
187 @list_decorator(must_own
=False)
188 def rate_list(request
, plist
, owner
):
189 rating_val
= int(request
.GET
.get('rate', None))
191 @repeat_on_conflict(['plist'])
192 def _rate(plist
, rating_val
, user
):
193 plist
.rate(rating_val
, user
._id
)
196 _rate(plist
, rating_val
, request
.user
)
198 messages
.success(request
, _('Thanks for rating!'))
200 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
201 return HttpResponseRedirect(list_url
)
204 class FavoritesPublic(View
):
208 @method_decorator(vary_on_cookie
)
209 @method_decorator(cache_control(private
=True))
210 @method_decorator(login_required
)
211 def post(self
, request
):
214 request
.user
.favorite_feeds_token
= ''
218 request
.user
.create_new_token('favorite_feeds_token', 8)
221 token
= request
.user
.favorite_feeds_token
223 return HttpResponseRedirect(reverse('share-favorites'))
227 class ShareFavorites(View
):
229 @method_decorator(vary_on_cookie
)
230 @method_decorator(cache_control(private
=True))
231 @method_decorator(login_required
)
232 def get(self
, request
):
235 favfeed
= FavoriteFeed(user
)
236 site
= RequestSite(request
)
237 feed_url
= favfeed
.get_public_url(site
.domain
)
239 podcast
= podcast_for_url(feed_url
)
241 token
= request
.user
.favorite_feeds_token
243 return render(request
, 'share/favorites.html', {
250 class PublicSubscriptions(View
):
254 @method_decorator(vary_on_cookie
)
255 @method_decorator(cache_control(private
=True))
256 @method_decorator(login_required
)
257 def post(self
, request
):
259 self
.update(request
.user
)
261 return HttpResponseRedirect(reverse('share'))
264 @repeat_on_conflict(['user'])
265 def update(self
, user
):
267 user
.subscriptions_token
= ''
269 user
.create_new_token('subscriptions_token')
274 class FavoritesFeedCreateEntry(View
):
275 """ Creates a Podcast object for the user's favorites feed """
277 @method_decorator(vary_on_cookie
)
278 @method_decorator(cache_control(private
=True))
279 @method_decorator(login_required
)
280 def post(self
, request
):
283 feed
= FavoriteFeed(user
)
284 site
= RequestSite(request
)
285 feed_url
= feed
.get_public_url(site
.domain
)
287 podcast
= podcast_for_url(feed_url
, create
=True)
289 if not podcast
.get_id() in user
.published_objects
:
290 user
.published_objects
.append(podcast
.get_id())
293 updater
= PodcastUpdater()
294 updater
.update(feed_url
)
296 return HttpResponseRedirect(reverse('share-favorites'))
300 def overview(request
):
302 site
= RequestSite(request
)
304 subscriptions_token
= user
.get_token('subscriptions_token')
305 userpage_token
= user
.get_token('userpage_token')
306 favfeed_token
= user
.get_token('favorite_feeds_token')
308 favfeed
= FavoriteFeed(user
)
309 favfeed_url
= favfeed
.get_public_url(site
.domain
)
310 favfeed_podcast
= podcast_for_url(favfeed_url
)
312 return render(request
, 'share/overview.html', {
314 'subscriptions_token': subscriptions_token
,
315 'userpage_token': userpage_token
,
316 'favfeed_token': favfeed_token
,
317 'favfeed_podcast': favfeed_podcast
,
322 def set_token_public(request
, token_name
, public
):
325 @repeat_on_conflict(['user'])
327 setattr(user
, token_name
, '')
331 @repeat_on_conflict(['user'])
333 user
.create_new_token(token_name
)
336 _update(user
=request
.user
)
338 return HttpResponseRedirect(reverse('share'))