94 lines
2.8 KiB
Python
94 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Data directory, profile path, CLI path debugging output.
|
|
"""
|
|
import os
|
|
import re
|
|
import sys
|
|
from typing import Optional
|
|
|
|
from jiangchang_skill_core.runtime_env import get_data_root, get_user_id
|
|
from util.constants import SKILL_SLUG
|
|
|
|
|
|
def get_skill_data_dir() -> str:
|
|
path = os.path.join(get_data_root(), get_user_id(), SKILL_SLUG)
|
|
os.makedirs(path, exist_ok=True)
|
|
return path
|
|
|
|
|
|
def get_db_path() -> str:
|
|
return os.path.join(get_skill_data_dir(), "account-manager.db")
|
|
|
|
|
|
def _runtime_paths_debug_text() -> str:
|
|
"""For debugging: print current data path info to stderr."""
|
|
env_root = (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip() or "(未设置)"
|
|
env_uid = (os.getenv("JIANGCHANG_USER_ID") or "").strip() or "(未设置→使用 _anon)"
|
|
return (
|
|
"[account-manager] "
|
|
f"JIANGCHANG_DATA_ROOT={env_root} | "
|
|
f"JIANGCHANG_USER_ID={env_uid} | "
|
|
f"实际数据根={get_data_root()} | "
|
|
f"实际用户目录={get_user_id()} | "
|
|
f"数据库文件={get_db_path()}"
|
|
)
|
|
|
|
|
|
def _maybe_print_paths_debug_cli() -> None:
|
|
"""Set JIANGCHANG_ACCOUNT_DEBUG_PATHS=1 to print paths in stderr."""
|
|
v = (os.getenv("JIANGCHANG_ACCOUNT_DEBUG_PATHS") or "").strip().lower()
|
|
if v in ("1", "true", "yes", "on"):
|
|
print(_runtime_paths_debug_text(), file=sys.stderr)
|
|
|
|
|
|
_WIN_FS_FORBIDDEN = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
|
|
_WIN_RESERVED_NAMES = frozenset(
|
|
["CON", "PRN", "AUX", "NUL"]
|
|
+ [f"COM{i}" for i in range(1, 10)]
|
|
+ [f"LPT{i}" for i in range(1, 10)]
|
|
)
|
|
|
|
|
|
def _fs_safe_segment(name: str, fallback: str) -> str:
|
|
"""Single directory segment: strip Windows-unsafe chars; empty -> fallback."""
|
|
t = _WIN_FS_FORBIDDEN.sub("_", (name or "").strip())
|
|
t = t.rstrip(" .")
|
|
if not t:
|
|
t = fallback
|
|
if t.upper() in _WIN_RESERVED_NAMES:
|
|
t = f"_{t}"
|
|
return t
|
|
|
|
|
|
def get_default_profile_dir_for_web(
|
|
platform_key: str,
|
|
label: str,
|
|
login_id: Optional[str] = None,
|
|
domain: str = "generic",
|
|
) -> str:
|
|
"""
|
|
Generate a browser profile directory path.
|
|
|
|
Structure:
|
|
{DATA_ROOT}/{USER_ID}/account-manager/profiles/{domain}/{platform_key}/{safe_label}[_{login_id_suffix]/
|
|
|
|
This keeps profiles organized by domain and platform for easy
|
|
identification in file explorer.
|
|
"""
|
|
label_seg = _fs_safe_segment(label, platform_key)
|
|
login_suffix = ""
|
|
if login_id:
|
|
safe_login = _fs_safe_segment(login_id, "")
|
|
if safe_login:
|
|
login_suffix = f"_{safe_login[:16]}"
|
|
path = os.path.join(
|
|
get_skill_data_dir(),
|
|
"profiles",
|
|
_fs_safe_segment(domain, "generic"),
|
|
_fs_safe_segment(platform_key, "unknown"),
|
|
f"{label_seg}{login_suffix}",
|
|
)
|
|
os.makedirs(path, exist_ok=True)
|
|
return path
|