适配微信4.0.3正式版,修复media.db不存在的问题,修复图片、视频、文件路径异常的问题
This commit is contained in:
@@ -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__':
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -57,6 +57,7 @@ def parser_emoji(xml_content):
|
||||
}
|
||||
except:
|
||||
logger.error(traceback.format_exc())
|
||||
logger.error(xml_content)
|
||||
finally:
|
||||
return result
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user