新增了Zalo用户频道的完整适配器实现,包括: - 基础的适配器初始化与导出结构 - 群组同步与成员获取功能 - 请求限流与退避重试机制 - 健康检查与状态探针 - 消息反应/表情处理工具 - 贴纸缓存与消息去重功能 - 消息ID格式化与追踪 - TTS语音合成支持 - 消息发送权限校验 - 长文本分块发送 - 操作审批流程 - 常量配置与国际化支持 - 图像视觉分析功能 - 贴纸消息处理 - 登录与配置向导 - 群组上下文缓存 - 网关连接管理 - 配置Schema校验 - 状态问题与安全审计 - 内联按钮与交互组件 - 交互式回调分发 - 联系人与群组目录管理 - 富媒体卡片消息支持
64 lines
1.8 KiB
Python
64 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
ZALO_MAX_TEXT_LENGTH = 2000
|
|
_SENTENCE_BOUNDARY = re.compile(r"[。!?.!?\n]")
|
|
|
|
|
|
def chunk_text(text: str, limit: int = ZALO_MAX_TEXT_LENGTH) -> list[str]:
|
|
if len(text) <= limit:
|
|
return [text]
|
|
|
|
chunks: list[str] = []
|
|
paragraphs = text.split("\n\n")
|
|
current = ""
|
|
|
|
for para in paragraphs:
|
|
if len(current) + len(para) + 2 <= limit:
|
|
current = f"{current}\n\n{para}" if current else para
|
|
else:
|
|
if current:
|
|
chunks.append(current)
|
|
if len(para) > limit:
|
|
sub_chunks = _chunk_long_paragraph(para, limit)
|
|
if sub_chunks:
|
|
if sub_chunks[-1]:
|
|
current = sub_chunks.pop()
|
|
else:
|
|
sub_chunks.pop()
|
|
current = ""
|
|
chunks.extend(sub_chunks)
|
|
else:
|
|
current = ""
|
|
else:
|
|
current = para
|
|
|
|
if current:
|
|
chunks.append(current)
|
|
return chunks or [text]
|
|
|
|
|
|
def _chunk_long_paragraph(text: str, limit: int) -> list[str]:
|
|
chunks: list[str] = []
|
|
remaining = text
|
|
while len(remaining) > limit:
|
|
split_at = _find_split_point(remaining, limit)
|
|
chunks.append(remaining[:split_at].rstrip())
|
|
remaining = remaining[split_at:].lstrip()
|
|
chunks.append(remaining)
|
|
return chunks
|
|
|
|
|
|
def _find_split_point(text: str, limit: int) -> int:
|
|
candidates = [m.start() for m in _SENTENCE_BOUNDARY.finditer(text, limit // 2, limit)]
|
|
if candidates:
|
|
return candidates[-1] + 1
|
|
newline = text.rfind("\n", limit // 2, limit)
|
|
if newline != -1:
|
|
return newline + 1
|
|
space = text.rfind(" ", limit // 2, limit)
|
|
if space != -1:
|
|
return space + 1
|
|
return limit
|