新增大量WhatsApp适配器相关代码,包括账号管理、会话处理、消息收发、验证授权、媒体处理、互动命令、审批流程、健康检测等完整功能模块,搭建基础的Baileys协议WhatsApp接入能力
71 lines
2.4 KiB
Python
71 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import json
|
|
from collections.abc import Callable
|
|
from typing import Any
|
|
|
|
import aiohttp
|
|
|
|
from yuxi.utils.logging_config import logger
|
|
|
|
|
|
class WhatsAppMonitor:
|
|
def __init__(self, config: dict[str, Any] | None = None, bridge=None):
|
|
self._config = config or {}
|
|
self._bridge = bridge
|
|
self._on_raw: Callable[[dict[str, Any]], None] | None = None
|
|
self._task: asyncio.Task | None = None
|
|
|
|
def on_raw_message(self, handler: Callable[[dict[str, Any]], None]) -> None:
|
|
self._on_raw = handler
|
|
|
|
async def start(self) -> None:
|
|
if self._task and not self._task.done():
|
|
return
|
|
self._task = asyncio.create_task(self._sse_loop())
|
|
|
|
async def stop(self) -> None:
|
|
if self._task:
|
|
self._task.cancel()
|
|
try:
|
|
await self._task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
self._task = None
|
|
|
|
async def _sse_loop(self) -> None:
|
|
while True:
|
|
try:
|
|
await self._connect_sse()
|
|
except asyncio.CancelledError:
|
|
break
|
|
except Exception as e:
|
|
logger.error(f"WhatsApp monitor error, reconnecting in 5s: {e}")
|
|
await asyncio.sleep(5)
|
|
|
|
async def _connect_sse(self) -> None:
|
|
url = f"{self._bridge.base_url}/api/events"
|
|
logger.info(f"Connecting to WhatsApp SSE: {url}")
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(url) as resp:
|
|
byte_lines = []
|
|
async for chunk in resp.content.iter_any():
|
|
if chunk:
|
|
byte_lines.append(chunk)
|
|
raw_line = b"".join(byte_lines).decode("utf-8", errors="replace")
|
|
|
|
while "\n" in raw_line:
|
|
line, raw_line = raw_line.split("\n", 1)
|
|
byte_lines = [raw_line.encode("utf-8")]
|
|
|
|
if line.startswith("data: "):
|
|
data_str = line[6:].strip()
|
|
try:
|
|
data = json.loads(data_str)
|
|
if self._on_raw:
|
|
self._on_raw(data)
|
|
except json.JSONDecodeError:
|
|
continue
|