From 4bf1729d208cfd421de75732e497f6599e9abfcb Mon Sep 17 00:00:00 2001
From: shuaikangzhou <863909694@qq.com>
Date: Sun, 10 Dec 2023 18:55:17 +0800
Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8F=AF=E8=87=AA=E5=AE=9A?=
=?UTF-8?q?=E4=B9=89=E9=80=89=E6=8B=A9=E5=AF=BC=E5=87=BAHTML=E7=9A=84?=
=?UTF-8?q?=E6=B6=88=E6=81=AF=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/DataBase/output_pc.py | 505 +++++++++++++++--------------
app/main/__init__.py | 9 -
app/ui_pc/contact/contactInfo.py | 25 +-
app/ui_pc/contact/export_dialog.py | 92 ++++++
readme.md | 4 +-
5 files changed, 377 insertions(+), 258 deletions(-)
delete mode 100644 app/main/__init__.py
create mode 100644 app/ui_pc/contact/export_dialog.py
diff --git a/app/DataBase/output_pc.py b/app/DataBase/output_pc.py
index 1ca25f4..20a6370 100644
--- a/app/DataBase/output_pc.py
+++ b/app/DataBase/output_pc.py
@@ -1,7 +1,7 @@
import csv
import html
import os
-
+from re import findall
from PyQt5.QtCore import pyqtSignal, QThread
from PyQt5.QtWidgets import QFileDialog
@@ -58,10 +58,11 @@ class Output(QThread):
CSV_ALL = 3
CONTACT_CSV = 4
- def __init__(self, contact, parent=None, type_=DOCX):
+ def __init__(self, contact, type_=DOCX, message_types={}, parent=None):
super().__init__(parent)
self.Child0 = None
self.last_timestamp = 0
+ self.message_types = message_types
self.sec = 2 # 默认1000秒
self.contact = contact
self.ta_username = contact.wxid if contact else ''
@@ -122,7 +123,7 @@ class Output(QThread):
elif self.output_type == self.CONTACT_CSV:
self.contact_to_csv()
else:
- self.Child = ChildThread(self.contact, type_=self.output_type)
+ self.Child = ChildThread(self.contact, type_=self.output_type,message_types=self.message_types)
self.Child.progressSignal.connect(self.progress)
self.Child.rangeSignal.connect(self.rangeSignal)
self.Child.okSignal.connect(self.okSignal)
@@ -144,27 +145,85 @@ class ChildThread(QThread):
DOCX = 1
HTML = 2
- def __init__(self, contact, parent=None, type_=DOCX):
+ def __init__(self, contact, type_=DOCX, message_types={}, parent=None):
super().__init__(parent)
self.contact = contact
+ self.message_types = message_types
self.last_timestamp = 0
self.sec = 2 # 默认1000秒
self.msg_id = 0
self.output_type = type_
+
def is_5_min(self, timestamp):
if abs(timestamp - self.last_timestamp) > 300:
self.last_timestamp = timestamp
return True
return False
- def text(self, doc, isSend, message, status):
+ def text(self, doc, message):
+ type_ = message[2]
+ str_content = message[7]
+ str_time = message[8]
+ is_send = message[4]
+ avatar = 'myhead.png' if is_send else 'tahead.png'
+ timestamp = message[5]
+ str_content = escape_js_and_html(str_content)
+ if self.is_5_min(timestamp):
+ doc.write(
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ )
+ emojiText = findall(r"(\[.+?\])", str_content)
+ for emoji_text in emojiText:
+ if emoji_text in emoji:
+ str_content = str_content.replace(emoji_text, emoji[emoji_text])
+ doc.write(
+ f'''{{ type:{type_}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ )
+
+ def image(self, doc, message):
+ type_ = message[2]
+ str_content = message[7]
+ str_time = message[8]
+ is_send = message[4]
+ avatar = 'myhead.png' if is_send else 'tahead.png'
+ timestamp = message[5]
+ BytesExtra = message[10]
+ str_content = escape_js_and_html(str_content)
+ image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False)
+ image_thumb_path = hard_link_db.get_image(str_content, BytesExtra, thumb=True)
+ if image_path is None and image_thumb_path is not None:
+ image_path = image_thumb_path
+ if image_path is None and image_thumb_path is None:
+ return
+ image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
+ image_path = image_path.replace('\\', '/')
+ # print(f"tohtml:---{image_path}")
+ if self.is_5_min(timestamp):
+ doc.write(
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ )
+ doc.write(
+ f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ )
return
- def image(self, doc, isSend, Type, content, imgPath):
- return
-
- def emoji(self, doc, isSend, content, imgPath):
+ def emoji(self, doc, message):
+ origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
+ str_content = message[7]
+ str_time = message[8]
+ is_send = message[4]
+ avatar = 'myhead.png' if is_send else 'tahead.png'
+ timestamp = message[5]
+ emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji')
+ emoji_path = './emoji/' + os.path.basename(emoji_path)
+ if self.is_5_min(timestamp):
+ doc.write(
+ f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
+ )
+ doc.write(
+ f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
+ )
return
def wx_file(self, doc, isSend, content, status):
@@ -176,11 +235,55 @@ class ChildThread(QThread):
def reply(self, doc, isSend, content, status):
return
- def pat_a_pat(self, doc, isSend, content, status):
- return
+ def system_msg(self, doc, message):
+ str_content = message[7]
+ is_send = message[4]
+ str_content = escape_js_and_html(str_content.lstrip('
',
+ '[撇嘴]': '
',
+ '[色]': '
',
+ '[发呆]': '
',
+ '[得意]': '
',
+ '[流泪]': '
',
+ '[害羞]': '
',
+ '[闭嘴]': '
',
+ '[睡]': '
',
+ '[大哭]': '
',
+ '[尴尬]': '
',
+ '[发怒]': '
',
+ '[调皮]': '
',
+ '[呲牙]': '
',
+ '[惊讶]': '
',
+ '[难过]': '
',
+ '[抓狂]': '
',
+ '[吐]': '
',
+ '[偷笑]': '
',
+ '[愉快]': '
',
+ '[白眼]': '
',
+ '[傲慢]': '
',
+ '[困]': '
',
+ '[惊恐]': '
',
+ '[憨笑]': '
',
+ '[悠闲]': '
',
+ '[咒骂]': '
',
+ '[疑问]': '
',
+ '[嘘]': '
',
+ '[晕]': '
',
+ '[衰]': '
',
+ '[骷髅]': '
',
+ '[敲打]': '
',
+ '[再见]': '
',
+ '[擦汗]': '
',
+ '[抠鼻]': '
',
+ '[鼓掌]': '
',
+ '[坏笑]': '
',
+ '[右哼哼]': '
',
+ '[鄙视]': '
',
+ '[委屈]': '
',
+ '[快哭了]': '
',
+ '[阴险]': '
',
+ '[亲亲]': '
',
+ '[可怜]': '
',
+ '[笑脸]': '
',
+ '[生病]': '
',
+ '[脸红]': '
',
+ '[破涕为笑]': '
',
+ '[恐惧]': '
',
+ '[失望]': '
',
+ '[无语]': '
',
+ '[嘿哈]': '
',
+ '[捂脸]': '
',
+ '[奸笑]': '
',
+ '[机智]': '
',
+ '[皱眉]': '
',
+ '[耶]': '
',
+ '[吃瓜]': '
',
+ '[加油]': '
',
+ '[汗]': '
',
+ '[天啊]': '
',
+ '[Emm]': '
',
+ '[社会社会]': '
',
+ '[旺柴]': '
',
+ '[好的]': '
',
+ '[打脸]': '
',
+ '[哇]': '
',
+ '[翻白眼]': '
',
+ '[666]': '
',
+ '[让我看看]': '
',
+ '[叹气]': '
',
+ '[苦涩]': '
',
+ '[裂开]': '
',
+ '[嘴唇]': '
',
+ '[爱心]': '
',
+ '[心碎]': '
',
+ '[拥抱]': '
',
+ '[强]': '
',
+ '[弱]': '
',
+ '[握手]': '
',
+ '[胜利]': '
',
+ '[抱拳]': '
',
+ '[勾引]': '
',
+ '[拳头]': '
',
+ '[OK]': '
',
+ '[合十]': '
',
+ '[啤酒]': '
',
+ '[咖啡]': '
',
+ '[蛋糕]': '
',
+ '[玫瑰]': '
',
+ '[凋谢]': '
',
+ '[菜刀]': '
',
+ '[炸弹]': '
',
+ '[便便]': '
',
+ '[月亮]': '
',
+ '[太阳]': '
',
+ '[庆 祝]': '
',
+ '[礼物]': '
',
+ '[红包]': '
',
+ '[發]': '
',
+ '[福]': '
',
+ '[烟花]': '
',
+ '[爆竹]': '
',
+ '[猪头]': '
',
+ '[跳跳]': '
',
+ '[发抖]': '
',
+ '[转圈]': '
'}
+html_head = '''
',
- '[撇嘴]': '
',
- '[色]': '
',
- '[发呆]': '
',
- '[得意]': '
',
- '[流泪]': '
',
- '[害羞]': '
',
- '[闭嘴]': '
',
- '[睡]': '
',
- '[大哭]': '
',
- '[尴尬]': '
',
- '[发怒]': '
',
- '[调皮]': '
',
- '[呲牙]': '
',
- '[惊讶]': '
',
- '[难过]': '
',
- '[抓狂]': '
',
- '[吐]': '
',
- '[偷笑]': '
',
- '[愉快]': '
',
- '[白眼]': '
',
- '[傲慢]': '
',
- '[困]': '
',
- '[惊恐]': '
',
- '[憨笑]': '
',
- '[悠闲]': '
',
- '[咒骂]': '
',
- '[疑问]': '
',
- '[嘘]': '
',
- '[晕]': '
',
- '[衰]': '
',
- '[骷髅]': '
',
- '[敲打]': '
',
- '[再见]': '
',
- '[擦汗]': '
',
- '[抠鼻]': '
',
- '[鼓掌]': '
',
- '[坏笑]': '
',
- '[右哼哼]': '
',
- '[鄙视]': '
',
- '[委屈]': '
',
- '[快哭了]': '
',
- '[阴险]': '
',
- '[亲亲]': '
',
- '[可怜]': '
',
- '[笑脸]': '
',
- '[生病]': '
',
- '[脸红]': '
',
- '[破涕为笑]': '
',
- '[恐惧]': '
',
- '[失望]': '
',
- '[无语]': '
',
- '[嘿哈]': '
',
- '[捂脸]': '
',
- '[奸笑]': '
',
- '[机智]': '
',
- '[皱眉]': '
',
- '[耶]': '
',
- '[吃瓜]': '
',
- '[加油]': '
',
- '[汗]': '
',
- '[天啊]': '
',
- '[Emm]': '
',
- '[社会社会]': '
',
- '[旺柴]': '
',
- '[好的]': '
',
- '[打脸]': '
',
- '[哇]': '
',
- '[翻白眼]': '
',
- '[666]': '
',
- '[让我看看]': '
',
- '[叹气]': '
',
- '[苦涩]': '
',
- '[裂开]': '
',
- '[嘴唇]': '
',
- '[爱心]': '
',
- '[心碎]': '
',
- '[拥抱]': '
',
- '[强]': '
',
- '[弱]': '
',
- '[握手]': '
',
- '[胜利]': '
',
- '[抱拳]': '
',
- '[勾引]': '
',
- '[拳头]': '
',
- '[OK]': '
',
- '[合十]': '
',
- '[啤酒]': '
',
- '[咖啡]': '
',
- '[蛋糕]': '
',
- '[玫瑰]': '
',
- '[凋谢]': '
',
- '[菜刀]': '
',
- '[炸弹]': '
',
- '[便便]': '
',
- '[月亮]': '
',
- '[太阳]': '
',
- '[庆 祝]': '
',
- '[礼物]': '
',
- '[红包]': '
',
- '[發]': '
',
- '[福]': '
',
- '[烟花]': '
',
- '[爆竹]': '
',
- '[猪头]': '
',
- '[跳跳]': '
',
- '[发抖]': '
',
- '[转圈]': '
'}
- from re import findall
- for index, message in enumerate(messages):
- type_ = message[2]
- str_content = message[7]
- str_time = message[8]
- # print(type_, type(type_))
- is_send = message[4]
- BytesExtra = message[10]
- # avatar = MePC().avatar_path if is_send else self.contact.avatar_path
- # avatar = avatar.replace('\\', '\\\\')
- avatar = 'myhead.png' if is_send else 'tahead.png'
- timestamp = message[5]
- self.progressSignal.emit(index)
- if type_ == 1:
- str_content = escape_js_and_html(str_content)
- if self.is_5_min(timestamp):
- f.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
- )
-
- emojiText = findall(r"(\[.+?\])", str_content)
- for emoji_text in emojiText:
- if emoji_text in emoji:
- str_content = str_content.replace(emoji_text, emoji[emoji_text])
- f.write(
- f'''{{ type:{type_}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}'}},'''
- )
- elif type_ == 3:
- image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False)
- image_thumb_path = hard_link_db.get_image(str_content, BytesExtra, thumb=True)
- if image_path is None and image_thumb_path is not None:
- image_path = image_thumb_path
- if image_path is None and image_thumb_path is None:
- continue
- image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
- image_path = image_path.replace('\\', '/')
- # print(f"tohtml:---{image_path}")
- if self.is_5_min(timestamp):
- f.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
- )
- f.write(
- f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
- )
- elif type_ == 43:
- video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False)
- image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True)
- if video_path is None and image_path is not None:
- print(video_path, image_path)
- image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
- print(image_path)
- image_path = image_path.replace('\\', '/')
- # print(f"tohtml:---{image_path}")
- if self.is_5_min(timestamp):
- f.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
- )
- f.write(
- f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
- )
- continue
- if video_path is None and image_path is None:
- continue
- video_path = f'{MePC().wx_dir}/{video_path}'
- if os.path.exists(video_path):
- new_path = origin_docx_path + '/video/' + os.path.basename(video_path)
- if not os.path.exists(new_path):
- shutil.copy(video_path, os.path.join(origin_docx_path, 'video'))
- video_path = f'./video/{os.path.basename(video_path)}'
- video_path = video_path.replace('\\', '/')
- if self.is_5_min(timestamp):
- f.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
- )
- f.write(
- f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
- )
- elif type_ == 47:
- emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji')
- emoji_path = './emoji/'+os.path.basename(emoji_path)
- if self.is_5_min(timestamp):
- f.write(
- f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:''}},'''
- )
- f.write(
- f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}'}},'''
- )
- elif type_ == 10000:
- str_content = escape_js_and_html(str_content.lstrip('