File size: 1,529 Bytes
a31f556
 
 
 
 
 
 
 
 
 
 
850b3bb
 
 
122042d
 
 
 
850b3bb
122042d
 
850b3bb
 
a31f556
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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 <your password> — 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