+ mobj = re.match(self._VALID_URL, url)
+ video_id = mobj.group('id') or mobj.group('id_2')
+ display_id = mobj.group('display_id') or mobj.group('display_id_2')
+
+ desktop_url = re.sub(r'^(https?://(?:.+?\.)?)m\.', r'\1', url)
+ webpage = self._download_webpage(desktop_url, video_id)
+
+ error = self._html_search_regex(
+ r'<div[^>]+id=["\']videoClosed["\'][^>]*>(.+?)</div>',
+ webpage, 'error', default=None)
+ if error:
+ raise ExtractorError(error, expected=True)
+
+ age_limit = self._rta_search(webpage)
+
+ def get_height(s):
+ return int_or_none(self._search_regex(
+ r'^(\d+)[pP]', s, 'height', default=None))
+
+ initials = self._parse_json(
+ self._search_regex(
+ r'window\.initials\s*=\s*({.+?})\s*;\s*\n', webpage, 'initials',
+ default='{}'),
+ video_id, fatal=False)
+ if initials:
+ video = initials['videoModel']
+ title = video['title']
+ formats = []
+ for format_id, formats_dict in video['sources'].items():
+ if not isinstance(formats_dict, dict):
+ continue
+ for quality, format_item in formats_dict.items():
+ if format_id == 'download':
+ # Download link takes some time to be generated,
+ # skipping for now
+ continue
+ if not isinstance(format_item, dict):
+ continue
+ format_url = format_item.get('link')
+ filesize = int_or_none(
+ format_item.get('size'), invscale=1000000)
+ else:
+ format_url = format_item
+ filesize = None
+ format_url = url_or_none(format_url)
+ if not format_url:
+ continue
+ formats.append({
+ 'format_id': '%s-%s' % (format_id, quality),
+ 'url': format_url,
+ 'ext': determine_ext(format_url, 'mp4'),
+ 'height': get_height(quality),
+ 'filesize': filesize,
+ })
+ self._sort_formats(formats)
+
+ categories_list = video.get('categories')
+ if isinstance(categories_list, list):
+ categories = []
+ for c in categories_list:
+ if not isinstance(c, dict):
+ continue
+ c_name = c.get('name')
+ if isinstance(c_name, compat_str):
+ categories.append(c_name)