新增小红书、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
69 lines
2.2 KiB
Python
69 lines
2.2 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from yuxi.channel.protocols import SessionResolution
|
|
|
|
_RE_DIGITS = re.compile(r"^\d+$")
|
|
|
|
|
|
class ZaloSession:
|
|
@staticmethod
|
|
def build_conversation_id(chat_type: str, target_id: str) -> str:
|
|
if chat_type == "GROUP":
|
|
return f"zalo:group:{target_id}"
|
|
return f"zalo:{target_id}"
|
|
|
|
@staticmethod
|
|
def build_session_key(agent_id: str, account_id: str, chat_type: str, target_id: str) -> str:
|
|
chat = "direct" if chat_type in ("PRIVATE", "direct") else "group"
|
|
return f"agent:{agent_id}:zalo:{chat}:{target_id}"
|
|
|
|
@staticmethod
|
|
def normalize_target(raw: str) -> str:
|
|
target = raw.strip()
|
|
for prefix in ("zalo:", "zl:"):
|
|
if target.lower().startswith(prefix.lower()):
|
|
target = target[len(prefix) :]
|
|
break
|
|
return target
|
|
|
|
@staticmethod
|
|
def parse_target(raw: str) -> tuple[str, str]:
|
|
"""Parse a target string into (chat_type, target_id).
|
|
|
|
Supported formats:
|
|
- zalo:{userId} → ("direct", userId)
|
|
- zl:{userId} → ("direct", userId)
|
|
- zalo:group:{chatId} → ("group", chatId)
|
|
- zl:group:{chatId} → ("group", chatId)
|
|
- {digits} → ("direct", digits)
|
|
"""
|
|
target = raw.strip()
|
|
|
|
for prefix in ("zalo:", "zl:"):
|
|
if target.lower().startswith(prefix.lower()):
|
|
remainder = target[len(prefix) :]
|
|
if remainder.lower().startswith("group:"):
|
|
return ("group", remainder[len("group:") :])
|
|
return ("direct", remainder)
|
|
|
|
if _RE_DIGITS.match(target):
|
|
return ("direct", target)
|
|
|
|
return ("direct", target)
|
|
|
|
@staticmethod
|
|
def resolve_dm_session(sender_id: str) -> SessionResolution:
|
|
return SessionResolution(
|
|
kind="direct",
|
|
conversation_id=f"zalo:{sender_id}",
|
|
)
|
|
|
|
@staticmethod
|
|
def resolve_group_session(chat_id: str) -> SessionResolution:
|
|
return SessionResolution(
|
|
kind="group",
|
|
conversation_id=f"zalo:group:{chat_id}",
|
|
)
|