2024-01-02 22:33:46 +08:00
|
|
|
|
import os
|
|
|
|
|
import shutil
|
|
|
|
|
import sys
|
|
|
|
|
import traceback
|
|
|
|
|
from re import findall
|
|
|
|
|
|
|
|
|
|
from PyQt5.QtCore import pyqtSignal, QThread
|
|
|
|
|
|
|
|
|
|
from app.DataBase import msg_db, hard_link_db, media_msg_db
|
|
|
|
|
from app.DataBase.output import ExporterBase, escape_js_and_html
|
|
|
|
|
from app.log import logger
|
|
|
|
|
from app.person import Me
|
|
|
|
|
from app.util import path
|
2024-01-18 13:51:14 +08:00
|
|
|
|
from app.util.compress_content import (
|
|
|
|
|
parser_reply,
|
|
|
|
|
share_card,
|
|
|
|
|
music_share,
|
|
|
|
|
file,
|
|
|
|
|
transfer_decompress,
|
|
|
|
|
call_decompress,
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
from app.util.emoji import get_emoji_url
|
|
|
|
|
from app.util.image import get_image_path, get_image
|
|
|
|
|
from app.util.music import get_music_path
|
|
|
|
|
|
2024-01-03 21:11:23 +08:00
|
|
|
|
icon_files = {
|
2024-01-18 13:51:14 +08:00
|
|
|
|
"./icon/word.png": ["doc", "docx"],
|
|
|
|
|
"./icon/excel.png": ["xls", "xlsx"],
|
|
|
|
|
"./icon/csv.png": ["csv"],
|
|
|
|
|
"./icon/txt.png": ["txt"],
|
|
|
|
|
"./icon/zip.png": ["zip", "7z", "rar"],
|
|
|
|
|
"./icon/ppt.png": ["ppt", "pptx"],
|
|
|
|
|
"./icon/pdf.png": ["pdf"],
|
2024-01-03 21:11:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-01-02 22:33:46 +08:00
|
|
|
|
class HtmlExporter(ExporterBase):
|
|
|
|
|
def text(self, doc, message):
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
str_content = escape_js_and_html(str_content)
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:{1}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def image(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
BytesExtra = message[10]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
str_content = escape_js_and_html(str_content)
|
|
|
|
|
image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False)
|
|
|
|
|
if not os.path.exists(os.path.join(Me().wx_dir, image_path)):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_thumb_path = hard_link_db.get_image(
|
|
|
|
|
str_content, BytesExtra, thumb=True
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(os.path.join(Me().wx_dir, image_thumb_path)):
|
|
|
|
|
return
|
|
|
|
|
image_path = image_thumb_path
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_path = get_image_path(
|
|
|
|
|
image_path, base_path=f"/data/聊天记录/{self.contact.remark}/image"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def audio(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
msgSvrId = message[9]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
try:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
audio_path = media_msg_db.get_audio_path(
|
|
|
|
|
msgSvrId, output_path=origin_docx_path + "/voice"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
audio_path = "./voice/" + os.path.basename(audio_path)
|
|
|
|
|
except:
|
|
|
|
|
logger.error(traceback.format_exc())
|
|
|
|
|
return
|
2024-01-05 22:14:32 +08:00
|
|
|
|
voice_to_text = media_msg_db.get_audio_text(str_content)
|
|
|
|
|
if voice_to_text and voice_to_text != "":
|
|
|
|
|
voice_to_text = escape_js_and_html(voice_to_text)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:34, text:'{audio_path}',is_send:{is_send},avatar_path:'{avatar}',voice_to_text:'{voice_to_text}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def emoji(self, doc, message):
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
emoji_path = get_emoji_url(str_content, thumb=True)
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def file(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
bytesExtra = message[10]
|
2024-01-03 21:11:23 +08:00
|
|
|
|
compress_content = message[11]
|
2024-01-02 22:33:46 +08:00
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
2024-01-18 13:51:14 +08:00
|
|
|
|
file_info = file(
|
|
|
|
|
bytesExtra, compress_content, output_path=origin_docx_path + "/file"
|
|
|
|
|
)
|
|
|
|
|
if file_info.get("is_error") == False:
|
2024-01-03 21:11:23 +08:00
|
|
|
|
icon_path = None
|
|
|
|
|
for icon, extensions in icon_files.items():
|
2024-01-18 13:51:14 +08:00
|
|
|
|
if file_info.get("file_ext") in extensions:
|
2024-01-03 21:11:23 +08:00
|
|
|
|
icon_path = icon
|
|
|
|
|
break
|
|
|
|
|
# 如果没有与文件后缀匹配的图标,则使用默认图标
|
|
|
|
|
if icon_path is None:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
default_icon = "./icon/file.png"
|
2024-01-03 21:11:23 +08:00
|
|
|
|
icon_path = default_icon
|
2024-01-18 13:51:14 +08:00
|
|
|
|
file_path = file_info.get("file_path")
|
2024-01-03 21:11:23 +08:00
|
|
|
|
if file_path != "":
|
2024-01-18 13:51:14 +08:00
|
|
|
|
file_path = "./file/" + file_info.get("file_name")
|
2024-01-03 21:11:23 +08:00
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:49, text: '{file_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp}
|
2024-01-03 21:11:23 +08:00
|
|
|
|
,is_chatroom:{is_chatroom},displayname:'{display_name}',icon_path: '{icon_path}'
|
|
|
|
|
,sub_type:6,file_name: '{file_info.get('file_name')}',file_size: '{file_info.get('file_len')}'
|
2024-01-18 13:51:14 +08:00
|
|
|
|
,app_name: '{file_info.get('app_name')}'}},"""
|
2024-01-03 21:11:23 +08:00
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
|
|
|
|
|
def refermsg(self, doc, message):
|
|
|
|
|
"""
|
|
|
|
|
处理回复消息
|
|
|
|
|
@param doc:
|
|
|
|
|
@param message:
|
|
|
|
|
@return:
|
|
|
|
|
"""
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
content = parser_reply(message[11])
|
2024-01-18 13:51:14 +08:00
|
|
|
|
refer_msg = content.get("refer")
|
2024-01-02 22:33:46 +08:00
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
2024-01-18 13:51:14 +08:00
|
|
|
|
contentText = escape_js_and_html(content.get("title"))
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if refer_msg:
|
|
|
|
|
referText = f"{escape_js_and_html(refer_msg.get('displayname'))}:{escape_js_and_html(refer_msg.get('content'))}"
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},refer_text: '{referText}',avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def system_msg(self, doc, message):
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
|
2024-01-18 13:51:14 +08:00
|
|
|
|
str_content = str_content.replace("<![CDATA[", "").replace(
|
|
|
|
|
' <a href="weixin://revoke_edit_click">重新编辑</a>]]>', ""
|
|
|
|
|
)
|
|
|
|
|
res = findall("(</{0,1}(img|revo|_wc_cus|a).*?>)", str_content)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
for xmlstr, b in res:
|
|
|
|
|
str_content = str_content.replace(xmlstr, "")
|
|
|
|
|
str_content = escape_js_and_html(str_content)
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:''}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def video(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
BytesExtra = message[10]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False)
|
|
|
|
|
image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True)
|
|
|
|
|
if video_path is None and image_path is not None:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_path = path.get_relative_path(
|
|
|
|
|
image_path, base_path=f"/data/聊天记录/{self.contact.remark}/image"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
try:
|
|
|
|
|
# todo 网络图片问题
|
|
|
|
|
print(origin_docx_path + image_path[1:])
|
|
|
|
|
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
except:
|
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:1, text: '视频丢失',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
return
|
|
|
|
|
if video_path is None and image_path is None:
|
|
|
|
|
return
|
2024-01-18 13:51:14 +08:00
|
|
|
|
video_path = f"{Me().wx_dir}/{video_path}"
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if os.path.exists(video_path):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
new_path = origin_docx_path + "/video/" + os.path.basename(video_path)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(new_path):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
shutil.copy(video_path, os.path.join(origin_docx_path, "video"))
|
2024-01-02 22:33:46 +08:00
|
|
|
|
os.utime(new_path, (timestamp, timestamp))
|
2024-01-18 13:51:14 +08:00
|
|
|
|
video_path = f"./video/{os.path.basename(video_path)}"
|
2024-01-02 22:33:46 +08:00
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def music_share(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
content = music_share(message[11])
|
2024-01-18 13:51:14 +08:00
|
|
|
|
music_path = ""
|
|
|
|
|
if content.get("is_error") == False:
|
|
|
|
|
if content.get("audio_url") != "":
|
|
|
|
|
music_path = get_music_path(
|
|
|
|
|
content.get("audio_url"),
|
|
|
|
|
content.get("title"),
|
|
|
|
|
output_path=origin_docx_path + "/music",
|
|
|
|
|
)
|
|
|
|
|
if music_path != "":
|
|
|
|
|
music_path = f"./music/{os.path.basename(music_path)}"
|
|
|
|
|
music_path = music_path.replace("\\", "/")
|
2024-01-03 21:11:23 +08:00
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:49, text:'{music_path}',is_send:{is_send},avatar_path:'{avatar}',link_url:'{content.get('link_url')}',
|
2024-01-02 22:33:46 +08:00
|
|
|
|
timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',sub_type:3,title:'{content.get('title')}',
|
2024-01-18 13:51:14 +08:00
|
|
|
|
artist:'{content.get('artist')}', website_name:'{content.get('website_name')}'}},"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def share_card(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
bytesExtra = message[10]
|
|
|
|
|
compress_content_ = message[11]
|
|
|
|
|
card_data = share_card(bytesExtra, compress_content_)
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
2024-01-18 13:51:14 +08:00
|
|
|
|
thumbnail = ""
|
|
|
|
|
if card_data.get("thumbnail"):
|
|
|
|
|
thumbnail = os.path.join(Me().wx_dir, card_data.get("thumbnail"))
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if os.path.exists(thumbnail):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
shutil.copy(
|
|
|
|
|
thumbnail,
|
|
|
|
|
os.path.join(
|
|
|
|
|
origin_docx_path, "image", os.path.basename(thumbnail)
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
thumbnail = "./image/" + os.path.basename(thumbnail)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
else:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
thumbnail = ""
|
|
|
|
|
app_logo = ""
|
|
|
|
|
if card_data.get("app_logo"):
|
|
|
|
|
app_logo = os.path.join(Me().wx_dir, card_data.get("app_logo"))
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if os.path.exists(app_logo):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
shutil.copy(
|
|
|
|
|
app_logo,
|
|
|
|
|
os.path.join(origin_docx_path, "image", os.path.basename(app_logo)),
|
|
|
|
|
)
|
|
|
|
|
app_logo = "./image/" + os.path.basename(app_logo)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
else:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
app_logo = card_data.get("app_logo")
|
2024-01-02 22:33:46 +08:00
|
|
|
|
doc.write(
|
2024-01-18 13:51:14 +08:00
|
|
|
|
f"""{{ type:49,sub_type:5, text:'',is_send:{is_send},avatar_path:'{avatar}',url:'{card_data.get('url')}',
|
2024-01-02 22:33:46 +08:00
|
|
|
|
timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',title:'{card_data.get('title')}',
|
|
|
|
|
description:'{card_data.get('description')}',thumbnail:'{thumbnail}',app_logo:'{app_logo}',
|
|
|
|
|
app_name:'{card_data.get('app_name')}'
|
2024-01-18 13:51:14 +08:00
|
|
|
|
}},\n"""
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def transfer(self, doc, message):
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
compress_content_ = message[11]
|
|
|
|
|
open("test.bin", "wb").write(compress_content_)
|
|
|
|
|
transfer_detail = transfer_decompress(compress_content_)
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
text_info_map = {
|
|
|
|
|
1: transfer_detail["pay_memo"] or "转账",
|
|
|
|
|
3: "已收款",
|
|
|
|
|
4: "已退还",
|
|
|
|
|
}
|
|
|
|
|
doc.write(
|
|
|
|
|
f"""{{ type:49, sub_type:2000,
|
|
|
|
|
text:'{text_info_map[transfer_detail["paysubtype"]]}',
|
|
|
|
|
is_send:{is_send},avatar_path:'{avatar}',
|
|
|
|
|
timestamp:{timestamp},is_chatroom:{is_chatroom},
|
|
|
|
|
displayname:'{display_name}',paysubtype:{transfer_detail["paysubtype"]},
|
|
|
|
|
pay_memo:'{transfer_detail["pay_memo"]}',feedesc:'{transfer_detail["feedesc"]}',
|
|
|
|
|
}},\n"""
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def call(self, doc, message):
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
bytes_extra = message[10]
|
|
|
|
|
display_content = message[12]
|
|
|
|
|
call_detail = call_decompress(
|
|
|
|
|
is_send, bytes_extra, display_content, str_content
|
|
|
|
|
)
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
avatar = self.get_avatar_path(is_send, message)
|
|
|
|
|
display_name = self.get_display_name(is_send, message)
|
|
|
|
|
doc.write(
|
|
|
|
|
f"""{{ type:50, text:'{call_detail["display_content"]}',
|
|
|
|
|
call_type:{call_detail["call_type"]},avatar_path:'{avatar}',
|
|
|
|
|
timestamp:{timestamp},is_chatroom:{is_chatroom},
|
|
|
|
|
displayname:'{display_name}',
|
|
|
|
|
}},\n"""
|
2024-01-02 22:33:46 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def export(self):
|
2024-01-11 20:14:21 +08:00
|
|
|
|
print(f"【开始导出 HTML {self.contact.remark}】")
|
2024-01-09 23:55:39 +08:00
|
|
|
|
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html"
|
2024-01-18 13:51:14 +08:00
|
|
|
|
file_path = "./app/resources/data/template.html"
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(file_path):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
resource_dir = getattr(
|
|
|
|
|
sys, "_MEIPASS", os.path.abspath(os.path.dirname(__file__))
|
|
|
|
|
)
|
|
|
|
|
file_path = os.path.join(
|
|
|
|
|
resource_dir, "app", "resources", "data", "template.html"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
|
|
|
|
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
|
|
|
content = f.read()
|
2024-01-18 13:51:14 +08:00
|
|
|
|
html_head, html_end = content.split("/*注意看这是分割线*/")
|
|
|
|
|
f = open(filename, "w", encoding="utf-8")
|
|
|
|
|
html_head = html_head.replace(
|
|
|
|
|
"<title>出错了</title>", f"<title>{self.contact.remark}</title>"
|
|
|
|
|
)
|
|
|
|
|
html_head = html_head.replace(
|
|
|
|
|
'<p id="title">出错了</p>', f'<p id="title">{self.contact.remark}</p>'
|
|
|
|
|
)
|
2024-01-15 21:58:12 +08:00
|
|
|
|
f.write(html_head)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
self.rangeSignal.emit(len(messages))
|
|
|
|
|
for index, message in enumerate(messages):
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
sub_type = message[3]
|
|
|
|
|
timestamp = message[5]
|
2024-01-18 13:51:14 +08:00
|
|
|
|
if (
|
|
|
|
|
(type_ == 3 and self.message_types.get(3))
|
|
|
|
|
or (type_ == 34 and self.message_types.get(34))
|
|
|
|
|
or (type_ == 47 and self.message_types.get(47))
|
|
|
|
|
):
|
2024-01-02 22:33:46 +08:00
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
self.progressSignal.emit(1)
|
|
|
|
|
|
|
|
|
|
if type_ == 1 and self.message_types.get(type_):
|
|
|
|
|
self.text(f, message)
|
|
|
|
|
elif type_ == 3 and self.message_types.get(type_):
|
|
|
|
|
self.image(f, message)
|
|
|
|
|
elif type_ == 34 and self.message_types.get(type_):
|
|
|
|
|
self.audio(f, message)
|
|
|
|
|
elif type_ == 43 and self.message_types.get(type_):
|
|
|
|
|
self.video(f, message)
|
|
|
|
|
elif type_ == 47 and self.message_types.get(type_):
|
|
|
|
|
self.emoji(f, message)
|
|
|
|
|
elif type_ == 10000 and self.message_types.get(type_):
|
|
|
|
|
self.system_msg(f, message)
|
|
|
|
|
elif type_ == 49 and sub_type == 57 and self.message_types.get(1):
|
|
|
|
|
self.refermsg(f, message)
|
|
|
|
|
elif type_ == 49 and sub_type == 6 and self.message_types.get(4906):
|
|
|
|
|
self.file(f, message)
|
|
|
|
|
elif type_ == 49 and sub_type == 3 and self.message_types.get(4903):
|
|
|
|
|
self.music_share(f, message)
|
|
|
|
|
elif type_ == 49 and sub_type == 5 and self.message_types.get(4905):
|
|
|
|
|
self.share_card(f, message)
|
2024-01-18 13:51:14 +08:00
|
|
|
|
elif type_ == 49 and sub_type == 2000 and self.message_types.get(492000):
|
|
|
|
|
self.transfer(f, message)
|
|
|
|
|
elif type_ == 50 and self.message_types.get(50):
|
|
|
|
|
self.call(f, message)
|
2024-01-11 20:14:21 +08:00
|
|
|
|
if index % 2000 == 0:
|
|
|
|
|
print(f"【导出 HTML {self.contact.remark}】{index}/{len(messages)}")
|
2024-01-02 22:33:46 +08:00
|
|
|
|
f.write(html_end)
|
|
|
|
|
f.close()
|
2024-01-11 20:14:21 +08:00
|
|
|
|
print(f"【完成导出 HTML {self.contact.remark}】{len(messages)}")
|
2024-01-02 22:33:46 +08:00
|
|
|
|
self.count_finish_num(1)
|
|
|
|
|
|
|
|
|
|
def count_finish_num(self, num):
|
|
|
|
|
"""
|
|
|
|
|
记录子线程完成个数
|
|
|
|
|
@param num:
|
|
|
|
|
@return:
|
|
|
|
|
"""
|
|
|
|
|
self.num += 1
|
2024-01-18 13:51:14 +08:00
|
|
|
|
print("子线程完成", self.num, "/", self.total_num)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if self.num == self.total_num:
|
|
|
|
|
# 所有子线程都完成之后就发送完成信号
|
|
|
|
|
self.okSignal.emit(1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OutputMedia(QThread):
|
|
|
|
|
"""
|
|
|
|
|
导出语音消息
|
|
|
|
|
"""
|
2024-01-18 13:51:14 +08:00
|
|
|
|
|
2024-01-02 22:33:46 +08:00
|
|
|
|
okSingal = pyqtSignal(int)
|
|
|
|
|
progressSignal = pyqtSignal(int)
|
|
|
|
|
|
|
|
|
|
def __init__(self, contact):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.contact = contact
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
messages = msg_db.get_messages_by_type(self.contact.wxid, 34)
|
|
|
|
|
for message in messages:
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
msgSvrId = message[9]
|
|
|
|
|
try:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
audio_path = media_msg_db.get_audio(
|
|
|
|
|
msgSvrId, output_path=origin_docx_path + "/voice"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
except:
|
|
|
|
|
logger.error(traceback.format_exc())
|
|
|
|
|
finally:
|
|
|
|
|
self.progressSignal.emit(1)
|
|
|
|
|
self.okSingal.emit(34)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OutputEmoji(QThread):
|
|
|
|
|
"""
|
|
|
|
|
导出表情包
|
|
|
|
|
"""
|
2024-01-18 13:51:14 +08:00
|
|
|
|
|
2024-01-02 22:33:46 +08:00
|
|
|
|
okSingal = pyqtSignal(int)
|
|
|
|
|
progressSignal = pyqtSignal(int)
|
|
|
|
|
|
|
|
|
|
def __init__(self, contact):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.contact = contact
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
messages = msg_db.get_messages_by_type(self.contact.wxid, 47)
|
|
|
|
|
for message in messages:
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
try:
|
|
|
|
|
pass
|
|
|
|
|
# emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji')
|
|
|
|
|
except:
|
|
|
|
|
logger.error(traceback.format_exc())
|
|
|
|
|
finally:
|
|
|
|
|
self.progressSignal.emit(1)
|
|
|
|
|
self.okSingal.emit(47)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OutputImage(QThread):
|
|
|
|
|
"""
|
|
|
|
|
导出图片
|
|
|
|
|
"""
|
2024-01-18 13:51:14 +08:00
|
|
|
|
|
2024-01-02 22:33:46 +08:00
|
|
|
|
okSingal = pyqtSignal(int)
|
|
|
|
|
progressSignal = pyqtSignal(int)
|
|
|
|
|
|
|
|
|
|
def __init__(self, contact):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.contact = contact
|
|
|
|
|
self.child_thread_num = 2
|
|
|
|
|
self.child_threads = [0] * (self.child_thread_num + 1)
|
|
|
|
|
self.num = 0
|
|
|
|
|
|
|
|
|
|
def count1(self, num):
|
|
|
|
|
self.num += 1
|
2024-01-18 13:51:14 +08:00
|
|
|
|
print("图片导出完成一个")
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if self.num == self.child_thread_num:
|
|
|
|
|
self.okSingal.emit(47)
|
2024-01-18 13:51:14 +08:00
|
|
|
|
print("图片导出完成")
|
2024-01-02 22:33:46 +08:00
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
messages = msg_db.get_messages_by_type(self.contact.wxid, 3)
|
|
|
|
|
for message in messages:
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
BytesExtra = message[10]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
try:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_path = hard_link_db.get_image(
|
|
|
|
|
str_content, BytesExtra, thumb=False
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(os.path.join(Me().wx_dir, image_path)):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_thumb_path = hard_link_db.get_image(
|
|
|
|
|
str_content, BytesExtra, thumb=True
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(os.path.join(Me().wx_dir, image_thumb_path)):
|
|
|
|
|
continue
|
|
|
|
|
image_path = image_thumb_path
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_path = get_image(
|
|
|
|
|
image_path, base_path=f"/data/聊天记录/{self.contact.remark}/image"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
try:
|
|
|
|
|
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
except:
|
|
|
|
|
logger.error(traceback.format_exc())
|
|
|
|
|
finally:
|
|
|
|
|
self.progressSignal.emit(1)
|
|
|
|
|
self.okSingal.emit(47)
|
|
|
|
|
# sublist_length = len(messages) // self.child_thread_num
|
|
|
|
|
# index = 0
|
|
|
|
|
# for i in range(0, len(messages), sublist_length):
|
|
|
|
|
# child_messages = messages[i:i + sublist_length]
|
|
|
|
|
# self.child_threads[index] = OutputImageChild(self.contact, child_messages)
|
|
|
|
|
# self.child_threads[index].okSingal.connect(self.count1)
|
|
|
|
|
# self.child_threads[index].progressSignal.connect(self.progressSignal)
|
|
|
|
|
# self.child_threads[index].start()
|
|
|
|
|
# print('开启一个新线程')
|
|
|
|
|
# index += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OutputImageChild(QThread):
|
|
|
|
|
okSingal = pyqtSignal(int)
|
|
|
|
|
progressSignal = pyqtSignal(int)
|
|
|
|
|
|
|
|
|
|
def __init__(self, contact, messages):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self.contact = contact
|
|
|
|
|
self.messages = messages
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
for message in self.messages:
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
BytesExtra = message[10]
|
|
|
|
|
timestamp = message[5]
|
|
|
|
|
try:
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_path = hard_link_db.get_image(
|
|
|
|
|
str_content, BytesExtra, thumb=False
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(os.path.join(Me().wx_dir, image_path)):
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_thumb_path = hard_link_db.get_image(
|
|
|
|
|
str_content, BytesExtra, thumb=True
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
if not os.path.exists(os.path.join(Me().wx_dir, image_thumb_path)):
|
|
|
|
|
continue
|
|
|
|
|
image_path = image_thumb_path
|
2024-01-18 13:51:14 +08:00
|
|
|
|
image_path = get_image(
|
|
|
|
|
image_path, base_path=f"/data/聊天记录/{self.contact.remark}/image"
|
|
|
|
|
)
|
2024-01-02 22:33:46 +08:00
|
|
|
|
try:
|
|
|
|
|
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
except:
|
|
|
|
|
logger.error(traceback.format_exc())
|
|
|
|
|
finally:
|
|
|
|
|
self.progressSignal.emit(1)
|
|
|
|
|
self.okSingal.emit(47)
|
2024-01-18 13:51:14 +08:00
|
|
|
|
print("图片子线程完成")
|