Files
2026-07-17 09:24:47 +08:00

117 lines
3.1 KiB
Python

"""应用路径:开发目录 vs PyInstaller 打包 exe。"""
from __future__ import annotations
import os
import sys
from pathlib import Path
def is_frozen() -> bool:
return bool(getattr(sys, "frozen", False))
def app_root() -> Path:
"""exe 所在目录 / 源码目录(可写:浏览器、输出 JSON)。"""
if is_frozen():
return Path(sys.executable).resolve().parent
return Path(__file__).resolve().parent
def bundle_root() -> Path:
"""打包内资源目录(只读)。"""
if is_frozen():
return Path(getattr(sys, "_MEIPASS", app_root()))
return app_root()
def ui_html_path() -> Path:
for candidate in (
bundle_root() / "douyin_collector_ui.html",
app_root() / "douyin_collector_ui.html",
):
if candidate.is_file():
return candidate
return app_root() / "douyin_collector_ui.html"
def is_gui_mode() -> bool:
"""无黑窗口模式:pythonw / 无控制台 exe / COLLECTOR_GUI=1。"""
if os.environ.get("DOUYIN_CONSOLE") == "1":
return False
if os.environ.get("COLLECTOR_GUI") == "1":
return True
if Path(sys.executable).name.lower() == "pythonw.exe":
return True
if is_frozen() and sys.platform == "win32":
try:
import ctypes
return ctypes.windll.kernel32.GetConsoleWindow() == 0
except Exception:
return True
return False
def splash_html_path() -> Path:
for candidate in (
bundle_root() / "splash.html",
app_root() / "splash.html",
):
if candidate.is_file():
return candidate
return app_root() / "splash.html"
def launch_splash() -> None:
"""立即打开启动动画页(空白期反馈)。"""
if os.environ.get("SPLASH_LAUNCHED") == "1":
return
splash = splash_html_path()
if not splash.is_file():
return
os.environ["SPLASH_LAUNCHED"] = "1"
if sys.platform == "win32":
try:
import subprocess
subprocess.Popen(
["cmd", "/c", "start", "", str(splash.resolve())],
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
close_fds=True,
)
return
except Exception:
pass
try:
import webbrowser
webbrowser.open(splash.resolve().as_uri())
except Exception:
pass
def use_incognito_ui() -> bool:
"""凭证页与登录页均在 Playwright 无痕窗口内打开(默认开启)。"""
if os.environ.get("DOUYIN_CONSOLE") == "1":
return False
if os.environ.get("COLLECTOR_EXTERNAL_BROWSER") == "1":
return False
return True
def browser_ready_file() -> Path:
return app_root() / ".browser_ready"
def clear_browser_ready() -> None:
try:
path = browser_ready_file()
if path.is_file():
path.unlink()
except Exception:
pass
def signal_browser_ready() -> None:
try:
browser_ready_file().write_text(str(int(__import__("time").time())), encoding="utf-8")
except Exception:
pass