ForcePilot/backend/package/yuxi/channels/adapters/imessage/sanitize.py

68 lines
1.8 KiB
Python
Raw Normal View History

from __future__ import annotations
import re
_CONTROL_CHAR_RE = re.compile(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]")
_MULTI_NEWLINE_RE = re.compile(r"\n{3,}")
_LENGTH_PREFIX_RE = re.compile(r"^(\d+)\n")
_TERMINAL_ESCAPE_RE = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
_MAX_TERMINAL_MSG_LEN = 200
def sanitize_terminal_text(text: str, max_len: int = _MAX_TERMINAL_MSG_LEN) -> str:
"""净化终端输出文本,移除 ANSI 转义序列和控制字符。
用于日志记录和错误消息净化
"""
if not text:
return ""
text = _TERMINAL_ESCAPE_RE.sub("", text)
text = _CONTROL_CHAR_RE.sub("", text)
if len(text) > max_len:
text = text[:max_len] + "..."
return text
def sanitize_outbound_text(text: str) -> str:
"""净化出站文本,移除 iMessage 中不支持的格式。
- 去除 \\r 字符换行标准化
- 去除长度前缀损坏 "42\\nThis is message"
- 过滤控制字符
- 合并多余空白行
"""
text = text.replace("\r", "")
text = _strip_length_prefix(text)
text = _CONTROL_CHAR_RE.sub("", text)
text = _MULTI_NEWLINE_RE.sub("\n\n", text)
text = text.strip()
return text
def _strip_length_prefix(text: str) -> str:
match = _LENGTH_PREFIX_RE.match(text)
if match:
prefix_len = int(match.group(1))
remaining = text[match.end() :]
if abs(len(remaining) - prefix_len) <= 5:
return remaining
return text
def media_placeholder(media_type: str) -> str:
"""为纯媒体消息生成占位文本。
OpenClaw 在无文本媒体消息中生成 <media:image> 等占位符
"""
placeholders = {
"image": "<media:image>",
"video": "<media:video>",
"audio": "<media:audio>",
"file": "<media:file>",
}
return placeholders.get(media_type, "<media:file>")