ForcePilot/backend/package/yuxi/channel/extensions/bluebubbles/probe.py

64 lines
1.7 KiB
Python
Raw Normal View History

import time
import re
from dataclasses import dataclass
from yuxi.channel.extensions.bluebubbles.client import BlueBubblesClient
@dataclass
class ServerInfo:
os_version: str | None = None
macos_major: int | None = None
private_api_enabled: bool = False
imessage_logged_in: bool = False
fetched_at: float = 0.0
_info_cache: dict[str, ServerInfo] = {}
_CACHE_TTL = 600
async def probe_server(client: BlueBubblesClient) -> bool:
return await client.ping()
async def fetch_server_info(client: BlueBubblesClient) -> ServerInfo:
now = time.time()
cached = _info_cache.get(client.account_id)
if cached and (now - cached.fetched_at) < _CACHE_TTL:
return cached
try:
resp = await client.get("/api/v1/server/info")
data = resp.json().get("data", resp.json())
info = ServerInfo(
os_version=data.get("os_version"),
macos_major=_parse_macos_major(data.get("os_version", "")),
private_api_enabled=data.get("private_api", False),
imessage_logged_in=data.get("imessage", {}).get("logged_in", False),
fetched_at=now,
)
except Exception:
info = ServerInfo(fetched_at=now)
_info_cache[client.account_id] = info
return info
def _parse_macos_major(os_version: str) -> int | None:
m = re.search(r"macOS\s+(\d+)", os_version, re.IGNORECASE)
return int(m.group(1)) if m else None
def is_macos26_or_higher(info: ServerInfo) -> bool:
return info.macos_major is not None and info.macos_major >= 26
async def get_private_api_status(client: BlueBubblesClient) -> bool:
info = await fetch_server_info(client)
return info.private_api_enabled
def clear_probe_cache():
_info_cache.clear()