ForcePilot/backend/package/yuxi/channel/extensions/pinduoduo/outbound.py
Kris 1476e82ef0 feat(channel): 添加拼多多渠道扩展
新增拼多多(Pinduoduo)渠道扩展,支持在 Yuxi 平台中集成拼多多电商客服渠道。

包含以下功能模块:
- client: 拼多多 API 客户端封装
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- webhook: Webhook 事件处理
- outbound: 外发消息管理
- pairing: 用户配对与绑定
- security: 安全校验
- signature: 请求签名验证
- token: Token 管理
- dedupe: 消息去重
- monitor: 渠道状态监控
- status: 会话状态管理
- tools: Agent 工具集成
- window: 窗口管理
- types: 类型定义
2026-05-21 11:33:31 +08:00

93 lines
2.9 KiB
Python

from __future__ import annotations
import logging
from yuxi.channel.extensions.pinduoduo.client import PddCSClient
from yuxi.channel.extensions.pinduoduo.format import (
pdd_split_long_text,
pdd_strip_markdown,
)
from yuxi.channel.extensions.pinduoduo.types import PinduoduoAccount
from yuxi.channel.extensions.pinduoduo.window import PinduoduoWindowTracker
logger = logging.getLogger(__name__)
class PinduoduoOutbound:
def __init__(
self,
cs_client: PddCSClient,
account: PinduoduoAccount,
window_tracker: PinduoduoWindowTracker | None = None,
):
self._cs = cs_client
self._account = account
self._window_tracker = window_tracker
async def send_text(
self,
session_id: str,
buyer_id: str,
content: str,
) -> None:
if self._window_tracker and not self._window_tracker.can_reply(buyer_id):
logger.warning(
"48h 窗口期已过,跳过发送 buyer=%s session=%s",
buyer_id,
session_id,
)
return
clean = pdd_strip_markdown(content)
if len(clean) <= 2000:
await self._send_single(session_id, buyer_id, clean)
else:
chunks = pdd_split_long_text(clean)
for chunk in chunks:
await self._send_single(session_id, buyer_id, chunk)
async def _send_single(self, session_id: str, buyer_id: str, text: str) -> None:
try:
await self._cs.send_text(
session_id=session_id,
from_user=self._account.mall_id,
to_user=buyer_id,
mall_id=self._account.mall_id,
content=text,
)
except Exception:
logger.exception(
"Failed to send text to buyer=%s in session=%s",
buyer_id,
session_id,
)
async def send_image(self, session_id: str, buyer_id: str, image_url: str) -> None:
try:
await self._cs.send_image(
session_id=session_id,
from_user=self._account.mall_id,
to_user=buyer_id,
mall_id=self._account.mall_id,
image_url=image_url,
)
except Exception:
logger.exception("Failed to send image to buyer=%s", buyer_id)
async def send_order_card(self, session_id: str, buyer_id: str, order_sn: str) -> None:
try:
await self._cs.send_order_card(
session_id=session_id,
from_user=self._account.mall_id,
to_user=buyer_id,
mall_id=self._account.mall_id,
order_sn=order_sn,
)
except Exception:
logger.exception(
"Failed to send order card to buyer=%s, order=%s",
buyer_id,
order_sn,
)