ForcePilot/backend/package/yuxi/channel/extensions/imessage/pairing.py
Kris 4d52f634fe feat(imessage): 新增iMessage渠道插件完整实现
该提交新增了基于BlueBubbles的iMessage渠道插件,支持单聊和群组消息,包含文本、图片、语音、文件和视频消息收发,支持消息编辑、撤回、回复、 reactions和输入状态提示,同时实现了账号配置、安全校验、配对授权、消息格式化与分片等完整功能。
2026-05-21 10:50:15 +08:00

69 lines
2.0 KiB
Python

from __future__ import annotations
import secrets
import time
import logging
logger = logging.getLogger(__name__)
PAIRING_CODE_LENGTH = 8
PAIRING_CODE_EXPIRY_SECONDS = 600
PAIRING_CODE_CHARS = "ABCDEFGHJKMNPQRSTUVWXYZ23456789" # 无歧义: 排除 0/O/1/I
PAIRING_APPROVED_MESSAGE = (
"Your access has been approved. "
"You can now interact with this iMessage bot."
)
class IMessagePairingAdapter:
def __init__(self):
self._pending: dict[str, dict] = {}
self._approved: set[str] = set()
def generate_code(self, peer_id: str) -> str:
self._cleanup_expired()
code = "".join(secrets.choice(PAIRING_CODE_CHARS) for _ in range(PAIRING_CODE_LENGTH))
self._pending[peer_id] = {
"code": code,
"created_at": time.monotonic(),
"status": "pending",
}
return code
def verify_code(self, peer_id: str, code: str) -> bool:
entry = self._pending.get(peer_id)
if not entry:
return False
if time.monotonic() - entry["created_at"] > PAIRING_CODE_EXPIRY_SECONDS:
del self._pending[peer_id]
return False
if secrets.compare_digest(entry["code"], code.upper().strip()):
entry["status"] = "approved"
self._approved.add(peer_id)
return True
return False
def is_approved(self, peer_id: str) -> bool:
return peer_id in self._approved
def revoke(self, peer_id: str) -> None:
self._approved.discard(peer_id)
self._pending.pop(peer_id, None)
def _cleanup_expired(self):
now = time.monotonic()
expired = [
pid for pid, entry in self._pending.items()
if (now - entry["created_at"]) > PAIRING_CODE_EXPIRY_SECONDS
]
for pid in expired:
del self._pending[pid]
def pending_count(self) -> int:
self._cleanup_expired()
return sum(1 for v in self._pending.values() if v["status"] == "pending")