补充已过期或丢失文件的处理,添加文件和大小和类型等信息,集中处理一些用到的图标

This commit is contained in:
wuyanyun 2024-01-03 21:11:23 +08:00
parent 3dd8683944
commit 119b082024
17 changed files with 158 additions and 83 deletions

View File

@ -12,13 +12,24 @@ from app.DataBase.package_msg import PackageMsg
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 parser_reply, share_card, music_share from app.util.compress_content import parser_reply, share_card, music_share, file
from app.util.emoji import get_emoji_url from app.util.emoji import get_emoji_url
from app.util.file import get_file
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/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'],
}
class HtmlExporter(ExporterBase): class HtmlExporter(ExporterBase):
def text(self, doc, message): def text(self, doc, message):
type_ = message[2] type_ = message[2]
@ -95,20 +106,32 @@ class HtmlExporter(ExporterBase):
def file(self, doc, message): def file(self, doc, message):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
bytesExtra = message[10] bytesExtra = message[10]
compress_content = message[11]
str_time = message[8] str_time = message[8]
is_send = message[4] is_send = message[4]
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)
link = get_file(bytesExtra, thumb=True, output_path=origin_docx_path + '/file') file_info = file(bytesExtra, compress_content, output_path=origin_docx_path + '/file')
file_name = '' if file_info.get('is_error') == False:
file_path = './icon/file.png' icon_path = None
if link != "": for icon, extensions in icon_files.items():
file_name = os.path.basename(link) if file_info.get('file_ext') in extensions:
link = './file/' + file_name icon_path = icon
break
# 如果没有与文件后缀匹配的图标,则使用默认图标
if icon_path is None:
default_icon = './icon/file.png'
icon_path = default_icon
file_path = file_info.get('file_path')
if file_path != "":
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},is_chatroom:{is_chatroom},displayname:'{display_name}',link: '{link}',sub_type:6,file_name: '{file_name}'}},''' 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')}'}},'''
) )
def refermsg(self, doc, message): def refermsg(self, doc, message):
@ -200,6 +223,7 @@ class HtmlExporter(ExporterBase):
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('audio_url') != '': if content.get('audio_url') != '':
music_path = get_music_path(content.get('audio_url'), content.get('title'), music_path = get_music_path(content.get('audio_url'), content.get('title'),
output_path=origin_docx_path + '/music') output_path=origin_docx_path + '/music')
@ -209,7 +233,6 @@ 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)
if content.get('is_error') == False:
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')}', timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{display_name}',sub_type:3,title:'{content.get('title')}',

View File

@ -5,6 +5,7 @@ import shutil
import sys import sys
import time import time
import traceback import traceback
import filecmp
from re import findall from re import findall
import docx import docx
@ -51,21 +52,24 @@ def makedirs(path):
os.makedirs(os.path.join(path, 'avatar'), exist_ok=True) os.makedirs(os.path.join(path, 'avatar'), exist_ok=True)
os.makedirs(os.path.join(path, 'music'), exist_ok=True) os.makedirs(os.path.join(path, 'music'), exist_ok=True)
os.makedirs(os.path.join(path, 'icon'), exist_ok=True) os.makedirs(os.path.join(path, 'icon'), exist_ok=True)
file = './app/resources/data/file.png' resource_dir = os.path.join('app', 'resources', 'data', 'icons')
if not os.path.exists(file): target_folder = os.path.join(path, 'icon')
resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) # 拷贝一些必备的图标
file = os.path.join(resource_dir, 'app', 'resources', 'data', 'file.png') for root, dirs, files in os.walk(resource_dir):
shutil.copy(file, path + '/icon/file.png') relative_path = os.path.relpath(root, resource_dir)
play_file = './app/resources/data/play.png' target_path = os.path.join(target_folder, relative_path)
if not os.path.exists(play_file):
resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) # 遍历文件夹中的文件
play_file = os.path.join(resource_dir, 'app', 'resources', 'data', 'play.png') for file in files:
shutil.copy(play_file, path + '/icon/play.png') source_file_path = os.path.join(root, file)
pause_file = './app/resources/data/pause.png' target_file_path = os.path.join(target_path, file)
if not os.path.exists(pause_file): if not os.path.exists(target_file_path):
resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) shutil.copy(source_file_path, target_file_path)
pause_file = os.path.join(resource_dir, 'app', 'resources', 'data', 'pause.png') else:
shutil.copy(pause_file, path + '/icon/pause.png') # 比较文件内容
if not filecmp.cmp(source_file_path, target_file_path, shallow=False):
# 文件内容不一致,进行覆盖拷贝
shutil.copy(source_file_path, target_file_path)
def escape_js_and_html(input_str): def escape_js_and_html(input_str):

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 716 B

View File

@ -187,30 +187,7 @@ audio{
margin-right: 9px; margin-right: 9px;
} }
.chat-file { .chat-music-audio, .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;
}
.chat-music-audio {
width: 300px; width: 300px;
margin-right: 20px; margin-right: 20px;
display: flex; display: flex;
@ -222,8 +199,11 @@ audio{
height: 100px; height: 100px;
margin-left: 10px; margin-left: 10px;
} }
.chat-file img{
width: 50px;
}
.chat-music-audio .player-box { .chat-music-audio .player-box,.chat-file .file-box {
width: 300px; width: 300px;
display: flex; display: flex;
align-items: center; align-items: center;
@ -231,43 +211,43 @@ audio{
height: 80px; height: 80px;
} }
.chat-music-audio .player-original { .chat-music-audio .player-original ,.chat-file .app-info{
border-top: 1px solid #ede3e3; border-top: 1px solid #ede3e3;
} }
.chat-music-audio .player-original p { .chat-music-audio .player-original p ,.chat-file .app-info p{
margin-top: 5px; margin-top: 5px;
color: #888; color: #888;
} }
.chat-music-audio .player-controls { .chat-music-audio .player-controls, .chat-file .file-img{
display: flex; display: flex;
align-items: center;; align-items: center;;
} }
.chat-music-audio .flex1 { .chat-music-audio .flex1,.chat-file .flex1 {
flex: 1; flex: 1;
justify-content: start; justify-content: start;
} }
.chat-music-audio .flex2 { .chat-music-audio .flex2 ,.chat-file .flex2{
flex: 2; flex: 2;
justify-content: end; justify-content: end;
} }
.chat-music-audio .player-info { .chat-music-audio .player-info ,.chat-file .file-info{
width: 200px; width: 200px;
height: 80px; height: 80px;
white-space: normal; white-space: normal;
flex-basis: 200px; flex-basis: 200px;
} }
.chat-music-audio .song-title { .chat-music-audio .song-title,.chat-file .file-name {
font-weight: bold; font-weight: bold;
overflow-wrap: break-word; overflow-wrap: break-word;
} }
.chat-music-audio .artist { .chat-music-audio .artist ,.chat-file .file-size{
margin-top: 10px; margin-top: 10px;
color: #888; color: #888;
} }
@ -749,12 +729,26 @@ input {
function messageFileBox(message) { function messageFileBox(message) {
const messageFileTag = document.createElement('div'); const messageFileTag = document.createElement('div');
messageFileTag.className = `chat-file`; messageFileTag.className = `chat-file`;
if (message.link !== ''){ messageFileTag.onclick = function (event) {
messageFileTag.innerHTML = ` if (message.text !== '') {
<a href="${message.link}" target="_blank"><span>${message.file_name}</span><img loading="lazy" src="${message.text}"/></a>` window.open(message.text, '_blank');
}else{ }else{
messageFileTag.innerHTML = `<div><span>文件已丢失</span><img loading="lazy" src="${message.text}"/></div>`; alert("文件可能丢失、过期或不存放在该主机上")
} }
}
if (message.file_name.length >= 26) {
message.file_name = message.file_name.slice(0, 25) + '...'
}
messageFileTag.innerHTML = `<div class="file-box">
<div class="file-info flex1">
<div class="file-title">${message.file_name}</div>
<div class="file-size">${message.file_size}</div>
</div>
<div class="file-img flex2">
<img src="${message.icon_path}"/>
</div>
</div>
<div class="app-info"><p>${message.app_name}</p></div>`
return messageFileTag; return messageFileTag;
} }

View File

@ -4,10 +4,13 @@ import xml.etree.ElementTree as ET
import lz4.block import lz4.block
import requests import requests
import re
from urllib.parse import urlparse from urllib.parse import urlparse
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from app.DataBase.hard_link import parseBytes from app.DataBase.hard_link import parseBytes
from ..util.file import get_file
def decompress_CompressContent(data): def decompress_CompressContent(data):
@ -206,3 +209,58 @@ def get_audio_url(url):
except Exception as e: except Exception as e:
print(f"Get Audio Url Error: {e}") print(f"Get Audio Url Error: {e}")
return path return path
def file(bytes_extra, compress_content, output_path):
xml_content = decompress_CompressContent(compress_content)
if not xml_content:
return {
'type': 6,
'title': "发生错误",
"is_error": True
}
try:
root = ET.XML(xml_content)
appmsg = root.find('appmsg')
msg_type = int(appmsg.find('type').text)
file_name = appmsg.find('title').text
pattern = r'[\\/:*?"<>|\r\n]+'
file_name = re.sub(pattern, "_", file_name)
appattach = appmsg.find('appattach')
file_len = int(appattach.find('totallen').text)
app_name = ''
file_len = format_bytes(file_len)
file_ext = appattach.find('fileext').text
if root.find("appinfo") is not None:
app_info = root.find('appinfo')
app_name = app_info.find('appname').text
if app_name is None:
app_name = ''
file_path = get_file(bytes_extra, file_name, output_path)
return {
'type': msg_type,
'file_name': file_name,
'file_len': file_len,
'file_ext': file_ext,
'file_path': file_path,
'app_name': app_name,
"is_error": False
}
except Exception as e:
print(f"File Get Info Error: {e}")
return {
'type': 6,
'title': "发生错误",
"is_error": True
}
def format_bytes(size):
units = ["B", "KB", "MB", "GB"]
def convert_bytes(size, unit_index):
if size < 1024 or unit_index >= len(units) - 1:
return size, unit_index
return convert_bytes(size / 1024, unit_index + 1)
final_size, final_unit_index = convert_bytes(size, 0)
return f"{final_size:.2f} {units[final_unit_index]}"

View File

@ -20,25 +20,21 @@ class File:
self.open_flag = False self.open_flag = False
def get_file(bytes_extra, thumb=False, output_path=root_path) -> str: def get_file(bytes_extra, file_name, output_path=root_path) -> str:
try: try:
msg_bytes = MessageBytesExtra() msg_bytes = MessageBytesExtra()
msg_bytes.ParseFromString(bytes_extra) msg_bytes.ParseFromString(bytes_extra)
file_original_path = ''
file_path = '' file_path = ''
file_name = ''
real_path = '' real_path = ''
if len(msg_bytes.message2) > 0: if len(msg_bytes.message2) > 0:
file_field = msg_bytes.message2[-1].field2 for filed in msg_bytes.message2:
if file_field.find('sec_msg_node') == -1: if filed.field1 == 4:
file_original_path = file_field file_original_path = filed.field2
file_name = os.path.basename(file_original_path)
if file_name != '' and file_name != Me().wxid:
file_path = os.path.join(output_path, file_name) file_path = os.path.join(output_path, file_name)
if os.path.exists(file_path): if os.path.exists(file_path):
print('文件' + file_path + '已存在') # print('文件' + file_path + '已存在')
return file_path return file_path
if os.path.isabs(file_original_path): if os.path.isabs(file_original_path): # 绝对路径可能迁移过文件目录,也可能存在其他位置
if os.path.exists(file_original_path): if os.path.exists(file_original_path):
real_path = file_original_path real_path = file_original_path
else: # 如果没找到再判断一次是否是迁移了目录 else: # 如果没找到再判断一次是否是迁移了目录