fix(platform): parse QQ official face messages to readable text (#6355)
Fixes #6294 QQ official bot receives emoji/sticker messages as raw XML-like tags: `<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">` This made the LLM unable to understand the emoji content. Changes: - Added `_parse_face_message()` method to parse face message format - Decode base64 `ext` field to get emoji description text - Replace face tags with `[表情:描述]` format for readability Example: - Input: `<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">` - Output: `[表情:[满头问号]]` Co-authored-by: ccsang <ccsang@users.noreply.github.com>
This commit is contained in:
@@ -391,6 +391,47 @@ class QQOfficialPlatformAdapter(Platform):
|
||||
else:
|
||||
msg.append(File(name=filename, file=url, url=url))
|
||||
|
||||
@staticmethod
|
||||
def _parse_face_message(content: str) -> str:
|
||||
"""Parse QQ official face message format and convert to readable text.
|
||||
|
||||
QQ official face message format:
|
||||
<faceType=4,faceId="",ext="eyJ0ZXh0IjoiW+a7oeWktOmXruWPt10ifQ==">
|
||||
|
||||
The ext field contains base64-encoded JSON with a 'text' field
|
||||
describing the emoji (e.g., '[满头问号]').
|
||||
|
||||
Args:
|
||||
content: The message content that may contain face tags.
|
||||
|
||||
Returns:
|
||||
Content with face tags replaced by readable emoji descriptions.
|
||||
"""
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
|
||||
def replace_face(match):
|
||||
face_tag = match.group(0)
|
||||
# Extract ext field from the face tag
|
||||
ext_match = re.search(r'ext="([^"]*)"', face_tag)
|
||||
if ext_match:
|
||||
try:
|
||||
ext_encoded = ext_match.group(1)
|
||||
# Decode base64 and parse JSON
|
||||
ext_decoded = base64.b64decode(ext_encoded).decode("utf-8")
|
||||
ext_data = json.loads(ext_decoded)
|
||||
emoji_text = ext_data.get("text", "")
|
||||
if emoji_text:
|
||||
return f"[表情:{emoji_text}]"
|
||||
except Exception:
|
||||
pass
|
||||
# Fallback if parsing fails
|
||||
return "[表情]"
|
||||
|
||||
# Match face tags: <faceType=...>
|
||||
return re.sub(r"<faceType=\d+[^>]*>", replace_face, content)
|
||||
|
||||
@staticmethod
|
||||
def _parse_from_qqofficial(
|
||||
message: botpy.message.Message
|
||||
@@ -416,7 +457,10 @@ class QQOfficialPlatformAdapter(Platform):
|
||||
abm.group_id = message.group_openid
|
||||
else:
|
||||
abm.sender = MessageMember(message.author.user_openid, "")
|
||||
abm.message_str = message.content.strip()
|
||||
# Parse face messages to readable text
|
||||
abm.message_str = QQOfficialPlatformAdapter._parse_face_message(
|
||||
message.content.strip()
|
||||
)
|
||||
abm.self_id = "unknown_selfid"
|
||||
msg.append(At(qq="qq_official"))
|
||||
msg.append(Plain(abm.message_str))
|
||||
@@ -432,10 +476,12 @@ class QQOfficialPlatformAdapter(Platform):
|
||||
else:
|
||||
abm.self_id = ""
|
||||
|
||||
plain_content = message.content.replace(
|
||||
"<@!" + str(abm.self_id) + ">",
|
||||
"",
|
||||
).strip()
|
||||
plain_content = QQOfficialPlatformAdapter._parse_face_message(
|
||||
message.content.replace(
|
||||
"<@!" + str(abm.self_id) + ">",
|
||||
"",
|
||||
).strip()
|
||||
)
|
||||
|
||||
QQOfficialPlatformAdapter._append_attachments(msg, message.attachments)
|
||||
abm.message = msg
|
||||
|
||||
Reference in New Issue
Block a user