新增大量WhatsApp适配器相关代码,包括账号管理、会话处理、消息收发、验证授权、媒体处理、互动命令、审批流程、健康检测等完整功能模块,搭建基础的Baileys协议WhatsApp接入能力
76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import threading
|
|
from dataclasses import dataclass
|
|
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
@dataclass
|
|
class PairRequest:
|
|
phone_number: str
|
|
pairing_code: str | None = None
|
|
expires_at: float | None = None
|
|
|
|
@property
|
|
def is_expired(self) -> bool:
|
|
if self.expires_at is None:
|
|
return False
|
|
return asyncio.get_event_loop().time() > self.expires_at
|
|
|
|
|
|
class PairingManager:
|
|
def __init__(self):
|
|
self._pending: dict[str, PairRequest] = {}
|
|
self._paired: set[str] = set()
|
|
self._lock = threading.Lock()
|
|
|
|
def create_pair_request(self, phone_number: str, code: str, timeout: float = 300) -> PairRequest:
|
|
req = PairRequest(
|
|
phone_number=phone_number,
|
|
pairing_code=code,
|
|
expires_at=asyncio.get_event_loop().time() + timeout,
|
|
)
|
|
with self._lock:
|
|
self._pending[phone_number] = req
|
|
logger.info(f"PairingManager: pair request created for {phone_number}")
|
|
return req
|
|
|
|
def confirm_pair(self, phone_number: str) -> bool:
|
|
with self._lock:
|
|
req = self._pending.get(phone_number)
|
|
if req is None or req.is_expired:
|
|
logger.warning(f"PairingManager: no valid request for {phone_number}")
|
|
return False
|
|
del self._pending[phone_number]
|
|
self._paired.add(phone_number)
|
|
logger.info(f"PairingManager: confirmed pair for {phone_number}")
|
|
return True
|
|
|
|
def is_paired(self, phone_number: str) -> bool:
|
|
with self._lock:
|
|
return phone_number in self._paired
|
|
|
|
def revoke_pair(self, phone_number: str) -> bool:
|
|
with self._lock:
|
|
removed_pending = self._pending.pop(phone_number, None) is not None
|
|
removed_paired = phone_number in self._paired
|
|
self._paired.discard(phone_number)
|
|
return removed_pending or removed_paired
|
|
|
|
def get_pending_phones(self) -> list[str]:
|
|
with self._lock:
|
|
return list(self._pending.keys())
|
|
|
|
def cleanup_expired(self) -> int:
|
|
count = 0
|
|
with self._lock:
|
|
expired = [phone for phone, req in self._pending.items() if req.is_expired]
|
|
for phone in expired:
|
|
del self._pending[phone]
|
|
count += 1
|
|
if count:
|
|
logger.info(f"PairingManager: cleaned {count} expired requests")
|
|
return count
|