5 from .common
import InfoExtractor
12 class WPPilotBaseIE(InfoExtractor
):
13 _VIDEO_URL
= 'https://pilot.wp.pl/api/v1/channel/%s'
14 _VIDEO_GUEST_URL
= 'https://pilot.wp.pl/api/v1/guest/channel/%s'
17 'Content-Type': 'application/json; charset=UTF-8',
18 'Referer': 'https://pilot.wp.pl/tv/',
21 def _get_channel_list(self
, cache
=True):
23 cache_res
= self
.cache
.load('wppilot', 'channel-list')
25 return cache_res
, True
26 webpage
= self
._download
_webpage
('https://pilot.wp.pl/tv/', None, 'Downloading webpage')
27 page_data_base_url
= self
._search
_regex
(
28 r
'<script src="(https://wp-pilot-gatsby\.wpcdn\.pl/v[\d.-]+/desktop)',
29 webpage
, 'gatsby build version') + '/page-data'
30 page_data
= self
._download
_json
(f
'{page_data_base_url}/tv/page-data.json', None, 'Downloading page data')
31 for qhash
in page_data
['staticQueryHashes']:
32 qhash_content
= self
._download
_json
(
33 f
'{page_data_base_url}/sq/d/{qhash}.json', None,
34 'Searching for channel list')
35 channel_list
= try_get(qhash_content
, lambda x
: x
['data']['allChannels']['nodes'])
36 if channel_list
is None:
38 self
.cache
.store('wppilot', 'channel-list', channel_list
)
39 return channel_list
, False
40 raise ExtractorError('Unable to find the channel list')
42 def _parse_channel(self
, chan
):
44 'id': str(chan
['id']),
45 'title': chan
['name'],
50 } for key
in ('thumbnail', 'thumbnail_mobile', 'icon') if chan
.get(key
)],
54 class WPPilotIE(WPPilotBaseIE
):
55 _VALID_URL
= r
'(?:https?://pilot\.wp\.pl/tv/?#|wppilot:)(?P<id>[a-z\d-]+)'
59 'url': 'https://pilot.wp.pl/tv/#telewizja-wp-hd',
63 'title': 'Telewizja WP HD',
66 'format': 'bestvideo',
70 'url': 'https://pilot.wp.pl/tv/#radio-nowy-swiat',
74 'title': 'Radio Nowy Świat',
77 'format': 'bestaudio',
81 'only_matching': True,
84 def _get_channel(self
, id_or_slug
):
85 video_list
, is_cached
= self
._get
_channel
_list
(cache
=True)
86 key
= 'id' if re
.match(r
'^\d+$', id_or_slug
) else 'slug'
87 for video
in video_list
:
88 if video
.get(key
) == id_or_slug
:
89 return self
._parse
_channel
(video
)
90 # if cached channel not found, download and retry
92 video_list
, _
= self
._get
_channel
_list
(cache
=False)
93 for video
in video_list
:
94 if video
.get(key
) == id_or_slug
:
95 return self
._parse
_channel
(video
)
96 raise ExtractorError('Channel not found')
98 def _real_extract(self
, url
):
99 video_id
= self
._match
_id
(url
)
101 channel
= self
._get
_channel
(video_id
)
102 video_id
= str(channel
['id'])
104 is_authorized
= next((c
for c
in self
.cookiejar
if c
.name
== 'netviapisessid'), None)
105 # cookies starting with "g:" are assigned to guests
106 is_authorized
= is_authorized
is not None and not is_authorized
.value
.startswith('g:')
108 video
= self
._download
_json
(
109 (self
._VIDEO
_URL
if is_authorized
else self
._VIDEO
_GUEST
_URL
) % video_id
,
111 'device_type': 'web',
112 }, headers
=self
._HEADERS
_WEB
,
113 expected_status
=(200, 422))
115 stream_token
= try_get(video
, lambda x
: x
['_meta']['error']['info']['stream_token'])
117 close
= self
._download
_json
(
118 'https://pilot.wp.pl/api/v1/channels/close', video_id
,
119 'Invalidating previous stream session', headers
=self
._HEADERS
_WEB
,
121 'channelId': video_id
,
124 if try_get(close
, lambda x
: x
['data']['status']) == 'ok':
125 return self
.url_result(url
, ie
=WPPilotIE
.ie_key())
129 for fmt
in video
['data']['stream_channel']['streams']:
130 # live DASH does not work for now
131 # if fmt['type'] == 'dash@live:abr':
133 # self._extract_mpd_formats(
134 # random.choice(fmt['url']), video_id))
135 if fmt
['type'] == 'hls@live:abr':
137 self
._extract
_m
3u8_formats
(
138 random
.choice(fmt
['url']),
139 video_id
, live
=True))
141 channel
['formats'] = formats
145 class WPPilotChannelsIE(WPPilotBaseIE
):
146 _VALID_URL
= r
'(?:https?://pilot\.wp\.pl/(?:tv/?)?(?:\?[^#]*)?#?|wppilot:)$'
147 IE_NAME
= 'wppilot:channels'
155 'playlist_mincount': 100,
157 'url': 'https://pilot.wp.pl/',
158 'only_matching': True,
162 channel_list
, _
= self
._get
_channel
_list
()
163 for chan
in channel_list
:
164 entry
= self
._parse
_channel
(chan
)
166 '_type': 'url_transparent',
167 'url': f
'wppilot:{chan["id"]}',
168 'ie_key': WPPilotIE
.ie_key(),
172 def _real_extract(self
, url
):
173 return self
.playlist_result(self
._entries
(), 'wppilot', 'WP Pilot')