This commit is contained in:
STDquantum 2024-01-19 18:37:56 +08:00
parent a440aee168
commit 9d69f0e4cb
4 changed files with 160 additions and 125 deletions

View File

@ -25,6 +25,7 @@ encoded_chars = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f\x10\x11\x
# 创建一个字典,将要删除的字符映射为 None # 创建一个字典,将要删除的字符映射为 None
char_mapping = {char: None for char in encoded_chars} char_mapping = {char: None for char in encoded_chars}
def filter_control_characters(input_string): def filter_control_characters(input_string):
""" """
过滤掉不可打印字符 过滤掉不可打印字符
@ -39,6 +40,84 @@ def filter_control_characters(input_string):
class DocxExporter(ExporterBase): class DocxExporter(ExporterBase):
def merge_docx(self, n):
self.process_num += 1
conRemark = self.contact.remark
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{conRemark}"
filename = f"{origin_docx_path}/{conRemark}_{n}.docx"
# print(all_file_path)
doc = docx.Document(filename)
if self.merged_doc_index == [-1, -1]:
self.document.append(doc)
self.merged_doc_index = [n, n]
else:
if n == self.merged_doc_index[0] - 1:
self.document.insert(0, doc)
self.merged_doc_index[0] -= 1
elif n == self.merged_doc_index[1] + 1:
self.document.append(doc)
self.merged_doc_index[1] += 1
else:
self.docs.append([doc, n])
self.docs_set.add(n)
new_docx = []
new_set = set()
# print(self.docs)
while new_set!=self.docs_set:
self.docs.sort(key=lambda x: x[1])
for doc_, index in self.docs:
if index == self.merged_doc_index[0] - 1:
self.document.insert(0, doc_)
self.merged_doc_index[0] -= 1
elif index == self.merged_doc_index[1] + 1:
self.document.append(doc_)
self.merged_doc_index[1] += 1
else:
new_docx.append([doc_, index])
new_set.add(index)
self.docs = new_docx
self.docs_set = new_set
os.remove(filename)
if self.process_num == self.child_thread_num:
# self.document.append(self.document)
file = os.path.join(origin_docx_path, f'{conRemark}.docx')
try:
self.document.save(file)
except PermissionError:
file = file[:-5] + f'{time.time()}' + '.docx'
self.document.save(file)
self.okSignal.emit(1)
def export(self):
self.child_threads = []
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range)
# 计算每个子列表的长度
num = 1
# num = len(messages) // 500 +1
sublist_length = len(messages) // num
# 使用列表切片将列表分成n个子列表
divided_list = [messages[i:i + sublist_length] for i in range(0, len(messages), sublist_length)]
self.child_thread_num = len(divided_list)
self.process_num = 0
doc = docx.Document()
doc.styles["Normal"].font.name = "Cambria"
doc.styles["Normal"]._element.rPr.rFonts.set(qn("w:eastAsia"), "宋体")
self.document = Composer(doc)
self.merged_doc_index = [-1, -1]
self.docs = []
self.docs_set = set()
# self.document.append(self.document)
for i in range(self.child_thread_num):
child_thread = DocxExporterChildThread(self.contact, type_=self.DOCX, message_types=self.message_types,
time_range=self.time_range, messages=divided_list[i], index=i)
self.child_threads.append(child_thread)
child_thread.okSignal.connect(self.merge_docx)
child_thread.progressSignal.connect(self.progressSignal)
child_thread.start()
class DocxExporterChildThread(ExporterBase):
def text(self, doc, message): def text(self, doc, message):
type_ = message[2] type_ = message[2]
str_content = message[7] str_content = message[7]
@ -313,15 +392,15 @@ class DocxExporter(ExporterBase):
def export(self): def export(self):
print(f"【开始导出 DOCX {self.contact.remark}") print(f"【开始导出 DOCX {self.contact.remark}")
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
messages = msg_db.get_messages(self.contact.wxid, time_range=self.time_range) messages = self.messages
Me().save_avatar(os.path.join(f"{origin_docx_path}/avatar/{Me().wxid}.png")) Me().save_avatar(os.path.join(f"{origin_docx_path}/avatar/{Me().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[13].wxid}.png" chatroom_avatar_path = f"{origin_docx_path}/avatar/{message[12].wxid}.png"
message[13].save_avatar(chatroom_avatar_path) message[12].save_avatar(chatroom_avatar_path)
except: except:
print(message) print(message)
pass pass
@ -329,6 +408,8 @@ class DocxExporter(ExporterBase):
self.contact.save_avatar(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))
index = 0
def newdoc(): def newdoc():
nonlocal n, doc nonlocal n, doc
doc = docx.Document() doc = docx.Document()
@ -347,8 +428,8 @@ class DocxExporter(ExporterBase):
for index, message in enumerate(messages): for index, message in enumerate(messages):
if index % 200 == 0 and index: if index % 200 == 0 and index:
# doc = document.add_paragraph() # doc = document.add_paragraph()
filename = os.path.join(origin_docx_path, f"{self.contact.remark}{n}.docx") # filename = os.path.join(origin_docx_path, f"{self.contact.remark}{n}.docx")
doc.save(filename) # doc.save(filename)
newdoc() newdoc()
type_ = message[2] type_ = message[2]
@ -391,6 +472,7 @@ class DocxExporter(ExporterBase):
for index, dx in enumerate(docs[::-1]): for index, dx in enumerate(docs[::-1]):
print(f"【合并 DOCX {self.contact.remark}{index + 1}/{len(docs)}") print(f"【合并 DOCX {self.contact.remark}{index + 1}/{len(docs)}")
doc.insert(0, dx) doc.insert(0, dx)
filename = os.path.join(origin_docx_path, f"{self.contact.remark}_{self.index}.docx")
try: try:
# document.save(filename) # document.save(filename)
doc.save(filename) doc.save(filename)
@ -399,4 +481,4 @@ class DocxExporter(ExporterBase):
# document.save(filename) # document.save(filename)
doc.save(filename) doc.save(filename)
print(f"【完成导出 DOCX {self.contact.remark}") print(f"【完成导出 DOCX {self.contact.remark}")
self.okSignal.emit(1) self.okSignal.emit(self.index)

View File

@ -11,26 +11,19 @@ from app.DataBase.output import ExporterBase, escape_js_and_html
from app.log import logger from app.log import logger
from app.person import Me from app.person import Me
from app.util import path from app.util import path
from app.util.compress_content import ( from app.util.compress_content import parser_reply, share_card, music_share, file, transfer_decompress, call_decompress
parser_reply,
share_card,
music_share,
file,
transfer_decompress,
call_decompress,
)
from app.util.emoji import get_emoji_url from app.util.emoji import get_emoji_url
from app.util.image import get_image_path, get_image from app.util.image import get_image_path, get_image
from app.util.music import get_music_path from app.util.music import get_music_path
icon_files = { icon_files = {
"./icon/word.png": ["doc", "docx"], './icon/word.png': ['doc', 'docx'],
"./icon/excel.png": ["xls", "xlsx"], './icon/excel.png': ['xls', 'xlsx'],
"./icon/csv.png": ["csv"], './icon/csv.png': ['csv'],
"./icon/txt.png": ["txt"], './icon/txt.png': ['txt'],
"./icon/zip.png": ["zip", "7z", "rar"], './icon/zip.png': ['zip', '7z', 'rar'],
"./icon/ppt.png": ["ppt", "pptx"], './icon/ppt.png': ['ppt', 'pptx'],
"./icon/pdf.png": ["pdf"], './icon/pdf.png': ['pdf'],
} }
@ -47,7 +40,7 @@ class HtmlExporter(ExporterBase):
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)
doc.write( doc.write(
f"""{{ type:{1}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},""" f'''{{ type:{1}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},'''
) )
def image(self, doc, message): def image(self, doc, message):
@ -64,17 +57,13 @@ class HtmlExporter(ExporterBase):
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)
if not os.path.exists(os.path.join(Me().wx_dir, image_path)): if not os.path.exists(os.path.join(Me().wx_dir, image_path)):
image_thumb_path = hard_link_db.get_image( image_thumb_path = hard_link_db.get_image(str_content, BytesExtra, thumb=True)
str_content, BytesExtra, thumb=True
)
if not os.path.exists(os.path.join(Me().wx_dir, image_thumb_path)): if not os.path.exists(os.path.join(Me().wx_dir, image_thumb_path)):
return return
image_path = image_thumb_path image_path = image_thumb_path
image_path = get_image_path( image_path = get_image_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
image_path, base_path=f"/data/聊天记录/{self.contact.remark}/image"
)
doc.write( doc.write(
f"""{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},""" f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},'''
) )
def audio(self, doc, message): def audio(self, doc, message):
@ -88,9 +77,7 @@ class HtmlExporter(ExporterBase):
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)
try: try:
audio_path = media_msg_db.get_audio_path( audio_path = media_msg_db.get_audio_path(msgSvrId, output_path=origin_docx_path + "/voice")
msgSvrId, output_path=origin_docx_path + "/voice"
)
audio_path = "./voice/" + os.path.basename(audio_path) audio_path = "./voice/" + os.path.basename(audio_path)
except: except:
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
@ -99,7 +86,7 @@ class HtmlExporter(ExporterBase):
if voice_to_text and voice_to_text != "": if voice_to_text and voice_to_text != "":
voice_to_text = escape_js_and_html(voice_to_text) voice_to_text = escape_js_and_html(voice_to_text)
doc.write( doc.write(
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}'}},""" 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}'}},'''
) )
def emoji(self, doc, message): def emoji(self, doc, message):
@ -112,7 +99,7 @@ class HtmlExporter(ExporterBase):
display_name = self.get_display_name(is_send, message) display_name = self.get_display_name(is_send, message)
emoji_path = get_emoji_url(str_content, thumb=True) emoji_path = get_emoji_url(str_content, thumb=True)
doc.write( doc.write(
f"""{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},""" f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},'''
) )
def file(self, doc, message): def file(self, doc, message):
@ -125,27 +112,22 @@ class HtmlExporter(ExporterBase):
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)
file_info = file( file_info = file(bytesExtra, compress_content, output_path=origin_docx_path + '/file')
bytesExtra, compress_content, output_path=origin_docx_path + "/file" if file_info.get('is_error') == False:
)
if file_info.get("is_error") == False:
icon_path = None icon_path = None
for icon, extensions in icon_files.items(): for icon, extensions in icon_files.items():
if file_info.get("file_ext") in extensions: if file_info.get('file_ext') in extensions:
icon_path = icon icon_path = icon
break break
# 如果没有与文件后缀匹配的图标,则使用默认图标 # 如果没有与文件后缀匹配的图标,则使用默认图标
if icon_path is None: if icon_path is None:
default_icon = "./icon/file.png" default_icon = './icon/file.png'
icon_path = default_icon icon_path = default_icon
file_path = file_info.get("file_path") file_path = file_info.get('file_path')
if file_path != "": if file_path != "":
file_path = "./file/" + file_info.get("file_name") file_path = './file/' + file_info.get('file_name')
doc.write( doc.write(
f"""{{ type:49, text: '{file_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp} f'''{{ type:49, text: '{file_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},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')}',app_name: '{file_info.get('app_name')}'}},'''
,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')}'
,app_name: '{file_info.get('app_name')}'}},"""
) )
def refermsg(self, doc, message): def refermsg(self, doc, message):
@ -158,20 +140,20 @@ class HtmlExporter(ExporterBase):
str_time = message[8] str_time = message[8]
is_send = message[4] is_send = message[4]
content = parser_reply(message[11]) content = parser_reply(message[11])
refer_msg = content.get("refer") refer_msg = content.get('refer')
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)
contentText = escape_js_and_html(content.get("title")) contentText = escape_js_and_html(content.get('title'))
if refer_msg: if refer_msg:
referText = f"{escape_js_and_html(refer_msg.get('displayname'))}{escape_js_and_html(refer_msg.get('content'))}" referText = f"{escape_js_and_html(refer_msg.get('displayname'))}{escape_js_and_html(refer_msg.get('content'))}"
doc.write( doc.write(
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}'}},""" 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}'}},'''
) )
else: else:
doc.write( doc.write(
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}'}},""" 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}'}},'''
) )
def system_msg(self, doc, message): def system_msg(self, doc, message):
@ -181,15 +163,14 @@ class HtmlExporter(ExporterBase):
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
str_content = str_content.replace("<![CDATA[", "").replace( str_content = str_content.replace('<![CDATA[', "").replace(
' <a href="weixin://revoke_edit_click">重新编辑</a>]]>', "" ' <a href="weixin://revoke_edit_click">重新编辑</a>]]>', "")
) res = findall('(</{0,1}(img|revo|_wc_cus|a).*?>)', str_content)
res = findall("(</{0,1}(img|revo|_wc_cus|a).*?>)", str_content)
for xmlstr, b in res: for xmlstr, b in res:
str_content = str_content.replace(xmlstr, "") str_content = str_content.replace(xmlstr, "")
str_content = escape_js_and_html(str_content) str_content = escape_js_and_html(str_content)
doc.write( doc.write(
f"""{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:''}},""" f'''{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:''}},'''
) )
def video(self, doc, message): def video(self, doc, message):
@ -206,32 +187,30 @@ class HtmlExporter(ExporterBase):
video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False) video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False)
image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True) image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True)
if video_path is None and image_path is not None: if video_path is None and image_path is not None:
image_path = path.get_relative_path( image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
image_path, base_path=f"/data/聊天记录/{self.contact.remark}/image"
)
try: try:
# todo 网络图片问题 # todo 网络图片问题
print(origin_docx_path + image_path[1:]) print(origin_docx_path + image_path[1:])
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp)) os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
doc.write( doc.write(
f"""{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},""" f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},'''
) )
except: except:
doc.write( doc.write(
f"""{{ type:1, text: '视频丢失',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},""" f'''{{ type:1, text: '视频丢失',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},'''
) )
return return
if video_path is None and image_path is None: if video_path is None and image_path is None:
return return
video_path = f"{Me().wx_dir}/{video_path}" video_path = f'{Me().wx_dir}/{video_path}'
if os.path.exists(video_path): if os.path.exists(video_path):
new_path = origin_docx_path + "/video/" + os.path.basename(video_path) new_path = origin_docx_path + '/video/' + os.path.basename(video_path)
if not os.path.exists(new_path): if not os.path.exists(new_path):
shutil.copy(video_path, os.path.join(origin_docx_path, "video")) shutil.copy(video_path, os.path.join(origin_docx_path, 'video'))
os.utime(new_path, (timestamp, timestamp)) os.utime(new_path, (timestamp, timestamp))
video_path = f"./video/{os.path.basename(video_path)}" video_path = f'./video/{os.path.basename(video_path)}'
doc.write( doc.write(
f"""{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},""" f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}'}},'''
) )
def music_share(self, doc, message): def music_share(self, doc, message):
@ -239,24 +218,20 @@ class HtmlExporter(ExporterBase):
is_send = message[4] is_send = message[4]
timestamp = message[5] timestamp = message[5]
content = music_share(message[11]) content = music_share(message[11])
music_path = "" music_path = ''
if content.get("is_error") == False: if content.get('is_error') == False:
if content.get("audio_url") != "": if content.get('audio_url') != '':
music_path = get_music_path( music_path = get_music_path(content.get('audio_url'), content.get('title'),
content.get("audio_url"), output_path=origin_docx_path + '/music')
content.get("title"), if music_path != '':
output_path=origin_docx_path + "/music", music_path = f'./music/{os.path.basename(music_path)}'
) music_path = music_path.replace('\\', '/')
if music_path != "":
music_path = f"./music/{os.path.basename(music_path)}"
music_path = music_path.replace("\\", "/")
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)
music_path = escape_js_and_html(music_path)
doc.write( doc.write(
f"""{{ type:49, text:'{music_path}',is_send:{is_send},avatar_path:'{avatar}',link_url:'{content.get('link_url')}', f'''{{ type:49, text:'{music_path}',is_send:{is_send},avatar_path:'{avatar}',link_url:'{content.get('link_url')}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',sub_type:3,title:'{content.get('title')}',artist:'{content.get('artist')}', website_name:'{content.get('website_name')}'}},'''
timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',sub_type:3,title:'{content.get('title')}',
artist:'{content.get('artist')}', website_name:'{content.get('website_name')}'}},"""
) )
def share_card(self, doc, message): def share_card(self, doc, message):
@ -269,36 +244,24 @@ class HtmlExporter(ExporterBase):
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)
thumbnail = "" thumbnail = ''
if card_data.get("thumbnail"): if card_data.get('thumbnail'):
thumbnail = os.path.join(Me().wx_dir, card_data.get("thumbnail")) thumbnail = os.path.join(Me().wx_dir, card_data.get('thumbnail'))
if os.path.exists(thumbnail): if os.path.exists(thumbnail):
shutil.copy( shutil.copy(thumbnail, os.path.join(origin_docx_path, 'image', os.path.basename(thumbnail)))
thumbnail, thumbnail = './image/' + os.path.basename(thumbnail)
os.path.join(
origin_docx_path, "image", os.path.basename(thumbnail)
),
)
thumbnail = "./image/" + os.path.basename(thumbnail)
else: else:
thumbnail = "" thumbnail = ''
app_logo = "" app_logo = ''
if card_data.get("app_logo"): if card_data.get('app_logo'):
app_logo = os.path.join(Me().wx_dir, card_data.get("app_logo")) app_logo = os.path.join(Me().wx_dir, card_data.get('app_logo'))
if os.path.exists(app_logo): if os.path.exists(app_logo):
shutil.copy( shutil.copy(app_logo, os.path.join(origin_docx_path, 'image', os.path.basename(app_logo)))
app_logo, app_logo = './image/' + os.path.basename(app_logo)
os.path.join(origin_docx_path, "image", os.path.basename(app_logo)),
)
app_logo = "./image/" + os.path.basename(app_logo)
else: else:
app_logo = card_data.get("app_logo") app_logo = card_data.get('app_logo')
doc.write( doc.write(
f"""{{ type:49,sub_type:5, text:'',is_send:{is_send},avatar_path:'{avatar}',url:'{card_data.get('url')}', f'''{{ type:49,sub_type:5, text:'',is_send:{is_send},avatar_path:'{avatar}',url:'{card_data.get('url')}',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')}'}},\n'''
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')}'
}},\n"""
) )
def transfer(self, doc, message): def transfer(self, doc, message):
@ -315,15 +278,7 @@ class HtmlExporter(ExporterBase):
3: "已收款", 3: "已收款",
4: "已退还", 4: "已退还",
} }
doc.write( 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""")
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): def call(self, doc, message):
is_send = message[4] is_send = message[4]
@ -337,13 +292,7 @@ class HtmlExporter(ExporterBase):
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)
doc.write( 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""")
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"""
)
def export(self): def export(self):
print(f"【开始导出 HTML {self.contact.remark}") print(f"【开始导出 HTML {self.contact.remark}")

View File

@ -90,19 +90,23 @@ class ExporterBase(QThread):
CONTACT_CSV = 4 CONTACT_CSV = 4
TXT = 5 TXT = 5
def __init__(self, contact, type_=DOCX, message_types={},time_range=None, parent=None): def __init__(self, contact, type_=DOCX, message_types={}, time_range=None, messages=None,index=0, parent=None):
super().__init__(parent) super().__init__(parent)
self.message_types = message_types # 导出的消息类型 self.message_types = message_types # 导出的消息类型
self.contact: Contact = contact # 联系人 self.contact: Contact = contact # 联系人
self.output_type = type_ # 导出文件类型 self.output_type = type_ # 导出文件类型
self.total_num = 1 # 总的消息数量 self.total_num = 1 # 总的消息数量
self.num = 0 # 当前处理的消息数量 self.num = 0 # 当前处理的消息数量
self.index = index #
self.last_timestamp = 0 self.last_timestamp = 0
self.time_range = time_range self.time_range = time_range
self.messages = messages
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)
def run(self): def run(self):
self.export() self.export()
def export(self): def export(self):
raise NotImplementedError("export method must be implemented in subclasses") raise NotImplementedError("export method must be implemented in subclasses")
@ -166,4 +170,4 @@ class ExporterBase(QThread):
return return
def share_card(self, doc, message): def share_card(self, doc, message):
return return

View File

@ -3,7 +3,7 @@ import os
import traceback import traceback
from typing import List from typing import List
from PyQt5.QtCore import pyqtSignal, QThread from PyQt5.QtCore import pyqtSignal, QThread, QObject
from PyQt5.QtWidgets import QFileDialog from PyQt5.QtWidgets import QFileDialog
from app.DataBase.exporter_csv import CSVExporter from app.DataBase.exporter_csv import CSVExporter
@ -20,7 +20,7 @@ from ..util.image import get_image
os.makedirs('./data/聊天记录', exist_ok=True) os.makedirs('./data/聊天记录', exist_ok=True)
class Output(QThread): class Output(QObject):
""" """
发送信息线程 发送信息线程
""" """
@ -222,7 +222,7 @@ class Output(QThread):
Child.okSignal.connect(self.okSignal if not is_batch else self.batch_finish_one) Child.okSignal.connect(self.okSignal if not is_batch else self.batch_finish_one)
Child.start() Child.start()
def run(self): def start(self):
if self.output_type == self.DOCX: if self.output_type == self.DOCX:
self.to_docx(self.contact, self.message_types) self.to_docx(self.contact, self.message_types)
elif self.output_type == self.CSV_ALL: elif self.output_type == self.CSV_ALL: