2 from __future__ 
import unicode_literals
 
   6 from .theplatform 
import ThePlatformIE
 
  14 from ..compat 
import ( 
  19 class AENetworksBaseIE(ThePlatformIE
): 
  20     _THEPLATFORM_KEY 
= 'crazyjava' 
  21     _THEPLATFORM_SECRET 
= 's3cr3t' 
  23     def _extract_aen_smil(self
, smil_url
, video_id
, auth
=None): 
  24         query 
= {'mbr': 'true'} 
  28             'assetTypes': 'high_video_ak', 
  29             'switch': 'hls_high_ak' 
  31             'assetTypes': 'high_video_s3' 
  33             'assetTypes': 'high_video_s3', 
  34             'switch': 'hls_ingest_fastly' 
  39         for q 
in TP_SMIL_QUERY
: 
  41             m_url 
= update_url_query(smil_url
, q
) 
  42             m_url 
= self
._sign
_url
(m_url
, self
._THEPLATFORM
_KEY
, self
._THEPLATFORM
_SECRET
) 
  44                 tp_formats
, tp_subtitles 
= self
._extract
_theplatform
_smil
( 
  45                     m_url
, video_id
, 'Downloading %s SMIL data' % (q
.get('switch') or q
['assetTypes'])) 
  46             except ExtractorError 
as e
: 
  49             formats
.extend(tp_formats
) 
  50             subtitles 
= self
._merge
_subtitles
(subtitles
, tp_subtitles
) 
  51         if last_e 
and not formats
: 
  53         self
._sort
_formats
(formats
) 
  57             'subtitles': subtitles
, 
  61 class AENetworksIE(AENetworksBaseIE
): 
  62     IE_NAME 
= 'aenetworks' 
  63     IE_DESC 
= 'A+E Networks: A&E, Lifetime, History.com, FYI Network and History Vault' 
  68                             (?:history(?:vault)?|aetv|mylifetime|lifetimemovieclub)\.com| 
  72                             shows/(?P<show_path>[^/]+(?:/[^/]+){0,2})| 
  73                             movies/(?P<movie_display_id>[^/]+)(?:/full-movie)?| 
  74                             specials/(?P<special_display_id>[^/]+)/(?:full-special|preview-)| 
  75                             collections/[^/]+/(?P<collection_display_id>[^/]+) 
  79         'url': 'http://www.history.com/shows/mountain-men/season-1/episode-1', 
  83             'title': 'Winter is Coming', 
  84             'description': 'md5:641f424b7a19d8e24f26dea22cf59d74', 
  85             'timestamp': 1338306241, 
  86             'upload_date': '20120529', 
  87             'uploader': 'AENE-NEW', 
  91             'skip_download': True, 
  93         'add_ie': ['ThePlatform'], 
  95         'url': 'http://www.history.com/shows/ancient-aliens/season-1', 
  99         'playlist_mincount': 5, 
 101         'url': 'http://www.mylifetime.com/shows/atlanta-plastic', 
 104             'title': 'Atlanta Plastic', 
 106         'playlist_mincount': 2, 
 108         'url': 'http://www.aetv.com/shows/duck-dynasty/season-9/episode-1', 
 109         'only_matching': True 
 111         'url': 'http://www.fyi.tv/shows/tiny-house-nation/season-1/episode-8', 
 112         'only_matching': True 
 114         'url': 'http://www.mylifetime.com/shows/project-runway-junior/season-1/episode-6', 
 115         'only_matching': True 
 117         'url': 'http://www.mylifetime.com/movies/center-stage-on-pointe/full-movie', 
 118         'only_matching': True 
 120         'url': 'https://www.lifetimemovieclub.com/movies/a-killer-among-us', 
 121         'only_matching': True 
 123         'url': 'http://www.history.com/specials/sniper-into-the-kill-zone/full-special', 
 124         'only_matching': True 
 126         'url': 'https://www.historyvault.com/collections/america-the-story-of-us/westward', 
 127         'only_matching': True 
 129         'url': 'https://www.aetv.com/specials/hunting-jonbenets-killer-the-untold-story/preview-hunting-jonbenets-killer-the-untold-story', 
 130         'only_matching': True 
 132     _DOMAIN_TO_REQUESTOR_ID 
= { 
 133         'history.com': 'HISTORY', 
 135         'mylifetime.com': 'LIFETIME', 
 136         'lifetimemovieclub.com': 'LIFETIMEMOVIECLUB', 
 140     def _real_extract(self
, url
): 
 141         domain
, show_path
, movie_display_id
, special_display_id
, collection_display_id 
= re
.match(self
._VALID
_URL
, url
).groups() 
 142         display_id 
= show_path 
or movie_display_id 
or special_display_id 
or collection_display_id
 
 143         webpage 
= self
._download
_webpage
(url
, display_id
, headers
=self
.geo_verification_headers()) 
 145             url_parts 
= show_path
.split('/') 
 146             url_parts_len 
= len(url_parts
) 
 147             if url_parts_len 
== 1: 
 149                 for season_url_path 
in re
.findall(r
'(?s)<li[^>]+data-href="(/shows/%s/season-\d+)"' % url_parts
[0], webpage
): 
 150                     entries
.append(self
.url_result( 
 151                         compat_urlparse
.urljoin(url
, season_url_path
), 'AENetworks')) 
 153                     return self
.playlist_result( 
 154                         entries
, self
._html
_search
_meta
('aetn:SeriesId', webpage
), 
 155                         self
._html
_search
_meta
('aetn:SeriesTitle', webpage
)) 
 159             if url_parts_len 
== 2: 
 161                 for episode_item 
in re
.findall(r
'(?s)<[^>]+class="[^"]*(?:episode|program)-item[^"]*"[^>]*>', webpage
): 
 162                     episode_attributes 
= extract_attributes(episode_item
) 
 163                     episode_url 
= compat_urlparse
.urljoin( 
 164                         url
, episode_attributes
['data-canonical']) 
 165                     entries
.append(self
.url_result( 
 166                         episode_url
, 'AENetworks', 
 167                         episode_attributes
.get('data-videoid') or episode_attributes
.get('data-video-id'))) 
 168                 return self
.playlist_result( 
 169                     entries
, self
._html
_search
_meta
('aetn:SeasonId', webpage
)) 
 171         video_id 
= self
._html
_search
_meta
('aetn:VideoID', webpage
) 
 172         media_url 
= self
._search
_regex
( 
 173             [r
"media_url\s*=\s*'(?P<url>[^']+)'", 
 174              r
'data-media-url=(?P<url>(?:https?:)?//[^\s>]+)', 
 175              r
'data-media-url=(["\'])(?P
<url
>(?
:(?
!\
1).)+?
)\
1'], 
 176             webpage, 'video url
', group='url
') 
 177         theplatform_metadata = self._download_theplatform_metadata(self._search_regex( 
 178             r'https?
://link\
.theplatform\
.com
/s
/([^?
]+)', media_url, 'theplatform_path
'), video_id) 
 179         info = self._parse_theplatform_metadata(theplatform_metadata) 
 181         if theplatform_metadata.get('AETN$isBehindWall
'): 
 182             requestor_id = self._DOMAIN_TO_REQUESTOR_ID[domain] 
 183             resource = self._get_mvpd_resource( 
 184                 requestor_id, theplatform_metadata['title
'], 
 185                 theplatform_metadata.get('AETN$PPL_pplProgramId
') or theplatform_metadata.get('AETN$PPL_pplProgramId_OLD
'), 
 186                 theplatform_metadata['ratings
'][0]['rating
']) 
 187             auth = self._extract_mvpd_auth( 
 188                 url, video_id, requestor_id, resource) 
 189         info.update(self._search_json_ld(webpage, video_id, fatal=False)) 
 190         info.update(self._extract_aen_smil(media_url, video_id, auth)) 
 194 class HistoryTopicIE(AENetworksBaseIE): 
 195     IE_NAME = 'history
:topic
' 
 196     IE_DESC = 'History
.com Topic
' 
 197     _VALID_URL = r'https?
://(?
:www\
.)?history\
.com
/topics
/[^
/]+/(?P
<id>[\w
+-]+?
)-video
' 
 199         'url
': 'https
://www
.history
.com
/topics
/valentines
-day
/history
-of
-valentines
-day
-video
', 
 203             'title
': "History of Valentine’s Day", 
 204             'description
': 'md5
:7b57ea4829b391995b405fa60bd7b5f7
', 
 205             'timestamp
': 1375819729, 
 206             'upload_date
': '20130806', 
 210             'skip_download
': True, 
 212         'add_ie
': ['ThePlatform
'], 
 215     def theplatform_url_result(self, theplatform_url, video_id, query): 
 217             '_type
': 'url_transparent
', 
 220                 update_url_query(theplatform_url, query), 
 223                         'key
': self._THEPLATFORM_KEY, 
 224                         'secret
': self._THEPLATFORM_SECRET, 
 226                     'force_smil_url
': True 
 228             'ie_key
': 'ThePlatform
', 
 231     def _real_extract(self, url): 
 232         display_id = self._match_id(url) 
 233         webpage = self._download_webpage(url, display_id) 
 234         video_id = self._search_regex( 
 235             r'<phoenix
-iframe
[^
>]+src
="[^"]+\btpid
=(\d
+)', webpage, 'tpid
') 
 236         result = self._download_json( 
 237             'https
://feeds
.video
.aetnd
.com
/api
/v2
/history
/videos
', 
 238             video_id, query={'filter[id]': video_id})['results
'][0] 
 239         title = result['title
'] 
 240         info = self._extract_aen_smil(result['publicUrl
'], video_id) 
 243             'description
': result.get('description
'), 
 244             'duration
': int_or_none(result.get('duration
')), 
 245             'timestamp
': int_or_none(result.get('added
'), 1000),