mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-23 03:22:17 +08:00
添加html导出部分文件的支持
This commit is contained in:
parent
8fb7fdd1b0
commit
dec7bd0be7
@ -16,6 +16,7 @@ import shutil
|
|||||||
|
|
||||||
from ..util.compress_content import parser_reply
|
from ..util.compress_content import parser_reply
|
||||||
from ..util.emoji import get_emoji
|
from ..util.emoji import get_emoji
|
||||||
|
from ..util.file import get_file
|
||||||
|
|
||||||
os.makedirs('./data/聊天记录', exist_ok=True)
|
os.makedirs('./data/聊天记录', exist_ok=True)
|
||||||
|
|
||||||
@ -138,7 +139,7 @@ class Output(QThread):
|
|||||||
self.requestInterruption()
|
self.requestInterruption()
|
||||||
|
|
||||||
|
|
||||||
def modify_audio_metadata(audiofile, new_artist): # 修改音频元数据中的“创作者”标签
|
def modify_audio_metadata(audiofile, new_artist): # 修改音频元数据中的“创作者”标签
|
||||||
return
|
return
|
||||||
audiofile = load(audiofile)
|
audiofile = load(audiofile)
|
||||||
|
|
||||||
@ -254,7 +255,7 @@ class ChildThread(QThread):
|
|||||||
try:
|
try:
|
||||||
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
||||||
except:
|
except:
|
||||||
print("网络图片",image_path)
|
print("网络图片", image_path)
|
||||||
pass
|
pass
|
||||||
image_path = image_path.replace('\\', '/')
|
image_path = image_path.replace('\\', '/')
|
||||||
# print(f"tohtml:---{image_path}")
|
# print(f"tohtml:---{image_path}")
|
||||||
@ -354,8 +355,41 @@ class ChildThread(QThread):
|
|||||||
f'''{str_time} {name}\n[表情包]\n\n'''
|
f'''{str_time} {name}\n[表情包]\n\n'''
|
||||||
)
|
)
|
||||||
|
|
||||||
def wx_file(self, doc, isSend, content, status):
|
def file(self, doc, message):
|
||||||
return
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
||||||
|
bytesExtra = message[10]
|
||||||
|
str_time = message[8]
|
||||||
|
is_send = message[4]
|
||||||
|
timestamp = message[5]
|
||||||
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
||||||
|
if is_chatroom:
|
||||||
|
avatar = f"./avatar/{message[12].wxid}.png"
|
||||||
|
else:
|
||||||
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
||||||
|
if is_chatroom:
|
||||||
|
if is_send:
|
||||||
|
displayname = MePC().name
|
||||||
|
else:
|
||||||
|
displayname = message[12].remark
|
||||||
|
else:
|
||||||
|
displayname = MePC().name if is_send else self.contact.remark
|
||||||
|
displayname = escape_js_and_html(displayname)
|
||||||
|
if self.output_type == Output.HTML:
|
||||||
|
link = get_file(bytesExtra, thumb=True, output_path=origin_docx_path + '/file')
|
||||||
|
file_name = ''
|
||||||
|
shutil.copy(f"{os.path.abspath('.')}/app/resources/icons/file.png", origin_docx_path + '/file/file.png')
|
||||||
|
file_path = './file/file.png'
|
||||||
|
if link != "":
|
||||||
|
file_name = os.path.basename(link)
|
||||||
|
link = './file/' + file_name
|
||||||
|
|
||||||
|
if self.is_5_min(timestamp):
|
||||||
|
doc.write(
|
||||||
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
||||||
|
)
|
||||||
|
doc.write(
|
||||||
|
f'''{{ type:49, text: '{file_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}',link: '{link}',sub_type:6,file_name: '{file_name}'}},'''
|
||||||
|
)
|
||||||
|
|
||||||
def retract_message(self, doc, isSend, content, status):
|
def retract_message(self, doc, isSend, content, status):
|
||||||
return
|
return
|
||||||
@ -424,7 +458,8 @@ class ChildThread(QThread):
|
|||||||
str_time = message[8]
|
str_time = message[8]
|
||||||
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(' <a href="weixin://revoke_edit_click">重新编辑</a>]]>', "")
|
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)
|
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, "")
|
||||||
@ -542,7 +577,7 @@ class ChildThread(QThread):
|
|||||||
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"))
|
||||||
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"
|
||||||
@ -572,6 +607,8 @@ class ChildThread(QThread):
|
|||||||
self.system_msg(f, message)
|
self.system_msg(f, message)
|
||||||
elif type_ == 49 and sub_type == 57 and self.message_types.get(1):
|
elif type_ == 49 and sub_type == 57 and self.message_types.get(1):
|
||||||
self.refermsg(f, message)
|
self.refermsg(f, message)
|
||||||
|
elif type_ == 49 and sub_type == 6 and self.message_types.get(4906):
|
||||||
|
self.file(f, message)
|
||||||
f.write(html_end)
|
f.write(html_end)
|
||||||
f.close()
|
f.close()
|
||||||
self.okSignal.emit(1)
|
self.okSignal.emit(1)
|
||||||
@ -893,7 +930,7 @@ body{
|
|||||||
color: darkgray;
|
color: darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-image img{
|
.chat-image img,.chat-file img{
|
||||||
margin-right: 18px;
|
margin-right: 18px;
|
||||||
margin-left: 18px;
|
margin-left: 18px;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
@ -916,6 +953,29 @@ audio{
|
|||||||
margin-left: 9px;
|
margin-left: 9px;
|
||||||
margin-right: 9px;
|
margin-right: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chat-file {
|
||||||
|
width: 300px;
|
||||||
|
background-color: #fff;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
.chat-file a ,.chat-file div{
|
||||||
|
display: flex;
|
||||||
|
color: #000;
|
||||||
|
outline: none;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 0 20px 20px 20px;
|
||||||
|
}
|
||||||
|
.chat-file div{
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
.chat-file a span ,.chat-file div span{
|
||||||
|
/* flex-grow: 1; */
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
.chat-file a img,.chat-file div img{
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
.input-area{
|
.input-area{
|
||||||
border-top:0.5px solid #e0e0e0;
|
border-top:0.5px solid #e0e0e0;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
@ -1139,6 +1199,17 @@ html_end = '''
|
|||||||
messageAudioTag.innerHTML = `<audio src="${message.text}" controls></audio>`;
|
messageAudioTag.innerHTML = `<audio src="${message.text}" controls></audio>`;
|
||||||
return messageAudioTag;
|
return messageAudioTag;
|
||||||
}
|
}
|
||||||
|
function messageFileBox(message) {
|
||||||
|
const messageFileTag = document.createElement('div');
|
||||||
|
messageFileTag.className = `chat-file`;
|
||||||
|
if (message.link !== ''){
|
||||||
|
messageFileTag.innerHTML = `
|
||||||
|
<a href="${message.link}" target="_blank"><span>${message.file_name}</span><img src="${message.text}"/></a>`
|
||||||
|
}else{
|
||||||
|
messageFileTag.innerHTML = `<div><span>文件已丢失</span><img src="${message.text}"/></div>`;
|
||||||
|
}
|
||||||
|
return messageFileTag;
|
||||||
|
}
|
||||||
|
|
||||||
// 从数据列表中取出对应范围的元素并添加到容器中
|
// 从数据列表中取出对应范围的元素并添加到容器中
|
||||||
for (let i = startIndex; i < endIndex && i < chatMessages.length; i++) {
|
for (let i = startIndex; i < endIndex && i < chatMessages.length; i++) {
|
||||||
@ -1224,6 +1295,19 @@ html_end = '''
|
|||||||
messageContent.appendChild(messageElementReferText(message, side));
|
messageContent.appendChild(messageElementReferText(message, side));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 整合
|
||||||
|
messageElement.className = `item item-${side}`;
|
||||||
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
||||||
|
messageElement.appendChild(message.is_send ? avatarTag : messageContent);
|
||||||
|
}
|
||||||
|
if (message.sub_type == 6) {
|
||||||
|
// displayname 和 file
|
||||||
|
messageContent.className = `content-wrapper content-wrapper-${side}`;
|
||||||
|
if (message.is_chatroom && !message.is_send) {
|
||||||
|
messageContent.appendChild(displayNameBox(message));
|
||||||
|
}
|
||||||
|
messageContent.appendChild(messageFileBox(message));
|
||||||
|
|
||||||
// 整合
|
// 整合
|
||||||
messageElement.className = `item item-${side}`;
|
messageElement.className = `item item-${side}`;
|
||||||
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
||||||
|
BIN
app/resources/icons/file.png
Normal file
BIN
app/resources/icons/file.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 568 B |
@ -9,7 +9,9 @@ types = {
|
|||||||
'语音': 34,
|
'语音': 34,
|
||||||
'视频': 43,
|
'视频': 43,
|
||||||
'表情包': 47,
|
'表情包': 47,
|
||||||
|
'文件': 49_06,
|
||||||
'拍一拍等系统消息': 10000
|
'拍一拍等系统消息': 10000
|
||||||
|
|
||||||
}
|
}
|
||||||
Stylesheet = """
|
Stylesheet = """
|
||||||
QPushButton{
|
QPushButton{
|
||||||
@ -28,6 +30,7 @@ class ExportDialog(QDialog):
|
|||||||
if file_type == 'html':
|
if file_type == 'html':
|
||||||
self.export_type = Output.HTML
|
self.export_type = Output.HTML
|
||||||
self.export_choices = {"文本": True, "图片": True, "语音": True, "视频": True, "表情包": True,
|
self.export_choices = {"文本": True, "图片": True, "语音": True, "视频": True, "表情包": True,
|
||||||
|
'文件': True,
|
||||||
'拍一拍等系统消息': True} # 定义导出的数据类型,默认全部选择
|
'拍一拍等系统消息': True} # 定义导出的数据类型,默认全部选择
|
||||||
elif file_type == 'csv':
|
elif file_type == 'csv':
|
||||||
self.export_type = Output.CSV
|
self.export_type = Output.CSV
|
||||||
|
63
app/util/file.py
Normal file
63
app/util/file.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import os
|
||||||
|
import traceback
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from app.log import log, logger
|
||||||
|
from app.util.protocbuf.msg_pb2 import MessageBytesExtra
|
||||||
|
from ..person import MePC
|
||||||
|
|
||||||
|
root_path = './data/files/'
|
||||||
|
if not os.path.exists('./data'):
|
||||||
|
os.mkdir('./data')
|
||||||
|
if not os.path.exists(root_path):
|
||||||
|
os.mkdir(root_path)
|
||||||
|
|
||||||
|
|
||||||
|
class File:
|
||||||
|
def __init__(self):
|
||||||
|
self.open_flag = False
|
||||||
|
|
||||||
|
|
||||||
|
def get_file(bytes_extra, thumb=False, output_path=root_path) -> str:
|
||||||
|
try:
|
||||||
|
msg_bytes = MessageBytesExtra()
|
||||||
|
msg_bytes.ParseFromString(bytes_extra)
|
||||||
|
file_original_path = ''
|
||||||
|
file_path = ''
|
||||||
|
file_name = ''
|
||||||
|
real_path = ''
|
||||||
|
if len(msg_bytes.message2) > 0:
|
||||||
|
file_field = msg_bytes.message2[-1].field2
|
||||||
|
if file_field.find('sec_msg_node') == -1:
|
||||||
|
file_original_path = file_field
|
||||||
|
file_name = os.path.basename(file_original_path)
|
||||||
|
if file_name != '' and file_name != MePC().wxid:
|
||||||
|
file_path = os.path.join(output_path, file_name)
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
print('文件' + file_path + '已存在')
|
||||||
|
return file_path
|
||||||
|
if os.path.isabs(file_original_path):
|
||||||
|
if os.path.exists(file_original_path):
|
||||||
|
real_path = file_original_path
|
||||||
|
else: # 如果没找到再判断一次是否是迁移了目录
|
||||||
|
if file_original_path.find(r"FileStorage") != -1:
|
||||||
|
real_path = MePC().wx_dir + file_original_path[
|
||||||
|
file_original_path.find("FileStorage") - 1:]
|
||||||
|
else:
|
||||||
|
if file_original_path.find(MePC().wxid) != -1:
|
||||||
|
real_path = MePC().wx_dir + file_original_path.replace(MePC().wxid, '')
|
||||||
|
else:
|
||||||
|
real_path = MePC().wx_dir + file_original_path
|
||||||
|
if real_path != "":
|
||||||
|
if os.path.exists(real_path):
|
||||||
|
print('开始获取文件' + real_path)
|
||||||
|
shutil.copy2(real_path, file_path)
|
||||||
|
else:
|
||||||
|
print('文件' + file_original_path + '已丢失')
|
||||||
|
file_path = ''
|
||||||
|
return file_path
|
||||||
|
except:
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
return ""
|
Loading…
Reference in New Issue
Block a user