2 from __future__ 
import unicode_literals
 
   6 from .common 
import InfoExtractor
 
   9     compat_urllib_parse_urlparse
, 
  23 class SVTBaseIE(InfoExtractor
): 
  24     _GEO_COUNTRIES 
= ['SE'] 
  26     def _extract_video(self
, video_info
, video_id
): 
  27         is_live 
= dict_get(video_info
, ('live', 'simulcast'), default
=False) 
  28         m3u8_protocol 
= 'm3u8' if is_live 
else 'm3u8_native' 
  30         for vr 
in video_info
['videoReferences']: 
  31             player_type 
= vr
.get('playerType') or vr
.get('format') 
  33             ext 
= determine_ext(vurl
) 
  35                 formats
.extend(self
._extract
_m
3u8_formats
( 
  37                     ext
='mp4', entry_protocol
=m3u8_protocol
, 
  38                     m3u8_id
=player_type
, fatal
=False)) 
  40                 formats
.extend(self
._extract
_f
4m
_formats
( 
  41                     vurl 
+ '?hdcore=3.3.0', video_id
, 
  42                     f4m_id
=player_type
, fatal
=False)) 
  44                 if player_type 
== 'dashhbbtv': 
  45                     formats
.extend(self
._extract
_mpd
_formats
( 
  46                         vurl
, video_id
, mpd_id
=player_type
, fatal
=False)) 
  49                     'format_id': player_type
, 
  52         if not formats 
and video_info
.get('rights', {}).get('geoBlockedSweden'): 
  53             self
.raise_geo_restricted( 
  54                 'This video is only available in Sweden', 
  55                 countries
=self
._GEO
_COUNTRIES
) 
  56         self
._sort
_formats
(formats
) 
  59         subtitle_references 
= dict_get(video_info
, ('subtitles', 'subtitleReferences')) 
  60         if isinstance(subtitle_references
, list): 
  61             for sr 
in subtitle_references
: 
  62                 subtitle_url 
= sr
.get('url') 
  63                 subtitle_lang 
= sr
.get('language', 'sv') 
  65                     if determine_ext(subtitle_url
) == 'm3u8': 
  66                         # TODO(yan12125): handle WebVTT in m3u8 manifests 
  69                     subtitles
.setdefault(subtitle_lang
, []).append({'url': subtitle_url
}) 
  71         title 
= video_info
.get('title') 
  73         series 
= video_info
.get('programTitle') 
  74         season_number 
= int_or_none(video_info
.get('season')) 
  75         episode 
= video_info
.get('episodeTitle') 
  76         episode_number 
= int_or_none(video_info
.get('episodeNumber')) 
  78         duration 
= int_or_none(dict_get(video_info
, ('materialLength', 'contentDuration'))) 
  81             video_info
, ('inappropriateForChildren', 'blockedForChildren'), 
  82             skip_false_values
=False) 
  84             age_limit 
= 18 if adult 
else 0 
  90             'subtitles': subtitles
, 
  92             'age_limit': age_limit
, 
  94             'season_number': season_number
, 
  96             'episode_number': episode_number
, 
 101 class SVTIE(SVTBaseIE
): 
 102     _VALID_URL 
= r
'https?://(?:www\.)?svt\.se/wd\?(?:.*?&)?widgetId=(?P<widget_id>\d+)&.*?\barticleId=(?P<id>\d+)' 
 104         'url': 'http://www.svt.se/wd?widgetId=23991§ionId=541&articleId=2900353&type=embed&contextSectionId=123&autostart=false', 
 105         'md5': '33e9a5d8f646523ce0868ecfb0eed77d', 
 109             'title': 'Stjärnorna skojar till det - under SVT-intervjun', 
 116     def _extract_url(webpage
): 
 118             r
'(?:<iframe src|href)="(?P<url>%s[^"]*)"' % SVTIE
._VALID
_URL
, webpage
) 
 120             return mobj
.group('url') 
 122     def _real_extract(self
, url
): 
 123         mobj 
= re
.match(self
._VALID
_URL
, url
) 
 124         widget_id 
= mobj
.group('widget_id') 
 125         article_id 
= mobj
.group('id') 
 127         info 
= self
._download
_json
( 
 128             'http://www.svt.se/wd?widgetId=%s&articleId=%s&format=json&type=embed&output=json' % (widget_id
, article_id
), 
 131         info_dict 
= self
._extract
_video
(info
['video'], article_id
) 
 132         info_dict
['title'] = info
['context']['title'] 
 136 class SVTPlayBaseIE(SVTBaseIE
): 
 137     _SVTPLAY_RE 
= r
'root\s*\[\s*(["\'])_
*svtplay\
1\s
*\
]\s
*=\s
*(?P
<json
>{.+?
})\s
*;\s
*\n' 
 140 class SVTPlayIE(SVTPlayBaseIE): 
 141     IE_DESC = 'SVT Play 
and Öppet arkiv
' 
 142     _VALID_URL = r'''(?x) 
 144                         svt:(?P<svt_id>[^/?#&]+)| 
 145                         https?://(?:www\.)?(?:svtplay|oppetarkiv)\.se/(?:video|klipp|kanaler)/(?P<id>[^/?#&]+) 
 149         'url
': 'http
://www
.svtplay
.se
/video
/5996901/flygplan
-till
-haile
-selassie
/flygplan
-till
-haile
-selassie
-2', 
 150         'md5
': '2b6704fe4a28801e1a098bbf3c5ac611
', 
 154             'title
': 'Flygplan till Haile Selassie
', 
 156             'thumbnail
': r're
:^https?
://.*[\
.-]jpg$
', 
 165         # geo restricted to Sweden 
 166         'url
': 'http
://www
.oppetarkiv
.se
/video
/5219710/trollflojten
', 
 167         'only_matching
': True, 
 169         'url
': 'http
://www
.svtplay
.se
/klipp
/9023742/stopptid
-om
-bjorn
-borg
', 
 170         'only_matching
': True, 
 172         'url
': 'https
://www
.svtplay
.se
/kanaler
/svt1
', 
 173         'only_matching
': True, 
 175         'url
': 'svt
:1376446-003A
', 
 176         'only_matching
': True, 
 178         'url
': 'svt
:14278044', 
 179         'only_matching
': True, 
 182     def _adjust_title(self, info): 
 184             info['title
'] = self._live_title(info['title
']) 
 186     def _extract_by_video_id(self, video_id, webpage=None): 
 187         data = self._download_json( 
 188             'https
://api
.svt
.se
/videoplayer
-api
/video
/%s' % video_id, 
 189             video_id, headers=self.geo_verification_headers()) 
 190         info_dict = self._extract_video(data, video_id) 
 191         if not info_dict.get('title
'): 
 192             title = dict_get(info_dict, ('episode
', 'series
')) 
 193             if not title and webpage: 
 195                     r'\s
*\|\s
*.+?$
', '', self._og_search_title(webpage)) 
 198             info_dict['title
'] = title 
 199         self._adjust_title(info_dict) 
 202     def _real_extract(self, url): 
 203         mobj = re.match(self._VALID_URL, url) 
 204         video_id, svt_id = mobj.group('id', 'svt_id
') 
 207             return self._extract_by_video_id(svt_id) 
 209         webpage = self._download_webpage(url, video_id) 
 211         data = self._parse_json( 
 213                 self._SVTPLAY_RE, webpage, 'embedded data
', default='{}', 
 215             video_id, fatal=False) 
 217         thumbnail = self._og_search_thumbnail(webpage) 
 220             video_info = try_get( 
 221                 data, lambda x: x['context
']['dispatcher
']['stores
']['VideoTitlePageStore
']['data
']['video
'], 
 224                 info_dict = self._extract_video(video_info, video_id) 
 226                     'title
': data['context
']['dispatcher
']['stores
']['MetaStore
']['title
'], 
 227                     'thumbnail
': thumbnail, 
 229                 self._adjust_title(info_dict) 
 232         svt_id = self._search_regex( 
 233             r'<video
[^
>]+data
-video
-id=["\']([\da-zA-Z-]+)', 
 236         return self._extract_by_video_id(svt_id, webpage) 
 239 class SVTSeriesIE(SVTPlayBaseIE): 
 240     _VALID_URL = r'https?://(?:www\.)?svtplay\.se/(?P<id>[^/?&#]+)' 
 242         'url': 'https://www.svtplay.se/rederiet', 
 246             'description': 'md5:505d491a58f4fcf6eb418ecab947e69e', 
 248         'playlist_mincount': 318, 
 250         'url': 'https://www.svtplay.se/rederiet?tab=sasong2', 
 252             'id': 'rederiet-sasong2', 
 253             'title': 'Rederiet - Säsong 2', 
 254             'description': 'md5:505d491a58f4fcf6eb418ecab947e69e', 
 256         'playlist_count': 12, 
 260     def suitable(cls, url): 
 261         return False if SVTIE.suitable(url) or SVTPlayIE.suitable(url) else super(SVTSeriesIE, cls).suitable(url) 
 263     def _real_extract(self, url): 
 264         series_id = self._match_id(url) 
 266         qs = compat_parse_qs(compat_urllib_parse_urlparse(url).query) 
 267         season_slug = qs.get('tab', [None])[0] 
 270             series_id += '-%s' % season_slug 
 272         webpage = self._download_webpage( 
 273             url, series_id, 'Downloading series page') 
 275         root = self._parse_json( 
 277                 self._SVTPLAY_RE, webpage, 'content', group='json'), 
 283         for season in root['relatedVideoContent']['relatedVideosAccordion']: 
 284             if not isinstance(season, dict): 
 287                 if season.get('slug') != season_slug: 
 289                 season_name = season.get('name') 
 290             videos = season.get('videos') 
 291             if not isinstance(videos, list): 
 294                 content_url = video.get('contentUrl') 
 295                 if not content_url or not isinstance(content_url, compat_str): 
 299                         urljoin(url, content_url), 
 300                         ie=SVTPlayIE.ie_key(), 
 301                         video_title=video.get('title') 
 304         metadata = root.get('metaData') 
 305         if not isinstance(metadata, dict): 
 308         title = metadata.get('title') 
 309         season_name = season_name or season_slug 
 311         if title and season_name: 
 312             title = '%s - %s' % (title, season_name) 
 316         return self.playlist_result( 
 317             entries, series_id, title, metadata.get('description')) 
 320 class SVTPageIE(InfoExtractor): 
 321     _VALID_URL = r'https?://(?:www\.)?svt\.se/(?:[^/]+/)*(?P<id>[^/?&#]+)' 
 323         'url': 'https://www.svt.se/sport/oseedat/guide-sommartraningen-du-kan-gora-var-och-nar-du-vill', 
 325             'id': 'guide-sommartraningen-du-kan-gora-var-och-nar-du-vill', 
 326             'title': 'GUIDE: Sommarträning du kan göra var och när du vill', 
 330         'url': 'https://www.svt.se/nyheter/inrikes/ebba-busch-thor-kd-har-delvis-ratt-om-no-go-zoner', 
 332             'id': 'ebba-busch-thor-kd-har-delvis-ratt-om-no-go-zoner', 
 333             'title': 'Ebba Busch Thor har bara delvis rätt om ”no-go-zoner”', 
 338         'url': 'http://www.svt.se/sport/ishockey/jagr-tacklar-giroux-under-intervjun', 
 342             'title': 'Stjärnorna skojar till det - under SVT-intervjun', 
 347         'url': 'https://www.svt.se/nyheter/lokalt/vast/svt-testar-tar-nagon-upp-skrapet-1', 
 348         'only_matching': True, 
 350         'url': 'https://www.svt.se/vader/manadskronikor/maj2018', 
 351         'only_matching': True, 
 355     def suitable(cls, url): 
 356         return False if SVTIE.suitable(url) else super(SVTPageIE, cls).suitable(url) 
 358     def _real_extract(self, url): 
 359         playlist_id = self._match_id(url) 
 361         webpage = self._download_webpage(url, playlist_id) 
 365                 'svt:%s' % video_id, ie=SVTPlayIE.ie_key(), video_id=video_id) 
 366             for video_id in orderedSet(re.findall( 
 367                 r'data-video-id=["\'](\d
+)', webpage))] 
 369         title = strip_or_none(self._og_search_title(webpage, default=None)) 
 371         return self.playlist_result(entries, playlist_id, title)