Merge pull request #793 from gpodder/remove-advertise
[mygpo.git] / mygpo / api / advanced / episode.py
blobea417c894080e88684da319cd2baee8c92532e87
1 from datetime import datetime
3 from mygpo.api import APIView, RequestException
4 from mygpo.api.httpresponse import JsonResponse
5 from mygpo.api.exceptions import ParameterMissing
6 from mygpo.chapters.models import Chapter
7 from mygpo.utils import parse_time, normalize_feed_url, get_timestamp
10 class ChaptersAPI(APIView):
11 def post(self, request, username):
12 """Add / remove Chapters to/from an episode"""
13 user = request.user
14 now_ = get_timestamp(datetime.utcnow())
16 body = self.parsed_body(request)
18 podcast_url, episode_url, update_urls = self.get_urls(body)
19 body["podcast"] = podcast_url
20 body["episode"] = episode_url
22 if not podcast_url or not episode_url:
23 raise RequestException("Invalid Podcast or Episode URL")
25 self.update_chapters(body, user)
26 return JsonResponse({"update_url": update_urls, "timestamp": now_})
28 def get(self, request, username):
29 """Get chapters for an episode"""
30 user = request.user
31 now_ = get_timestamp(datetime.utcnow())
33 podcast_url, episode_url, _update_urls = self.get_urls(request)
35 episode = Episode.objects.filter(
36 podcast__urls__url=podcast_url, urls__url=episode_url
37 ).get()
39 chapters = Chapter.objects.filter(user=user, episode=episode)
41 since = self.get_since(request)
42 if since:
43 chapters = chapters.filter(created__gte=since)
45 chapters_json = map(self.chapter_to_json, chapters)
47 return JsonResponse({"chapters": chapters_json, "timestamp": now_})
49 def update_chapters(self, req, user):
50 """Add / remove chapters according to the client's request"""
51 podcast = Podcast.objects.get_or_create_for_url(podcast_url).object
52 episode = Episode.objects.get_or_create_for_url(podcast, episode_url).object
54 # add chapters
55 for chapter_data in req.get("chapters_add", []):
56 chapter = self.parse_new(user, chapter_data)
57 chapter.save()
59 # remove chapters
60 for chapter_data in req.get("chapters_remove", []):
61 start, end = self.parse_rem(chapter_data)
62 Chapter.objects.filter(
63 user=user, episode=episode, start=start, end=end
64 ).delete()
66 def parse_new(self, user, chapter_data):
67 """Parse a chapter to be added"""
68 chapter = Chapter()
69 if not "start" in chapter_data:
70 raise ParameterMissing("start parameter missing")
71 chapter.start = parse_time(chapter_data["start"])
73 if not "end" in chapter_data:
74 raise ParameterMissing("end parameter missing")
75 chapter.end = parse_time(chapter_data["end"])
77 chapter.label = chapter_data.get("label", "")
78 chapter.advertisement = chapter_data.get("advertisement", False)
79 return chapter
81 def parse_rem(self, chapter_data):
82 """Parse a chapter to be removed"""
83 if not "start" in chapter_data:
84 raise ParameterMissing("start parameter missing")
85 start = parse_time(chapter_data["start"])
87 if not "end" in chapter_data:
88 raise ParameterMissing("end parameter missing")
89 end = parse_time(chapter_data["end"])
91 return (start, end)
93 def get_urls(self, body):
94 """Parse and normalize the URLs from the request"""
95 podcast_url = body.get("podcast", "")
96 episode_url = body.get("episode", "")
98 if not podcast_url:
99 raise RequestException("Podcast URL missing")
101 if not episode_url:
102 raise RequestException("Episode URL missing")
104 update_urls = []
106 # podcast sanitizing
107 s_podcast_url = normalize_feed_url(podcast_url)
108 if s_podcast_url != podcast_url:
109 update_urls.append((podcast_url, s_podcast_url or ""))
111 # episode sanitizing
112 s_episode_url = normalize_feed_url(episode_url, "episode")
113 if s_episode_url != episode_url:
114 update_urls.append((episode_url, s_episode_url or ""))
116 return s_podcast_url, s_episode_url, update_urls
118 def chapter_to_json(self, chapter):
119 """JSON representation of Chapter for GET response"""
120 return {
121 "start": chapter.start,
122 "end": chapter.end,
123 "label": chapter.label,
124 "advertisement": chapter.advertisement,
125 "timestamp": chapter.created,