mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-22 02:22:17 +08:00
适配
This commit is contained in:
parent
a440aee168
commit
9d69f0e4cb
@ -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)
|
||||||
|
@ -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}】")
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user