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 mygpo
.api
.basic_auth
import require_valid_user
, check_username
19 from django
.http
import HttpResponse
, HttpResponseBadRequest
, HttpResponseForbidden
20 from mygpo
.api
.httpresponse
import JsonResponse
21 from mygpo
.exceptions
import ParameterMissing
22 from django
.shortcuts
import get_object_or_404
23 from mygpo
.api
.sanitizing
import sanitize_url
24 from mygpo
.api
.models
import Device
, Podcast
, Episode
25 from mygpo
.api
.models
.episodes
import Chapter
26 from django
.utils
.translation
import ugettext
as _
27 from datetime
import datetime
, timedelta
28 from mygpo
.log
import log
29 from mygpo
.utils
import parse_time
30 from mygpo
.decorators
import allowed_methods
31 import dateutil
.parser
32 from django
.views
.decorators
.csrf
import csrf_exempt
35 #try to import the JSON module (if we are on Python 2.6)
38 # Python 2.5 seems to have a different json module
39 if not 'dumps' in dir(json
):
43 # No JSON module available - fallback to simplejson (Python < 2.6)
44 print "No JSON module available - fallback to simplejson (Python < 2.6)"
45 import simplejson
as json
51 @allowed_methods(['POST', 'GET'])
52 def chapters(request
, username
):
55 now_
= int(mktime(now
.timetuple()))
57 if request
.method
== 'POST':
58 req
= json
.loads(request
.raw_post_data
)
60 if not 'podcast' in req
:
61 return HttpResponseBadRequest('Podcast URL missing')
63 if not 'episode' in req
:
64 return HttpResponseBadRequest('Episode URL missing')
66 podcast_url
= req
.get('podcast', '')
67 episode_url
= req
.get('episode', '')
71 s_podcast_url
= sanitize_url(podcast_url
)
72 if s_podcast_url
!= podcast_url
:
73 req
['podcast'] = s_podcast_url
74 update_urls
.append((podcast_url
, s_podcast_url
))
77 s_episode_url
= sanitize_url(episode_url
, podcast
=False, episode
=True)
78 if s_episode_url
!= episode_url
:
79 req
['episode'] = s_episode_url
80 update_urls
.append((episode_url
, s_episode_url
))
82 if (s_podcast_url
!= '') and (s_episode_url
!= ''):
84 update_chapters(req
, request
.user
)
85 except ParameterMissing
, e
:
86 return HttpResponseBadRequest(e
)
89 'update_url': update_url
,
93 elif request
.method
== 'GET':
94 if not 'podcast' in request
.GET
:
95 return HttpResponseBadRequest('podcast URL missing')
97 if not 'episode' in request
.GET
:
98 return HttpResponseBadRequest('Episode URL missing')
100 podcast_url
= request
.GET
['podcast']
101 episode_url
= request
.GET
['episode']
103 since_
= request
.GET
.get('since', None)
104 since
= datetime
.fromtimestamp(float(since_
)) if since_
else None
106 podcast
= Podcast
.objects
.get(url
=sanitize_url(podcast_url
))
107 episode
= Episode
.objects
.get(url
=sanitize_url(episode_url
, podcast
=False, episode
=True), podcast
=podcast
)
108 chapter_q
= Chapter
.objects
.filter(user
=request
.user
, episode
=episode
).order_by('start')
111 chapter_q
= chapter_q
.filter(timestamp__gt
=since
)
119 'advertisement': c
.advertisement
,
120 'timestamp': c
.created
,
121 'device': c
.device
.uid
124 return JsonResponse({
125 'chapters': chapters
,
130 def update_chapters(req
, user
):
131 podcast
, c
= Podcast
.objects
.get_or_create(url
=req
['podcast'])
132 episode
, c
= Episode
.objects
.get_or_create(url
=req
['episode'], podcast
=podcast
)
136 device
, c
= Device
.objects
.get_or_create(user
=user
, uid
=req
['device'], defaults
= {'type': 'other', 'name': _('New Device')})
138 timestamp
= dateutil
.parser
.parse(req
['timestamp']) if 'timestamp' in req
else datetime
.now()
140 for c
in req
.get('chapters_add', []):
142 raise ParameterMissing('start parameter missing')
143 start
= parse_time(c
['start'])
146 raise ParameterMissing('end parameter missing')
147 end
= parse_time(c
['end'])
149 label
= c
.get('label', '')
150 adv
= c
.get('advertisement', False)
153 Chapter
.objects
.create(
164 for c
in req
.get('chapters_remove', []):
166 raise ParameterMissing('start parameter missing')
167 start
= parse_time(c
['start'])
170 raise ParameterMissing('end parameter missing')
171 end
= parse_time(c
['end'])
173 Chapter
.objects
.filter(