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/>.
19 from functools
import partial
20 from datetime
import datetime
22 from django
.http
import HttpResponse
, HttpResponseBadRequest
, \
24 from django
.views
.decorators
.csrf
import csrf_exempt
25 from django
.core
.urlresolvers
import reverse
26 from django
.contrib
.sites
.requests
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
, \
42 from mygpo
.podcastlists
.views
import list_decorator
50 @allowed_methods(['POST'])
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)
58 return HttpResponseBadRequest('Title missing')
63 return HttpResponseBadRequest('Invalid title')
65 plist
, created
= PodcastList
.objects
.get_or_create(
72 'created': datetime
.utcnow(),
73 'modified': datetime
.utcnow(),
78 return HttpResponse('List already exists', status
=409)
80 urls
= parse_subscription(request
.body
.decode('utf-8'), 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
94 def _get_list_data(l
, username
, domain
):
98 web
= 'http://%s%s' % (domain
,
99 reverse('list-show', args
=[username
, l
.slug
])),
105 @allowed_methods(['GET'])
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
)
115 lists
= PodcastList
.objects
.filter(user
=user
)
117 site
= RequestSite(request
)
119 get_data
= partial(_get_list_data
, username
=user
.username
,
121 lists_data
= list(map(get_data
, lists
))
123 return JsonResponse(lists_data
)
129 @allowed_methods(['GET', 'PUT', 'DELETE'])
131 def podcast_list(request
, username
, slug
, format
):
136 DELETE
= delete_list
,
138 return handlers
[request
.method
](request
, username
, slug
, format
)
141 @list_decorator(must_own
=False)
143 def get_list(request
, plist
, owner
, format
):
144 """ Returns the contents of the podcast list """
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)
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
.decode('utf-8'), 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)
176 def delete_list(request
, plist
, owner
, format
):
177 """ Delete the podcast list and returns 204 No Content """
179 return HttpResponse(status
=204)