2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
9 compat_urllib_parse_urlparse
,
20 class CiscoLiveBaseIE(InfoExtractor
):
21 # These appear to be constant across all Cisco Live presentations
22 # and are not tied to any user session or event
23 RAINFOCUS_API_URL
= 'https://events.rainfocus.com/api/%s'
24 RAINFOCUS_API_PROFILE_ID
= 'Na3vqYdAlJFSxhYTYQGuMbpafMqftalz'
25 RAINFOCUS_WIDGET_ID
= 'n6l4Lo05R8fiy3RpUBm447dZN8uNWoye'
26 BRIGHTCOVE_URL_TEMPLATE
= 'http://players.brightcove.net/5647924234001/SyK2FdqjM_default/index.html?videoId=%s'
29 'Origin': 'https://ciscolive.cisco.com',
30 'rfApiProfileId': RAINFOCUS_API_PROFILE_ID
,
31 'rfWidgetId': RAINFOCUS_WIDGET_ID
,
34 def _call_api(self
, ep
, rf_id
, query
, referrer
, note
=None):
35 headers
= self
.HEADERS
.copy()
36 headers
['Referer'] = referrer
37 return self
._download
_json
(
38 self
.RAINFOCUS_API_URL
% ep
, rf_id
, note
=note
,
39 data
=urlencode_postdata(query
), headers
=headers
)
41 def _parse_rf_item(self
, rf_item
):
42 event_name
= rf_item
.get('eventName')
43 title
= rf_item
['title']
44 description
= clean_html(rf_item
.get('abstract'))
45 presenter_name
= try_get(rf_item
, lambda x
: x
['participants'][0]['fullName'])
46 bc_id
= rf_item
['videos'][0]['url']
47 bc_url
= self
.BRIGHTCOVE_URL_TEMPLATE
% bc_id
48 duration
= float_or_none(try_get(rf_item
, lambda x
: x
['times'][0]['length']))
49 location
= try_get(rf_item
, lambda x
: x
['times'][0]['room'])
52 duration
= duration
* 60
55 '_type': 'url_transparent',
57 'ie_key': 'BrightcoveNew',
59 'description': description
,
61 'creator': presenter_name
,
67 class CiscoLiveSessionIE(CiscoLiveBaseIE
):
68 _VALID_URL
= r
'https?://ciscolive\.cisco\.com/on-demand-library/\??[^#]*#/session/(?P<id>[^/?&]+)'
70 'url': 'https://ciscolive.cisco.com/on-demand-library/?#/session/1423353499155001FoSs',
71 'md5': 'c98acf395ed9c9f766941c70f5352e22',
73 'id': '5803694304001',
75 'title': '13 Smart Automations to Monitor Your Cisco IOS Network',
76 'description': 'md5:ec4a436019e09a918dec17714803f7cc',
77 'timestamp': 1530305395,
78 'upload_date': '20180629',
79 'uploader_id': '5647924234001',
80 'location': '16B Mezz.',
84 def _real_extract(self
, url
):
85 rf_id
= self
._match
_id
(url
)
86 rf_result
= self
._call
_api
('session', rf_id
, {'id': rf_id
}, url
)
87 return self
._parse
_rf
_item
(rf_result
['items'][0])
90 class CiscoLiveSearchIE(CiscoLiveBaseIE
):
91 _VALID_URL
= r
'https?://ciscolive\.cisco\.com/on-demand-library/'
93 'url': 'https://ciscolive.cisco.com/on-demand-library/?search.event=ciscoliveus2018&search.technicallevel=scpsSkillLevel_aintroductory&search.focus=scpsSessionFocus_designAndDeployment#/',
95 'title': 'Search query',
99 'url': 'https://ciscolive.cisco.com/on-demand-library/?search.technology=scpsTechnology_applicationDevelopment&search.technology=scpsTechnology_ipv6&search.focus=scpsSessionFocus_troubleshootingTroubleshooting#/',
100 'only_matching': True,
104 def suitable(cls
, url
):
105 return False if CiscoLiveSessionIE
.suitable(url
) else super(CiscoLiveSearchIE
, cls
).suitable(url
)
108 def _check_bc_id_exists(rf_item
):
109 return int_or_none(try_get(rf_item
, lambda x
: x
['videos'][0]['url'])) is not None
111 def _entries(self
, query
, url
):
114 for page_num
in itertools
.count(1):
115 results
= self
._call
_api
(
116 'search', None, query
, url
,
117 'Downloading search JSON page %d' % page_num
)
118 sl
= try_get(results
, lambda x
: x
['sectionList'][0], dict)
121 items
= results
.get('items')
122 if not items
or not isinstance(items
, list):
125 if not isinstance(item
, dict):
127 if not self
._check
_bc
_id
_exists
(item
):
129 yield self
._parse
_rf
_item
(item
)
130 size
= int_or_none(results
.get('size'))
133 total
= int_or_none(results
.get('total'))
134 if total
is not None and query
['from'] + query
['size'] > total
:
136 query
['from'] += query
['size']
138 def _real_extract(self
, url
):
139 query
= compat_parse_qs(compat_urllib_parse_urlparse(url
).query
)
140 query
['type'] = 'session'
141 return self
.playlist_result(
142 self
._entries
(query
, url
), playlist_title
='Search query')