diff --git a/mediaflow_proxy/__pycache__/__init__.cpython-312.pyc b/mediaflow_proxy/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..d4b727f Binary files /dev/null and b/mediaflow_proxy/__pycache__/__init__.cpython-312.pyc differ diff --git a/mediaflow_proxy/__pycache__/configs.cpython-312.pyc b/mediaflow_proxy/__pycache__/configs.cpython-312.pyc new file mode 100644 index 0000000..fab030a Binary files /dev/null and b/mediaflow_proxy/__pycache__/configs.cpython-312.pyc differ diff --git a/mediaflow_proxy/__pycache__/const.cpython-312.pyc b/mediaflow_proxy/__pycache__/const.cpython-312.pyc new file mode 100644 index 0000000..031dc1c Binary files /dev/null and b/mediaflow_proxy/__pycache__/const.cpython-312.pyc differ diff --git a/mediaflow_proxy/__pycache__/handlers.cpython-312.pyc b/mediaflow_proxy/__pycache__/handlers.cpython-312.pyc new file mode 100644 index 0000000..efc259f Binary files /dev/null and b/mediaflow_proxy/__pycache__/handlers.cpython-312.pyc differ diff --git a/mediaflow_proxy/__pycache__/main.cpython-312.pyc b/mediaflow_proxy/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000..82599c9 Binary files /dev/null and b/mediaflow_proxy/__pycache__/main.cpython-312.pyc differ diff --git a/mediaflow_proxy/__pycache__/mpd_processor.cpython-312.pyc b/mediaflow_proxy/__pycache__/mpd_processor.cpython-312.pyc new file mode 100644 index 0000000..8595850 Binary files /dev/null and b/mediaflow_proxy/__pycache__/mpd_processor.cpython-312.pyc differ diff --git a/mediaflow_proxy/__pycache__/schemas.cpython-312.pyc b/mediaflow_proxy/__pycache__/schemas.cpython-312.pyc new file mode 100644 index 0000000..f2c3dfc Binary files /dev/null and b/mediaflow_proxy/__pycache__/schemas.cpython-312.pyc differ diff --git a/mediaflow_proxy/drm/__pycache__/__init__.cpython-312.pyc b/mediaflow_proxy/drm/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..2cfa91f Binary files /dev/null and b/mediaflow_proxy/drm/__pycache__/__init__.cpython-312.pyc differ diff --git a/mediaflow_proxy/drm/__pycache__/decrypter.cpython-312.pyc b/mediaflow_proxy/drm/__pycache__/decrypter.cpython-312.pyc new file mode 100644 index 0000000..586cc1d Binary files /dev/null and b/mediaflow_proxy/drm/__pycache__/decrypter.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/__init__.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..895de73 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/__init__.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/base.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000..1eb9996 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/base.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/doodstream.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/doodstream.cpython-312.pyc new file mode 100644 index 0000000..5600b30 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/doodstream.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/factory.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/factory.cpython-312.pyc new file mode 100644 index 0000000..8b822df Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/factory.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/livetv.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/livetv.cpython-312.pyc new file mode 100644 index 0000000..7e50e39 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/livetv.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/maxstream.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/maxstream.cpython-312.pyc new file mode 100644 index 0000000..05b71a4 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/maxstream.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-312.pyc new file mode 100644 index 0000000..dfbf305 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/okru.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/okru.cpython-312.pyc new file mode 100644 index 0000000..c6d57db Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/okru.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/streamtape.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/streamtape.cpython-312.pyc new file mode 100644 index 0000000..1965124 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/streamtape.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/supervideo.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/supervideo.cpython-312.pyc new file mode 100644 index 0000000..68fb79a Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/supervideo.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/uqload.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/uqload.cpython-312.pyc new file mode 100644 index 0000000..63430c8 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/uqload.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-312.pyc b/mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-312.pyc new file mode 100644 index 0000000..46a84a6 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-312.pyc differ diff --git a/mediaflow_proxy/extractors/vixcloud.py b/mediaflow_proxy/extractors/vixcloud.py index 696fced..21118a7 100644 --- a/mediaflow_proxy/extractors/vixcloud.py +++ b/mediaflow_proxy/extractors/vixcloud.py @@ -15,18 +15,18 @@ class VixCloudExtractor(BaseExtractor): super().__init__(*args, **kwargs) 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.""" - base_url = f"https://streamingcommunity.{domain}/richiedi-un-titolo" + base_url = f"{site_url}/richiedi-un-titolo" response = await self._make_request( base_url, headers={ - "Referer": f"https://streamingcommunity.{domain}/", - "Origin": f"https://streamingcommunity.{domain}", + "Referer": f"{site_url}/", + "Origin": f"{site_url}", }, ) if response.status_code != 200: - raise ExtractorError("Outdated Domain") + raise ExtractorError("Outdated Url") # Soup the response soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("div", {"id": "app"})) if soup: @@ -39,8 +39,8 @@ class VixCloudExtractor(BaseExtractor): async def extract(self, url: str, **kwargs) -> Dict[str, Any]: """Extract Vixcloud URL.""" - domain = url.split("://")[1].split("/")[0].split(".")[1] - version = await self.version(domain) + site_url = url.split("/iframe")[0] + version = await self.version(site_url) response = await self._make_request(url, headers={"x-inertia": "true", "x-inertia-version": version}) soup = BeautifulSoup(response.text, "lxml", parse_only=SoupStrainer("iframe")) iframe = soup.find("iframe").get("src") diff --git a/mediaflow_proxy/routes/__pycache__/__init__.cpython-312.pyc b/mediaflow_proxy/routes/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..fcc7506 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/__init__.cpython-312.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/extractor.cpython-312.pyc b/mediaflow_proxy/routes/__pycache__/extractor.cpython-312.pyc new file mode 100644 index 0000000..300e8b8 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/extractor.cpython-312.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/proxy.cpython-312.pyc b/mediaflow_proxy/routes/__pycache__/proxy.cpython-312.pyc new file mode 100644 index 0000000..262d0a3 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/proxy.cpython-312.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/speedtest.cpython-312.pyc b/mediaflow_proxy/routes/__pycache__/speedtest.cpython-312.pyc new file mode 100644 index 0000000..a587b2e Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/speedtest.cpython-312.pyc differ diff --git a/mediaflow_proxy/speedtest/__pycache__/__init__.cpython-312.pyc b/mediaflow_proxy/speedtest/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..29a87f0 Binary files /dev/null and b/mediaflow_proxy/speedtest/__pycache__/__init__.cpython-312.pyc differ diff --git a/mediaflow_proxy/speedtest/__pycache__/models.cpython-312.pyc b/mediaflow_proxy/speedtest/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000..1cb7912 Binary files /dev/null and b/mediaflow_proxy/speedtest/__pycache__/models.cpython-312.pyc differ diff --git a/mediaflow_proxy/speedtest/__pycache__/service.cpython-312.pyc b/mediaflow_proxy/speedtest/__pycache__/service.cpython-312.pyc new file mode 100644 index 0000000..f6f604e Binary files /dev/null and b/mediaflow_proxy/speedtest/__pycache__/service.cpython-312.pyc differ diff --git a/mediaflow_proxy/speedtest/providers/__pycache__/all_debrid.cpython-312.pyc b/mediaflow_proxy/speedtest/providers/__pycache__/all_debrid.cpython-312.pyc new file mode 100644 index 0000000..f399fde Binary files /dev/null and b/mediaflow_proxy/speedtest/providers/__pycache__/all_debrid.cpython-312.pyc differ diff --git a/mediaflow_proxy/speedtest/providers/__pycache__/base.cpython-312.pyc b/mediaflow_proxy/speedtest/providers/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000..01373e6 Binary files /dev/null and b/mediaflow_proxy/speedtest/providers/__pycache__/base.cpython-312.pyc differ diff --git a/mediaflow_proxy/speedtest/providers/__pycache__/real_debrid.cpython-312.pyc b/mediaflow_proxy/speedtest/providers/__pycache__/real_debrid.cpython-312.pyc new file mode 100644 index 0000000..6aa4e67 Binary files /dev/null and b/mediaflow_proxy/speedtest/providers/__pycache__/real_debrid.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/__init__.cpython-312.pyc b/mediaflow_proxy/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..cc06084 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/__init__.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/cache_utils.cpython-312.pyc b/mediaflow_proxy/utils/__pycache__/cache_utils.cpython-312.pyc new file mode 100644 index 0000000..e5046f3 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/cache_utils.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-312.pyc b/mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-312.pyc new file mode 100644 index 0000000..a0113df Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/http_utils.cpython-312.pyc b/mediaflow_proxy/utils/__pycache__/http_utils.cpython-312.pyc new file mode 100644 index 0000000..075e0bf Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/http_utils.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-312.pyc b/mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-312.pyc new file mode 100644 index 0000000..347371e Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-312.pyc b/mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-312.pyc new file mode 100644 index 0000000..7450e5f Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-312.pyc differ diff --git a/mediaflow_proxy/utils/crypto_utils.py b/mediaflow_proxy/utils/crypto_utils.py index d57edc8..3dc87a8 100644 --- a/mediaflow_proxy/utils/crypto_utils.py +++ b/mediaflow_proxy/utils/crypto_utils.py @@ -67,30 +67,24 @@ class EncryptionMiddleware(BaseHTTPMiddleware): encrypted_token = None # Check for token in path - if token_marker in path and self.encryption_handler: + if path.startswith(token_marker) and self.encryption_handler: try: - # Extract token from path - token_start = path.find(token_marker) + len(token_marker) + # Extract token from the beginning of the path + token_start = len(token_marker) token_end = path.find("/", token_start) - if token_end == -1: # No trailing slash (no filename after token) - token_end = len(path) - filename_part = "" + if token_end == -1: # No trailing slash + encrypted_token = path[token_start:] + remaining_path = "" else: - # There's something after the token (likely a filename) - filename_part = path[token_end:] + encrypted_token = path[token_start:token_end] + remaining_path = path[token_end:] - # Get the encrypted token - encrypted_token = path[token_start:token_end] - - # 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 + # Modify the path to remove the token part + request.scope["path"] = remaining_path # Update the raw path as well - request.scope["raw_path"] = original_path.encode() + request.scope["raw_path"] = remaining_path.encode() except Exception as e: logging.error(f"Error processing token in path: {str(e)}") diff --git a/mediaflow_proxy/utils/http_utils.py b/mediaflow_proxy/utils/http_utils.py index 9554907..6bb9ba0 100644 --- a/mediaflow_proxy/utils/http_utils.py +++ b/mediaflow_proxy/utils/http_utils.py @@ -330,15 +330,25 @@ def encode_mediaflow_proxy_url( # Handle encryption if needed if encryption_handler: 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 if filename: - path_parts.append(parse.quote(filename)) - - return "/".join(path_parts) + url = f"{url}/{parse.quote(filename)}" + return url else: # No encryption, use regular query parameters url = base_url diff --git a/mediaflow_proxy/utils/mpd_utils.py b/mediaflow_proxy/utils/mpd_utils.py index 19827bf..7e14e26 100644 --- a/mediaflow_proxy/utils/mpd_utils.py +++ b/mediaflow_proxy/utils/mpd_utils.py @@ -233,8 +233,21 @@ def parse_representation( profile["audioSamplingRate"] = representation.get("@audioSamplingRate") or adaptation.get("@audioSamplingRate") profile["channels"] = representation.get("AudioChannelConfiguration", {}).get("@value", "2") else: - profile["width"] = int(representation["@width"]) - profile["height"] = int(representation["@height"]) + # Handle video-specific attributes, making them optional with sensible defaults + 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 = 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) @@ -317,7 +330,9 @@ def parse_segment_timeline(parsed_dict: dict, item: dict, profile: dict, source: """ timelines = item["SegmentTimeline"]["S"] 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)) start_number = int(item.get("@startNumber", 1)) @@ -354,13 +369,14 @@ def preprocess_timeline( for _ in range(repeat + 1): segment_start_time = period_start + timedelta(seconds=(start_time - presentation_time_offset) / timescale) segment_end_time = segment_start_time + timedelta(seconds=duration / timescale) + presentation_time = start_time - presentation_time_offset processed_data.append( { "number": start_number, "start_time": segment_start_time, "end_time": segment_end_time, "duration": duration, - "time": start_time, + "time": presentation_time, } ) 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"])) 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"): 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: - duration = segment["duration"] + duration_seconds = segment["duration"] / timescale segment_data.update( { "start_time": segment["start_time"], - "end_time": segment["start_time"] + timedelta(seconds=duration), - "extinf": duration, + "end_time": segment["start_time"] + timedelta(seconds=duration_seconds), + "extinf": duration_seconds, "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: + # If no timescale is provided, assume duration is already in seconds segment_data["extinf"] = segment["duration"] return segment_data