ForcePilot/backend/package/yuxi/channel/extensions/viber/format.py
Kris 1c590097be feat(channel): 添加 Twitter 和 Viber 渠道扩展
新增 Twitter 和 Viber 两个渠道扩展。

Twitter 渠道扩展功能模块:
- auth: OAuth 认证管理
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- webhook: Webhook 事件处理
- outbound: 外发消息管理
- streaming: 流式消息处理
- pairing: 用户配对与绑定
- security: 安全校验
- dedupe: 消息去重
- monitor: 渠道状态监控
- status: 会话状态管理
- session: 会话管理
- tweets: 推文管理
- social: 社交互动
- reactions: 表情反应
- media: 媒体资源处理

Viber 渠道扩展功能模块:
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- webhook: Webhook 事件处理
- outbound: 外发消息管理
- streaming: 流式消息处理
- pairing: 用户配对与绑定
- security: 安全校验
- dedupe: 消息去重
- monitor: 渠道状态监控
- status: 会话状态管理
- rate_limiter: 速率限制
- media: 媒体资源处理
2026-05-21 11:57:22 +08:00

52 lines
1.7 KiB
Python

from __future__ import annotations
import re
def markdown_to_viber(md_text: str) -> str:
text = md_text
text = re.sub(r"\*\*(.+?)\*\*", r"<b>\1</b>", text)
text = re.sub(r"__([^_]+)__", r"<b>\1</b>", text)
text = re.sub(r"\*([^*\n]+)\*", r"<i>\1</i>", text)
text = re.sub(r"(?<!\w)_([^_\n]+)_(?!\w)", r"<i>\1</i>", text)
text = re.sub(r"`([^`\n]+)`", r"<font color='#888888'>\1</font>", text)
text = re.sub(r"~~(.+?)~~", r"", text)
text = re.sub(r"!\[[^\]]*\]\([^)]*\)", "", text)
text = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", r"<a href='\2'>\1</a>", text)
text = re.sub(r"^#{1,6}\s+(.+)$", r"<b>\1</b>", text, flags=re.MULTILINE)
text = re.sub(r"^>\s+(.+)$", r"<i>\1</i>", text, flags=re.MULTILINE)
text = re.sub(r"^-{3,}$", "────────────", text, flags=re.MULTILINE)
text = re.sub(r"^[*-]\s+(.+)$", r"\1", text, flags=re.MULTILINE)
return text.strip()
def escape_viber_html(text: str) -> str:
text = text.replace("&", "&amp;")
text = text.replace("<", "&lt;")
text = text.replace(">", "&gt;")
return text
def chunk_text(text: str, limit: int = 7000) -> list[str]:
if len(text) <= limit:
return [text]
chunks: list[str] = []
while len(text) > limit:
split_point = text.rfind("\n", 0, limit)
if split_point == -1 or split_point < limit // 2:
split_point = text.rfind(". ", 0, limit)
if split_point == -1 or split_point < limit // 2:
split_point = text.rfind(" ", 0, limit)
if split_point == -1 or split_point < limit // 2:
split_point = limit
chunks.append(text[:split_point].strip())
text = text[split_point:].strip()
if text:
chunks.append(text)
return chunks