该提交新增了完整的BlueBubbles渠道插件,支持通过BlueBubbles Server集成iMessage功能,包含以下核心能力: 1. 支持私聊和群聊会话管理,自动区分会话类型 2. 完整的消息收发支持,包括文本、图片、语音、文件、视频消息 3. 支持消息反应、已读回执、消息编辑与撤回 4. 内置去重、防抖处理机制 5. 支持Webhook和WebSocket两种事件接收方式 6. 完善的权限与安全校验机制 7. 历史消息同步与抓包功能 8. TTS语音合成与发送支持 9. 群组管理能力,包括重命名、修改头像、增减成员等
64 lines
1.7 KiB
Python
64 lines
1.7 KiB
Python
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()
|