"""Install the native macOS background material-name refresher.""" from __future__ import annotations import argparse import os import plistlib import subprocess import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] LABEL = "com.am516.material-name-refresh" def launch_agent(project: Path, python: Path, log_dir: Path, client: Path | None = None) -> dict: command = [str(python), str(project / "capabilities/am516-delivery-prediction/scripts/refresh_material_names.py"), "--due", "--interval-hours", "48"] if client is not None: command.extend(["--kingdee-client", str(client)]) return { "Label": LABEL, "ProgramArguments": command, "WorkingDirectory": str(project), "RunAtLoad": True, "StartInterval": 3600, "ProcessType": "Background", "EnvironmentVariables": {"PYTHONDONTWRITEBYTECODE": "1", "PYTHONUNBUFFERED": "1"}, "StandardOutPath": str(log_dir / "material_name_refresh.log"), "StandardErrorPath": str(log_dir / "material_name_refresh.error.log"), } def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("action", choices=("install", "status", "uninstall", "preview")) parser.add_argument("--python", type=Path, default=Path(sys.executable)) parser.add_argument("--kingdee-client", type=Path) args = parser.parse_args() if args.kingdee_client is not None: args.kingdee_client = args.kingdee_client.resolve() destination = Path.home() / "Library/LaunchAgents" / f"{LABEL}.plist" logs = Path.home() / "Library/Logs/AM516_Feishu_Bot" domain = f"gui/{os.getuid()}" service = f"{domain}/{LABEL}" if args.action == "preview": print(plistlib.dumps(launch_agent(PROJECT_ROOT, args.python.resolve(), logs, args.kingdee_client)).decode()) return 0 if args.action == "status": return subprocess.run(["launchctl", "print", service]).returncode if args.action in ("install", "uninstall"): exists = subprocess.run(["launchctl", "print", service], capture_output=True).returncode == 0 if exists: subprocess.run(["launchctl", "bootout", service], check=True) if args.action == "uninstall": destination.unlink(missing_ok=True) print("已移除物料名称后台刷新服务。") return 0 destination.parent.mkdir(parents=True, exist_ok=True) logs.mkdir(parents=True, exist_ok=True) (PROJECT_ROOT / "logs").mkdir(exist_ok=True) with destination.open("wb") as handle: plistlib.dump(launch_agent(PROJECT_ROOT, args.python.resolve(), logs, args.kingdee_client), handle) subprocess.run(["launchctl", "bootstrap", domain, str(destination)], check=True) print("已安装物料名称后台刷新:每小时检查,成功刷新后间隔48小时再次查询 ERP。") print(f"服务:{service}") return 0 if __name__ == "__main__": raise SystemExit(main())