WeChatMsg/app/DataBase/output.py

175 lines
5.5 KiB
Python
Raw Normal View History

2024-01-02 22:33:46 +08:00
import csv
import html
2023-01-23 09:47:40 +08:00
import os
2024-01-02 22:33:46 +08:00
import shutil
import sys
2023-01-23 09:47:40 +08:00
import time
2024-01-02 22:33:46 +08:00
import traceback
from re import findall
2023-03-31 11:15:44 +08:00
2023-01-23 09:47:40 +08:00
import docx
2024-01-02 22:33:46 +08:00
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtWidgets import QFileDialog
2023-01-23 09:47:40 +08:00
from docx import shared
from docx.enum.table import WD_ALIGN_VERTICAL
from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT
2024-01-02 22:33:46 +08:00
from docx.oxml.ns import qn
from .package_msg import PackageMsg
from ..DataBase import media_msg_db, hard_link_db, micro_msg_db, msg_db
from ..log import logger
from ..person import Me, Contact
from ..util import path
from ..util.compress_content import parser_reply, music_share, share_card
from ..util.emoji import get_emoji_url
from ..util.file import get_file
from ..util.music import get_music_path
from ..util.image import get_image_path, get_image, get_image_abs_path
os.makedirs('./data/聊天记录', exist_ok=True)
def set_global_font(doc, font_name):
# 创建一个新样式
style = doc.styles['Normal']
# 设置字体名称
style.font.name = font_name
# 遍历文档中的所有段落,将样式应用到每个段落
for paragraph in doc.paragraphs:
for run in paragraph.runs:
run.font.name = font_name
def makedirs(path):
os.makedirs(path, exist_ok=True)
os.makedirs(os.path.join(path, 'image'), exist_ok=True)
os.makedirs(os.path.join(path, 'emoji'), exist_ok=True)
os.makedirs(os.path.join(path, 'video'), exist_ok=True)
os.makedirs(os.path.join(path, 'voice'), exist_ok=True)
os.makedirs(os.path.join(path, 'file'), 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, 'icon'), exist_ok=True)
file = './app/resources/data/file.png'
if not os.path.exists(file):
resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__)))
file = os.path.join(resource_dir, 'app', 'resources', 'data', 'file.png')
shutil.copy(file, path + '/icon/file.png')
play_file = './app/resources/data/play.png'
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')
shutil.copy(play_file, path + '/icon/play.png')
pause_file = './app/resources/data/pause.png'
if not os.path.exists(pause_file):
resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__)))
pause_file = os.path.join(resource_dir, 'app', 'resources', 'data', 'pause.png')
shutil.copy(pause_file, path + '/icon/pause.png')
def escape_js_and_html(input_str):
# 转义HTML特殊字符
html_escaped = html.escape(input_str, quote=False)
# 手动处理JavaScript转义字符
js_escaped = (
html_escaped
.replace("\\", "\\\\")
.replace("'", r"\'")
.replace('"', r'\"')
.replace("\n", r'\n')
.replace("\r", r'\r')
.replace("\t", r'\t')
)
return js_escaped
class ExporterBase(QThread):
2023-01-23 09:47:40 +08:00
progressSignal = pyqtSignal(int)
2023-02-02 00:26:44 +08:00
rangeSignal = pyqtSignal(int)
okSignal = pyqtSignal(int)
i = 1
2023-10-26 22:45:44 +08:00
CSV = 0
DOCX = 1
HTML = 2
2024-01-02 22:33:46 +08:00
CSV_ALL = 3
CONTACT_CSV = 4
TXT = 5
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def __init__(self, contact, type_=DOCX, message_types={}, parent=None):
2023-01-23 09:47:40 +08:00
super().__init__(parent)
2024-01-02 22:33:46 +08:00
self.message_types = message_types # 导出的消息类型
self.contact: Contact = contact # 联系人
self.output_type = type_ # 导出文件类型
self.total_num = 1 # 总的消息数量
self.num = 0 # 当前处理的消息数量
self.last_timestamp = 0
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
makedirs(origin_docx_path)
2023-02-02 00:26:44 +08:00
def run(self):
2024-01-02 22:33:46 +08:00
self.export()
def export(self):
raise NotImplementedError("export method must be implemented in subclasses")
def cancel(self):
self.requestInterruption()
def is_5_min(self, timestamp) -> bool:
if abs(timestamp - self.last_timestamp) > 300:
self.last_timestamp = timestamp
return True
return False
def get_avatar_path(self, is_send, message, is_absolute_path=False) -> str:
if self.contact.is_chatroom:
avatar = message[12].smallHeadImgUrl
2023-01-23 09:47:40 +08:00
else:
2024-01-02 22:33:46 +08:00
avatar = Me().smallHeadImgUrl if is_send else self.contact.smallHeadImgUrl
if is_absolute_path:
if self.contact.is_chatroom:
avatar = message[12].avatar_path
2023-01-23 09:47:40 +08:00
else:
2024-01-02 22:33:46 +08:00
avatar = Me().avatar_path if is_send else self.contact.avatar_path
return avatar
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def get_display_name(self, is_send, message) -> str:
if self.contact.is_chatroom:
if is_send:
display_name = Me().name
else:
display_name = message[12].remark
else:
display_name = Me().name if is_send else self.contact.remark
return escape_js_and_html(display_name)
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def text(self, doc, message):
return
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def image(self, doc, message):
return
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def audio(self, doc, message):
return
2023-02-02 00:26:44 +08:00
2024-01-02 22:33:46 +08:00
def emoji(self, doc, message):
return
2023-02-02 00:26:44 +08:00
2024-01-02 22:33:46 +08:00
def file(self, doc, message):
return
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def refermsg(self, doc, message):
return
2023-10-26 22:45:44 +08:00
2024-01-02 22:33:46 +08:00
def system_msg(self, doc, message):
return
2023-10-26 22:45:44 +08:00
2024-01-02 22:33:46 +08:00
def video(self, doc, message):
return
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def music_share(self, doc, message):
return
2023-01-23 09:47:40 +08:00
2024-01-02 22:33:46 +08:00
def share_card(self, doc, message):
return