]>
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 NJ |
51 | }) |
52 | self._sort_formats(formats) | |
53 | ||
54 | return { | |
bd3f9eca | 55 | 'id': content_id, |
39ca3b5c | 56 | 'title': title, |
2c25a2bd NJ |
57 | 'formats': formats, |
58 | 'thumbnail': thumbnail, | |
59 | 'location': location, | |
60 | 'is_live': is_live, | |
61 | } | |
bd3f9eca | 62 | |
63 | ||
64 | class TuneInClipIE(TuneInBaseIE): | |
65 | IE_NAME = 'tunein:clip' | |
66 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/station/.*?audioClipId\=(?P<id>\d+)' | |
67 | _API_URL_QUERY = '?tuneType=AudioClip&audioclipId=%s' | |
68 | ||
027e2312 S |
69 | _TESTS = [{ |
70 | 'url': 'http://tunein.com/station/?stationId=246119&audioClipId=816', | |
71 | 'md5': '99f00d772db70efc804385c6b47f4e77', | |
72 | 'info_dict': { | |
73 | 'id': '816', | |
74 | 'title': '32m', | |
75 | 'ext': 'mp3', | |
bd3f9eca | 76 | }, |
027e2312 | 77 | }] |
bd3f9eca | 78 | |
79 | ||
80 | class TuneInStationIE(TuneInBaseIE): | |
81 | IE_NAME = 'tunein:station' | |
027e2312 | 82 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/(?:radio/.*?-s|station/.*?StationId=|embed/player/s)(?P<id>\d+)' |
bfd973ec | 83 | _EMBED_REGEX = [r'<iframe[^>]+src=["\'](?P<url>(?:https?://)?tunein\.com/embed/player/[pst]\d+)'] |
bd3f9eca | 84 | _API_URL_QUERY = '?tuneType=Station&stationId=%s' |
85 | ||
86 | @classmethod | |
87 | def suitable(cls, url): | |
88 | return False if TuneInClipIE.suitable(url) else super(TuneInStationIE, cls).suitable(url) | |
89 | ||
027e2312 S |
90 | _TESTS = [{ |
91 | 'url': 'http://tunein.com/radio/Jazz24-885-s34682/', | |
92 | 'info_dict': { | |
93 | 'id': '34682', | |
94 | 'title': 'Jazz 24 on 88.5 Jazz24 - KPLU-HD2', | |
95 | 'ext': 'mp3', | |
96 | 'location': 'Tacoma, WA', | |
97 | }, | |
98 | 'params': { | |
99 | 'skip_download': True, # live stream | |
bd3f9eca | 100 | }, |
027e2312 S |
101 | }, { |
102 | 'url': 'http://tunein.com/embed/player/s6404/', | |
103 | 'only_matching': True, | |
104 | }] | |
bd3f9eca | 105 | |
106 | ||
107 | class TuneInProgramIE(TuneInBaseIE): | |
108 | IE_NAME = 'tunein:program' | |
027e2312 | 109 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/(?:radio/.*?-p|program/.*?ProgramId=|embed/player/p)(?P<id>\d+)' |
bd3f9eca | 110 | _API_URL_QUERY = '?tuneType=Program&programId=%s' |
111 | ||
027e2312 S |
112 | _TESTS = [{ |
113 | 'url': 'http://tunein.com/radio/Jazz-24-p2506/', | |
114 | 'info_dict': { | |
115 | 'id': '2506', | |
116 | 'title': 'Jazz 24 on 91.3 WUKY-HD3', | |
117 | 'ext': 'mp3', | |
118 | 'location': 'Lexington, KY', | |
bd3f9eca | 119 | }, |
027e2312 S |
120 | 'params': { |
121 | 'skip_download': True, # live stream | |
122 | }, | |
123 | }, { | |
124 | 'url': 'http://tunein.com/embed/player/p191660/', | |
125 | 'only_matching': True, | |
126 | }] | |
bd3f9eca | 127 | |
128 | ||
129 | class TuneInTopicIE(TuneInBaseIE): | |
130 | IE_NAME = 'tunein:topic' | |
027e2312 | 131 | _VALID_URL = r'https?://(?:www\.)?tunein\.com/(?:topic/.*?TopicId=|embed/player/t)(?P<id>\d+)' |
bd3f9eca | 132 | _API_URL_QUERY = '?tuneType=Topic&topicId=%s' |
133 | ||
027e2312 S |
134 | _TESTS = [{ |
135 | 'url': 'http://tunein.com/topic/?TopicId=101830576', | |
136 | 'md5': 'c31a39e6f988d188252eae7af0ef09c9', | |
137 | 'info_dict': { | |
138 | 'id': '101830576', | |
139 | 'title': 'Votez pour moi du 29 octobre 2015 (29/10/15)', | |
140 | 'ext': 'mp3', | |
141 | 'location': 'Belgium', | |
bd3f9eca | 142 | }, |
027e2312 S |
143 | }, { |
144 | 'url': 'http://tunein.com/embed/player/t101830576/', | |
145 | 'only_matching': True, | |
146 | }] | |
bd3f9eca | 147 | |
148 | ||
149 | class TuneInShortenerIE(InfoExtractor): | |
150 | IE_NAME = 'tunein:shortener' | |
151 | IE_DESC = False # Do not list | |
152 | _VALID_URL = r'https?://tun\.in/(?P<id>[A-Za-z0-9]+)' | |
153 | ||
154 | _TEST = { | |
155 | # test redirection | |
156 | 'url': 'http://tun.in/ser7s', | |
157 | 'info_dict': { | |
158 | 'id': '34682', | |
159 | 'title': 'Jazz 24 on 88.5 Jazz24 - KPLU-HD2', | |
160 | 'ext': 'mp3', | |
161 | 'location': 'Tacoma, WA', | |
162 | }, | |
163 | 'params': { | |
164 | 'skip_download': True, # live stream | |
165 | }, | |
166 | } | |
167 | ||
168 | def _real_extract(self, url): | |
169 | redirect_id = self._match_id(url) | |
170 | # The server doesn't support HEAD requests | |
171 | urlh = self._request_webpage( | |
172 | url, redirect_id, note='Downloading redirect page') | |
173 | url = urlh.geturl() | |
174 | self.to_screen('Following redirect: %s' % url) | |
175 | return self.url_result(url) |