ForcePilot/backend/package/yuxi/channel/extensions/zalo/polling.py
Kris 5946478772 feat(channel): 添加小红书、XMPP、元宝和 Zalo 渠道扩展
新增小红书、XMPP、元宝、Zalo 四个渠道扩展。

小红书渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, media, status, window

XMPP 渠道扩展主要模块:plugin, config, gateway, outbound, streaming, pairing, security, dedupe, accounts, commands, muc, rate_limiter, stanza_utils, status, monitor

元宝渠道扩展主要模块:plugin, client, config_schema, gateway, outbound(chunk/queue/transport), inbound(dispatcher), streaming, pairing, security, accounts, actions, commands, codec(biz/conn), session, shared, utils

Zalo 渠道扩展主要模块:api, config, gateway, webhook, outbound, pairing, security, session, polling, monitor, status
2026-05-21 12:04:05 +08:00

58 lines
2.0 KiB
Python

import asyncio
import logging
from yuxi.channel.extensions.zalo.api import ZaloBotApi
from yuxi.channel.extensions.zalo.errors import ZaloApiError
from yuxi.channel.extensions.zalo.types import ZaloAccount
logger = logging.getLogger(__name__)
SLEEP_BETWEEN_POLLS_S = 0.25
async def start_polling_loop(account: ZaloAccount, abort_event: asyncio.Event, gateway):
api = ZaloBotApi(account.bot_token, proxy=account.proxy)
try:
await _clean_webhook_before_polling(api)
except ZaloApiError:
logger.debug("Zalo webhook cleanup failed or not available, continuing")
logger.info("Zalo polling loop started for account %s", account.account_id)
while not abort_event.is_set():
try:
resp = await api.get_updates(timeout=30)
result = resp.get("result", {})
if isinstance(result, dict) and result:
await gateway.process_update(result, account)
except ZaloApiError as e:
logger.warning("Zalo polling API error: %s", e)
await asyncio.sleep(5.0)
except Exception as e:
if isinstance(e, ZaloApiError):
pass
else:
logger.debug("Zalo polling error (likely 408 timeout): %s", e)
finally:
await asyncio.sleep(SLEEP_BETWEEN_POLLS_S)
await api.close()
logger.info("Zalo polling loop stopped for account %s", account.account_id)
async def _clean_webhook_before_polling(api: ZaloBotApi):
try:
info = await api.get_webhook_info()
if info.get("result", {}).get("url"):
await api.delete_webhook()
logger.info("Zalo webhook cleaned before polling")
except ZaloApiError as e:
if e.error_code == 404:
logger.debug("Zalo webhook info endpoint not available (404), skipping cleanup")
else:
logger.warning("Zalo webhook cleanup warning: %s", e)
except Exception as e:
logger.warning("Zalo webhook cleanup error: %s", e)