fix: fallback quoted image lookup by md5
This commit is contained in:
@@ -123,18 +123,24 @@ def get_messages():
|
|||||||
msg['quoted_preview_image'] = quote_data.get('preview_image', '')
|
msg['quoted_preview_image'] = quote_data.get('preview_image', '')
|
||||||
msg['quoted_preview_video_thumb'] = quote_data.get('preview_video_thumb', '')
|
msg['quoted_preview_video_thumb'] = quote_data.get('preview_video_thumb', '')
|
||||||
msg['quoted_reference_svrid'] = quote_data.get('reference_svrid', '')
|
msg['quoted_reference_svrid'] = quote_data.get('reference_svrid', '')
|
||||||
|
msg['quoted_reference_md5'] = quote_data.get('reference_md5', '')
|
||||||
|
|
||||||
# 优先使用原始被引用消息自己已落库的图片/缩略图地址
|
# 优先使用原始被引用消息自己已落库的图片/缩略图地址
|
||||||
reference_svrid = quote_data.get('reference_svrid')
|
reference_svrid = quote_data.get('reference_svrid')
|
||||||
|
reference_md5 = quote_data.get('reference_md5')
|
||||||
|
referenced_msg = None
|
||||||
if reference_svrid:
|
if reference_svrid:
|
||||||
referenced_msg = server.message_storage.get_message_by_message_id(reference_svrid)
|
referenced_msg = server.message_storage.get_message_by_message_id(reference_svrid)
|
||||||
if referenced_msg:
|
if not referenced_msg and reference_md5 and msg['quoted_type'] == 'image':
|
||||||
if msg['quoted_type'] == 'image':
|
referenced_msg = server.message_storage.get_image_message_by_md5(reference_md5)
|
||||||
image_path = referenced_msg.get('image_path') or ''
|
|
||||||
msg['quoted_preview_image'] = image_path if _is_usable_local_media_path(image_path) else ''
|
if referenced_msg:
|
||||||
elif msg['quoted_type'] == 'video':
|
if msg['quoted_type'] == 'image':
|
||||||
video_thumb = referenced_msg.get('message_thumb') or referenced_msg.get('image_path') or ''
|
image_path = referenced_msg.get('image_path') or ''
|
||||||
msg['quoted_preview_video_thumb'] = video_thumb if _is_usable_local_media_path(video_thumb) else ''
|
msg['quoted_preview_image'] = image_path if _is_usable_local_media_path(image_path) else ''
|
||||||
|
elif msg['quoted_type'] == 'video':
|
||||||
|
video_thumb = referenced_msg.get('message_thumb') or referenced_msg.get('image_path') or ''
|
||||||
|
msg['quoted_preview_video_thumb'] = video_thumb if _is_usable_local_media_path(video_thumb) else ''
|
||||||
else:
|
else:
|
||||||
# 其他类型的应用消息,解析 XML 提取标题
|
# 其他类型的应用消息,解析 XML 提取标题
|
||||||
root = ET.fromstring(msg['content'])
|
root = ET.fromstring(msg['content'])
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
|
|
||||||
<div v-else class="message-text-preview is-muted">
|
<div v-else class="message-text-preview is-muted">
|
||||||
{% raw %}{{ scope.row.content || `【消息类型: ${scope.row.message_type}】` }}{% endraw %}
|
{% raw %}{{ scope.row.content || `【消息类型: ${scope.row.message_type}】` }}{% endraw %}
|
||||||
<div v-if="scope.row.quoted_type === 'image' && scope.row.quoted_preview_image" class="quoted-media-preview">
|
<div v-if="scope.row.quoted_type === 'image' && hasQuotedPreview(scope.row.quoted_preview_image)" class="quoted-media-preview">
|
||||||
<div class="message-media-label">【引用图片】</div>
|
<div class="message-media-label">【引用图片】</div>
|
||||||
<img :src="getQuotedPreviewUrl(scope.row.quoted_preview_image)" class="message-thumb" @click="showQuotedImage(scope.row.quoted_preview_image)">
|
<img :src="getQuotedPreviewUrl(scope.row.quoted_preview_image)" class="message-thumb" @click="showQuotedImage(scope.row.quoted_preview_image)">
|
||||||
</div>
|
</div>
|
||||||
@@ -323,6 +323,7 @@
|
|||||||
},
|
},
|
||||||
showQuotedImage(url) {
|
showQuotedImage(url) {
|
||||||
const resolvedUrl = this.getQuotedPreviewUrl(url);
|
const resolvedUrl = this.getQuotedPreviewUrl(url);
|
||||||
|
if (!resolvedUrl) return;
|
||||||
this.selectedMessage = { image_path: '', message_thumb: resolvedUrl };
|
this.selectedMessage = { image_path: '', message_thumb: resolvedUrl };
|
||||||
this.imageDialogVisible = true;
|
this.imageDialogVisible = true;
|
||||||
},
|
},
|
||||||
@@ -373,8 +374,27 @@
|
|||||||
}
|
}
|
||||||
return `/api/messages/media_proxy?url=${encodeURIComponent(url)}`;
|
return `/api/messages/media_proxy?url=${encodeURIComponent(url)}`;
|
||||||
},
|
},
|
||||||
|
isUsableQuotedPreview(url) {
|
||||||
|
if (!url) return false;
|
||||||
|
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (url.includes('static/images') || url.includes('static\\images')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (url.includes('/') || url.includes('\\')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
hasQuotedPreview(url) {
|
||||||
|
return !!this.getQuotedPreviewUrl(url);
|
||||||
|
},
|
||||||
getQuotedPreviewUrl(url) {
|
getQuotedPreviewUrl(url) {
|
||||||
if (!url) return '';
|
if (!url) return '';
|
||||||
|
if (!this.isUsableQuotedPreview(url)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||||
return this.getMediaProxyUrl(url);
|
return this.getMediaProxyUrl(url);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,21 @@ class MessageStorageDB(BaseDBOperator):
|
|||||||
"""
|
"""
|
||||||
return self.execute_query(sql, (message_id,), fetch_one=True)
|
return self.execute_query(sql, (message_id,), fetch_one=True)
|
||||||
|
|
||||||
|
def get_image_message_by_md5(self, md5: str) -> Optional[Dict]:
|
||||||
|
"""根据图片消息 attachment_url 中的 md5 反查原图消息"""
|
||||||
|
sql = """
|
||||||
|
SELECT id, group_id, timestamp, sender, content, message_type,
|
||||||
|
attachment_url, message_id, message_xml, message_thumb, image_path
|
||||||
|
FROM messages
|
||||||
|
WHERE message_type = 3
|
||||||
|
AND attachment_url IS NOT NULL
|
||||||
|
AND attachment_url <> ''
|
||||||
|
AND attachment_url LIKE %s
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 1
|
||||||
|
"""
|
||||||
|
return self.execute_query(sql, (f'%md5="{md5}"%',), fetch_one=True)
|
||||||
|
|
||||||
def get_member_recent_messages(self, group_id: str, wxid: str, days: int = 30,
|
def get_member_recent_messages(self, group_id: str, wxid: str, days: int = 30,
|
||||||
limit: int = 200, include_today: bool = True) -> List[Dict]:
|
limit: int = 200, include_today: bool = True) -> List[Dict]:
|
||||||
"""获取指定群成员近期消息"""
|
"""获取指定群成员近期消息"""
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ def parse_quote_message(xml_content: str) -> dict:
|
|||||||
quoted_content = _extract_first(r'<refermsg>.*?<content>(.*?)</content>', xml_content)
|
quoted_content = _extract_first(r'<refermsg>.*?<content>(.*?)</content>', xml_content)
|
||||||
ref_type = _extract_first(r'<refermsg>.*?<type>(.*?)</type>', xml_content)
|
ref_type = _extract_first(r'<refermsg>.*?<type>(.*?)</type>', xml_content)
|
||||||
reference_svrid = _extract_first(r'<refermsg>.*?<svrid>(.*?)</svrid>', xml_content)
|
reference_svrid = _extract_first(r'<refermsg>.*?<svrid>(.*?)</svrid>', xml_content)
|
||||||
|
reference_md5 = (
|
||||||
|
_extract_first(r'md5="(.*?)"', html.unescape(quoted_content or ""))
|
||||||
|
or _extract_first(r"<md5>(.*?)</md5>", html.unescape(quoted_content or ""))
|
||||||
|
)
|
||||||
pretty_reference = _format_referenced_content(ref_type, quoted_content, xml_content)
|
pretty_reference = _format_referenced_content(ref_type, quoted_content, xml_content)
|
||||||
media_preview = _extract_media_preview(ref_type, quoted_content)
|
media_preview = _extract_media_preview(ref_type, quoted_content)
|
||||||
|
|
||||||
@@ -85,6 +89,7 @@ def parse_quote_message(xml_content: str) -> dict:
|
|||||||
"display_name": display_name,
|
"display_name": display_name,
|
||||||
"quoted_content": pretty_reference,
|
"quoted_content": pretty_reference,
|
||||||
"reference_svrid": reference_svrid,
|
"reference_svrid": reference_svrid,
|
||||||
|
"reference_md5": reference_md5,
|
||||||
"reference_type": media_preview.get("reference_type", "text"),
|
"reference_type": media_preview.get("reference_type", "text"),
|
||||||
"preview_image": media_preview.get("preview_image", ""),
|
"preview_image": media_preview.get("preview_image", ""),
|
||||||
"preview_video_thumb": media_preview.get("preview_video_thumb", ""),
|
"preview_video_thumb": media_preview.get("preview_video_thumb", ""),
|
||||||
|
|||||||
Reference in New Issue
Block a user