From e4a39135c217b00284e49390f6ae2e1ee22092f0 Mon Sep 17 00:00:00 2001
From: SiYuan <863909694@qq.com>
Date: Thu, 3 Apr 2025 13:18:13 +0800
Subject: [PATCH] =?UTF-8?q?=E9=80=82=E9=85=8D=E5=BE=AE=E4=BF=A14.0.3?=
=?UTF-8?q?=E6=AD=A3=E5=BC=8F=E7=89=88=EF=BC=8C=E4=BF=AE=E5=A4=8Dmedia.db?=
=?UTF-8?q?=E4=B8=8D=E5=AD=98=E5=9C=A8=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C?=
=?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BE=E7=89=87=E3=80=81=E8=A7=86=E9=A2=91?=
=?UTF-8?q?=E3=80=81=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E5=BC=82=E5=B8=B8?=
=?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
exporter/exporter_html.py | 2 -
exporter/resources/template.html | 683 +++++++++---------
wxManager/db_v4/media.py | 26 +-
wxManager/db_v4/message.py | 2 +-
wxManager/decrypt/wx_info_v4.py | 5 -
wxManager/manager_v3.py | 3 +-
wxManager/manager_v4.py | 5 +-
wxManager/model/db_model.py | 4 +-
wxManager/parser/emoji_parser.py | 1 +
.../protocbuf/packed_info_data_img2.proto | 25 +
.../protocbuf/packed_info_data_img2_pb2.py | 18 +-
.../protocbuf/packed_info_data_merged.proto | 8 +-
wxManager/parser/wechat_v4.py | 78 +-
13 files changed, 471 insertions(+), 389 deletions(-)
diff --git a/exporter/exporter_html.py b/exporter/exporter_html.py
index a142609..fe6d3e2 100644
--- a/exporter/exporter_html.py
+++ b/exporter/exporter_html.py
@@ -133,7 +133,6 @@ class HtmlExporter(ExporterBase):
self.update_progress_callback(index / total_steps)
type_ = message.type
if not self.is_selected(message):
- msg_index -= 1
continue
server_id = message.server_id
if type_ == MessageType.Image:
@@ -201,7 +200,6 @@ class HtmlExporter(ExporterBase):
VideoNumberIndex.append(msg_index)
elif type_ == MessageType.MergedMessages:
parser_merged(message)
-
msg_index += 1
is_select = True
html_json.append(message.to_json())
diff --git a/exporter/resources/template.html b/exporter/resources/template.html
index 4964241..013321a 100644
--- a/exporter/resources/template.html
+++ b/exporter/resources/template.html
@@ -4242,12 +4242,12 @@
personal_card.appendChild(card_bottom);
return personal_card;
}
- function openIMCard(message) {
+ function OpenIMCard(message) {
const OpenIM_card = document.createElement("div");
OpenIM_card.className = "OpenIM-card";
const contner = document.createElement("div");
contner.className = "contner";
- contner.innerHTML = `
`
+ contner.innerHTML = `
`
const contner_text = document.createElement("div");
contner_text.className = "text";
if (message.sex == '男') {
@@ -4260,7 +4260,7 @@
contner_text.innerHTML = `
${record.display_name}
+ recordItem.innerHTML = `
${record.display_name}
${timestampToTime(record.timestamp)}
`;
- recordItem.appendChild(innermessageMergeCard(record, zindex + 1, i, parent_server_id));
- // messageContent.appendChild(messageMergeModal(record, messageContent));
- messageContent.insertBefore(messageMergeModal(record, messageContent, zindex + 1, i, parent_server_id), messageContent.firstChild);
- } else if (record.type == MessageType.Video) {
- // 视频消息
- recordItem.innerHTML = `
${record.display_name}
- ${timestampToTime(record.timestamp)}
-
`;
- } else if (record.type == MessageType.Image || record.type == MessageType.Emoji) {
- // 文件消息
- recordItem.innerHTML = `
${record.display_name}
- ${timestampToTime(record.timestamp)}
`;
- recordItem.appendChild(messageImgBox(record));
- } else if (record.type == MessageType.File) {
- // 文件消息
- record.icon_path = getFileIcon(record.datafmt)
- recordItem.innerHTML = `
${record.display_name}
- ${timestampToTime(record.timestamp)}
`;
- recordItem.appendChild(messageFileBox(record));
- } else if (record.type == MessageType.Position) {
- // 文件消息
- recordItem.innerHTML = `
${record.display_name}
- ${timestampToTime(record.timestamp)}
`;
- recordItem.appendChild(messageLocation(record, newMapID));
- } else if (record.type == MessageType.LinkMessage) {
- // 文件消息
- recordItem.innerHTML = `
${record.display_name}
- ${timestampToTime(record.timestamp)}
`;
- recordItem.appendChild(messageCard(record));
- }
+ const record_params = {record, recordItem, messageContent, zindex, i, parent_server_id};
+ processMessage(record_params);
OnePersonMsgRight.appendChild(recordItem);
}
@@ -4510,70 +4792,10 @@
ModalContent.appendChild(ModalContainer);
message_MergeModal.appendChild(ModalContent);
- function getFileIcon(datafmt) {
- icon_files = {
- 'DOCX': ['doc', 'docx'],
- 'XLS': ['xls', 'xlsx'],
- 'CSV': ['csv'],
- 'TXT': ['txt'],
- 'ZIP': ['zip', '7z', 'rar'],
- 'PPT': ['ppt', 'pptx'],
- 'PDF': ['pdf'],
- }
-
- for (var key in icon_files) {
- if (icon_files[key].includes(datafmt)) {
- return key
- }
- }
- return 'Default'
- }
-
return message_MergeModal;
}
- function messageMiniProgram(message) {
- const message_MiniProgram = document.createElement('div');
- message_MiniProgram.className = `mini-program`;
-
- message_MiniProgram.innerHTML = `
-
-

-
${message.app_name}
-
- ${message.title}
-
-
- `;
- return message_MiniProgram;
- }
-
- function messageVideoNumber(message) {
- const message_VideoNumber = document.createElement('div');
- message_VideoNumber.className = `video-number`;
- const message_VideoNumber_title = document.createElement('div');
- message_VideoNumber_title.className = `title`;
- const message_VideoNumber_container = document.createElement('div');
- message_VideoNumber_container.className = `container`;
- message_VideoNumber_container.style.backgroundImage = `url(${message.cover_url})`;
- message_VideoNumber_container.style.backgroundSize = "cover";
- message_VideoNumber_container.style.backgroundRepeat = "no-repeat";
- message_VideoNumber_title.innerHTML = replaceEmoji(message.title);
- message_VideoNumber_container.innerHTML = `
-
-
-
-
${message.publisher_nickname}
-
-
-
`;
-
- message_VideoNumber.appendChild(message_VideoNumber_title);
- message_VideoNumber.appendChild(message_VideoNumber_container);
-
- return message_VideoNumber;
- }
// 从数据列表中取出对应范围的元素并添加到容器中
for (let i = startIndex; i < endIndex && i < ChatMsgIndex.length; i++) {
@@ -4589,242 +4811,15 @@
if (isChatroom && !message.is_send) {
messageContent.appendChild(displayNameBox(message));
}
- if (message.type == MessageType.Text && is_valid_data(message.server_id, message.token)) {
- // displayname 和 bubble
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- messageContent.appendChild(messageBubble(message, side));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.System) {
- messageElement.className = "item item-center";
- messageElement.innerHTML = `
${replaceEmoji(message.text.replace('\\"', '"'))}`;
- } else if ((message.type == MessageType.Image || message.type == MessageType.Emoji)&& is_valid_data(message.server_id, message.token)) {
- // displayname 和 img
- messageContent.className = `content-wrapper content-wrapper-${side}`;
-
- messageContent.appendChild(messageImgBox(message));
-
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.Video && is_valid_data(message.server_id, message.token)) {
- // displayname 和 video
- messageContent.className = `content-wrapper content-wrapper-${side}`;
-
- messageContent.appendChild(messageVideoBox(message));
-
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.File) {
- console.log('file');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- messageContent.appendChild(messageFileBox(message));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.Transfer) {
- console.log('Transfer');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageTransfer(message));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.LinkMessage) {
- console.log('LinkMessage');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageCard(message));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.Music) {
- console.log('LinkMessage');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageMusicAudioBox(message));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.Applet) {
- console.log('LinkMessage');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageMiniProgram(message));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.MergedMessages) {
- console.log('MergedMessages');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageMergeCard(message));
- // messageContent.appendChild(messageMergeModal(message, messageContent));
- messageContent.insertBefore(messageMergeModal(message, messageContent, 1), messageContent.firstChild);
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.Quote) {
- console.log('Quote');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageBubble(message, side));
- if (message.quote_text) {
- messageContent.appendChild(messageElementReferText(message, side));
- }
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.WeChatVideo) {
- console.log('WeChatVideo');
- // displayname 和 file
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageVideoNumber(message));
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == 49 && is_valid_data(message.server_id, message.token)) {
- if (message.sub_type == 57) {
- // displayname 和 bubble 和 refer
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageBubble(message, side));
- if (message.refer_text) {
- messageContent.appendChild(messageElementReferText(message, side));
- }
-
- } else if (message.sub_type == 3 || message.sub_type == 76) {
- // music share
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageMusicAudioBox(message));
- } else if (message.sub_type == 5) {
- // displayname 和 card
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageCard(message));
- } else if (message.sub_type == 2000) {
- // displayname 和 messageTransfer
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageTransfer(message));
- } else if (message.sub_type == 19) {
- // displayname 和 messageMergeCard
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageMergeCard(message));
- // messageContent.appendChild(messageMergeModal(message, messageContent));
- messageContent.insertBefore(messageMergeModal(message, messageContent, 1), messageContent.firstChild);
-
- } else if (message.sub_type == 33 || message.sub_type == 36) {
- // 小程序
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageMiniProgram(message));
- } else if (message.sub_type == 51) {
- // 视频号
- messageContent.className = `content-wrapper content-wrapper-${side}`;
- if (message.is_chatroom && !message.is_send) {
- messageContent.appendChild(displayNameBox(message));
- }
- messageContent.appendChild(messageVideoNumber(message));
- }
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == 34 && is_valid_data(message.server_id, message.token)) {
- // displayname 和 转的文字 和 audio
- messageContent.className = `content-wrapper content-wrapper-${side}`;
-
- messageContent.appendChild(messageAudioBox(message));
- if (message.voice_to_text) {
- messageContent.appendChild(messageVoiceToTextBubble(message, side));
- }
-
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.Voip && is_valid_data(message.server_id, message.token)) {
- // displayname 和 转的文字 和 audio
- messageContent.className = `content-wrapper content-wrapper-${side}`;
-
- messageContent.appendChild(messageVideoAudioCall(message, side));
-
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == MessageType.BusinessCard) {
- // 个人名片
- messageContent.className = `content-wrapper content-wrapper-${side}`;
-
- messageContent.appendChild(MessageType.is_open_im?openIMCard(message):personalCard(message));
-
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- } else if (message.type == 48 && is_valid_data(message.server_id, message.token)) {
- // 定位
- messageContent.className = `content-wrapper content-wrapper-${side}`;
-
- messageContent.appendChild(messageLocation(message, newMapID));
-
- // 整合
- messageElement.className = `item item-${side}`;
- messageElement.appendChild(message.is_send ? messageContent : avatarTag);
- messageElement.appendChild(message.is_send ? avatarTag : messageContent);
- }
+ const params = {
+ message, // 消息对象
+ side, // 消息显示位置(左/右)
+ messageContent, // 消息内容容器
+ messageElement, // 消息元素
+ avatarTag, // 头像标签
+ };
+ processMessage(params);
OnePageMessage.appendChild(messageElement);
}
@@ -4949,7 +4944,7 @@
var lastTimeStamp = 0;
// search init
-
+
var idx = lunr(function () {
this.use(lunr.zh);
this.ref('server_id')
diff --git a/wxManager/db_v4/media.py b/wxManager/db_v4/media.py
index bb93ca4..ebd46ae 100644
--- a/wxManager/db_v4/media.py
+++ b/wxManager/db_v4/media.py
@@ -9,6 +9,7 @@
@Description :
"""
import os
+import shutil
import subprocess
import sys
import traceback
@@ -35,6 +36,8 @@ class MediaDB(DataBaseBase):
from VoiceInfo
where svr_id = ?
'''
+ if not self.DB:
+ return b''
for db in self.DB:
cursor = db.cursor()
cursor.execute(sql, [server_id])
@@ -100,16 +103,19 @@ class MediaDB(DataBaseBase):
if not (os.path.exists(db_path) or os.path.isfile(db_path)):
print(f'{db_path} 不存在')
return
- for db in self.DB:
- cursor = db.cursor()
- try:
- # 获取列名
- increase_data(db_path, cursor, db, 'VoiceInfo', 'svr_id')
- increase_data(db_path, cursor, db, 'Name2Id', 'user_name')
- increase_update_data(db_path, cursor, db, 'Timestamp', 'timestamp')
- except:
- print(f"数据库操作错误: {traceback.format_exc()}")
- db.rollback()
+ if not self.DB:
+ shutil.copy(db_path,os.path.join(self.db_dir,self.db_file_name))
+ else:
+ for db in self.DB:
+ cursor = db.cursor()
+ try:
+ # 获取列名
+ increase_data(db_path, cursor, db, 'VoiceInfo', 'svr_id')
+ increase_data(db_path, cursor, db, 'Name2Id', 'user_name')
+ increase_update_data(db_path, cursor, db, 'Timestamp', 'timestamp')
+ except:
+ print(f"数据库操作错误: {traceback.format_exc()}")
+ db.rollback()
if __name__ == '__main__':
diff --git a/wxManager/db_v4/message.py b/wxManager/db_v4/message.py
index d1068ff..633ed2d 100644
--- a/wxManager/db_v4/message.py
+++ b/wxManager/db_v4/message.py
@@ -309,7 +309,7 @@ order by sort_seq
task_(db_path, cursor, db)
tasks.append([db_path, cursor, db])
else:
- shutil.copy(db_path, os.path.join(self.db_dir, 'Multi', file_name))
+ shutil.copy(db_path, os.path.join(self.db_dir, 'message', file_name))
# print(tasks)
# 使用线程池 (没有加快合并速度)
# with ThreadPoolExecutor(max_workers=len(tasks)) as executor:
diff --git a/wxManager/decrypt/wx_info_v4.py b/wxManager/decrypt/wx_info_v4.py
index 0a0cc0c..2b9a29c 100644
--- a/wxManager/decrypt/wx_info_v4.py
+++ b/wxManager/decrypt/wx_info_v4.py
@@ -430,11 +430,6 @@ def get_nickname(pid):
for string in match.strings:
instance = string.instances[0]
offset, content = instance.offset, instance.matched_data
- # print(
- # f"匹配字符串: {identifier} 内容: 偏移: {offset} 在地址: {hex(base_address + offset + 0x10)}")
- # print(string)
- with open('a.bin','wb') as f:
- f.write(target_data)
phone_addr = offset + 0x10
phone = read_string(target_data, phone_addr, 11)
diff --git a/wxManager/manager_v3.py b/wxManager/manager_v3.py
index 5c4b04a..2d36c7c 100644
--- a/wxManager/manager_v3.py
+++ b/wxManager/manager_v3.py
@@ -210,7 +210,8 @@ class DataBaseV3(DataBaseInterface):
flag &= self.open_media_db.init_database(db_dir)
flag &= self.open_msg_db.init_database(db_dir)
flag &= self.audio2text_db.init_database(db_dir)
- self.audio2text_db.create() # 初始化数据转文字数据库
+ if flag:
+ self.audio2text_db.create() # 初始化语音转文字数据库
return flag
# self.sns_db.init_database(db_dir)
diff --git a/wxManager/manager_v4.py b/wxManager/manager_v4.py
index 8aa5214..fed53eb 100644
--- a/wxManager/manager_v4.py
+++ b/wxManager/manager_v4.py
@@ -96,11 +96,12 @@ class DataBaseV4(DataBaseInterface):
flag &= self.session_db.init_database(db_dir)
flag &= self.message_db.init_database(db_dir)
flag &= self.biz_message_db.init_database(db_dir)
- flag &= self.media_db.init_database(db_dir)
+ self.media_db.init_database(db_dir)
flag &= self.hardlink_db.init_database(db_dir)
flag &= self.emotion_db.init_database(db_dir)
flag &= self.audio2text_db.init_database(db_dir)
- self.audio2text_db.create() # 初始化数据转文字数据库
+ if flag:
+ self.audio2text_db.create() # 初始化语音转文字数据库
return flag
def close(self):
diff --git a/wxManager/model/db_model.py b/wxManager/model/db_model.py
index 986b206..4d00d98 100644
--- a/wxManager/model/db_model.py
+++ b/wxManager/model/db_model.py
@@ -24,12 +24,14 @@ class DataBaseBase:
def init_database(self, db_dir=''):
self.db_dir = db_dir
+ if not os.path.exists(db_dir):
+ return False
db_path = os.path.join(db_dir, self.db_file_name)
if not os.path.exists(db_path) and self.db_file_name != 'Audio2Text.db':
return False
db_file_name = self.db_file_name
- self.db_file_name = []
if self.is_series:
+ self.db_file_name = []
self.DB = []
self.cursor = []
for i in range(100):
diff --git a/wxManager/parser/emoji_parser.py b/wxManager/parser/emoji_parser.py
index a9af038..ff04bed 100644
--- a/wxManager/parser/emoji_parser.py
+++ b/wxManager/parser/emoji_parser.py
@@ -57,6 +57,7 @@ def parser_emoji(xml_content):
}
except:
logger.error(traceback.format_exc())
+ logger.error(xml_content)
finally:
return result
diff --git a/wxManager/parser/util/protocbuf/packed_info_data_img2.proto b/wxManager/parser/util/protocbuf/packed_info_data_img2.proto
index 4fd3a1c..e288c54 100644
--- a/wxManager/parser/util/protocbuf/packed_info_data_img2.proto
+++ b/wxManager/parser/util/protocbuf/packed_info_data_img2.proto
@@ -4,10 +4,35 @@ message PackedInfoDataImg2 {
int32 field1 = 1;
int32 field2 = 2;
ImageInfo imageInfo = 3;
+ VideoInfo videoInfo = 4;
+ FileInfo fileInfo = 7;
}
message ImageInfo {
int32 height = 1;
int32 width = 2;
string filename = 4;
+}
+
+message VideoInfo {
+ int32 height = 4;
+ int32 width = 5;
+ string filename = 8;
+}
+
+message FileInfo {
+ FileSubMessage1 fileInfo = 1;
+ FileSubMessage2 field2 = 2;
+ string field3 = 3;
+}
+
+message FileSubMessage1 {
+ int32 field1 = 1;
+ string filename = 2;
+}
+
+message FileSubMessage2 {
+ string field1 = 1;
+ string field2 = 2;
+ string field3 = 3;
}
\ No newline at end of file
diff --git a/wxManager/parser/util/protocbuf/packed_info_data_img2_pb2.py b/wxManager/parser/util/protocbuf/packed_info_data_img2_pb2.py
index ea163dc..301f5db 100644
--- a/wxManager/parser/util/protocbuf/packed_info_data_img2_pb2.py
+++ b/wxManager/parser/util/protocbuf/packed_info_data_img2_pb2.py
@@ -13,15 +13,23 @@ _sym_db = _symbol_database.Default()
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bpacked_info_data_img2.proto\"S\n\x12PackedInfoDataImg2\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\x05\x12\x1d\n\timageInfo\x18\x03 \x01(\x0b\x32\n.ImageInfo\"<\n\tImageInfo\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05width\x18\x02 \x01(\x05\x12\x10\n\x08\x66ilename\x18\x04 \x01(\tb\x06proto3')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bpacked_info_data_img2.proto\"\x8f\x01\n\x12PackedInfoDataImg2\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\x05\x12\x1d\n\timageInfo\x18\x03 \x01(\x0b\x32\n.ImageInfo\x12\x1d\n\tvideoInfo\x18\x04 \x01(\x0b\x32\n.VideoInfo\x12\x1b\n\x08\x66ileInfo\x18\x07 \x01(\x0b\x32\t.FileInfo\"<\n\tImageInfo\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05width\x18\x02 \x01(\x05\x12\x10\n\x08\x66ilename\x18\x04 \x01(\t\"<\n\tVideoInfo\x12\x0e\n\x06height\x18\x04 \x01(\x05\x12\r\n\x05width\x18\x05 \x01(\x05\x12\x10\n\x08\x66ilename\x18\x08 \x01(\t\"`\n\x08\x46ileInfo\x12\"\n\x08\x66ileInfo\x18\x01 \x01(\x0b\x32\x10.FileSubMessage1\x12 \n\x06\x66ield2\x18\x02 \x01(\x0b\x32\x10.FileSubMessage2\x12\x0e\n\x06\x66ield3\x18\x03 \x01(\t\"3\n\x0f\x46ileSubMessage1\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\x05\x12\x10\n\x08\x66ilename\x18\x02 \x01(\t\"A\n\x0f\x46ileSubMessage2\x12\x0e\n\x06\x66ield1\x18\x01 \x01(\t\x12\x0e\n\x06\x66ield2\x18\x02 \x01(\t\x12\x0e\n\x06\x66ield3\x18\x03 \x01(\tb\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'packed_info_data_img2_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
- _PACKEDINFODATAIMG2._serialized_start=31
- _PACKEDINFODATAIMG2._serialized_end=114
- _IMAGEINFO._serialized_start=116
- _IMAGEINFO._serialized_end=176
+ _PACKEDINFODATAIMG2._serialized_start=32
+ _PACKEDINFODATAIMG2._serialized_end=175
+ _IMAGEINFO._serialized_start=177
+ _IMAGEINFO._serialized_end=237
+ _VIDEOINFO._serialized_start=239
+ _VIDEOINFO._serialized_end=299
+ _FILEINFO._serialized_start=301
+ _FILEINFO._serialized_end=397
+ _FILESUBMESSAGE1._serialized_start=399
+ _FILESUBMESSAGE1._serialized_end=450
+ _FILESUBMESSAGE2._serialized_start=452
+ _FILESUBMESSAGE2._serialized_end=517
# @@protoc_insertion_point(module_scope)
diff --git a/wxManager/parser/util/protocbuf/packed_info_data_merged.proto b/wxManager/parser/util/protocbuf/packed_info_data_merged.proto
index 506ec59..18f4a17 100644
--- a/wxManager/parser/util/protocbuf/packed_info_data_merged.proto
+++ b/wxManager/parser/util/protocbuf/packed_info_data_merged.proto
@@ -3,19 +3,19 @@ syntax = "proto3";
message PackedInfoData {
int32 field1 = 1;
int32 field2 = 2;
- NestedMessage field7 = 7;
+ FileInfo fileInfo = 7;
AnotherNestedMessage info = 9;
}
-message NestedMessage {
- SubMessage1 field1 = 1;
+message FileInfo {
+ SubMessage1 fileInfo = 1;
SubMessage2 field2 = 2;
string field3 = 3;
}
message SubMessage1 {
int32 field1 = 1;
- string field2 = 2;
+ string filename = 2;
}
message SubMessage2 {
diff --git a/wxManager/parser/wechat_v4.py b/wxManager/parser/wechat_v4.py
index 6cb68c2..99bb42e 100644
--- a/wxManager/parser/wechat_v4.py
+++ b/wxManager/parser/wechat_v4.py
@@ -42,9 +42,12 @@ source,message_content,compress_content"
def decompress(data):
- dctx = zstd.ZstdDecompressor() # 创建解压对象
- x = dctx.decompress(data).strip(b'\x00').strip()
- return x.decode('utf-8').strip()
+ try:
+ dctx = zstd.ZstdDecompressor() # 创建解压对象
+ x = dctx.decompress(data).strip(b'\x00').strip()
+ return x.decode('utf-8').strip()
+ except:
+ return ''
class LimitedDict:
@@ -255,8 +258,8 @@ class ImageMessageFactory(MessageFactory, Singleton):
# 转换为 JSON 格式
packed_info_data = MessageToDict(packed_info_data_proto)
image_info = packed_info_data.get('imageInfo', {})
- width = image_info.get('width',0)
- height = image_info.get('height',0)
+ width = image_info.get('width', 0)
+ height = image_info.get('height', 0)
filename = image_info.get('filename', '').strip().strip('"').strip()
except:
pass
@@ -344,6 +347,19 @@ class AudioMessageFactory(MessageFactory, Singleton):
class VideoMessageFactory(MessageFactory, Singleton):
def create(self, message, username, manager):
is_sender, wxid, message_content = self.common_attribute(message, username, manager)
+ filename = ''
+ try:
+ # 2025年3月微信4.0.3正式版修改了img命名方式才有了这个东西
+ packed_info_data_proto = packed_info_data_img2_pb2.PackedInfoDataImg2()
+ packed_info_data_proto.ParseFromString(message[14])
+ # 转换为 JSON 格式
+ packed_info_data = MessageToDict(packed_info_data_proto)
+ image_info = packed_info_data.get('videoInfo', {})
+ width = image_info.get('width', 0)
+ height = image_info.get('height', 0)
+ filename = image_info.get('filename', '').strip().strip('"').strip()
+ except:
+ pass
msg = VideoMessage(
local_id=message[0],
server_id=message[1],
@@ -361,7 +377,7 @@ class VideoMessageFactory(MessageFactory, Singleton):
md5='',
path='',
file_size=0,
- file_name='',
+ file_name=filename,
file_type='mp4',
thumb_path='',
duration=0,
@@ -372,12 +388,25 @@ class VideoMessageFactory(MessageFactory, Singleton):
msg.file_size = video_dic.get('size', 0)
msg.md5 = video_dic.get('md5', '')
msg.raw_md5 = video_dic.get('rawmd5', '')
- msg.path = manager.hardlink_db.get_video(msg.raw_md5, False)
- msg.thumb_path = manager.hardlink_db.get_video(msg.raw_md5, True)
- if not msg.path:
- msg.path = manager.hardlink_db.get_video(msg.md5, False)
- msg.thumb_path = manager.hardlink_db.get_video(msg.md5, True)
- # logger.error(f'{msg.path} {msg.thumb_path}')
+ month = msg.str_time[:7] # 2025-01
+ if filename:
+ # 微信4.0.3正式版增加
+ video_dir = os.path.join('msg', 'video', month)
+ video_path = os.path.join(video_dir, f'{filename}_raw.mp4')
+ if os.path.exists(os.path.join(Me().wx_dir, video_path)):
+ msg.path = video_path
+ msg.thumb_path = os.path.join(video_dir, f'{filename}.jpg')
+ else:
+ msg.path = os.path.join(video_dir, f'{filename}.mp4')
+ msg.thumb_path = os.path.join(video_dir, f'{filename}.jpg')
+ else:
+ msg.path = manager.hardlink_db.get_video(msg.raw_md5, False)
+ msg.thumb_path = manager.hardlink_db.get_video(msg.raw_md5, True)
+ if not msg.path:
+ msg.path = manager.hardlink_db.get_video(msg.md5, False)
+ msg.thumb_path = manager.hardlink_db.get_video(msg.md5, True)
+ # logger.error(f'{msg.path} {msg.thumb_path}')
+
self.add_message(msg)
return msg
@@ -847,7 +876,19 @@ class FileMessageFactory(MessageFactory, Singleton):
is_sender, wxid, message_content = self.common_attribute(message, username, manager)
info = parser_file(message_content)
md5 = info.get('md5', '')
- file_path = manager.get_file(md5)
+ filename = info.get('filename','')
+ if not filename:
+ try:
+ # 2025年3月微信4.0.3正式版修改了img命名方式才有了这个东西
+ packed_info_data_proto = packed_info_data_img2_pb2.PackedInfoDataImg2()
+ packed_info_data_proto.ParseFromString(message[14])
+ # 转换为 JSON 格式
+ packed_info_data = MessageToDict(packed_info_data_proto)
+ image_info = packed_info_data.get('fileInfo', {})
+ file_info = image_info.get('fileInfo', {})
+ filename = file_info.get('filename', '').strip()
+ except:
+ pass
msg = FileMessage(
local_id=message[0],
server_id=message[1],
@@ -862,12 +903,21 @@ class FileMessageFactory(MessageFactory, Singleton):
avatar_src=self.contacts[wxid].small_head_img_url,
status=message[7],
xml_content=message_content,
- path=file_path,
+ path='',
md5=md5,
file_type=info.get('file_type', ''),
file_name=info.get('file_name', ''),
file_size=info.get('file_size', 0)
)
+ # file_path = manager.get_file(md5)
+ if filename:
+ month = msg.str_time[:7] # 2025-01
+ # 微信4.0.3正式版增加
+ video_dir = os.path.join('msg', 'file', month)
+ file_path = os.path.join(video_dir, f'{filename}')
+ msg.path = file_path
+ else:
+ msg.path = manager.get_file(md5)
self.add_message(msg)
return msg