diff --git a/yt_dlp/extractor/tnaflix.py b/yt_dlp/extractor/tnaflix.py
index 8cbfeb7fb..eceaadb30 100644
--- a/yt_dlp/extractor/tnaflix.py
+++ b/yt_dlp/extractor/tnaflix.py
@@ -1,3 +1,5 @@
+import re
+
from .common import InfoExtractor
from ..compat import compat_str
from ..utils import (
@@ -7,6 +9,7 @@ from ..utils import (
parse_duration,
str_to_int,
unescapeHTML,
+ url_basename,
xpath_text,
)
@@ -18,9 +21,6 @@ class TNAFlixNetworkBaseIE(InfoExtractor):
r']+name="config\d?" value="(?P[^"]+)"',
r'config\s*=\s*(["\'])(?P(?:https?:)?//(?:(?!\1).)+)\1',
]
- _HOST = 'tna'
- _VIDEO_XML_URL = 'https://www.tnaflix.com/cdn/cdn.php?file={}.fid&key={}&VID={}&nomp4=1&catID=0&rollover=1&startThumb=12&embed=0&utm_source=0&multiview=0&premium=1&country=0user=0&vip=1&cd=0&ref=0&alpha'
- _VKEY_SUFFIX = ''
_TITLE_REGEX = r']+name="title" value="([^"]+)"'
_DESCRIPTION_REGEX = r']+name="description" value="([^"]+)"'
_UPLOADER_REGEX = r']+name="username" value="([^"]+)"'
@@ -71,11 +71,7 @@ class TNAFlixNetworkBaseIE(InfoExtractor):
def _real_extract(self, url):
mobj = self._match_valid_url(url)
- video_id = mobj.group('id')
-
- def extract_field(pattern, name):
- return self._html_search_regex(pattern, webpage, name, default=None) if pattern else None
-
+ video_id, host = mobj.group('id', 'host')
for display_id_key in ('display_id', 'display_id_2'):
if display_id_key in mobj.groupdict():
display_id = mobj.group(display_id_key)
@@ -86,122 +82,138 @@ class TNAFlixNetworkBaseIE(InfoExtractor):
webpage = self._download_webpage(url, display_id)
+ # check for MovieFap-style config
cfg_url = self._proto_relative_url(self._html_search_regex(
self._CONFIG_REGEX, webpage, 'flashvars.config', default=None,
group='url'), 'http:')
+ query = {}
- if not cfg_url:
- vkey = extract_field(r']+\bid="vkey"\b[^>]+\bvalue="([^"]+)"', 'vkey')
- nkey = extract_field(r']+\bid="nkey"\b[^>]+\bvalue="([^"]+)"', 'nkey')
- vid = extract_field(r']+\bid="VID"\b[^>]+\bvalue="([^"]+)"', 'vid')
- if vkey and nkey and vid:
- cfg_url = self._proto_relative_url(self._VIDEO_XML_URL.format(vkey, nkey, vid), 'http:')
-
+ # check for TNAFlix-style config
if not cfg_url:
inputs = self._hidden_inputs(webpage)
- cfg_url = ('https://cdn-fck.%sflix.com/%sflix/%s%s.fid?key=%s&VID=%s&premium=1&vip=1&alpha'
- % (self._HOST, self._HOST, inputs['vkey'], self._VKEY_SUFFIX, inputs['nkey'], video_id))
-
- cfg_xml = self._download_xml(
- cfg_url, display_id, 'Downloading metadata',
- transform_source=fix_xml_ampersands, headers={'Referer': url})
-
- formats = []
-
- def extract_video_url(vl):
- # Any URL modification now results in HTTP Error 403: Forbidden
- return unescapeHTML(vl.text)
-
- video_link = cfg_xml.find('./videoLink')
- if video_link is not None:
- formats.append({
- 'url': extract_video_url(video_link),
- 'ext': xpath_text(cfg_xml, './videoConfig/type', 'type', default='flv'),
- })
-
- for item in cfg_xml.findall('./quality/item'):
- video_link = item.find('./videoLink')
- if video_link is None:
- continue
- res = item.find('res')
- format_id = None if res is None else res.text
- height = int_or_none(self._search_regex(
- r'^(\d+)[pP]', format_id, 'height', default=None))
- formats.append({
- 'url': self._proto_relative_url(extract_video_url(video_link), 'http:'),
- 'format_id': format_id,
- 'height': height,
+ if inputs.get('vkey') and inputs.get('nkey'):
+ cfg_url = f'https://www.{host}.com/cdn/cdn.php'
+ query.update({
+ 'file': inputs['vkey'],
+ 'key': inputs['nkey'],
+ 'VID': video_id,
+ 'premium': '1',
+ 'vip': '1',
+ 'alpha': '',
+ })
+
+ formats, json_ld = [], {}
+
+ # TNAFlix and MovieFap extraction
+ if cfg_url:
+ cfg_xml = self._download_xml(
+ cfg_url, display_id, 'Downloading metadata',
+ transform_source=fix_xml_ampersands, headers={'Referer': url}, query=query)
+
+ def extract_video_url(vl):
+ # Any URL modification now results in HTTP Error 403: Forbidden
+ return unescapeHTML(vl.text)
+
+ video_link = cfg_xml.find('./videoLink')
+ if video_link is not None:
+ formats.append({
+ 'url': extract_video_url(video_link),
+ 'ext': xpath_text(cfg_xml, './videoConfig/type', 'type', default='flv'),
+ })
+
+ for item in cfg_xml.findall('./quality/item'):
+ video_link = item.find('./videoLink')
+ if video_link is None:
+ continue
+ res = item.find('res')
+ format_id = None if res is None else res.text
+ height = int_or_none(self._search_regex(
+ r'^(\d+)[pP]', format_id, 'height', default=None))
+ formats.append({
+ 'url': self._proto_relative_url(extract_video_url(video_link), 'http:'),
+ 'format_id': format_id,
+ 'height': height,
+ })
+
+ thumbnails = self._extract_thumbnails(cfg_xml) or []
+ thumbnails.append({
+ 'url': self._proto_relative_url(xpath_text(cfg_xml, './startThumb', 'thumbnail'), 'http:')
})
- self._sort_formats(formats)
-
- thumbnail = self._proto_relative_url(
- xpath_text(cfg_xml, './startThumb', 'thumbnail'), 'http:')
- thumbnails = self._extract_thumbnails(cfg_xml)
-
- title = None
- if self._TITLE_REGEX:
- title = self._html_search_regex(
- self._TITLE_REGEX, webpage, 'title', default=None)
- if not title:
- title = self._og_search_title(webpage)
-
- age_limit = self._rta_search(webpage) or 18
-
- duration = parse_duration(self._html_search_meta(
- 'duration', webpage, 'duration', default=None))
-
- description = extract_field(self._DESCRIPTION_REGEX, 'description')
- uploader = extract_field(self._UPLOADER_REGEX, 'uploader')
- view_count = str_to_int(extract_field(self._VIEW_COUNT_REGEX, 'view count'))
- comment_count = str_to_int(extract_field(self._COMMENT_COUNT_REGEX, 'comment count'))
- average_rating = float_or_none(extract_field(self._AVERAGE_RATING_REGEX, 'average rating'))
+ # check for EMPFlix-style JSON and extract
+ else:
+ player = self._download_json(
+ f'http://www.{host}.com/ajax/video-player/{video_id}', video_id,
+ headers={'Referer': url}).get('html', '')
+ for mobj in re.finditer(r'