]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/ciscolive.py
2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
17 class CiscoLiveBaseIE(InfoExtractor
):
18 # These appear to be constant across all Cisco Live presentations
19 # and are not tied to any user session or event
20 RAINFOCUS_API_URL
= 'https://events.rainfocus.com/api/%s'
21 RAINFOCUS_API_PROFILE_ID
= 'Na3vqYdAlJFSxhYTYQGuMbpafMqftalz'
22 RAINFOCUS_WIDGET_ID
= 'n6l4Lo05R8fiy3RpUBm447dZN8uNWoye'
23 BRIGHTCOVE_URL_TEMPLATE
= 'http://players.brightcove.net/5647924234001/SyK2FdqjM_default/index.html?videoId=%s'
26 'Origin': 'https://ciscolive.cisco.com',
27 'rfApiProfileId': RAINFOCUS_API_PROFILE_ID
,
28 'rfWidgetId': RAINFOCUS_WIDGET_ID
,
31 def _call_api(self
, ep
, rf_id
, query
, referrer
, note
=None):
32 headers
= self
.HEADERS
.copy()
33 headers
['Referer'] = referrer
34 return self
._download
_json
(
35 self
.RAINFOCUS_API_URL
% ep
, rf_id
, note
=note
,
36 data
=urlencode_postdata(query
), headers
=headers
)
38 def _parse_rf_item(self
, rf_item
):
39 event_name
= rf_item
.get('eventName')
40 title
= rf_item
['title']
41 description
= clean_html(rf_item
.get('abstract'))
42 presenter_name
= try_get(rf_item
, lambda x
: x
['participants'][0]['fullName'])
43 bc_id
= rf_item
['videos'][0]['url']
44 bc_url
= self
.BRIGHTCOVE_URL_TEMPLATE
% bc_id
45 duration
= float_or_none(try_get(rf_item
, lambda x
: x
['times'][0]['length']))
46 location
= try_get(rf_item
, lambda x
: x
['times'][0]['room'])
49 duration
= duration
* 60
52 '_type': 'url_transparent',
54 'ie_key': 'BrightcoveNew',
56 'description': description
,
58 'creator': presenter_name
,
64 class CiscoLiveSessionIE(CiscoLiveBaseIE
):
65 _VALID_URL
= r
'https?://(?:www\.)?ciscolive(?:\.cisco)?\.com/[^#]*#/session/(?P<id>[^/?&]+)'
67 'url': 'https://ciscolive.cisco.com/on-demand-library/?#/session/1423353499155001FoSs',
68 'md5': 'c98acf395ed9c9f766941c70f5352e22',
70 'id': '5803694304001',
72 'title': '13 Smart Automations to Monitor Your Cisco IOS Network',
73 'description': 'md5:ec4a436019e09a918dec17714803f7cc',
74 'timestamp': 1530305395,
75 'upload_date': '20180629',
76 'uploader_id': '5647924234001',
77 'location': '16B Mezz.',
80 'url': 'https://www.ciscolive.com/global/on-demand-library.html?search.event=ciscoliveemea2019#/session/15361595531500013WOU',
81 'only_matching': True,
83 'url': 'https://www.ciscolive.com/global/on-demand-library.html?#/session/1490051371645001kNaS',
84 'only_matching': True,
87 def _real_extract(self
, url
):
88 rf_id
= self
._match
_id
(url
)
89 rf_result
= self
._call
_api
('session', rf_id
, {'id': rf_id}
, url
)
90 return self
._parse
_rf
_item
(rf_result
['items'][0])
93 class CiscoLiveSearchIE(CiscoLiveBaseIE
):
94 _VALID_URL
= r
'https?://(?:www\.)?ciscolive(?:\.cisco)?\.com/(?:global/)?on-demand-library(?:\.html|/)'
96 'url': 'https://ciscolive.cisco.com/on-demand-library/?search.event=ciscoliveus2018&search.technicallevel=scpsSkillLevel_aintroductory&search.focus=scpsSessionFocus_designAndDeployment#/',
98 'title': 'Search query',
102 'url': 'https://ciscolive.cisco.com/on-demand-library/?search.technology=scpsTechnology_applicationDevelopment&search.technology=scpsTechnology_ipv6&search.focus=scpsSessionFocus_troubleshootingTroubleshooting#/',
103 'only_matching': True,
105 'url': 'https://www.ciscolive.com/global/on-demand-library.html?search.technicallevel=scpsSkillLevel_aintroductory&search.event=ciscoliveemea2019&search.technology=scpsTechnology_dataCenter&search.focus=scpsSessionFocus_bestPractices#/',
106 'only_matching': True,
110 def suitable(cls
, url
):
111 return False if CiscoLiveSessionIE
.suitable(url
) else super(CiscoLiveSearchIE
, cls
).suitable(url
)
114 def _check_bc_id_exists(rf_item
):
115 return int_or_none(try_get(rf_item
, lambda x
: x
['videos'][0]['url'])) is not None
117 def _entries(self
, query
, url
):
120 for page_num
in itertools
.count(1):
121 results
= self
._call
_api
(
122 'search', None, query
, url
,
123 'Downloading search JSON page %d' % page_num
)
124 sl
= try_get(results
, lambda x
: x
['sectionList'][0], dict)
127 items
= results
.get('items')
128 if not items
or not isinstance(items
, list):
131 if not isinstance(item
, dict):
133 if not self
._check
_bc
_id
_exists
(item
):
135 yield self
._parse
_rf
_item
(item
)
136 size
= int_or_none(results
.get('size'))
139 total
= int_or_none(results
.get('total'))
140 if total
is not None and query
['from'] + query
['size'] > total
:
142 query
['from'] += query
['size']
144 def _real_extract(self
, url
):
145 query
= parse_qs(url
)
146 query
['type'] = 'session'
147 return self
.playlist_result(
148 self
._entries
(query
, url
), playlist_title
='Search query')