diff --git a/jd-webgui/app.py b/jd-webgui/app.py index 4fc2064..4cd5fcd 100644 --- a/jd-webgui/app.py +++ b/jd-webgui/app.py @@ -56,6 +56,7 @@ POLL_SECONDS = float(os.environ.get("POLL_SECONDS", "5")) # JDownloader writes here inside container JD_OUTPUT_PATH = "/output" +PROXY_EXPORT_PATH = os.environ.get("PROXY_EXPORT_PATH", "/output/jd-proxies.jdproxies") URL_RE = re.compile(r"^https?://", re.I) @@ -365,6 +366,96 @@ def fetch_proxy_list(url: str) -> str: with urllib.request.urlopen(req, timeout=20) as resp: return resp.read().decode("utf-8", "replace") +def build_jdproxies_payload(text: str) -> Dict[str, Any]: + if not text.strip(): + raise ValueError("Keine Proxy-Einträge zum Speichern.") + blacklist_filter = { + "entries": [ + "# Dies ist ein Kommentar", + "// Dies ist auch ein Kommentar", + "# Für jdownloader.org auskommentieren", + "# jdownloader.org", + "# unten für alle Accounts mit der ID 'test *' @ jdownloader.org auskommentieren", + "#test@jdownloader.org", + "# Kommentar unten für ein Konto mit der ID 'test' @ jdownloader.org", + "#test$@jdownloader.org", + "# Sie können Muster für Konto-ID und Host verwenden, z. B. accountPattern @ hostPattern", + "", + "my.jdownloader.org", + "", + "api.jdownloader.org", + "", + "*.jdownloader.org", + ], + "type": "BLACKLIST", + } + entries: List[Dict[str, Any]] = [] + type_map = { + "socks5": "SOCKS5", + "socks4": "SOCKS4", + "http": "HTTP", + } + entries.append({ + "filter": None, + "proxy": { + "address": None, + "password": None, + "port": 80, + "type": "NONE", + "username": None, + "connectMethodPrefered": False, + "preferNativeImplementation": False, + "resolveHostName": False, + }, + "enabled": True, + "pac": False, + "rangeRequestsSupported": True, + "reconnectSupported": True, + }) + for line in text.splitlines(): + s = line.strip() + if not s: + continue + parsed = urllib.parse.urlparse(s) + if not parsed.scheme or not parsed.hostname or parsed.port is None: + continue + proxy_type = type_map.get(parsed.scheme.lower()) + if not proxy_type: + continue + entries.append({ + "filter": blacklist_filter, + "proxy": { + "address": parsed.hostname, + "password": None, + "port": int(parsed.port), + "type": proxy_type, + "username": None, + "connectMethodPrefered": False, + "preferNativeImplementation": False, + "resolveHostName": False, + }, + "enabled": True, + "pac": False, + "rangeRequestsSupported": True, + "reconnectSupported": False, + }) + if not entries: + raise ValueError("Keine gültigen Proxy-Einträge gefunden.") + return {"customProxyList": entries} + +def save_proxy_export(text: str) -> str: + payload = build_jdproxies_payload(text) + export_path = PROXY_EXPORT_PATH + export_dir = os.path.dirname(export_path) + if export_dir: + os.makedirs(export_dir, exist_ok=True) + if os.path.exists(export_path): + os.remove(export_path) + with open(export_path, "w", encoding="utf-8") as handle: + handle.write(json.dumps(payload, indent=2)) + handle.write("\n") + return export_path + def pick_library_target(library_choice: str, filename: str, package_name: str) -> str: if library_choice not in {"movies", "series", "auto"}: library_choice = "auto" @@ -829,8 +920,17 @@ def render_nav(active: str) -> str: + "" ) -def render_proxies_page(error: str = "", socks5_in: str = "", socks4_in: str = "", http_in: str = "", out_text: str = "") -> str: +def render_proxies_page( + error: str = "", + message: str = "", + socks5_in: str = "", + socks4_in: str = "", + http_in: str = "", + out_text: str = "", + export_path: str = "", +) -> str: err_html = f"
{error}
" if error else "" + msg_html = f"{message}
" if message else "" return f""" @@ -842,6 +942,7 @@ def render_proxies_page(error: str = "", socks5_in: str = "", socks4_in: str = "Aktueller Pfad: {export_path or PROXY_EXPORT_PATH}