修复Word头像问题

This commit is contained in:
shuaikangzhou 2023-12-30 18:05:53 +08:00
parent 0a82714790
commit 3b75ba2455
6 changed files with 87 additions and 115 deletions

View File

@ -1,30 +1,29 @@
import csv import csv
import html import html
import os import os
import shutil
import sys import sys
import time import time
import traceback import traceback
from re import findall from re import findall
import docx
from PyQt5.QtCore import pyqtSignal, QThread from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtWidgets import QFileDialog from PyQt5.QtWidgets import QFileDialog
from docx.oxml.ns import qn
from . import msg_db
from .package_msg import PackageMsg
from ..DataBase import hard_link_db
from ..DataBase import media_msg_db
from ..log import logger
from ..person import MePC
from ..util import path
import shutil
from ..util.compress_content import parser_reply
from ..util.emoji import get_emoji_url
from ..util.image import get_image_path, get_image, get_image_abs_path
from ..util.file import get_file
import docx
from docx import shared from docx import shared
from docx.enum.table import WD_ALIGN_VERTICAL from docx.enum.table import WD_ALIGN_VERTICAL
from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from .package_msg import PackageMsg
from ..DataBase import media_msg_db, hard_link_db, micro_msg_db, msg_db
from ..log import logger
from ..person import MePC
from ..util import path
from ..util.compress_content import parser_reply
from ..util.emoji import get_emoji_url
from ..util.file import get_file
from ..util.image import get_image_path, get_image, get_image_abs_path
os.makedirs('./data/聊天记录', exist_ok=True) os.makedirs('./data/聊天记录', exist_ok=True)
@ -105,7 +104,23 @@ class Output(QThread):
def progress(self, value): def progress(self, value):
self.progressSignal.emit(value) self.progressSignal.emit(value)
def output_image(self):
"""
导出全部图片
@return:
"""
return
def output_emoji(self):
"""
导出全部表情包
@return:
"""
return
def to_csv_all(self): def to_csv_all(self):
"""
导出全部聊天记录到CSV
@return:
"""
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/"
os.makedirs(origin_docx_path, exist_ok=True) os.makedirs(origin_docx_path, exist_ok=True)
filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(), 'messages.csv'), filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(), 'messages.csv'),
@ -129,6 +144,10 @@ class Output(QThread):
self.okSignal.emit(1) self.okSignal.emit(1)
def contact_to_csv(self): def contact_to_csv(self):
"""
导出联系人到CSV
@return:
"""
filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(), 'contacts.csv'), filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(), 'contacts.csv'),
"csv files (*.csv);;all files(*.*)") "csv files (*.csv);;all files(*.*)")
if not filename[0]: if not filename[0]:
@ -193,8 +212,14 @@ class Output(QThread):
self.output_image.start() self.output_image.start()
def count_finish_num(self, num): def count_finish_num(self, num):
"""
记录子线程完成个数
@param num:
@return:
"""
self.num += 1 self.num += 1
if self.num == self.total_num: if self.num == self.total_num:
# 所有子线程都完成之后就发送完成信号
self.okSignal.emit(1) self.okSignal.emit(1)
def cancel(self): def cancel(self):
@ -241,13 +266,16 @@ class ChildThread(QThread):
return True return True
return False return False
def get_avatar_path(self, is_send, message,is_absolute_path=False) -> str: def get_avatar_path(self, is_send, message, is_absolute_path=False) -> str:
if self.contact.is_chatroom: if self.contact.is_chatroom:
avatar = message[12].smallHeadImgUrl avatar = message[12].smallHeadImgUrl
else: else:
avatar = MePC().smallHeadImgUrl if is_send else self.contact.smallHeadImgUrl avatar = MePC().smallHeadImgUrl if is_send else self.contact.smallHeadImgUrl
if is_absolute_path: if is_absolute_path:
avatar = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"+avatar if self.contact.is_chatroom:
avatar = message[12].avatar_path
else:
avatar = MePC().avatar_path if is_send else self.contact.avatar_path
return avatar return avatar
def get_display_name(self, is_send, message) -> str: def get_display_name(self, is_send, message) -> str:
@ -268,7 +296,7 @@ class ChildThread(QThread):
timestamp = message[5] timestamp = message[5]
is_chatroom = 1 if self.contact.is_chatroom else 0 is_chatroom = 1 if self.contact.is_chatroom else 0
display_name = self.get_display_name(is_send,message) display_name = self.get_display_name(is_send, message)
if self.output_type == Output.HTML: if self.output_type == Output.HTML:
avatar = self.get_avatar_path(is_send, message) avatar = self.get_avatar_path(is_send, message)
str_content = escape_js_and_html(str_content) str_content = escape_js_and_html(str_content)
@ -281,7 +309,7 @@ class ChildThread(QThread):
f'''{str_time} {name}\n{str_content}\n\n''' f'''{str_time} {name}\n{str_content}\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content_cell = self.create_table(doc, is_send, avatar) content_cell = self.create_table(doc, is_send, avatar)
content_cell.paragraphs[0].add_run(str_content) content_cell.paragraphs[0].add_run(str_content)
content_cell.paragraphs[0].font_size = shared.Inches(0.5) content_cell.paragraphs[0].font_size = shared.Inches(0.5)
@ -300,7 +328,7 @@ class ChildThread(QThread):
timestamp = message[5] timestamp = message[5]
is_chatroom = 1 if self.contact.is_chatroom else 0 is_chatroom = 1 if self.contact.is_chatroom else 0
avatar = self.get_avatar_path(is_send, message) avatar = self.get_avatar_path(is_send, message)
display_name = self.get_display_name(is_send,message) display_name = self.get_display_name(is_send, message)
if self.output_type == Output.HTML: if self.output_type == Output.HTML:
str_content = escape_js_and_html(str_content) str_content = escape_js_and_html(str_content)
image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False) image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False)
@ -318,7 +346,7 @@ class ChildThread(QThread):
f'''{str_time} {display_name}\n[图片]\n\n''' f'''{str_time} {display_name}\n[图片]\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content = self.create_table(doc, is_send, avatar) content = self.create_table(doc, is_send, avatar)
run = content.paragraphs[0].add_run() run = content.paragraphs[0].add_run()
str_content = escape_js_and_html(str_content) str_content = escape_js_and_html(str_content)
@ -361,7 +389,7 @@ class ChildThread(QThread):
f'''{str_time} {display_name}\n[语音]\n\n''' f'''{str_time} {display_name}\n[语音]\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content_cell = self.create_table(doc, is_send, avatar) content_cell = self.create_table(doc, is_send, avatar)
content_cell.paragraphs[0].add_run('【表情包】') content_cell.paragraphs[0].add_run('【表情包】')
content_cell.paragraphs[0].font_size = shared.Inches(0.5) content_cell.paragraphs[0].font_size = shared.Inches(0.5)
@ -369,6 +397,7 @@ class ChildThread(QThread):
p = content_cell.paragraphs[0] p = content_cell.paragraphs[0]
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
doc.add_paragraph() doc.add_paragraph()
def emoji(self, doc, message): def emoji(self, doc, message):
str_content = message[7] str_content = message[7]
str_time = message[8] str_time = message[8]
@ -387,7 +416,7 @@ class ChildThread(QThread):
f'''{str_time} {display_name}\n[表情包]\n\n''' f'''{str_time} {display_name}\n[表情包]\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content_cell = self.create_table(doc, is_send, avatar) content_cell = self.create_table(doc, is_send, avatar)
content_cell.paragraphs[0].add_run('【表情包】') content_cell.paragraphs[0].add_run('【表情包】')
content_cell.paragraphs[0].font_size = shared.Inches(0.5) content_cell.paragraphs[0].font_size = shared.Inches(0.5)
@ -420,7 +449,7 @@ class ChildThread(QThread):
f'''{str_time} {display_name}\n[文件]\n\n''' f'''{str_time} {display_name}\n[文件]\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content_cell = self.create_table(doc, is_send, avatar) content_cell = self.create_table(doc, is_send, avatar)
content_cell.paragraphs[0].add_run('【文件】') content_cell.paragraphs[0].add_run('【文件】')
content_cell.paragraphs[0].font_size = shared.Inches(0.5) content_cell.paragraphs[0].font_size = shared.Inches(0.5)
@ -465,7 +494,7 @@ class ChildThread(QThread):
f'''{str_time} {display_name}\n{content.get('title')}\n引用:未知\n\n''' f'''{str_time} {display_name}\n{content.get('title')}\n引用:未知\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content_cell = self.create_table(doc, is_send, avatar) content_cell = self.create_table(doc, is_send, avatar)
content_cell.paragraphs[0].add_run(content.get('title')) content_cell.paragraphs[0].add_run(content.get('title'))
content_cell.paragraphs[0].font_size = shared.Inches(0.5) content_cell.paragraphs[0].font_size = shared.Inches(0.5)
@ -552,7 +581,7 @@ class ChildThread(QThread):
f'''{str_time} {display_name}\n[视频]\n\n''' f'''{str_time} {display_name}\n[视频]\n\n'''
) )
elif self.output_type == Output.DOCX: elif self.output_type == Output.DOCX:
avatar = self.get_avatar_path(is_send,message,True) avatar = self.get_avatar_path(is_send, message, True)
content_cell = self.create_table(doc, is_send, avatar) content_cell = self.create_table(doc, is_send, avatar)
content_cell.paragraphs[0].add_run('【视频】') content_cell.paragraphs[0].add_run('【视频】')
content_cell.paragraphs[0].font_size = shared.Inches(0.5) content_cell.paragraphs[0].font_size = shared.Inches(0.5)
@ -612,7 +641,6 @@ class ChildThread(QThread):
writer.writerows(messages) writer.writerows(messages)
self.okSignal.emit('ok') self.okSignal.emit('ok')
def to_html_(self): def to_html_(self):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
makedirs(origin_docx_path) makedirs(origin_docx_path)
@ -715,19 +743,19 @@ class ChildThread(QThread):
messages = msg_db.get_messages(self.contact.wxid) messages = msg_db.get_messages(self.contact.wxid)
MePC().avatar.save(os.path.join(f"{origin_docx_path}/avatar/{MePC().wxid}.png")) MePC().avatar.save(os.path.join(f"{origin_docx_path}/avatar/{MePC().wxid}.png"))
MePC().save_avatar(os.path.join(f"{origin_docx_path}/avatar/{MePC().wxid}.png"))
if self.contact.is_chatroom: if self.contact.is_chatroom:
for message in messages: for message in messages:
if message[4]: # is_send if message[4]: # is_send
continue continue
try: try:
chatroom_avatar_path = f"{origin_docx_path}/avatar/{message[12].wxid}.png" chatroom_avatar_path = f"{origin_docx_path}/avatar/{message[12].wxid}.png"
if not os.path.exists(chatroom_avatar_path): message[12].save_avatar(chatroom_avatar_path)
message[12].avatar.save(chatroom_avatar_path)
except: except:
print(message) print(message)
pass pass
else: else:
self.contact.avatar.save(os.path.join(f"{origin_docx_path}/avatar/{self.contact.wxid}.png")) self.contact.save_avatar(os.path.join(f"{origin_docx_path}/avatar/{self.contact.wxid}.png"))
self.rangeSignal.emit(len(messages)) self.rangeSignal.emit(len(messages))
for index, message in enumerate(messages): for index, message in enumerate(messages):
type_ = message[2] type_ = message[2]
@ -767,8 +795,6 @@ class ChildThread(QThread):
self.to_csv() self.to_csv()
elif self.output_type == Output.HTML: elif self.output_type == Output.HTML:
self.to_html_() self.to_html_()
elif self.output_type == Output.CSV_ALL:
self.to_csv_all()
elif self.output_type == Output.TXT: elif self.output_type == Output.TXT:
self.to_txt() self.to_txt()
@ -777,6 +803,9 @@ class ChildThread(QThread):
class OutputMedia(QThread): class OutputMedia(QThread):
"""
导出语音消息
"""
okSingal = pyqtSignal(int) okSingal = pyqtSignal(int)
progressSignal = pyqtSignal(int) progressSignal = pyqtSignal(int)
@ -800,6 +829,9 @@ class OutputMedia(QThread):
class OutputEmoji(QThread): class OutputEmoji(QThread):
"""
导出表情包
"""
okSingal = pyqtSignal(int) okSingal = pyqtSignal(int)
progressSignal = pyqtSignal(int) progressSignal = pyqtSignal(int)
@ -823,6 +855,9 @@ class OutputEmoji(QThread):
class OutputImage(QThread): class OutputImage(QThread):
"""
导出图片
"""
okSingal = pyqtSignal(int) okSingal = pyqtSignal(int)
progressSignal = pyqtSignal(int) progressSignal = pyqtSignal(int)
@ -912,26 +947,4 @@ class OutputImageChild(QThread):
if __name__ == "__main__": if __name__ == "__main__":
from app.DataBase import micro_msg_db, misc_db pass
from app.person import ContactPC
from PyQt5.QtGui import QGuiApplication
app = QGuiApplication([])
contact_info_list = micro_msg_db.get_contact_by_username("wxid_lhbdvh3cnn4h22")
contact_info = {
'UserName': contact_info_list[0],
'Alias': contact_info_list[1],
'Type': contact_info_list[2],
'Remark': contact_info_list[3],
'NickName': contact_info_list[4],
'smallHeadImgUrl': contact_info_list[7]
}
contact = ContactPC(contact_info)
contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG)
mess = {1: True, 3: True, 34: True, 43: True, 47: True, 10000: True}
MePC().name = "无题"
MePC().wx_dir = r"C:\Users\HUAWEI\Documents\WeChat Files\wxid_05rvkbftizq822"
MePC().wxid = "wxid_05rvkbftizq822"
ChildThread(contact, 2, mess).to_html_()
app.quit()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 880 KiB

View File

@ -19,17 +19,7 @@ def singleton(cls):
return inner return inner
@singleton class Person:
class MePC:
def __init__(self):
self.avatar = QPixmap(Icon.Default_avatar_path)
self.avatar_path = ':/icons/icons/default_avatar.svg'
self.wxid = ''
self.wx_dir = ''
self.name = ''
self.mobile = ''
self.smallHeadImgUrl = ''
def set_avatar(self, img_bytes): def set_avatar(self, img_bytes):
if not img_bytes: if not img_bytes:
self.avatar.load(Icon.Default_avatar_path) self.avatar.load(Icon.Default_avatar_path)
@ -44,6 +34,9 @@ class MePC:
return return
if path: if path:
save_path = path save_path = path
if os.path.exists(save_path):
self.avatar_path = save_path
return save_path
else: else:
os.makedirs('./data/avatar', exist_ok=True) os.makedirs('./data/avatar', exist_ok=True)
save_path = os.path.join(f'data/avatar/', self.wxid + '.png') save_path = os.path.join(f'data/avatar/', self.wxid + '.png')
@ -52,7 +45,19 @@ class MePC:
print('保存头像', save_path) print('保存头像', save_path)
class ContactPC: @singleton
class MePC(Person):
def __init__(self):
self.avatar = QPixmap(Icon.Default_avatar_path)
self.avatar_path = ':/icons/icons/default_avatar.svg'
self.wxid = ''
self.wx_dir = ''
self.name = ''
self.mobile = ''
self.smallHeadImgUrl = ''
class ContactPC(Person):
def __init__(self, contact_info: Dict): def __init__(self, contact_info: Dict):
self.wxid = contact_info.get('UserName') self.wxid = contact_info.get('UserName')
self.remark = contact_info.get('Remark') self.remark = contact_info.get('Remark')
@ -68,29 +73,8 @@ class ContactPC:
self.avatar_path = Icon.Default_avatar_path self.avatar_path = Icon.Default_avatar_path
self.is_chatroom = self.wxid.__contains__('@chatroom') self.is_chatroom = self.wxid.__contains__('@chatroom')
def set_avatar(self, img_bytes):
if not img_bytes:
self.avatar.load(Icon.Default_avatar_path)
return
if img_bytes[:4] == b'\x89PNG':
self.avatar.loadFromData(img_bytes, format='PNG')
else:
self.avatar.loadFromData(img_bytes, format='jfif')
self.avatar.scaled(60, 60, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
def save_avatar(self, path=None): class ContactDefault(Person):
if not self.avatar:
return
if path:
save_path = path
else:
os.makedirs('./data/avatar', exist_ok=True)
save_path = os.path.join(f'data/avatar/', self.wxid + '.png')
self.avatar_path = save_path
self.avatar.save(save_path)
print('保存头像', save_path)
class ContactDefault:
def __init__(self, wxid=""): def __init__(self, wxid=""):
self.avatar = QPixmap(Icon.Default_avatar_path) self.avatar = QPixmap(Icon.Default_avatar_path)
self.avatar_path = ':/icons/icons/default_avatar.svg' self.avatar_path = ':/icons/icons/default_avatar.svg'
@ -101,28 +85,6 @@ class ContactDefault:
self.smallHeadImgUrl = "" self.smallHeadImgUrl = ""
self.smallHeadImgBLOG = b'' self.smallHeadImgBLOG = b''
self.is_chatroom = False self.is_chatroom = False
def set_avatar(self, img_bytes):
if not img_bytes:
self.avatar.load(Icon.Default_avatar_path)
return
if img_bytes[:4] == b'\x89PNG':
self.avatar.loadFromData(img_bytes, format='PNG')
else:
self.avatar.loadFromData(img_bytes, format='jfif')
self.avatar.scaled(60, 60, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
def save_avatar(self, path=None):
if not self.avatar:
return
if path:
save_path = path
else:
os.makedirs('./data/avatar', exist_ok=True)
save_path = os.path.join(f'data/avatar/', self.wxid + '.png')
self.avatar_path = save_path
self.avatar.save(save_path)
print('保存头像', save_path)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -133,8 +133,6 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog, QCursorGif):
QMessageBox.critical(self, "错误", QMessageBox.critical(self, "错误",
"密钥错误\n将软件放在桌面上试试\n如果还不可以的话我也我能为力,您可以等待后续版本解决该问题") "密钥错误\n将软件放在桌面上试试\n如果还不可以的话我也我能为力,您可以等待后续版本解决该问题")
close_db() close_db()
self.label_tip.setVisible(True)
self.label_tip.setText('点我之后没有反应那就多等儿吧,不要再点了')
self.thread2 = DecryptThread(db_dir, self.info['key']) self.thread2 = DecryptThread(db_dir, self.info['key'])
self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum) self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum)
self.thread2.signal.connect(self.progressBar_view) self.thread2.signal.connect(self.progressBar_view)

View File

@ -3,7 +3,6 @@ import xml.etree.ElementTree as ET
import lz4.block import lz4.block
def decompress_CompressContent(data): def decompress_CompressContent(data):
""" """
解压缩MsgCompressContent内容 解压缩MsgCompressContent内容

View File

@ -69,7 +69,7 @@
- 群组年度报告 - 群组年度报告
- 按日期、关键词索引 - 按日期、关键词索引
- 小伙伴们想要其他功能可以留言哦📬 - 小伙伴们想要其他功能可以留言哦📬
- 🔥项目正处于并将长期处于发展阶段,你所期望的未来都会实现,可关注文末公众号持续关注项目更新动态 - 🔥项目正处于并将长期处于发展阶段,给我一些时间♾️,你所期望的未来都会实现,可关注文末公众号持续关注项目更新动态
## 🥤效果 ## 🥤效果