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
, \
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
.utils
.text
import slugify
27 from django
.views
.decorators
.cache
import never_cache
28 from django
.http
import Http404
30 from mygpo
.utils
import get_timestamp
31 from mygpo
.api
.advanced
.directory
import podcast_data
32 from mygpo
.api
.httpresponse
import JsonResponse
33 from mygpo
.share
.models
import PodcastList
34 from mygpo
.api
.basic_auth
import require_valid_user
, check_username
35 from mygpo
.core
.models
import Podcast
36 from mygpo
.decorators
import allowed_methods
, repeat_on_conflict
, cors_origin
37 from mygpo
.api
.simple
import parse_subscription
, format_podcast_list
, \
39 from mygpo
.share
.views
import list_decorator
40 from mygpo
.users
.models
import User
41 from mygpo
.db
.couchdb
.podcast
import podcasts_by_id
, podcast_for_url
42 from mygpo
.db
.couchdb
.podcastlist
import podcastlist_for_user_slug
, \
52 @allowed_methods(['POST'])
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)
60 return HttpResponseBadRequest('Title missing')
65 return HttpResponseBadRequest('Invalid title')
67 plist
= podcastlist_for_user_slug(request
.user
._id
, slug
)
70 return HttpResponse('List already exists', status
=409)
72 urls
= parse_subscription(request
.body
, format
)
73 podcasts
= [podcast_for_url(url
, create
=True) for url
in urls
]
74 podcast_ids
= map(Podcast
.get_id
, podcasts
)
77 plist
.created_timestamp
= get_timestamp(datetime
.utcnow())
80 plist
.user
= request
.user
._id
81 plist
.podcasts
= podcast_ids
84 response
= HttpResponse(status
=201)
85 list_url
= reverse('api-get-list', args
=[request
.user
.username
, slug
, format
])
86 response
['Location'] = list_url
92 def _get_list_data(l
, username
, domain
):
96 web
= 'http://%s%s' % (domain
,
97 reverse('list-show', args
=[username
, l
.slug
])),
103 @allowed_methods(['GET'])
105 def get_lists(request
, username
):
106 """ Returns a list of all podcast lists by the given user """
108 user
= User
.get_user(username
)
112 lists
= podcastlists_for_user(user
._id
)
114 site
= RequestSite(request
)
116 get_data
= partial(_get_list_data
, username
=user
.username
,
118 lists_data
= map(get_data
, lists
)
120 return JsonResponse(lists_data
)
126 @allowed_methods(['GET', 'PUT', 'DELETE'])
128 def podcast_list(request
, *args
, **kwargs
):
133 DELETE
= delete_list
,
136 return handlers
[request
.method
](request
, *args
, **kwargs
)
140 @list_decorator(must_own
=False)
142 def get_list(request
, plist
, owner
, format
):
143 """ Returns the contents of the podcast list """
146 scale
= int(request
.GET
.get('scale_logo', 64))
147 except (TypeError, ValueError):
148 return HttpResponseBadRequest('scale_logo has to be a numeric value')
150 podcasts
= podcasts_by_id(plist
.podcasts
)
152 domain
= RequestSite(request
).domain
153 p_data
= lambda p
: podcast_data(p
, domain
, scale
)
154 title
= '{title} by {username}'.format(title
=plist
.title
,
155 username
=owner
.username
)
157 return format_podcast_list(podcasts
, format
, title
, json_map
=p_data
,
158 jsonp_padding
=request
.GET
.get('jsonp', ''),
159 xml_template
='podcasts.xml', request
=request
)
164 @list_decorator(must_own
=True)
166 def update_list(request
, plist
, owner
, format
):
167 """ Replaces the podcasts in the list and returns 204 No Content """
169 is_own
= owner
== request
.uuser
172 return HttpResponseForbidden()
174 urls
= parse_subscription(request
.body
, format
)
175 podcasts
= [podcast_for_url(url
, create
=True) for url
in urls
]
176 podcast_ids
= map(Podcast
.get_id
, podcasts
)
178 @repeat_on_conflict(['podcast_ids'])
179 def _update(plist
, podcast_ids
):
180 plist
.podcasts
= podcast_ids
183 _update(plist
=plist
, podcast_ids
=podcast_ids
)
185 return HttpResponse(status
=204)
190 @list_decorator(must_own
=True)
192 def delete_list(request
, plist
, owner
, format
):
193 """ Delete the podcast list and returns 204 No Content """
195 is_own
= owner
== request
.user
198 return HttpResponseForbidden()
200 @repeat_on_conflict(['plist'])
206 return HttpResponse(status
=204)