from __future__ import annotations import json import os import time from pathlib import Path ROOT = Path(__file__).resolve().parents[1] UNLOCK_JSON = ROOT / "data" / "session_unlocked.json" # One wording for the refusal, shared by every caller that has to explain it — # core.commands (voice/GUI) and phone.command_runner (phone and cloud relay) — # so a remote user is never told something different from a local one. # Tells the user what to do from WHERE THEY ARE. The old wording sent them to # the desktop for an activation key, which is useless advice to someone holding # a phone in another country — and that is the only situation in which a relayed # command hits this message at all. LOCKED_MESSAGE = ( "This PC is locked. Send: unlock pc — then this command " "will run." ) def _boot_id() -> int: try: import psutil # type: ignore return int(psutil.boot_time()) except Exception: return int(time.time() // 3600) def is_activated_for_this_boot() -> bool: """ True only if the session unlock marker matches this boot. Used to hard-block voice output before activation. """ try: if not UNLOCK_JSON.exists(): return False data = json.loads(UNLOCK_JSON.read_text(encoding="utf-8")) if not isinstance(data, dict): return False return int(data.get("boot_id", 0) or 0) == _boot_id() except Exception: return False