[Migration] Fix podcast group query
[mygpo.git] / mygpo / share / views.py
blob127e7c777927dc7de498a15eb7fc8aec30fa01c8
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):
35 def _tmp(f):
36 @wraps(f)
37 def _decorator(request, username, listname, *args, **kwargs):
39 user = User.get_user(username)
40 if not user:
41 raise Http404
43 if must_own and request.user != user:
44 return HttpResponseForbidden()
46 plist = podcastlist_for_user_slug(user._id, listname)
48 if plist is None:
49 raise Http404
51 return f(request, plist, user, *args, **kwargs)
53 return _decorator
55 return _tmp
58 @login_required
59 def search(request, username, listname):
60 return directory_search(request, 'list_search.html',
61 {'listname': listname})
64 @login_required
65 def lists_own(request):
67 lists = podcastlists_for_user(request.user._id)
69 return render(request, 'lists.html', {
70 'lists': lists
74 def lists_user(request, username):
76 user = User.get_user(username)
77 if not user:
78 raise Http404
80 lists = podcastlists_for_user(user._id)
82 return render(request, 'lists_user.html', {
83 'lists': lists,
84 'user': user,
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,
108 'owner': owner,
109 'flattr_autosubmit': flattr_autosubmit,
110 'domain': site.domain,
111 'is_own': is_own,
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)
121 @login_required
122 def create_list(request):
123 title = request.POST.get('title', None)
125 if not title:
126 messages.error(request, _('You have to specify a title.'))
127 return HttpResponseRedirect(reverse('lists-overview'))
129 slug = slugify(title)
131 if not slug:
132 messages.error(request, _('"{title}" is not a valid title').format(
133 title=title))
134 return HttpResponseRedirect(reverse('lists-overview'))
136 plist = podcastlist_for_user_slug(request.user._id, slug)
138 if plist is None:
139 plist = PodcastList()
140 plist.created_timestamp = get_timestamp(datetime.utcnow())
141 plist.title = title
142 plist.slug = slug
143 plist.user = request.user._id
144 plist.save()
146 list_url = reverse('list-show', args=[request.user.username, slug])
147 return HttpResponseRedirect(list_url)
150 @login_required
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)
158 @login_required
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)
166 @login_required
167 @list_decorator(must_own=True)
168 def delete_list(request, plist, owner):
169 delete_podcastlist(plist)
170 return HttpResponseRedirect(reverse('lists-overview'))
173 @login_required
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)
181 plist.save()
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):
193 public = True
195 @method_decorator(vary_on_cookie)
196 @method_decorator(cache_control(private=True))
197 @method_decorator(login_required)
198 def post(self, request):
200 if self.public:
201 request.user.favorite_feeds_token = ''
202 request.user.save()
204 else:
205 request.user.create_new_token('favorite_feeds_token', 8)
206 request.user.save()
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):
220 user = request.user
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', {
231 'feed_token': token,
232 'site': site,
233 'podcast': podcast,
237 class PublicSubscriptions(View):
239 public = True
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):
253 if self.public:
254 user.subscriptions_token = ''
255 else:
256 user.create_new_token('subscriptions_token')
258 user.save()
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):
268 user = request.user
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())
278 user.save()
280 updater = PodcastUpdater()
281 updater.update(feed_url)
283 return HttpResponseRedirect(reverse('share-favorites'))
286 @login_required
287 def overview(request):
288 user = request.user
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', {
300 'site': site,
301 'subscriptions_token': subscriptions_token,
302 'userpage_token': userpage_token,
303 'favfeed_token': favfeed_token,
304 'favfeed_podcast': favfeed_podcast,
308 @login_required
309 def set_token_public(request, token_name, public):
311 if public:
312 @repeat_on_conflict(['user'])
313 def _update(user):
314 setattr(user, token_name, '')
315 user.save()
317 else:
318 @repeat_on_conflict(['user'])
319 def _update(user):
320 user.create_new_token(token_name)
321 user.save()
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)