Run 2to3-3.4
[mygpo.git] / mygpo / api / advanced / lists.py
blob8bc244d90ab1d13fa9714eeb1a5be14374e8a19d
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 import uuid
19 from functools import partial
20 from datetime import datetime
22 from django.http import HttpResponse, HttpResponseBadRequest, \
23 HttpResponseForbidden
24 from django.views.decorators.csrf import csrf_exempt
25 from django.core.urlresolvers import reverse
26 from django.contrib.sites.models import RequestSite
27 from django.contrib.auth import get_user_model
28 from django.utils.text import slugify
29 from django.views.decorators.cache import never_cache
30 from django.http import Http404
31 from django.shortcuts import get_object_or_404
33 from mygpo.podcasts.models import Podcast
34 from mygpo.utils import get_timestamp
35 from mygpo.api.advanced.directory import podcast_data
36 from mygpo.api.httpresponse import JsonResponse
37 from mygpo.podcastlists.models import PodcastList
38 from mygpo.api.basic_auth import require_valid_user, check_username
39 from mygpo.decorators import allowed_methods, cors_origin
40 from mygpo.api.simple import parse_subscription, format_podcast_list, \
41 check_format
42 from mygpo.podcastlists.views import list_decorator
45 @csrf_exempt
46 @require_valid_user
47 @check_username
48 @check_format
49 @never_cache
50 @allowed_methods(['POST'])
51 @cors_origin()
52 def create(request, username, format):
53 """ Creates a new podcast list and links to it in the Location header """
55 title = request.GET.get('title', None)
57 if not title:
58 return HttpResponseBadRequest('Title missing')
60 slug = slugify(title)
62 if not slug:
63 return HttpResponseBadRequest('Invalid title')
65 plist, created = PodcastList.objects.get_or_create(
66 user=request.user,
67 slug=slug,
68 defaults={
69 'id': uuid.uuid1(),
70 'title': title,
71 'slug': slug,
72 'created': datetime.utcnow(),
73 'modified': datetime.utcnow(),
77 if not created:
78 return HttpResponse('List already exists', status=409)
80 urls = parse_subscription(request.body, format)
81 podcasts = [Podcast.objects.get_or_create_for_url(url) for url in urls]
83 for podcast in podcasts:
84 plist.add_entry(podcast)
86 response = HttpResponse(status=201)
87 list_url = reverse('api-get-list', args=[request.user.username, slug, format])
88 response['Location'] = list_url
90 return response
94 def _get_list_data(l, username, domain):
95 return dict(
96 title= l.title,
97 name = l.slug,
98 web = 'http://%s%s' % (domain,
99 reverse('list-show', args=[username, l.slug])),
103 @csrf_exempt
104 @never_cache
105 @allowed_methods(['GET'])
106 @cors_origin()
107 def get_lists(request, username):
108 """ Returns a list of all podcast lists by the given user """
110 User = get_user_model()
111 user = User.objects.get(username=username)
112 if not user:
113 raise Http404
115 lists = PodcastList.objects.filter(user=user)
117 site = RequestSite(request)
119 get_data = partial(_get_list_data, username=user.username,
120 domain=site.domain)
121 lists_data = list(map(get_data, lists))
123 return JsonResponse(lists_data)
126 @csrf_exempt
127 @check_format
128 @never_cache
129 @allowed_methods(['GET', 'PUT', 'DELETE'])
130 @cors_origin()
131 def podcast_list(request, username, slug, format):
133 handlers = dict(
134 GET = get_list,
135 PUT = update_list,
136 DELETE = delete_list,
138 return handlers[request.method](request, username, slug, format)
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 domain = RequestSite(request).domain
152 p_data = lambda p: podcast_data(p, domain, scale)
153 title = '{title} by {username}'.format(title=plist.title,
154 username=owner.username)
156 objs = [entry.content_object for entry in plist.entries.all()]
158 return format_podcast_list(objs, format, title, json_map=p_data,
159 jsonp_padding=request.GET.get('jsonp', ''),
160 xml_template='podcasts.xml', request=request)
163 @list_decorator(must_own=True)
164 @cors_origin()
165 def update_list(request, plist, owner, format):
166 """ Replaces the podcasts in the list and returns 204 No Content """
167 urls = parse_subscription(request.body, format)
168 podcasts = [Podcast.objects.get_or_create_for_url(url) for url in urls]
169 plist.set_entries(podcasts)
171 return HttpResponse(status=204)
174 @list_decorator(must_own=True)
175 @cors_origin()
176 def delete_list(request, plist, owner, format):
177 """ Delete the podcast list and returns 204 No Content """
178 plist.delete()
179 return HttpResponse(status=204)