Add qt support, some ui design changes and remove batch download support.

This commit is contained in:
2026-06-18 21:16:09 +08:00
parent 76904a62e3
commit eadc5c6267
5 changed files with 1397 additions and 918 deletions
+2
View File
@@ -1,2 +1,4 @@
/save/ /save/
/temp/ /temp/
/main.build/
/main.dist/
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+1299 -901
View File
File diff suppressed because it is too large Load Diff
+96 -17
View File
@@ -1,6 +1,8 @@
import base64 import base64
import binascii import binascii
import json import json
import platform
import shutil
import urllib import urllib
import winreg import winreg
from pathlib import Path from pathlib import Path
@@ -25,7 +27,7 @@ def key_exists(hive, sub_key):
except FileNotFoundError: except FileNotFoundError:
return False return False
def create_url_scheme(): def create_url_scheme(main_file_path, work_dir):
try: try:
scheme = "PlaylistSaver" scheme = "PlaylistSaver"
base = r"Software\Classes\\" + scheme base = r"Software\Classes\\" + scheme
@@ -40,23 +42,23 @@ def create_url_scheme():
command_key = winreg.CreateKey(open_key, "command") command_key = winreg.CreateKey(open_key, "command")
if getattr(sys, 'frozen', False): if getattr(sys, 'frozen', False):
command = f"\"{sys.executable}\" \"%1\"" command = f"\"{sys.executable}\" --new-work-dir \"{work_dir}\" \"%1\""
else: else:
command = f"\"{sys.executable}\" \"{os.path.abspath(__file__)}\" \"%1\"" command = f"\"{sys.executable}\" \"{main_file_path}\" --new-work-dir \"{work_dir}\" \"%1\""
winreg.SetValueEx(command_key, None, 0, winreg.REG_SZ, command) winreg.SetValueEx(command_key, None, 0, winreg.REG_SZ, command)
logger.info("URL scheme registered.") logger.info("URL scheme registered.")
except OSError as e: except OSError as e:
logger.error("Unable to create URL scheme:", e) logger.error("Unable to create URL scheme: %s", e)
def check_url_scheme(): def check_url_scheme(main_file_path, work_dir):
try: try:
if not key_exists(winreg.HKEY_LOCAL_MACHINE, "PlaylistSaver"): if not key_exists(winreg.HKEY_LOCAL_MACHINE, "PlaylistSaver"):
create_url_scheme() create_url_scheme(main_file_path, work_dir)
except FileNotFoundError: except FileNotFoundError:
create_url_scheme() create_url_scheme(main_file_path, work_dir)
def read_cookies(cookie_path): def read_cookies(cookie_path):
try: try:
@@ -65,7 +67,7 @@ def read_cookies(cookie_path):
except FileNotFoundError: except FileNotFoundError:
logger.error("Cookies file not found.") logger.error("Cookies file not found.")
except Exception as e: except Exception as e:
logger.error("An unexpected error occurred while reading cookies:", e) logger.error("An unexpected error occurred while reading cookies: %s", e)
def save_cookies(cookies, cookie_path): def save_cookies(cookies, cookie_path):
try: try:
@@ -73,13 +75,13 @@ def save_cookies(cookies, cookie_path):
with open(cookie_path, "w", encoding='utf-8') as f: with open(cookie_path, "w", encoding='utf-8') as f:
f.write(cookies) f.write(cookies)
except Exception as e: except Exception as e:
logger.error("An unexpected error occurred while saving cookies:", e) logger.error("An unexpected error occurred while saving cookies: %s", e)
def save_base64_netscape_cookie(cookies_encoded, cookie_path): def save_base64_netscape_cookie(cookies_encoded, cookie_path):
try: try:
cookies = base64.b64decode(cookies_encoded).decode("utf-8") cookies = base64.b64decode(cookies_encoded).decode("utf-8")
except binascii.Error: except binascii.Error:
logger.error("Unable to decode base64 cookie:", cookies_encoded) logger.error("Unable to decode base64 cookie: %s", cookies_encoded)
return return
logger.debug("==== COOKIE FILE ====") logger.debug("==== COOKIE FILE ====")
@@ -89,16 +91,16 @@ def save_base64_netscape_cookie(cookies_encoded, cookie_path):
save_cookies(cookies, cookie_path) save_cookies(cookies, cookie_path)
def parser_url_scheme(url, work_dir: Path): def parser_url_scheme(url, cookie_path: Path):
logger.debug("Parsing URL scheme:", url) logger.debug("Parsing URL scheme: %s", url)
url = urllib.parse.urlparse(unquote(sys.argv[1])) url = urllib.parse.urlparse(unquote(url))
parameters = urllib.parse.parse_qs(url.query) parameters = urllib.parse.parse_qs(url.query)
func_map = { func_map = {
"base64cookies": { "base64cookies": {
"func": save_base64_netscape_cookie, "func": save_base64_netscape_cookie,
"args": [parameters["base64cookies"][0], work_dir] "args": [parameters["base64cookies"][0], cookie_path]
}, },
} }
@@ -107,7 +109,7 @@ def parser_url_scheme(url, work_dir: Path):
if match_func: if match_func:
match_func(*func_map[arg_name].get("args", [])) match_func(*func_map[arg_name].get("args", []))
else: else:
logger.warning("Unknown parameter:", arg_name, " Value:", parameters[arg_name]) logger.warning("Unknown parameter: %s Value: %s", arg_name, parameters[arg_name])
def save_json(data: dict, dest): def save_json(data: dict, dest):
try: try:
@@ -115,11 +117,88 @@ def save_json(data: dict, dest):
with open(dest, "w", encoding='utf-8') as f: with open(dest, "w", encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4) json.dump(data, f, ensure_ascii=False, indent=4)
except Exception as e: except Exception as e:
logger.error("Unable to save json:", e) logger.error("Unable to save json: %s", e)
def read_json(path): def read_json(path):
try: try:
with open(path, "r", encoding='utf-8') as f: with open(path, "r", encoding='utf-8') as f:
return json.load(f) return json.load(f)
except Exception as e: except Exception as e:
logger.error("Unable to read json:", e) logger.error("Unable to read json: %s", e)
def find_mpv_path(program_dir: Path):
local_candidates = [
]
platform_name = platform.system().lower()
machine = platform.machine().lower()
if platform.system().lower() == "windows" and ("amd64" in machine or "x86_64" in machine):
local_candidates.append(Path(program_dir, "bin", "mpv", "nt", "x64", "mpv.exe"))
elif platform.system().lower() == "windows" and ("arm64" in machine or "aarch64" in machine):
local_candidates.append(Path(program_dir, "bin", "mpv", "nt", "arm", "mpv.exe"))
elif platform.system().lower() == "windows" and machine in {"x86", "i386", "i686"}:
local_candidates.append(Path(program_dir, "bin", "mpv", "nt", "x86", "mpv.exe"))
if platform.system().lower() == "darwin" and ("amd64" in machine or "x86_64" in machine):
local_candidates.append(Path(program_dir, "bin", "mpv", "darwin", "x64", "mpv"))
elif platform.system() == "darwin" and ("arm64" in machine or "aarch64" in machine):
local_candidates.append(Path(program_dir, "bin", "mpv", "darwin", "arm", "mpv"))
if platform.system().lower() == "linux" and ("amd64" in machine or "x86_64" in machine):
local_candidates.append(Path(program_dir, "bin", "mpv", "linux", "x64", "mpv"))
elif platform.system().lower() == "linux" and ("arm64" in machine or "aarch64" in machine):
local_candidates.append(Path(program_dir, "bin", "mpv", "linux", "arm", "mpv"))
elif platform.system().lower() == "linux" and machine in {"x86", "i386", "i686"}:
local_candidates.append(Path(program_dir, "bin", "mpv", "linux", "x86", "mpv.exe"))
for candidate in local_candidates:
if candidate.exists() and candidate.is_file():
return candidate
# failback to PATH mpv (if available)
return shutil.which("mpv")
def find_http_status(exc: Exception):
seen = set()
stack = [exc]
while stack:
cur = stack.pop()
if cur is None or id(cur) in seen:
continue
seen.add(id(cur))
status = getattr(cur, "status", None) or getattr(cur, "code", None)
if status is not None:
return status
stack.extend([
getattr(cur, "__cause__", None),
getattr(cur, "__context__", None),
])
return None
def cookie_string_to_netscape(cookie_str):
lines = ["# Netscape HTTP Cookie File"]
for pair in cookie_str.split(";"):
pair = pair.strip()
if not pair or "=" not in pair:
continue
name, value = pair.split("=", 1) # ← 關鍵修正
lines.append("\t".join([
".youtube.com",
"TRUE",
"/",
"TRUE",
"9999999999",
name.strip(),
value.strip()
]))
return "\n".join(lines)