Files

204 lines
6.8 KiB
Python

import base64
import binascii
import json
import platform
import shutil
import urllib
import winreg
from pathlib import Path
from urllib.parse import unquote
import sys
import os
import logging
logger = logging.getLogger("PlaylistSaver.Utils")
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler(sys.stdout))
def set_info(target_logger):
global logger
logger = target_logger
def key_exists(hive, sub_key):
try:
# Attempt to open the key for reading
with winreg.OpenKey(hive, sub_key, 0, winreg.KEY_READ) as key:
return True
except FileNotFoundError:
return False
def create_url_scheme(main_file_path, work_dir):
try:
scheme = "PlaylistSaver"
base = r"Software\Classes\\" + scheme
key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, base)
winreg.SetValueEx(key, None, 0, winreg.REG_SZ, f"URL:{scheme} Protocol")
winreg.SetValueEx(key, "URL Protocol", 0, winreg.REG_SZ, "")
shell_key = winreg.CreateKey(key, "shell")
open_key = winreg.CreateKey(shell_key, "open")
command_key = winreg.CreateKey(open_key, "command")
if getattr(sys, 'frozen', False):
command = f"\"{sys.executable}\" --new-work-dir \"{work_dir}\" \"%1\""
else:
command = f"\"{sys.executable}\" \"{main_file_path}\" --new-work-dir \"{work_dir}\" \"%1\""
winreg.SetValueEx(command_key, None, 0, winreg.REG_SZ, command)
logger.info("URL scheme registered.")
except OSError as e:
logger.error("Unable to create URL scheme: %s", e)
def check_url_scheme(main_file_path, work_dir):
try:
if not key_exists(winreg.HKEY_LOCAL_MACHINE, "PlaylistSaver"):
create_url_scheme(main_file_path, work_dir)
except FileNotFoundError:
create_url_scheme(main_file_path, work_dir)
def read_cookies(cookie_path):
try:
with open(cookie_path, "r", encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
logger.error("Cookies file not found.")
except Exception as e:
logger.error("An unexpected error occurred while reading cookies: %s", e)
def save_cookies(cookies, cookie_path):
try:
os.makedirs(os.path.dirname(cookie_path), exist_ok=True)
with open(cookie_path, "w", encoding='utf-8') as f:
f.write(cookies)
except Exception as e:
logger.error("An unexpected error occurred while saving cookies: %s", e)
def save_base64_netscape_cookie(cookies_encoded, cookie_path):
try:
cookies = base64.b64decode(cookies_encoded).decode("utf-8")
except binascii.Error:
logger.error("Unable to decode base64 cookie: %s", cookies_encoded)
return
logger.debug("==== COOKIE FILE ====")
for line in cookies.split("\n"):
print(line, "=>", len(line.split("\t")))
logger.debug("=====================")
save_cookies(cookies, cookie_path)
def parser_url_scheme(url, cookie_path: Path):
logger.debug("Parsing URL scheme: %s", url)
url = urllib.parse.urlparse(unquote(url))
parameters = urllib.parse.parse_qs(url.query)
func_map = {
"base64cookies": {
"func": save_base64_netscape_cookie,
"args": [parameters["base64cookies"][0], cookie_path]
},
}
for arg_name in parameters:
match_func = func_map.get(arg_name, {}).get("func")
if match_func:
match_func(*func_map[arg_name].get("args", []))
else:
logger.warning("Unknown parameter: %s Value: %s", arg_name, parameters[arg_name])
def save_json(data: dict, dest):
try:
os.makedirs(os.path.dirname(dest), exist_ok=True)
with open(dest, "w", encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
except Exception as e:
logger.error("Unable to save json: %s", e)
def read_json(path):
try:
with open(path, "r", encoding='utf-8') as f:
return json.load(f)
except Exception as 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)