fix: 系统消息/撤回消息解析,补全消息类型格式化

- type 10000 (系统消息): 解析 <content> 标签,显示 [系统] 内容
- type 10002 (撤回): 解析 <content>,显示 [撤回] 内容
- type 34 (语音) / 43 (视频): 之前漏了,现在显示 [语音]/[视频]
- 避免 raw XML 出现在 history/watch 输出中
pull/2/head
jackwener 2026-04-16 17:22:54 +08:00
parent 7f869e7c3b
commit 33b4249bd5
1 changed files with 35 additions and 0 deletions

View File

@ -647,8 +647,12 @@ fn fmt_content(local_id: i64, local_type: i64, content: &str, is_group: bool) ->
let base = (local_type as u64 & 0xFFFFFFFF) as i64; let base = (local_type as u64 & 0xFFFFFFFF) as i64;
match base { match base {
3 => return format!("[图片] local_id={}", local_id), 3 => return format!("[图片] local_id={}", local_id),
34 => return "[语音]".into(),
43 => return "[视频]".into(),
47 => return "[表情]".into(), 47 => return "[表情]".into(),
50 => return "[通话]".into(), 50 => return "[通话]".into(),
10000 => return parse_sysmsg(content).unwrap_or_else(|| "[系统消息]".into()),
10002 => return parse_revoke(content).unwrap_or_else(|| "[撤回了一条消息]".into()),
_ => {} _ => {}
} }
@ -666,6 +670,37 @@ fn fmt_content(local_id: i64, local_type: i64, content: &str, is_group: bool) ->
text.to_string() text.to_string()
} }
/// 解析撤回消息 XML提取被撤回的内容摘要
/// `<sysmsg type="revokemsg"><revokemsg><content>...</content></revokemsg></sysmsg>`
fn parse_revoke(xml: &str) -> Option<String> {
let inner = extract_xml_text(xml, "content")?;
// 有时 content 是 "xxx recalled a message" 英文,有时是中文
if inner.is_empty() {
return Some("[撤回了一条消息]".into());
}
// 尝试简化:如果是 XML 格式的撤回内容,直接显示摘要
Some(format!("[撤回] {}", inner
.chars()
.take(30)
.collect::<String>()))
}
/// 解析系统消息 XML群通知等
fn parse_sysmsg(xml: &str) -> Option<String> {
// 常见格式:<sysmsg type="...">...</sysmsg>
// 尝试提取 content 标签
if let Some(s) = extract_xml_text(xml, "content") {
if !s.is_empty() {
return Some(format!("[系统] {}", s.chars().take(50).collect::<String>()));
}
}
// 纯文本系统消息(无 XML
if !xml.starts_with('<') {
return Some(format!("[系统] {}", xml.chars().take(50).collect::<String>()));
}
Some("[系统消息]".into())
}
fn parse_appmsg(text: &str) -> Option<String> { fn parse_appmsg(text: &str) -> Option<String> {
// 简单 XML 解析,避免引入重量级 XML 库(或直接用 minidom // 简单 XML 解析,避免引入重量级 XML 库(或直接用 minidom
// 这里用基本字符串搜索实现 // 这里用基本字符串搜索实现