- mobj = re.match(self._VALID_URL, url)
- HEADERS = {
- 'Origin': 'https://ciscolive.cisco.com',
- 'rfApiProfileId': self.RAINFOCUS_APIPROFILEID,
- 'rfWidgetId': self.RAINFOCUS_WIDGETID,
- 'Referer': url,
- }
- # Single session URL (single video)
- if mobj.group('id'):
- rf_id = mobj.group('id')
- request = self.RAINFOCUS_API_URL % 'session'
- data = urlencode_postdata({'id': rf_id})
- rf_result = self._download_json(request, rf_id, data=data, headers=HEADERS)
- rf_item = self._check_bc_id_exists(rf_result['items'][0])
- return self._parse_rf_item(rf_item)
- else:
- # Filter query URL (multiple videos)
- rf_query = compat_parse_qs((compat_urllib_parse_urlparse(url).query))
- rf_query['type'] = 'session'
- rf_query['size'] = 1000
- data = urlencode_postdata(rf_query)
- request = self.RAINFOCUS_API_URL % 'search'
- rf_results = self._download_json(request, 'Filter query', data=data, headers=HEADERS)
- entries = [
- self._parse_rf_item(rf_item)
- for rf_item
- in rf_results['sectionList'][0]['items']
- if self._check_bc_id_exists(rf_item)
- ]
- return self.playlist_result(entries, 'Filter query')
+ rf_id = self._match_id(url)
+ rf_result = self._call_api('session', rf_id, {'id': rf_id}, url)
+ return self._parse_rf_item(rf_result['items'][0])
+
+
+class CiscoLiveSearchIE(CiscoLiveBaseIE):
+ _VALID_URL = r'https?://(?:www\.)?ciscolive(?:\.cisco)?\.com/(?:global/)?on-demand-library(?:\.html|/)'
+ _TESTS = [{
+ 'url': 'https://ciscolive.cisco.com/on-demand-library/?search.event=ciscoliveus2018&search.technicallevel=scpsSkillLevel_aintroductory&search.focus=scpsSessionFocus_designAndDeployment#/',
+ 'info_dict': {
+ 'title': 'Search query',
+ },
+ 'playlist_count': 5,
+ }, {
+ 'url': 'https://ciscolive.cisco.com/on-demand-library/?search.technology=scpsTechnology_applicationDevelopment&search.technology=scpsTechnology_ipv6&search.focus=scpsSessionFocus_troubleshootingTroubleshooting#/',
+ 'only_matching': True,
+ }, {
+ '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#/',
+ 'only_matching': True,
+ }]
+
+ @classmethod
+ def suitable(cls, url):
+ return False if CiscoLiveSessionIE.suitable(url) else super(CiscoLiveSearchIE, cls).suitable(url)
+
+ @staticmethod
+ def _check_bc_id_exists(rf_item):
+ return int_or_none(try_get(rf_item, lambda x: x['videos'][0]['url'])) is not None
+
+ def _entries(self, query, url):
+ query['size'] = 50
+ query['from'] = 0
+ for page_num in itertools.count(1):
+ results = self._call_api(
+ 'search', None, query, url,
+ 'Downloading search JSON page %d' % page_num)
+ sl = try_get(results, lambda x: x['sectionList'][0], dict)
+ if sl:
+ results = sl
+ items = results.get('items')
+ if not items or not isinstance(items, list):
+ break
+ for item in items:
+ if not isinstance(item, dict):
+ continue
+ if not self._check_bc_id_exists(item):
+ continue
+ yield self._parse_rf_item(item)
+ size = int_or_none(results.get('size'))
+ if size is not None:
+ query['size'] = size
+ total = int_or_none(results.get('total'))
+ if total is not None and query['from'] + query['size'] > total:
+ break
+ query['from'] += query['size']
+
+ def _real_extract(self, url):
+ query = compat_parse_qs(compat_urllib_parse_urlparse(url).query)
+ query['type'] = 'session'
+ return self.playlist_result(
+ self._entries(query, url), playlist_title='Search query')