]>
Commit | Line | Data |
---|---|---|
882c6992 | 1 | import re |
2c25a2bd NJ |
2 | |
3 | from .common import InfoExtractor | |
4 | from ..utils import ExtractorError | |
bd3f9eca | 5 | from ..compat import compat_urlparse |
2c25a2bd NJ |
6 | |
7 | ||
bd3f9eca | 8 | class TuneInBaseIE(InfoExtractor): |
9 | _API_BASE_URL = 'http://tunein.com/tuner/tune/' | |
2c25a2bd NJ |
10 | |
11 | def _real_extract(self, url): | |
bd3f9eca | 12 | content_id = self._match_id(url) |
13 | ||
14 | content_info = self._download_json( | |
15 | self._API_BASE_URL + self._API_URL_QUERY % content_id, | |
16 | content_id, note='Downloading JSON metadata') | |
17 | ||
18 | title = content_info['Title'] | |
19 | thumbnail = content_info.get('Logo') | |
20 | location = content_info.get('Location') | |
21 | streams_url = content_info.get('StreamUrl') | |
2c25a2bd | 22 | if not streams_url: |
bd3f9eca | 23 | raise ExtractorError('No downloadable streams found', expected=True) |
24 | if not streams_url.startswith('http://'): | |
25 | streams_url = compat_urlparse.urljoin(url, streams_url) | |
26 | ||
882c6992 S |
27 | streams = self._download_json( |
28 | streams_url, content_id, note='Downloading stream data', | |
29 | transform_source=lambda s: re.sub(r'^\s*\((.*)\);\s*$', r'\1', s))['Streams'] | |
2c25a2bd NJ |
30 | |
31 | is_live = None | |
32 | formats = [] | |
33 | for stream in streams: | |
34 | if stream.get('Type') == 'Live': | |
35 | is_live = True | |
ec3a6a31 PH |
36 | reliability = stream.get('Reliability') |
37 | format_note = ( | |
38 | 'Reliability: %d%%' % reliability | |
39 | if reliability is not None else None) | |
2c25a2bd | 40 | formats.append({ |
ec3a6a31 PH |
41 | 'preference': ( |
42 | 0 if reliability is None or reliability > 90 | |
43 | else 1), | |
2c25a2bd | 44 | 'abr': stream.get('Bandwidth'), |
ec3a6a31 | 45 | 'ext': stream.get('MediaType').lower(), |
2c25a2bd NJ |
46 | 'acodec': stream.get('MediaType'), |
47 | 'vcodec': 'none', | |
48 | 'url': stream.get('Url'), | |
ec3a6a31 PH |
49 | 'source_preference': reliability, |
50 | 'format_note': format_note, | |
2c25a2bd | 51 | }) |
2c25a2bd NJ |
52 | |
53 | return { | |
bd3f9eca | 54 | 'id': content_id, |
39ca3b5c | 55 | 'title': title, |
2c25a2bd NJ |
56 | 'formats': formats, |
57 | 'thumbnail': thumbnail, | |
58 | 'location': location, | |
59 | 'is_live': is_live, | |
60 | } | |
bd3f9eca | 61 | |
62 | ||
63 | class TuneInClipIE(TuneInBaseIE): | |
64 | IE_NAME = 'tunein:clip' | |
65 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/station/.*?audioClipId\=(?P<id>\d+)' | |
66 | _API_URL_QUERY = '?tuneType=AudioClip&audioclipId=%s' | |
67 | ||
027e2312 S |
68 | _TESTS = [{ |
69 | 'url': 'http://tunein.com/station/?stationId=246119&audioClipId=816', | |
70 | 'md5': '99f00d772db70efc804385c6b47f4e77', | |
71 | 'info_dict': { | |
72 | 'id': '816', | |
73 | 'title': '32m', | |
74 | 'ext': 'mp3', | |
bd3f9eca | 75 | }, |
027e2312 | 76 | }] |
bd3f9eca | 77 | |
78 | ||
79 | class TuneInStationIE(TuneInBaseIE): | |
80 | IE_NAME = 'tunein:station' | |
027e2312 | 81 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/(?:radio/.*?-s|station/.*?StationId=|embed/player/s)(?P<id>\d+)' |
bfd973ec | 82 | _EMBED_REGEX = [r'<iframe[^>]+src=["\'](?P<url>(?:https?://)?tunein\.com/embed/player/[pst]\d+)'] |
bd3f9eca | 83 | _API_URL_QUERY = '?tuneType=Station&stationId=%s' |
84 | ||
85 | @classmethod | |
86 | def suitable(cls, url): | |
87 | return False if TuneInClipIE.suitable(url) else super(TuneInStationIE, cls).suitable(url) | |
88 | ||
027e2312 S |
89 | _TESTS = [{ |
90 | 'url': 'http://tunein.com/radio/Jazz24-885-s34682/', | |
91 | 'info_dict': { | |
92 | 'id': '34682', | |
93 | 'title': 'Jazz 24 on 88.5 Jazz24 - KPLU-HD2', | |
94 | 'ext': 'mp3', | |
95 | 'location': 'Tacoma, WA', | |
96 | }, | |
97 | 'params': { | |
98 | 'skip_download': True, # live stream | |
bd3f9eca | 99 | }, |
027e2312 S |
100 | }, { |
101 | 'url': 'http://tunein.com/embed/player/s6404/', | |
102 | 'only_matching': True, | |
103 | }] | |
bd3f9eca | 104 | |
105 | ||
106 | class TuneInProgramIE(TuneInBaseIE): | |
107 | IE_NAME = 'tunein:program' | |
027e2312 | 108 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/(?:radio/.*?-p|program/.*?ProgramId=|embed/player/p)(?P<id>\d+)' |
bd3f9eca | 109 | _API_URL_QUERY = '?tuneType=Program&programId=%s' |
110 | ||
027e2312 S |
111 | _TESTS = [{ |
112 | 'url': 'http://tunein.com/radio/Jazz-24-p2506/', | |
113 | 'info_dict': { | |
114 | 'id': '2506', | |
115 | 'title': 'Jazz 24 on 91.3 WUKY-HD3', | |
116 | 'ext': 'mp3', | |
117 | 'location': 'Lexington, KY', | |
bd3f9eca | 118 | }, |
027e2312 S |
119 | 'params': { |
120 | 'skip_download': True, # live stream | |
121 | }, | |
122 | }, { | |
123 | 'url': 'http://tunein.com/embed/player/p191660/', | |
124 | 'only_matching': True, | |
125 | }] | |
bd3f9eca | 126 | |
127 | ||
128 | class TuneInTopicIE(TuneInBaseIE): | |
129 | IE_NAME = 'tunein:topic' | |
027e2312 | 130 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/(?:topic/.*?TopicId=|embed/player/t)(?P<id>\d+)' |
bd3f9eca | 131 | _API_URL_QUERY = '?tuneType=Topic&topicId=%s' |
132 | ||
027e2312 S |
133 | _TESTS = [{ |
134 | 'url': 'http://tunein.com/topic/?TopicId=101830576', | |
135 | 'md5': 'c31a39e6f988d188252eae7af0ef09c9', | |
136 | 'info_dict': { | |
137 | 'id': '101830576', | |
138 | 'title': 'Votez pour moi du 29 octobre 2015 (29/10/15)', | |
139 | 'ext': 'mp3', | |
140 | 'location': 'Belgium', | |
bd3f9eca | 141 | }, |
027e2312 S |
142 | }, { |
143 | 'url': 'http://tunein.com/embed/player/t101830576/', | |
144 | 'only_matching': True, | |
145 | }] | |
bd3f9eca | 146 | |
147 | ||
148 | class TuneInShortenerIE(InfoExtractor): | |
149 | IE_NAME = 'tunein:shortener' | |
150 | IE_DESC = False # Do not list | |
151 | _VALID_URL = r'https?://tun\.in/(?P<id>[A-Za-z0-9]+)' | |
152 | ||
153 | _TEST = { | |
154 | # test redirection | |
155 | 'url': 'http://tun.in/ser7s', | |
156 | 'info_dict': { | |
157 | 'id': '34682', | |
158 | 'title': 'Jazz 24 on 88.5 Jazz24 - KPLU-HD2', | |
159 | 'ext': 'mp3', | |
160 | 'location': 'Tacoma, WA', | |
161 | }, | |
162 | 'params': { | |
163 | 'skip_download': True, # live stream | |
164 | }, | |
165 | } | |
166 | ||
167 | def _real_extract(self, url): | |
168 | redirect_id = self._match_id(url) | |
169 | # The server doesn't support HEAD requests | |
170 | urlh = self._request_webpage( | |
171 | url, redirect_id, note='Downloading redirect page') | |
172 | url = urlh.geturl() | |
173 | self.to_screen('Following redirect: %s' % url) | |
174 | return self.url_result(url) |