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
.podcasts
.models
import Podcast
, PodcastGroup
18 from mygpo
.utils
import get_timestamp
19 from mygpo
.core
.proxy
import proxy_object
20 from mygpo
.api
.simple
import format_podcast_list
21 from mygpo
.share
.models
import PodcastList
22 from mygpo
.users
.models
import User
23 from mygpo
.directory
.views
import search
as directory_search
24 from mygpo
.decorators
import repeat_on_conflict
25 from mygpo
.flattr
import Flattr
26 from mygpo
.userfeeds
.feeds
import FavoriteFeed
27 from mygpo
.db
.couchdb
.podcastlist
import podcastlist_for_user_slug
, \
28 podcastlists_for_user
, add_podcast_to_podcastlist
, \
29 remove_podcast_from_podcastlist
, delete_podcastlist
30 from mygpo
.data
.feeddownloader
import PodcastUpdater
34 def list_decorator(must_own
=False):
37 def _decorator(request
, username
, listname
, *args
, **kwargs
):
39 user
= User
.get_user(username
)
43 if must_own
and request
.user
!= user
:
44 return HttpResponseForbidden()
46 plist
= podcastlist_for_user_slug(user
._id
, listname
)
51 return f(request
, plist
, user
, *args
, **kwargs
)
59 def search(request
, username
, listname
):
60 return directory_search(request
, 'list_search.html',
61 {'listname': listname
})
65 def lists_own(request
):
67 lists
= podcastlists_for_user(request
.user
._id
)
69 return render(request
, 'lists.html', {
74 def lists_user(request
, username
):
76 user
= User
.get_user(username
)
80 lists
= podcastlists_for_user(user
._id
)
82 return render(request
, 'lists_user.html', {
88 @list_decorator(must_own
=False)
89 def list_show(request
, plist
, owner
):
91 is_own
= owner
== request
.user
92 site
= RequestSite(request
)
94 plist
= proxy_object(plist
)
96 podcasts
= get_podcasts_groups(plist
.podcasts
)
97 plist
.podcasts
= podcasts
99 max_subscribers
= max([p
.subscriber_count() for p
in podcasts
] + [0])
101 thing
= plist
.get_flattr_thing(site
.domain
, owner
.username
)
102 flattr
= Flattr(owner
, site
.domain
, request
.is_secure())
103 flattr_autosubmit
= flattr
.get_autosubmit_url(thing
)
105 return render(request
, 'list.html', {
106 'podcastlist': plist
,
107 'max_subscribers': max_subscribers
,
109 'flattr_autosubmit': flattr_autosubmit
,
110 'domain': site
.domain
,
115 @list_decorator(must_own
=False)
116 def list_opml(request
, plist
, owner
):
117 podcasts
= get_podcasts_groups(plist
.podcasts
)
118 return format_podcast_list(podcasts
, 'opml', plist
.title
)
122 def create_list(request
):
123 title
= request
.POST
.get('title', None)
126 messages
.error(request
, _('You have to specify a title.'))
127 return HttpResponseRedirect(reverse('lists-overview'))
129 slug
= slugify(title
)
132 messages
.error(request
, _('"{title}" is not a valid title').format(
134 return HttpResponseRedirect(reverse('lists-overview'))
136 plist
= podcastlist_for_user_slug(request
.user
._id
, slug
)
139 plist
= PodcastList()
140 plist
.created_timestamp
= get_timestamp(datetime
.utcnow())
143 plist
.user
= request
.user
._id
146 list_url
= reverse('list-show', args
=[request
.user
.username
, slug
])
147 return HttpResponseRedirect(list_url
)
151 @list_decorator(must_own
=True)
152 def add_podcast(request
, plist
, owner
, podcast_id
):
153 add_podcast_to_podcastlist(plist
, podcast_id
)
154 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
155 return HttpResponseRedirect(list_url
)
159 @list_decorator(must_own
=True)
160 def remove_podcast(request
, plist
, owner
, podcast_id
):
161 remove_podcast_from_podcastlist(plist
, podcast_id
)
162 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
163 return HttpResponseRedirect(list_url
)
167 @list_decorator(must_own
=True)
168 def delete_list(request
, plist
, owner
):
169 delete_podcastlist(plist
)
170 return HttpResponseRedirect(reverse('lists-overview'))
174 @list_decorator(must_own
=False)
175 def rate_list(request
, plist
, owner
):
176 rating_val
= int(request
.GET
.get('rate', None))
178 @repeat_on_conflict(['plist'])
179 def _rate(plist
, rating_val
, user
):
180 plist
.rate(rating_val
, user
._id
)
183 _rate(plist
, rating_val
, request
.user
)
185 messages
.success(request
, _('Thanks for rating!'))
187 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
188 return HttpResponseRedirect(list_url
)
191 class FavoritesPublic(View
):
195 @method_decorator(vary_on_cookie
)
196 @method_decorator(cache_control(private
=True))
197 @method_decorator(login_required
)
198 def post(self
, request
):
201 request
.user
.favorite_feeds_token
= ''
205 request
.user
.create_new_token('favorite_feeds_token', 8)
208 token
= request
.user
.favorite_feeds_token
210 return HttpResponseRedirect(reverse('share-favorites'))
214 class ShareFavorites(View
):
216 @method_decorator(vary_on_cookie
)
217 @method_decorator(cache_control(private
=True))
218 @method_decorator(login_required
)
219 def get(self
, request
):
222 favfeed
= FavoriteFeed(user
)
223 site
= RequestSite(request
)
224 feed_url
= favfeed
.get_public_url(site
.domain
)
226 podcast
= Podcast
.objects
.filter(urls__url
=feed_url
).first()
228 token
= request
.user
.favorite_feeds_token
230 return render(request
, 'share/favorites.html', {
237 class PublicSubscriptions(View
):
241 @method_decorator(vary_on_cookie
)
242 @method_decorator(cache_control(private
=True))
243 @method_decorator(login_required
)
244 def post(self
, request
):
246 self
.update(request
.user
)
248 return HttpResponseRedirect(reverse('share'))
251 @repeat_on_conflict(['user'])
252 def update(self
, user
):
254 user
.subscriptions_token
= ''
256 user
.create_new_token('subscriptions_token')
261 class FavoritesFeedCreateEntry(View
):
262 """ Creates a Podcast object for the user's favorites feed """
264 @method_decorator(vary_on_cookie
)
265 @method_decorator(cache_control(private
=True))
266 @method_decorator(login_required
)
267 def post(self
, request
):
270 feed
= FavoriteFeed(user
)
271 site
= RequestSite(request
)
272 feed_url
= feed
.get_public_url(site
.domain
)
274 podcast
= Podcast
.objects
.get_or_create_for_url(feed_url
)
276 if not podcast
.get_id() in user
.published_objects
:
277 user
.published_objects
.append(podcast
.get_id())
280 updater
= PodcastUpdater()
281 updater
.update(feed_url
)
283 return HttpResponseRedirect(reverse('share-favorites'))
287 def overview(request
):
289 site
= RequestSite(request
)
291 subscriptions_token
= user
.get_token('subscriptions_token')
292 userpage_token
= user
.get_token('userpage_token')
293 favfeed_token
= user
.get_token('favorite_feeds_token')
295 favfeed
= FavoriteFeed(user
)
296 favfeed_url
= favfeed
.get_public_url(site
.domain
)
297 favfeed_podcast
= Podcast
.objects
.filter(urls__url
=favfeed_url
).first()
299 return render(request
, 'share/overview.html', {
301 'subscriptions_token': subscriptions_token
,
302 'userpage_token': userpage_token
,
303 'favfeed_token': favfeed_token
,
304 'favfeed_podcast': favfeed_podcast
,
309 def set_token_public(request
, token_name
, public
):
312 @repeat_on_conflict(['user'])
314 setattr(user
, token_name
, '')
318 @repeat_on_conflict(['user'])
320 user
.create_new_token(token_name
)
323 _update(user
=request
.user
)
325 return HttpResponseRedirect(reverse('share'))
328 def get_podcasts_groups(ids
):
329 # this could be optimized by using a View
330 groups
= PodcastGroup
.objects
.filter(id__in
=ids
)
331 podcasts
= PodcastGroup
.objects
.filter(id__in
=ids
)
332 # TODO: bring in right order, according to IDs
333 return list(groups
) + list(podcasts
)