diff --git a/mediaflow_proxy/__pycache__/__init__.cpython-313.pyc b/mediaflow_proxy/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..1090917 Binary files /dev/null and b/mediaflow_proxy/__pycache__/__init__.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/configs.cpython-313.pyc b/mediaflow_proxy/__pycache__/configs.cpython-313.pyc new file mode 100644 index 0000000..508031b Binary files /dev/null and b/mediaflow_proxy/__pycache__/configs.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/const.cpython-313.pyc b/mediaflow_proxy/__pycache__/const.cpython-313.pyc new file mode 100644 index 0000000..8e4cff0 Binary files /dev/null and b/mediaflow_proxy/__pycache__/const.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/handlers.cpython-313.pyc b/mediaflow_proxy/__pycache__/handlers.cpython-313.pyc new file mode 100644 index 0000000..337b14d Binary files /dev/null and b/mediaflow_proxy/__pycache__/handlers.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/main.cpython-313.pyc b/mediaflow_proxy/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000..41075c0 Binary files /dev/null and b/mediaflow_proxy/__pycache__/main.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/middleware.cpython-313.pyc b/mediaflow_proxy/__pycache__/middleware.cpython-313.pyc new file mode 100644 index 0000000..e0f249a Binary files /dev/null and b/mediaflow_proxy/__pycache__/middleware.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/mpd_processor.cpython-313.pyc b/mediaflow_proxy/__pycache__/mpd_processor.cpython-313.pyc new file mode 100644 index 0000000..2914060 Binary files /dev/null and b/mediaflow_proxy/__pycache__/mpd_processor.cpython-313.pyc differ diff --git a/mediaflow_proxy/__pycache__/schemas.cpython-313.pyc b/mediaflow_proxy/__pycache__/schemas.cpython-313.pyc new file mode 100644 index 0000000..564dba7 Binary files /dev/null and b/mediaflow_proxy/__pycache__/schemas.cpython-313.pyc differ diff --git a/mediaflow_proxy/drm/__pycache__/__init__.cpython-313.pyc b/mediaflow_proxy/drm/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..4995a07 Binary files /dev/null and b/mediaflow_proxy/drm/__pycache__/__init__.cpython-313.pyc differ diff --git a/mediaflow_proxy/drm/__pycache__/decrypter.cpython-313.pyc b/mediaflow_proxy/drm/__pycache__/decrypter.cpython-313.pyc new file mode 100644 index 0000000..824cebb Binary files /dev/null and b/mediaflow_proxy/drm/__pycache__/decrypter.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/__init__.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..8deddbd Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/__init__.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/base.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/base.cpython-313.pyc new file mode 100644 index 0000000..1fabf9e Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/base.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/dlhd.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/dlhd.cpython-313.pyc new file mode 100644 index 0000000..e1a645c Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/dlhd.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/doodstream.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/doodstream.cpython-313.pyc new file mode 100644 index 0000000..64216a6 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/doodstream.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/factory.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/factory.cpython-313.pyc new file mode 100644 index 0000000..81a282d Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/factory.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/fastream.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/fastream.cpython-313.pyc new file mode 100644 index 0000000..bcea29b Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/fastream.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/filelions.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/filelions.cpython-313.pyc new file mode 100644 index 0000000..0ac6995 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/filelions.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/livetv.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/livetv.cpython-313.pyc new file mode 100644 index 0000000..579d480 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/livetv.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/maxstream.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/maxstream.cpython-313.pyc new file mode 100644 index 0000000..ebf8661 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/maxstream.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-313.pyc new file mode 100644 index 0000000..d4698f8 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/mixdrop.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/okru.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/okru.cpython-313.pyc new file mode 100644 index 0000000..8314ec0 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/okru.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/streamtape.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/streamtape.cpython-313.pyc new file mode 100644 index 0000000..4aab4f2 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/streamtape.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/supervideo.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/supervideo.cpython-313.pyc new file mode 100644 index 0000000..9b56b02 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/supervideo.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/uqload.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/uqload.cpython-313.pyc new file mode 100644 index 0000000..4291a72 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/uqload.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/vavoo.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/vavoo.cpython-313.pyc new file mode 100644 index 0000000..8749a60 Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/vavoo.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-313.pyc b/mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-313.pyc new file mode 100644 index 0000000..a46cc6a Binary files /dev/null and b/mediaflow_proxy/extractors/__pycache__/vixcloud.cpython-313.pyc differ diff --git a/mediaflow_proxy/extractors/dlhd.py b/mediaflow_proxy/extractors/dlhd.py index d3556b4..2d58d5a 100644 --- a/mediaflow_proxy/extractors/dlhd.py +++ b/mediaflow_proxy/extractors/dlhd.py @@ -148,32 +148,51 @@ class DLHDExtractor(BaseExtractor): continue return None - def extract_bundle_format(js): - """Extract parameters from new BUNDLE format""" + def extract_xjz_format(js): + """Extract parameters from the new XJZ base64-encoded JSON format.""" + try: + # Look for the XJZ variable assignment + xjz_pattern = r'const\s+XJZ\s*=\s*["\']([^"\']+)["\']' + match = re.search(xjz_pattern, js) + if not match: + return None + xjz_b64 = match.group(1) + import json + # Decode the first base64 layer (JSON) + xjz_json = base64.b64decode(xjz_b64).decode('utf-8') + xjz_obj = json.loads(xjz_json) + # Each value is also base64-encoded, decode each + decoded = {} + for k, v in xjz_obj.items(): + try: + decoded[k] = base64.b64decode(v).decode('utf-8') + except Exception as e: + logger.warning(f"Failed to decode XJZ field {k}: {e}") + decoded[k] = v + return decoded + except Exception as e: + logger.warning(f"Failed to extract XJZ format: {e}") + return None + + def extract_bundle_format(js): + """Extract parameters from new BUNDLE format (legacy fallback).""" try: - # Look for BUNDLE variable bundle_patterns = [ r'const\s+BUNDLE\s*=\s*["\']([^"\']+)["\']', r'var\s+BUNDLE\s*=\s*["\']([^"\']+)["\']', r'let\s+BUNDLE\s*=\s*["\']([^"\']+)["\']' ] - bundle_data = None for pattern in bundle_patterns: match = re.search(pattern, js) if match: bundle_data = match.group(1) break - if not bundle_data: return None - - # Decode the bundle (base64 -> JSON -> decode each field) import json bundle_json = base64.b64decode(bundle_data).decode('utf-8') bundle_obj = json.loads(bundle_json) - - # Decode each base64 field decoded_bundle = {} for key, value in bundle_obj.items(): try: @@ -181,9 +200,7 @@ class DLHDExtractor(BaseExtractor): except Exception as e: logger.warning(f"Failed to decode bundle field {key}: {e}") decoded_bundle[key] = value - return decoded_bundle - except Exception as e: logger.warning(f"Failed to extract bundle format: {e}") return None @@ -204,28 +221,39 @@ class DLHDExtractor(BaseExtractor): channel_key = match.group(1) break - # Try new bundle format first - bundle_data = extract_bundle_format(iframe_content) - if bundle_data: - logger.info("Using new BUNDLE format for parameter extraction") - auth_host = bundle_data.get('b_host') - auth_php = bundle_data.get('b_script') - auth_ts = bundle_data.get('b_ts') - auth_rnd = bundle_data.get('b_rnd') - auth_sig = bundle_data.get('b_sig') - logger.debug(f"Bundle data extracted: {bundle_data}") + # Try new XJZ format first + xjz_data = extract_xjz_format(iframe_content) + if xjz_data: + logger.info("Using new XJZ format for parameter extraction") + auth_host = xjz_data.get('b_host') + auth_php = xjz_data.get('b_script') + auth_ts = xjz_data.get('b_ts') + auth_rnd = xjz_data.get('b_rnd') + auth_sig = xjz_data.get('b_sig') + logger.debug(f"XJZ data extracted: {xjz_data}") else: - logger.info("Falling back to old format for parameter extraction") - # Fall back to old format - auth_ts = extract_var_old_format(iframe_content, 'c') - auth_rnd = extract_var_old_format(iframe_content, 'd') - auth_sig = extract_var_old_format(iframe_content, 'e') - auth_host = extract_var_old_format(iframe_content, 'a') - auth_php = extract_var_old_format(iframe_content, 'b') - + # Try bundle format (legacy fallback) + bundle_data = extract_bundle_format(iframe_content) + if bundle_data: + logger.info("Using BUNDLE format for parameter extraction") + auth_host = bundle_data.get('b_host') + auth_php = bundle_data.get('b_script') + auth_ts = bundle_data.get('b_ts') + auth_rnd = bundle_data.get('b_rnd') + auth_sig = bundle_data.get('b_sig') + logger.debug(f"Bundle data extracted: {bundle_data}") + else: + logger.info("Falling back to old format for parameter extraction") + # Fall back to old format + auth_ts = extract_var_old_format(iframe_content, 'c') + auth_rnd = extract_var_old_format(iframe_content, 'd') + auth_sig = extract_var_old_format(iframe_content, 'e') + auth_host = extract_var_old_format(iframe_content, 'a') + auth_php = extract_var_old_format(iframe_content, 'b') + # Log what we found for debugging logger.debug(f"Extracted parameters: channel_key={channel_key}, auth_ts={auth_ts}, auth_rnd={auth_rnd}, auth_sig={auth_sig}, auth_host={auth_host}, auth_php={auth_php}") - + # Check which parameters are missing missing_params = [] if not channel_key: @@ -240,7 +268,7 @@ class DLHDExtractor(BaseExtractor): missing_params.append('auth_host (var a / b_host)') if not auth_php: missing_params.append('auth_php (var b / b_script)') - + if missing_params: logger.error(f"Missing parameters: {', '.join(missing_params)}") # Log a portion of the iframe content for debugging (first 2000 chars) @@ -248,7 +276,21 @@ class DLHDExtractor(BaseExtractor): raise ExtractorError(f"Error extracting parameters: missing {', '.join(missing_params)}") auth_sig = quote_plus(auth_sig) # 6. Richiesta auth - auth_url = f'{auth_host}{auth_php}?channel_id={channel_key}&ts={auth_ts}&rnd={auth_rnd}&sig={auth_sig}' + # Se il sito fornisce ancora /a.php ma ora serve /auth.php, sostituisci + # Normalize and robustly replace any variant of a.php with /auth.php + if auth_php: + normalized_auth_php = auth_php.strip().lstrip('/') + if normalized_auth_php == 'a.php': + logger.info("Sostituisco qualunque variante di a.php con /auth.php per compatibilità.") + auth_php = '/auth.php' + # Unisci host e script senza doppio slash + if auth_host.endswith('/') and auth_php.startswith('/'): + auth_url = f'{auth_host[:-1]}{auth_php}' + elif not auth_host.endswith('/') and not auth_php.startswith('/'): + auth_url = f'{auth_host}/{auth_php}' + else: + auth_url = f'{auth_host}{auth_php}' + auth_url = f'{auth_url}?channel_id={channel_key}&ts={auth_ts}&rnd={auth_rnd}&sig={auth_sig}' auth_resp = await self._make_request(auth_url, headers=daddylive_headers) # 7. Lookup server - Extract host parameter host = None diff --git a/mediaflow_proxy/extractors/factory.py b/mediaflow_proxy/extractors/factory.py index 233f4e2..f9b1ba1 100644 --- a/mediaflow_proxy/extractors/factory.py +++ b/mediaflow_proxy/extractors/factory.py @@ -3,6 +3,7 @@ from typing import Dict, Type from mediaflow_proxy.extractors.base import BaseExtractor, ExtractorError from mediaflow_proxy.extractors.dlhd import DLHDExtractor from mediaflow_proxy.extractors.doodstream import DoodStreamExtractor +from mediaflow_proxy.extractors.filelions import FileLionsExtractor from mediaflow_proxy.extractors.livetv import LiveTVExtractor from mediaflow_proxy.extractors.maxstream import MaxstreamExtractor from mediaflow_proxy.extractors.mixdrop import MixdropExtractor @@ -19,6 +20,7 @@ class ExtractorFactory: _extractors: Dict[str, Type[BaseExtractor]] = { "Doodstream": DoodStreamExtractor, + "FileLions": FileLionsExtractor, "Uqload": UqloadExtractor, "Mixdrop": MixdropExtractor, "Streamtape": StreamtapeExtractor, diff --git a/mediaflow_proxy/extractors/fastream.py b/mediaflow_proxy/extractors/fastream.py index 532137e..dcfe8c4 100644 --- a/mediaflow_proxy/extractors/fastream.py +++ b/mediaflow_proxy/extractors/fastream.py @@ -14,9 +14,9 @@ class FastreamExtractor(BaseExtractor): async def extract(self, url: str, **kwargs) -> Dict[str, Any]: headers = {'Accept': '*/*', 'Connection': 'keep-alive','Accept-Language': 'en-US,en;q=0.5','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:138.0) Gecko/20100101 Firefox/138.0'} - pattern = r'file:"(.*?)"' + patterns = [r'file:"(.*?)"'] - final_url = await eval_solver(self, url, headers, pattern) + final_url = await eval_solver(self, url, headers, patterns) self.base_headers["referer"] = f'https://{url.replace("https://","").split("/")[0]}/' self.base_headers["origin"] = f'https://{url.replace("https://","").split("/")[0]}' diff --git a/mediaflow_proxy/extractors/filelions.py b/mediaflow_proxy/extractors/filelions.py new file mode 100644 index 0000000..6f68763 --- /dev/null +++ b/mediaflow_proxy/extractors/filelions.py @@ -0,0 +1,25 @@ +from typing import Dict, Any + +from mediaflow_proxy.extractors.base import BaseExtractor +from mediaflow_proxy.utils.packed import eval_solver + +class FileLionsExtractor(BaseExtractor): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.mediaflow_endpoint = "hls_manifest_proxy" + + async def extract(self, url: str, **kwargs) -> Dict[str, Any]: + headers = {} + patterns = [ # See https://github.com/Gujal00/ResolveURL/blob/master/script.module.resolveurl/lib/resolveurl/plugins/filelions.py + r'''sources:\s*\[{file:\s*["'](?P[^"']+)''', + r'''["']hls[24]["']:\s*["'](?P[^"']+)''' + ] + + final_url = await eval_solver(self, url, headers, patterns) + + self.base_headers["referer"] = url + return { + "destination_url": final_url, + "request_headers": self.base_headers, + "mediaflow_endpoint": self.mediaflow_endpoint, + } diff --git a/mediaflow_proxy/extractors/mixdrop.py b/mediaflow_proxy/extractors/mixdrop.py index 5b3df08..bd77f34 100644 --- a/mediaflow_proxy/extractors/mixdrop.py +++ b/mediaflow_proxy/extractors/mixdrop.py @@ -13,9 +13,9 @@ class MixdropExtractor(BaseExtractor): url = url.replace("club", "ps").split("/2")[0] headers = {"accept-language": "en-US,en;q=0.5"} - pattern = r'MDCore.wurl ?= ?"(.*?)"' + patterns = [r'MDCore.wurl ?= ?"(.*?)"'] - final_url = f"https:{await eval_solver(self, url, headers, pattern)}" + final_url = await eval_solver(self, url, headers, patterns) self.base_headers["referer"] = url return { diff --git a/mediaflow_proxy/extractors/okru.py b/mediaflow_proxy/extractors/okru.py index 483e888..bf6d307 100644 --- a/mediaflow_proxy/extractors/okru.py +++ b/mediaflow_proxy/extractors/okru.py @@ -22,8 +22,7 @@ class OkruExtractor(BaseExtractor): data_options = div.get("data-options") data = json.loads(data_options) metadata = json.loads(data["flashvars"]["metadata"]) - final_url = metadata["hlsMasterPlaylistUrl"] - + final_url = metadata.get("hlsMasterPlaylistUrl") or metadata.get("hlsManifestUrl") self.base_headers["referer"] = url return { "destination_url": final_url, diff --git a/mediaflow_proxy/extractors/supervideo.py b/mediaflow_proxy/extractors/supervideo.py index 3161331..f2be69a 100644 --- a/mediaflow_proxy/extractors/supervideo.py +++ b/mediaflow_proxy/extractors/supervideo.py @@ -15,9 +15,9 @@ class SupervideoExtractor(BaseExtractor): async def extract(self, url: str, **kwargs) -> Dict[str, Any]: headers = {'Accept': '*/*', 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36', 'user-agent': 'Mozilla/5.0 (Linux; Android 12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.71 Mobile Safari/537.36'} - pattern = r'file:"(.*?)"' + patterns = [r'file:"(.*?)"'] - final_url = await eval_solver(self, url, headers, pattern) + final_url = await eval_solver(self, url, headers, patterns) self.base_headers["referer"] = url return { diff --git a/mediaflow_proxy/routes/__pycache__/__init__.cpython-313.pyc b/mediaflow_proxy/routes/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..92c3618 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/__init__.cpython-313.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/extractor.cpython-313.pyc b/mediaflow_proxy/routes/__pycache__/extractor.cpython-313.pyc new file mode 100644 index 0000000..9c7da36 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/extractor.cpython-313.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/playlist_builder.cpython-313.pyc b/mediaflow_proxy/routes/__pycache__/playlist_builder.cpython-313.pyc new file mode 100644 index 0000000..184a491 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/playlist_builder.cpython-313.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/proxy.cpython-313.pyc b/mediaflow_proxy/routes/__pycache__/proxy.cpython-313.pyc new file mode 100644 index 0000000..6d17bf7 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/proxy.cpython-313.pyc differ diff --git a/mediaflow_proxy/routes/__pycache__/speedtest.cpython-313.pyc b/mediaflow_proxy/routes/__pycache__/speedtest.cpython-313.pyc new file mode 100644 index 0000000..14a4287 Binary files /dev/null and b/mediaflow_proxy/routes/__pycache__/speedtest.cpython-313.pyc differ diff --git a/mediaflow_proxy/schemas.py b/mediaflow_proxy/schemas.py index 2684d98..94e0439 100644 --- a/mediaflow_proxy/schemas.py +++ b/mediaflow_proxy/schemas.py @@ -96,7 +96,7 @@ class MPDSegmentParams(GenericParams): class ExtractorURLParams(GenericParams): host: Literal[ - "Doodstream", "Mixdrop", "Uqload", "Streamtape", "Supervideo", "VixCloud", "Okru", "Maxstream", "LiveTV", "DLHD", "Fastream" + "Doodstream", "FileLions", "Mixdrop", "Uqload", "Streamtape", "Supervideo", "VixCloud", "Okru", "Maxstream", "LiveTV", "DLHD", "Fastream" ] = Field(..., description="The host to extract the URL from.") destination: str = Field(..., description="The URL of the stream.", alias="d") redirect_stream: bool = Field(False, description="Whether to redirect to the stream endpoint automatically.") diff --git a/mediaflow_proxy/speedtest/__pycache__/__init__.cpython-313.pyc b/mediaflow_proxy/speedtest/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..b662e93 Binary files /dev/null and b/mediaflow_proxy/speedtest/__pycache__/__init__.cpython-313.pyc differ diff --git a/mediaflow_proxy/speedtest/__pycache__/models.cpython-313.pyc b/mediaflow_proxy/speedtest/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000..d52f282 Binary files /dev/null and b/mediaflow_proxy/speedtest/__pycache__/models.cpython-313.pyc differ diff --git a/mediaflow_proxy/speedtest/__pycache__/service.cpython-313.pyc b/mediaflow_proxy/speedtest/__pycache__/service.cpython-313.pyc new file mode 100644 index 0000000..2e95076 Binary files /dev/null and b/mediaflow_proxy/speedtest/__pycache__/service.cpython-313.pyc differ diff --git a/mediaflow_proxy/speedtest/providers/__pycache__/all_debrid.cpython-313.pyc b/mediaflow_proxy/speedtest/providers/__pycache__/all_debrid.cpython-313.pyc new file mode 100644 index 0000000..9d47366 Binary files /dev/null and b/mediaflow_proxy/speedtest/providers/__pycache__/all_debrid.cpython-313.pyc differ diff --git a/mediaflow_proxy/speedtest/providers/__pycache__/base.cpython-313.pyc b/mediaflow_proxy/speedtest/providers/__pycache__/base.cpython-313.pyc new file mode 100644 index 0000000..2d2a5e9 Binary files /dev/null and b/mediaflow_proxy/speedtest/providers/__pycache__/base.cpython-313.pyc differ diff --git a/mediaflow_proxy/speedtest/providers/__pycache__/real_debrid.cpython-313.pyc b/mediaflow_proxy/speedtest/providers/__pycache__/real_debrid.cpython-313.pyc new file mode 100644 index 0000000..7b29313 Binary files /dev/null and b/mediaflow_proxy/speedtest/providers/__pycache__/real_debrid.cpython-313.pyc differ diff --git a/mediaflow_proxy/static/index.html b/mediaflow_proxy/static/index.html index 87860dd..bf2fe93 100644 --- a/mediaflow_proxy/static/index.html +++ b/mediaflow_proxy/static/index.html @@ -1,3 +1,137 @@ -

"The App is running"

+ + + + + MediaFlow Proxy + + + + +
+ MediaFlow Proxy Logo +

MediaFlow Proxy

+
+

A high-performance proxy server for streaming media, supporting HTTP(S), HLS, and MPEG-DASH with real-time DRM decryption.

+ +

Key Features

+
Convert MPEG-DASH streams (DRM-protected and non-protected) to HLS
+
Support for Clear Key DRM-protected MPD DASH streams
+
Handle both live and video-on-demand (VOD) DASH streams
+
Proxy HTTP/HTTPS links with custom headers
+
Proxy and modify HLS (M3U8) streams in real-time with custom headers and key URL modifications for bypassing some sneaky restrictions.
+
HLS and DASH pre-buffering for improved streaming performance and reduced latency
+
Protect against unauthorized access and network bandwidth abuses
+ +
+

🚀 Speed Test Tool

+

Test your connection speed with debrid services to optimize your streaming experience:

+ +

+ Browser Speed Test: Tests your actual connection speed through MediaFlow proxy vs direct connection with support for multiple servers, interactive charts, and comprehensive analytics. +

+
+ +
+

🔗 Playlist Builder

+

Create and combine M3U playlists with automatic link rewriting for optimal streaming experience:

+ +

+ Playlist Builder: Combine multiple M3U playlists, automatically rewrite links for optimal streaming, and support custom headers for enhanced compatibility. +

+
+ +

Getting Started

+

Visit the GitHub repository for installation instructions and documentation.

+ +

Premium Hosted Service

+

For a hassle-free experience, check out premium hosted service on ElfHosted.

+ +

API Documentation

+

Explore the Swagger UI for comprehensive details about the API endpoints and their usage.

+ + diff --git a/mediaflow_proxy/utils/__pycache__/__init__.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..fb260b3 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/__init__.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/base64_utils.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/base64_utils.cpython-313.pyc new file mode 100644 index 0000000..261c576 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/base64_utils.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/cache_utils.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/cache_utils.cpython-313.pyc new file mode 100644 index 0000000..09ac23c Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/cache_utils.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-313.pyc new file mode 100644 index 0000000..94816cd Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/crypto_utils.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/dash_prebuffer.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/dash_prebuffer.cpython-313.pyc new file mode 100644 index 0000000..37a4f60 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/dash_prebuffer.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/hls_prebuffer.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/hls_prebuffer.cpython-313.pyc new file mode 100644 index 0000000..45f152f Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/hls_prebuffer.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/http_utils.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/http_utils.cpython-313.pyc new file mode 100644 index 0000000..8a32b12 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/http_utils.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-313.pyc new file mode 100644 index 0000000..f702f98 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/m3u8_processor.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-313.pyc new file mode 100644 index 0000000..80decf4 Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/mpd_utils.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/__pycache__/packed.cpython-313.pyc b/mediaflow_proxy/utils/__pycache__/packed.cpython-313.pyc new file mode 100644 index 0000000..78cb77a Binary files /dev/null and b/mediaflow_proxy/utils/__pycache__/packed.cpython-313.pyc differ diff --git a/mediaflow_proxy/utils/packed.py b/mediaflow_proxy/utils/packed.py index b1f03e8..a4eb748 100644 --- a/mediaflow_proxy/utils/packed.py +++ b/mediaflow_proxy/utils/packed.py @@ -14,6 +14,7 @@ import re from bs4 import BeautifulSoup, SoupStrainer +from urllib.parse import urljoin, urlparse import logging @@ -142,7 +143,7 @@ class UnpackingError(Exception): -async def eval_solver(self, url: str, headers, pattern: str) -> str: +async def eval_solver(self, url: str, headers: dict[str, str] | None, patterns: list[str]) -> str: try: response = await self._make_request(url, headers=headers) soup = BeautifulSoup(response.text, "lxml",parse_only=SoupStrainer("script")) @@ -150,10 +151,15 @@ async def eval_solver(self, url: str, headers, pattern: str) -> str: for i in script_all: if detect(i.text): unpacked_code = unpack(i.text) - match = re.search(pattern, unpacked_code) - if match: - m3u8_url = match.group(1) - return m3u8_url + for pattern in patterns: + match = re.search(pattern, unpacked_code) + if match: + extracted_url = match.group(1) + if not urlparse(extracted_url).scheme: + extracted_url = urljoin(url, extracted_url) + + return extracted_url + raise UnpackingError("No p.a.c.k.e.d JS found or no pattern matched.") except Exception as e: - logger.error("Eval solver error\n",e) - raise Exception("Error in eval_solver") \ No newline at end of file + logger.exception("Eval solver error for %s", url) + raise UnpackingError("Error in eval_solver") from e \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2376853..fbea228 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,3 +17,4 @@ starlette cachetools tqdm aiofiles +psutil