[Migration] use migrated users
[mygpo.git] / mygpo / api / advanced / lists.py
blobfdf760c7b28da2cd8a36ca4aef4df486a280ac29
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from functools import partial
19 from datetime import datetime
21 from django.http import HttpResponse, HttpResponseBadRequest, \
22 HttpResponseForbidden
23 from django.views.decorators.csrf import csrf_exempt
24 from django.core.urlresolvers import reverse
25 from django.contrib.sites.models import RequestSite
26 from django.contrib.auth import get_user_model
27 from django.utils.text import slugify
28 from django.views.decorators.cache import never_cache
29 from django.http import Http404
30 from django.shortcuts import get_object_or_404
32 from mygpo.podcasts.models import Podcast
33 from mygpo.utils import get_timestamp
34 from mygpo.api.advanced.directory import podcast_data
35 from mygpo.api.httpresponse import JsonResponse
36 from mygpo.share.models import PodcastList
37 from mygpo.api.basic_auth import require_valid_user, check_username
38 from mygpo.decorators import allowed_methods, repeat_on_conflict, cors_origin
39 from mygpo.api.simple import parse_subscription, format_podcast_list, \
40 check_format
41 from mygpo.share.views import list_decorator
42 from mygpo.db.couchdb.podcastlist import podcastlist_for_user_slug, \
43 podcastlists_for_user
47 @csrf_exempt
48 @require_valid_user
49 @check_username
50 @check_format
51 @never_cache
52 @allowed_methods(['POST'])
53 @cors_origin()
54 def create(request, username, format):
55 """ Creates a new podcast list and links to it in the Location header """
57 title = request.GET.get('title', None)
59 if not title:
60 return HttpResponseBadRequest('Title missing')
62 slug = slugify(title)
64 if not slug:
65 return HttpResponseBadRequest('Invalid title')
67 plist = podcastlist_for_user_slug(request.user._id, slug)
69 if plist:
70 return HttpResponse('List already exists', status=409)
72 urls = parse_subscription(request.body, format)
73 podcasts = [Podcast.objects.get_or_create_for_url(url) for url in urls]
74 podcast_ids = [podcast.id.hex for podcast in podcasts]
76 plist = PodcastList()
77 plist.created_timestamp = get_timestamp(datetime.utcnow())
78 plist.title = title
79 plist.slug = slug
80 plist.user = request.user._id
81 plist.podcasts = podcast_ids
82 plist.save()
84 response = HttpResponse(status=201)
85 list_url = reverse('api-get-list', args=[request.user.username, slug, format])
86 response['Location'] = list_url
88 return response
92 def _get_list_data(l, username, domain):
93 return dict(
94 title= l.title,
95 name = l.slug,
96 web = 'http://%s%s' % (domain,
97 reverse('list-show', args=[username, l.slug])),
101 @csrf_exempt
102 @never_cache
103 @allowed_methods(['GET'])
104 @cors_origin()
105 def get_lists(request, username):
106 """ Returns a list of all podcast lists by the given user """
108 User = get_user_model()
109 user = User.objects.get(username=username)
110 if not user:
111 raise Http404
113 lists = podcastlists_for_user(user._id)
115 site = RequestSite(request)
117 get_data = partial(_get_list_data, username=user.username,
118 domain=site.domain)
119 lists_data = map(get_data, lists)
121 return JsonResponse(lists_data)
124 @csrf_exempt
125 @check_format
126 @never_cache
127 @allowed_methods(['GET', 'PUT', 'DELETE'])
128 @cors_origin()
129 def podcast_list(request, *args, **kwargs):
131 handlers = dict(
132 GET = get_list,
133 PUT = update_list,
134 DELETE = delete_list,
137 return handlers[request.method](request, *args, **kwargs)
140 @never_cache
141 @list_decorator(must_own=False)
142 @cors_origin()
143 def get_list(request, plist, owner, format):
144 """ Returns the contents of the podcast list """
146 try:
147 scale = int(request.GET.get('scale_logo', 64))
148 except (TypeError, ValueError):
149 return HttpResponseBadRequest('scale_logo has to be a numeric value')
151 podcasts = Podcast.objects.filter(id__in=plist.podcasts)
153 domain = RequestSite(request).domain
154 p_data = lambda p: podcast_data(p, domain, scale)
155 title = '{title} by {username}'.format(title=plist.title,
156 username=owner.username)
158 return format_podcast_list(podcasts, format, title, json_map=p_data,
159 jsonp_padding=request.GET.get('jsonp', ''),
160 xml_template='podcasts.xml', request=request)
163 @never_cache
164 @require_valid_user
165 @list_decorator(must_own=True)
166 @cors_origin()
167 def update_list(request, plist, owner, format):
168 """ Replaces the podcasts in the list and returns 204 No Content """
170 is_own = owner == request.uuser
172 if not is_own:
173 return HttpResponseForbidden()
175 urls = parse_subscription(request.body, format)
176 podcasts = [Podcast.objects.get_or_create_for_url(url) for url in urls]
177 podcast_ids = [podcast.id.hex for podcast in podcasts]
179 @repeat_on_conflict(['podcast_ids'])
180 def _update(plist, podcast_ids):
181 plist.podcasts = podcast_ids
182 plist.save()
184 _update(plist=plist, podcast_ids=podcast_ids)
186 return HttpResponse(status=204)
189 @never_cache
190 @require_valid_user
191 @list_decorator(must_own=True)
192 @cors_origin()
193 def delete_list(request, plist, owner, format):
194 """ Delete the podcast list and returns 204 No Content """
196 is_own = owner == request.user
198 if not is_own:
199 return HttpResponseForbidden()
201 @repeat_on_conflict(['plist'])
202 def _delete(plist):
203 plist.delete()
205 _delete(plist=plist)
207 return HttpResponse(status=204)