mirror of
https://github.com/UrloMythus/UnHided.git
synced 2026-04-11 03:40:54 +00:00
Update to the newest MFP version, including the Vixcloud PR
This commit is contained in:
BIN
mediaflow_proxy/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/__pycache__/configs.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/configs.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/__pycache__/const.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/const.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/__pycache__/handlers.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/handlers.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/__pycache__/main.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/main.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/__pycache__/mpd_processor.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/mpd_processor.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/__pycache__/schemas.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/__pycache__/schemas.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/drm/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/drm/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/drm/__pycache__/decrypter.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/drm/__pycache__/decrypter.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/base.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/base.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/factory.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/factory.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/livetv.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/livetv.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/maxstream.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/maxstream.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/okru.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/okru.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/uqload.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/uqload.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-312.pyc
Normal file
Binary file not shown.
@@ -15,18 +15,18 @@ class VixCloudExtractor(BaseExtractor):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.mediaflow_endpoint = "hls_manifest_proxy"
|
self.mediaflow_endpoint = "hls_manifest_proxy"
|
||||||
|
|
||||||
async def version(self, domain: str) -> str:
|
async def version(self, site_url: str) -> str:
|
||||||
"""Get version of VixCloud Parent Site."""
|
"""Get version of VixCloud Parent Site."""
|
||||||
base_url = f"https://streamingcommunity.{domain}/richiedi-un-titolo"
|
base_url = f"{site_url}/richiedi-un-titolo"
|
||||||
response = await self._make_request(
|
response = await self._make_request(
|
||||||
base_url,
|
base_url,
|
||||||
headers={
|
headers={
|
||||||
"Referer": f"https://streamingcommunity.{domain}/",
|
"Referer": f"{site_url}/",
|
||||||
"Origin": f"https://streamingcommunity.{domain}",
|
"Origin": f"{site_url}",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise ExtractorError("Outdated Domain")
|
raise ExtractorError("Outdated Url")
|
||||||
# Soup the response
|
# Soup the response
|
||||||
soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("div", {"id": "app"}))
|
soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("div", {"id": "app"}))
|
||||||
if soup:
|
if soup:
|
||||||
@@ -39,8 +39,8 @@ class VixCloudExtractor(BaseExtractor):
|
|||||||
|
|
||||||
async def extract(self, url: str, **kwargs) -> Dict[str, Any]:
|
async def extract(self, url: str, **kwargs) -> Dict[str, Any]:
|
||||||
"""Extract Vixcloud URL."""
|
"""Extract Vixcloud URL."""
|
||||||
domain = url.split("://")[1].split("/")[0].split(".")[1]
|
site_url = url.split("/iframe")[0]
|
||||||
version = await self.version(domain)
|
version = await self.version(site_url)
|
||||||
response = await self._make_request(url, headers={"x-inertia": "true", "x-inertia-version": version})
|
response = await self._make_request(url, headers={"x-inertia": "true", "x-inertia-version": version})
|
||||||
soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("iframe"))
|
soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("iframe"))
|
||||||
iframe = soup.find("iframe").get("src")
|
iframe = soup.find("iframe").get("src")
|
||||||
|
|||||||
BIN
mediaflow_proxy/routes/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/routes/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/routes/__pycache__/extractor.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/routes/__pycache__/extractor.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/routes/__pycache__/proxy.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/routes/__pycache__/proxy.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/routes/__pycache__/speedtest.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/routes/__pycache__/speedtest.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/speedtest/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/speedtest/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/speedtest/__pycache__/models.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/speedtest/__pycache__/models.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/speedtest/__pycache__/service.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/speedtest/__pycache__/service.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
mediaflow_proxy/utils/__pycache__/__init__.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/utils/__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/utils/__pycache__/cache_utils.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/utils/__pycache__/cache_utils.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/utils/__pycache__/http_utils.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/utils/__pycache__/http_utils.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-312.pyc
Normal file
Binary file not shown.
BIN
mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-312.pyc
Normal file
BIN
mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-312.pyc
Normal file
Binary file not shown.
@@ -67,30 +67,24 @@ class EncryptionMiddleware(BaseHTTPMiddleware):
|
|||||||
encrypted_token = None
|
encrypted_token = None
|
||||||
|
|
||||||
# Check for token in path
|
# Check for token in path
|
||||||
if token_marker in path and self.encryption_handler:
|
if path.startswith(token_marker) and self.encryption_handler:
|
||||||
try:
|
try:
|
||||||
# Extract token from path
|
# Extract token from the beginning of the path
|
||||||
token_start = path.find(token_marker) + len(token_marker)
|
token_start = len(token_marker)
|
||||||
token_end = path.find("/", token_start)
|
token_end = path.find("/", token_start)
|
||||||
|
|
||||||
if token_end == -1: # No trailing slash (no filename after token)
|
if token_end == -1: # No trailing slash
|
||||||
token_end = len(path)
|
encrypted_token = path[token_start:]
|
||||||
filename_part = ""
|
remaining_path = ""
|
||||||
else:
|
else:
|
||||||
# There's something after the token (likely a filename)
|
encrypted_token = path[token_start:token_end]
|
||||||
filename_part = path[token_end:]
|
remaining_path = path[token_end:]
|
||||||
|
|
||||||
# Get the encrypted token
|
# Modify the path to remove the token part
|
||||||
encrypted_token = path[token_start:token_end]
|
request.scope["path"] = remaining_path
|
||||||
|
|
||||||
# Modify the path to remove the token part but preserve the filename
|
|
||||||
original_path = path[: path.find(token_marker)]
|
|
||||||
original_path += filename_part # Add back the filename part
|
|
||||||
|
|
||||||
request.scope["path"] = original_path
|
|
||||||
|
|
||||||
# Update the raw path as well
|
# Update the raw path as well
|
||||||
request.scope["raw_path"] = original_path.encode()
|
request.scope["raw_path"] = remaining_path.encode()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error processing token in path: {str(e)}")
|
logging.error(f"Error processing token in path: {str(e)}")
|
||||||
|
|||||||
@@ -330,15 +330,25 @@ def encode_mediaflow_proxy_url(
|
|||||||
# Handle encryption if needed
|
# Handle encryption if needed
|
||||||
if encryption_handler:
|
if encryption_handler:
|
||||||
encrypted_token = encryption_handler.encrypt_data(query_params, expiration, ip)
|
encrypted_token = encryption_handler.encrypt_data(query_params, expiration, ip)
|
||||||
# Build the URL with token in path
|
|
||||||
path_parts = [base_url, f"_token_{encrypted_token}"]
|
# Parse the base URL to get its components
|
||||||
|
parsed_url = parse.urlparse(base_url)
|
||||||
|
|
||||||
|
# Insert the token at the beginning of the path
|
||||||
|
new_path = f"/_token_{encrypted_token}{parsed_url.path}"
|
||||||
|
|
||||||
|
# Reconstruct the URL with the token at the beginning of the path
|
||||||
|
url_parts = list(parsed_url)
|
||||||
|
url_parts[2] = new_path # Update the path component
|
||||||
|
|
||||||
|
# Build the URL
|
||||||
|
url = parse.urlunparse(url_parts)
|
||||||
|
|
||||||
# Add filename at the end if provided
|
# Add filename at the end if provided
|
||||||
if filename:
|
if filename:
|
||||||
path_parts.append(parse.quote(filename))
|
url = f"{url}/{parse.quote(filename)}"
|
||||||
|
|
||||||
return "/".join(path_parts)
|
|
||||||
|
|
||||||
|
return url
|
||||||
else:
|
else:
|
||||||
# No encryption, use regular query parameters
|
# No encryption, use regular query parameters
|
||||||
url = base_url
|
url = base_url
|
||||||
|
|||||||
@@ -233,8 +233,21 @@ def parse_representation(
|
|||||||
profile["audioSamplingRate"] = representation.get("@audioSamplingRate") or adaptation.get("@audioSamplingRate")
|
profile["audioSamplingRate"] = representation.get("@audioSamplingRate") or adaptation.get("@audioSamplingRate")
|
||||||
profile["channels"] = representation.get("AudioChannelConfiguration", {}).get("@value", "2")
|
profile["channels"] = representation.get("AudioChannelConfiguration", {}).get("@value", "2")
|
||||||
else:
|
else:
|
||||||
profile["width"] = int(representation["@width"])
|
# Handle video-specific attributes, making them optional with sensible defaults
|
||||||
profile["height"] = int(representation["@height"])
|
if "@width" in representation:
|
||||||
|
profile["width"] = int(representation["@width"])
|
||||||
|
elif "@width" in adaptation:
|
||||||
|
profile["width"] = int(adaptation["@width"])
|
||||||
|
else:
|
||||||
|
profile["width"] = 0 # Default if width is missing
|
||||||
|
|
||||||
|
if "@height" in representation:
|
||||||
|
profile["height"] = int(representation["@height"])
|
||||||
|
elif "@height" in adaptation:
|
||||||
|
profile["height"] = int(adaptation["@height"])
|
||||||
|
else:
|
||||||
|
profile["height"] = 0 # Default if height is missing
|
||||||
|
|
||||||
frame_rate = representation.get("@frameRate") or adaptation.get("@maxFrameRate") or "30000/1001"
|
frame_rate = representation.get("@frameRate") or adaptation.get("@maxFrameRate") or "30000/1001"
|
||||||
frame_rate = frame_rate if "/" in frame_rate else f"{frame_rate}/1"
|
frame_rate = frame_rate if "/" in frame_rate else f"{frame_rate}/1"
|
||||||
profile["frameRate"] = round(int(frame_rate.split("/")[0]) / int(frame_rate.split("/")[1]), 3)
|
profile["frameRate"] = round(int(frame_rate.split("/")[0]) / int(frame_rate.split("/")[1]), 3)
|
||||||
@@ -317,7 +330,9 @@ def parse_segment_timeline(parsed_dict: dict, item: dict, profile: dict, source:
|
|||||||
"""
|
"""
|
||||||
timelines = item["SegmentTimeline"]["S"]
|
timelines = item["SegmentTimeline"]["S"]
|
||||||
timelines = timelines if isinstance(timelines, list) else [timelines]
|
timelines = timelines if isinstance(timelines, list) else [timelines]
|
||||||
period_start = parsed_dict.get("availabilityStartTime", datetime.fromtimestamp(0, tz=timezone.utc)) + timedelta(seconds=parsed_dict.get("PeriodStart", 0))
|
period_start = parsed_dict.get("availabilityStartTime", datetime.fromtimestamp(0, tz=timezone.utc)) + timedelta(
|
||||||
|
seconds=parsed_dict.get("PeriodStart", 0)
|
||||||
|
)
|
||||||
presentation_time_offset = int(item.get("@presentationTimeOffset", 0))
|
presentation_time_offset = int(item.get("@presentationTimeOffset", 0))
|
||||||
start_number = int(item.get("@startNumber", 1))
|
start_number = int(item.get("@startNumber", 1))
|
||||||
|
|
||||||
@@ -354,13 +369,14 @@ def preprocess_timeline(
|
|||||||
for _ in range(repeat + 1):
|
for _ in range(repeat + 1):
|
||||||
segment_start_time = period_start + timedelta(seconds=(start_time - presentation_time_offset) / timescale)
|
segment_start_time = period_start + timedelta(seconds=(start_time - presentation_time_offset) / timescale)
|
||||||
segment_end_time = segment_start_time + timedelta(seconds=duration / timescale)
|
segment_end_time = segment_start_time + timedelta(seconds=duration / timescale)
|
||||||
|
presentation_time = start_time - presentation_time_offset
|
||||||
processed_data.append(
|
processed_data.append(
|
||||||
{
|
{
|
||||||
"number": start_number,
|
"number": start_number,
|
||||||
"start_time": segment_start_time,
|
"start_time": segment_start_time,
|
||||||
"end_time": segment_end_time,
|
"end_time": segment_end_time,
|
||||||
"duration": duration,
|
"duration": duration,
|
||||||
"time": start_time,
|
"time": presentation_time,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
start_time += duration
|
start_time += duration
|
||||||
@@ -475,7 +491,7 @@ def create_segment_data(segment: Dict, item: dict, profile: dict, source: str, t
|
|||||||
media = media.replace("$Bandwidth$", str(profile["bandwidth"]))
|
media = media.replace("$Bandwidth$", str(profile["bandwidth"]))
|
||||||
|
|
||||||
if "time" in segment and timescale is not None:
|
if "time" in segment and timescale is not None:
|
||||||
media = media.replace("$Time$", str(int(segment["time"] * timescale)))
|
media = media.replace("$Time$", str(int(segment["time"])))
|
||||||
|
|
||||||
if not media.startswith("http"):
|
if not media.startswith("http"):
|
||||||
media = f"{source}/{media}"
|
media = f"{source}/{media}"
|
||||||
@@ -496,16 +512,20 @@ def create_segment_data(segment: Dict, item: dict, profile: dict, source: str, t
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
elif "start_time" in segment and "duration" in segment:
|
elif "start_time" in segment and "duration" in segment:
|
||||||
duration = segment["duration"]
|
duration_seconds = segment["duration"] / timescale
|
||||||
segment_data.update(
|
segment_data.update(
|
||||||
{
|
{
|
||||||
"start_time": segment["start_time"],
|
"start_time": segment["start_time"],
|
||||||
"end_time": segment["start_time"] + timedelta(seconds=duration),
|
"end_time": segment["start_time"] + timedelta(seconds=duration_seconds),
|
||||||
"extinf": duration,
|
"extinf": duration_seconds,
|
||||||
"program_date_time": segment["start_time"].isoformat() + "Z",
|
"program_date_time": segment["start_time"].isoformat() + "Z",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
elif "duration" in segment and timescale is not None:
|
||||||
|
# Convert duration from timescale units to seconds
|
||||||
|
segment_data["extinf"] = segment["duration"] / timescale
|
||||||
elif "duration" in segment:
|
elif "duration" in segment:
|
||||||
|
# If no timescale is provided, assume duration is already in seconds
|
||||||
segment_data["extinf"] = segment["duration"]
|
segment_data["extinf"] = segment["duration"]
|
||||||
|
|
||||||
return segment_data
|
return segment_data
|
||||||
|
|||||||
Reference in New Issue
Block a user