chore: auto release commit (2026-04-06 12:10:31)
All checks were successful
技能自动化发布 / release (push) Successful in 13s
All checks were successful
技能自动化发布 / release (push) Successful in 13s
This commit is contained in:
100
scripts/util/runtime_paths.py
Normal file
100
scripts/util/runtime_paths.py
Normal file
@@ -0,0 +1,100 @@
|
||||
"""数据目录、profile 路径、CLI 路径调试输出。"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
from util.constants import SKILL_SLUG
|
||||
from util.platforms import _PLATFORM_PRIMARY_CN
|
||||
|
||||
|
||||
def get_data_root():
|
||||
env = (os.getenv("JIANGCHANG_DATA_ROOT") or "").strip()
|
||||
if env:
|
||||
return env
|
||||
if sys.platform == "win32":
|
||||
return r"D:\jiangchang-data"
|
||||
return os.path.join(os.path.expanduser("~"), ".jiangchang-data")
|
||||
|
||||
|
||||
def get_user_id():
|
||||
uid = (os.getenv("JIANGCHANG_USER_ID") or "").strip()
|
||||
return uid or "_anon"
|
||||
|
||||
|
||||
def get_skill_data_dir():
|
||||
path = os.path.join(get_data_root(), get_user_id(), SKILL_SLUG)
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
def get_skill_logs_dir() -> str:
|
||||
"""{DATA_ROOT}/{USER_ID}/account-manager/logs/"""
|
||||
path = os.path.join(get_skill_data_dir(), "logs")
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
def get_db_path():
|
||||
return os.path.join(get_skill_data_dir(), "account-manager.db")
|
||||
|
||||
|
||||
def _runtime_paths_debug_text():
|
||||
"""供排查「为何 list 没数据」:终端未注入环境变量时会落到 _anon 等默认目录,与网关里用的库不是同一个文件。"""
|
||||
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():
|
||||
"""设置 JIANGCHANG_ACCOUNT_DEBUG_PATHS=1 时,每次执行子命令前在 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:
|
||||
"""单级目录名:去掉 Windows 非法字符,避免末尾点/空格;空则用 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(
|
||||
platform_key: str, phone: Optional[str], account_id: Optional[int] = None
|
||||
) -> str:
|
||||
"""
|
||||
默认可读路径:profiles/<平台展示名>/<手机号>/(便于在资源管理器中辨认)。
|
||||
无手机号时退化为 profiles/<平台展示名>/no_phone_<id>/。
|
||||
"""
|
||||
label = _PLATFORM_PRIMARY_CN.get(platform_key, platform_key or "account")
|
||||
label_seg = _fs_safe_segment(label, _fs_safe_segment(platform_key or "", "platform"))
|
||||
ph = (phone or "").strip()
|
||||
if ph:
|
||||
phone_seg = _fs_safe_segment(ph, f"id_{account_id}" if account_id is not None else "phone")
|
||||
else:
|
||||
phone_seg = _fs_safe_segment(
|
||||
"", f"no_phone_{account_id}" if account_id is not None else "no_phone"
|
||||
)
|
||||
path = os.path.join(get_skill_data_dir(), "profiles", label_seg, phone_seg)
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
Reference in New Issue
Block a user