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
, get_object_or_404
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
.auth
import get_user_model
11 from django
.contrib
import messages
12 from django
.utils
.translation
import ugettext
as _
13 from django
.views
.decorators
.vary
import vary_on_cookie
14 from django
.views
.decorators
.cache
import cache_control
15 from django
.views
.generic
.base
import View
16 from django
.utils
.decorators
import method_decorator
18 from mygpo
.podcasts
.models
import Podcast
, PodcastGroup
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
.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
.podcastlist
import podcastlist_for_user_slug
, \
27 podcastlists_for_user
, add_podcast_to_podcastlist
, \
28 remove_podcast_from_podcastlist
, delete_podcastlist
, \
30 from mygpo
.data
.feeddownloader
import PodcastUpdater
33 logger
= logging
.getLogger(__name__
)
36 def list_decorator(must_own
=False):
39 def _decorator(request
, username
, listname
, *args
, **kwargs
):
41 User
= get_user_model()
42 user
= get_object_or_404(User
, username
=username
)
44 if must_own
and request
.user
!= user
:
45 return HttpResponseForbidden()
47 plist
= podcastlist_for_user_slug(user
.profile
.uuid
.hex, listname
)
52 return f(request
, plist
, user
, *args
, **kwargs
)
60 def search(request
, username
, listname
):
61 return directory_search(request
, 'list_search.html',
62 {'listname': listname
})
66 def lists_own(request
):
68 lists
= podcastlists_for_user(request
.user
.profile
.uuid
.hex)
70 return render(request
, 'lists.html', {
75 def lists_user(request
, username
):
77 User
= get_user_model()
78 user
= get_object_or_404(User
, username
=username
)
79 lists
= podcastlists_for_user(user
.profile
.uuid
.hex)
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
= get_podcasts_groups(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
= get_podcasts_groups(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
.profile
.uuid
.hex, slug
)
138 create_podcast_list(title
, slug
, request
.user
.profile
.uuid
.hex, datetime
.utcnow())
140 list_url
= reverse('list-show', args
=[request
.user
.username
, slug
])
141 return HttpResponseRedirect(list_url
)
145 @list_decorator(must_own
=True)
146 def add_podcast(request
, plist
, owner
, podcast_id
):
147 add_podcast_to_podcastlist(plist
, podcast_id
)
148 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
149 return HttpResponseRedirect(list_url
)
153 @list_decorator(must_own
=True)
154 def remove_podcast(request
, plist
, owner
, podcast_id
):
155 remove_podcast_from_podcastlist(plist
, podcast_id
)
156 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
157 return HttpResponseRedirect(list_url
)
161 @list_decorator(must_own
=True)
162 def delete_list(request
, plist
, owner
):
163 delete_podcastlist(plist
)
164 return HttpResponseRedirect(reverse('lists-overview'))
168 @list_decorator(must_own
=False)
169 def rate_list(request
, plist
, owner
):
170 rating_val
= int(request
.GET
.get('rate', None))
172 @repeat_on_conflict(['plist'])
173 def _rate(plist
, rating_val
, user
):
174 plist
.rate(rating_val
, user
.profile
.uuid
.hex)
177 _rate(plist
, rating_val
, request
.user
)
179 messages
.success(request
, _('Thanks for rating!'))
181 list_url
= reverse('list-show', args
=[owner
.username
, plist
.slug
])
182 return HttpResponseRedirect(list_url
)
185 class FavoritesPublic(View
):
189 @method_decorator(vary_on_cookie
)
190 @method_decorator(cache_control(private
=True))
191 @method_decorator(login_required
)
192 def post(self
, request
):
195 request
.user
.profile
.favorite_feeds_token
= ''
196 request
.user
.profile
.save()
199 request
.user
.profile
.create_new_token('favorite_feeds_token', 8)
200 request
.user
.profile
.save()
202 token
= request
.user
.favorite_feeds_token
204 return HttpResponseRedirect(reverse('share-favorites'))
208 class ShareFavorites(View
):
210 @method_decorator(vary_on_cookie
)
211 @method_decorator(cache_control(private
=True))
212 @method_decorator(login_required
)
213 def get(self
, request
):
216 favfeed
= FavoriteFeed(user
)
217 site
= RequestSite(request
)
218 feed_url
= favfeed
.get_public_url(site
.domain
)
220 podcast
= Podcast
.objects
.filter(urls__url
=feed_url
).first()
222 token
= user
.profile
.favorite_feeds_token
224 return render(request
, 'share/favorites.html', {
231 class PublicSubscriptions(View
):
235 @method_decorator(vary_on_cookie
)
236 @method_decorator(cache_control(private
=True))
237 @method_decorator(login_required
)
238 def post(self
, request
):
241 user
.profile
.subscriptions_token
= ''
243 user
.profile
.create_new_token('subscriptions_token')
247 return HttpResponseRedirect(reverse('share'))
250 class FavoritesFeedCreateEntry(View
):
251 """ Creates a Podcast object for the user's favorites feed """
253 @method_decorator(vary_on_cookie
)
254 @method_decorator(cache_control(private
=True))
255 @method_decorator(login_required
)
256 def post(self
, request
):
259 feed
= FavoriteFeed(user
)
260 site
= RequestSite(request
)
261 feed_url
= feed
.get_public_url(site
.domain
)
263 podcast
= Podcast
.objects
.get_or_create_for_url(feed_url
)
265 if not podcast
.get_id() in user
.published_objects
:
266 user
.published_objects
.append(podcast
.get_id())
269 updater
= PodcastUpdater()
270 updater
.update(feed_url
)
272 return HttpResponseRedirect(reverse('share-favorites'))
276 def overview(request
):
278 site
= RequestSite(request
)
280 subscriptions_token
= user
.profile
.get_token('subscriptions_token')
281 userpage_token
= user
.profile
.get_token('userpage_token')
282 favfeed_token
= user
.profile
.get_token('favorite_feeds_token')
284 favfeed
= FavoriteFeed(user
)
285 favfeed_url
= favfeed
.get_public_url(site
.domain
)
286 favfeed_podcast
= Podcast
.objects
.filter(urls__url
=favfeed_url
).first()
288 return render(request
, 'share/overview.html', {
290 'subscriptions_token': subscriptions_token
,
291 'userpage_token': userpage_token
,
292 'favfeed_token': favfeed_token
,
293 'favfeed_podcast': favfeed_podcast
,
298 def set_token_public(request
, token_name
, public
):
303 setattr(user
.profile
, token_name
, '')
307 user
.profile
.create_new_token(token_name
)
310 return HttpResponseRedirect(reverse('share'))
313 def get_podcasts_groups(ids
):
314 # this could be optimized by using a View
315 logger
.info('Getting podcasts and groups for IDs %r', ids
)
316 groups
= PodcastGroup
.objects
.filter(id__in
=ids
)
317 podcasts
= Podcast
.objects
.filter(id__in
=ids
)
318 # TODO: bring in right order, according to IDs
319 return list(groups
) + list(podcasts
)