]>
Commit | Line | Data |
---|---|---|
daaaf5f5 AC |
1 | # coding: utf-8 |
2 | from __future__ import unicode_literals | |
3 | ||
4 | from .common import InfoExtractor | |
a3ed14cb | 5 | from ..compat import compat_str |
e2b4808f S |
6 | from ..utils import ( |
7 | ExtractorError, | |
8 | int_or_none, | |
9 | try_get, | |
10 | unified_timestamp, | |
11 | ) | |
daaaf5f5 AC |
12 | |
13 | ||
14 | class VootIE(InfoExtractor): | |
a3ed14cb A |
15 | _VALID_URL = r'''(?x) |
16 | (?: | |
17 | voot:| | |
73f035e1 | 18 | https?://(?:www\.)?voot\.com/? |
a3ed14cb A |
19 | (?: |
20 | movies/[^/]+/| | |
21 | (?:shows|kids)/(?:[^/]+/){4} | |
22 | ) | |
23 | ) | |
24 | (?P<id>\d{3,}) | |
25 | ''' | |
e2b4808f S |
26 | _GEO_COUNTRIES = ['IN'] |
27 | _TESTS = [{ | |
daaaf5f5 AC |
28 | 'url': 'https://www.voot.com/shows/ishq-ka-rang-safed/1/360558/is-this-the-end-of-kamini-/441353', |
29 | 'info_dict': { | |
5c5e60cf | 30 | 'id': '0_8ledb18o', |
daaaf5f5 AC |
31 | 'ext': 'mp4', |
32 | 'title': 'Ishq Ka Rang Safed - Season 01 - Episode 340', | |
e2b4808f | 33 | 'description': 'md5:06291fbbbc4dcbe21235c40c262507c1', |
e2b4808f S |
34 | 'timestamp': 1472162937, |
35 | 'upload_date': '20160825', | |
e2b4808f S |
36 | 'series': 'Ishq Ka Rang Safed', |
37 | 'season_number': 1, | |
38 | 'episode': 'Is this the end of Kamini?', | |
39 | 'episode_number': 340, | |
40 | 'view_count': int, | |
41 | 'like_count': int, | |
42 | }, | |
43 | 'params': { | |
44 | 'skip_download': True, | |
45 | }, | |
46 | 'expected_warnings': ['Failed to download m3u8 information'], | |
47 | }, { | |
48 | 'url': 'https://www.voot.com/kids/characters/mighty-cat-masked-niyander-e-/400478/school-bag-disappears/440925', | |
49 | 'only_matching': True, | |
50 | }, { | |
51 | 'url': 'https://www.voot.com/movies/pandavas-5/424627', | |
52 | 'only_matching': True, | |
53 | }] | |
daaaf5f5 AC |
54 | |
55 | def _real_extract(self, url): | |
56 | video_id = self._match_id(url) | |
e2b4808f S |
57 | media_info = self._download_json( |
58 | 'https://wapi.voot.com/ws/ott/getMediaInfo.json', video_id, | |
59 | query={ | |
60 | 'platform': 'Web', | |
61 | 'pId': 2, | |
62 | 'mediaId': video_id, | |
63 | }) | |
64 | ||
65 | status_code = try_get(media_info, lambda x: x['status']['code'], int) | |
66 | if status_code != 0: | |
67 | raise ExtractorError(media_info['status']['message'], expected=True) | |
68 | ||
69 | media = media_info['assets'] | |
daaaf5f5 | 70 | |
5c5e60cf | 71 | entry_id = media['EntryId'] |
e2b4808f | 72 | title = media['MediaName'] |
1c4804ef | 73 | formats = self._extract_m3u8_formats( |
5c5e60cf | 74 | 'https://cdnapisec.kaltura.com/p/1982551/playManifest/pt/https/f/applehttp/t/web/e/' + entry_id, |
23f511f5 RA |
75 | video_id, 'mp4', m3u8_id='hls') |
76 | self._sort_formats(formats) | |
daaaf5f5 | 77 | |
e2b4808f | 78 | description, series, season_number, episode, episode_number = [None] * 5 |
daaaf5f5 | 79 | |
e2b4808f S |
80 | for meta in try_get(media, lambda x: x['Metas'], list) or []: |
81 | key, value = meta.get('Key'), meta.get('Value') | |
82 | if not key or not value: | |
83 | continue | |
84 | if key == 'ContentSynopsis': | |
85 | description = value | |
86 | elif key == 'RefSeriesTitle': | |
87 | series = value | |
88 | elif key == 'RefSeriesSeason': | |
89 | season_number = int_or_none(value) | |
90 | elif key == 'EpisodeMainTitle': | |
91 | episode = value | |
92 | elif key == 'EpisodeNo': | |
93 | episode_number = int_or_none(value) | |
daaaf5f5 | 94 | return { |
5c5e60cf S |
95 | 'extractor_key': 'Kaltura', |
96 | 'id': entry_id, | |
e2b4808f S |
97 | 'title': title, |
98 | 'description': description, | |
99 | 'series': series, | |
100 | 'season_number': season_number, | |
101 | 'episode': episode, | |
102 | 'episode_number': episode_number, | |
103 | 'timestamp': unified_timestamp(media.get('CreationDate')), | |
104 | 'duration': int_or_none(media.get('Duration')), | |
105 | 'view_count': int_or_none(media.get('ViewCounter')), | |
106 | 'like_count': int_or_none(media.get('like_counter')), | |
1c4804ef | 107 | 'formats': formats, |
daaaf5f5 | 108 | } |
a3ed14cb A |
109 | |
110 | ||
111 | class VootSeriesIE(InfoExtractor): | |
112 | _VALID_URL = r'https?://(?:www\.)?voot\.com/shows/[^/]+/(?P<id>\d{3,})' | |
113 | _TESTS = [{ | |
114 | 'url': 'https://www.voot.com/shows/chakravartin-ashoka-samrat/100002', | |
115 | 'playlist_mincount': 442, | |
116 | 'info_dict': { | |
117 | 'id': '100002', | |
118 | }, | |
119 | }, { | |
120 | 'url': 'https://www.voot.com/shows/ishq-ka-rang-safed/100003', | |
121 | 'playlist_mincount': 341, | |
122 | 'info_dict': { | |
123 | 'id': '100003', | |
124 | }, | |
125 | }] | |
126 | _SHOW_API = 'https://psapi.voot.com/media/voot/v1/voot-web/content/generic/season-by-show?sort=season%3Aasc&id={}&responseType=common' | |
127 | _SEASON_API = 'https://psapi.voot.com/media/voot/v1/voot-web/content/generic/series-wise-episode?sort=episode%3Aasc&id={}&responseType=common&page={:d}' | |
128 | ||
129 | def _entries(self, show_id): | |
130 | show_json = self._download_json(self._SHOW_API.format(show_id), video_id=show_id) | |
131 | for season in show_json.get('result', []): | |
132 | page_num = 1 | |
133 | season_id = try_get(season, lambda x: x['id'], compat_str) | |
134 | season_json = self._download_json(self._SEASON_API.format(season_id, page_num), | |
135 | video_id=season_id, | |
136 | note='Downloading JSON metadata page %d' % page_num) | |
137 | episodes_json = season_json.get('result', []) | |
138 | while episodes_json: | |
139 | page_num += 1 | |
140 | for episode in episodes_json: | |
141 | video_id = episode.get('id') | |
142 | yield self.url_result( | |
143 | 'voot:%s' % video_id, ie=VootIE.ie_key(), video_id=video_id) | |
144 | episodes_json = self._download_json(self._SEASON_API.format(season_id, page_num), | |
145 | video_id=season_id, | |
146 | note='Downloading JSON metadata page %d' % page_num)['result'] | |
147 | ||
148 | def _real_extract(self, url): | |
149 | show_id = self._match_id(url) | |
150 | return self.playlist_result(self._entries(show_id), playlist_id=show_id) |