pyqt支持群聊显示,合并群聊和非群聊的获取

This commit is contained in:
shuaikangzhou 2024-01-07 20:24:12 +08:00
parent 1209caa378
commit cc281fb352
15 changed files with 187 additions and 82 deletions

View File

@ -14,11 +14,7 @@ class CSVExporter(ExporterBase):
columns = ['localId', 'TalkerId', 'Type', 'SubType', columns = ['localId', 'TalkerId', 'Type', 'SubType',
'IsSender', 'CreateTime', 'Status', 'StrContent', 'IsSender', 'CreateTime', 'Status', 'StrContent',
'StrTime', 'Remark', 'NickName', 'Sender'] 'StrTime', 'Remark', 'NickName', 'Sender']
if self.contact.is_chatroom: messages = msg_db.get_messages(self.contact.wxid)
packagemsg = PackageMsg()
messages = packagemsg.get_package_message_by_wxid(self.contact.wxid)
else:
messages = msg_db.get_messages(self.contact.wxid)
# 写入CSV文件 # 写入CSV文件
with open(filename, mode='w', newline='', encoding='utf-8-sig') as file: with open(filename, mode='w', newline='', encoding='utf-8-sig') as file:
writer = csv.writer(file) writer = csv.writer(file)

View File

@ -1,27 +1,20 @@
import os import os
import shutil import shutil
import sys
import time import time
import traceback
from re import findall from re import findall
import docx import docx
from PyQt5.QtCore import pyqtSignal, QThread
from docx import shared from docx import shared
from docx.enum.table import WD_ALIGN_VERTICAL from docx.enum.table import WD_ALIGN_VERTICAL
from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT from docx.enum.text import WD_COLOR_INDEX, WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn from docx.oxml.ns import qn
from app.DataBase import msg_db, hard_link_db, media_msg_db from app.DataBase import msg_db, hard_link_db
from app.DataBase.output import ExporterBase, escape_js_and_html from app.DataBase.output import ExporterBase, escape_js_and_html
from app.DataBase.package_msg import PackageMsg from app.DataBase.package_msg import PackageMsg
from app.log import logger
from app.person import Me from app.person import Me
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
from app.util.emoji import get_emoji_url from app.util.image import get_image_abs_path
from app.util.file import get_file
from app.util.image import get_image_path, get_image, get_image_abs_path
from app.util.music import get_music_path from app.util.music import get_music_path
@ -296,11 +289,7 @@ class DocxExporter(ExporterBase):
doc = docx.Document() doc = docx.Document()
doc.styles['Normal'].font.name = u'Cambria' doc.styles['Normal'].font.name = u'Cambria'
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体') doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
if self.contact.is_chatroom: messages = msg_db.get_messages(self.contact.wxid)
packagemsg = PackageMsg()
messages = packagemsg.get_package_message_by_wxid(self.contact.wxid)
else:
messages = msg_db.get_messages(self.contact.wxid)
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:

View File

@ -276,11 +276,7 @@ class HtmlExporter(ExporterBase):
) )
def export(self): def export(self):
if self.contact.is_chatroom: messages = msg_db.get_messages(self.contact.wxid)
packagemsg = PackageMsg()
messages = packagemsg.get_package_message_by_wxid(self.contact.wxid)
else:
messages = msg_db.get_messages(self.contact.wxid)
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html" filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html"
file_path = './app/resources/data/template.html' file_path = './app/resources/data/template.html'
if not os.path.exists(file_path): if not os.path.exists(file_path):

View File

@ -114,11 +114,7 @@ class TxtExporter(ExporterBase):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
os.makedirs(origin_docx_path, exist_ok=True) os.makedirs(origin_docx_path, exist_ok=True)
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.txt" filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.txt"
if self.contact.is_chatroom: messages = msg_db.get_messages(self.contact.wxid)
packagemsg = PackageMsg()
messages = packagemsg.get_package_message_by_wxid(self.contact.wxid)
else:
messages = msg_db.get_messages(self.contact.wxid)
total_steps = len(messages) total_steps = len(messages)
with open(filename, mode='w', newline='', encoding='utf-8') as f: with open(filename, mode='w', newline='', encoding='utf-8') as f:
for index, message in enumerate(messages): for index, message in enumerate(messages):

View File

@ -93,6 +93,7 @@ class MicroMsg:
self.cursor.execute(sql, [username]) self.cursor.execute(sql, [username])
result = self.cursor.fetchone() result = self.cursor.fetchone()
except sqlite3.OperationalError: except sqlite3.OperationalError:
# 解决ContactLabel表不存在的问题
# lock.acquire(True) # lock.acquire(True)
sql = ''' sql = '''
SELECT UserName, Alias, Type, Remark, NickName, PYInitial, RemarkPYInitial, ContactHeadImgUrl.smallHeadImgUrl, ContactHeadImgUrl.bigHeadImgUrl,ExTraBuf,"None" SELECT UserName, Alias, Type, Remark, NickName, PYInitial, RemarkPYInitial, ContactHeadImgUrl.smallHeadImgUrl, ContactHeadImgUrl.bigHeadImgUrl,ExTraBuf,"None"

View File

@ -16,6 +16,70 @@ def is_database_exist():
return os.path.exists(db_path) return os.path.exists(db_path)
def parser_chatroom_message(messages):
from app.DataBase import micro_msg_db, misc_db
from app.util.protocbuf.msg_pb2 import MessageBytesExtra
from app.person import Contact, Me, ContactDefault
'''
获取一个群聊的聊天记录
return list
a[0]: localId,
a[1]: talkerId, 和strtalker对应的不是群聊信息发送人
a[2]: type,
a[3]: subType,
a[4]: is_sender,
a[5]: timestamp,
a[6]: status, 没啥用
a[7]: str_content,
a[8]: str_time, 格式化的时间
a[9]: msgSvrId,
a[10]: BytesExtra,
a[11]: CompressContent,
a[12]: msg_sender, ContactPC ContactDefault 类型这个才是群聊里的信息发送人不是群聊或者自己是发送者没有这个字段
'''
updated_messages = [] # 用于存储修改后的消息列表
for row in messages:
message = list(row)
if message[4] == 1: # 自己发送的就没必要解析了
message.append(Me())
updated_messages.append(tuple(message))
continue
if message[10] is None: # BytesExtra是空的跳过
message.append(ContactDefault(wxid))
updated_messages.append(tuple(message))
continue
msgbytes = MessageBytesExtra()
msgbytes.ParseFromString(message[10])
wxid = ''
for tmp in msgbytes.message2:
if tmp.field1 != 1:
continue
wxid = tmp.field2
if wxid == "": # 系统消息里面 wxid 不存在
message.append(ContactDefault(wxid))
updated_messages.append(tuple(message))
continue
contact_info_list = micro_msg_db.get_contact_by_username(wxid)
if contact_info_list is None: # 群聊中已退群的联系人不会保存在数据库里
message.append(ContactDefault(wxid))
updated_messages.append(tuple(message))
continue
contact_info = {
'UserName': contact_info_list[0],
'Alias': contact_info_list[1],
'Type': contact_info_list[2],
'Remark': contact_info_list[3],
'NickName': contact_info_list[4],
'smallHeadImgUrl': contact_info_list[7]
}
contact = Contact(contact_info)
contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG)
message.append(contact)
updated_messages.append(tuple(message))
return updated_messages
def singleton(cls): def singleton(cls):
_instance = {} _instance = {}
@ -105,7 +169,7 @@ class Msg:
result = self.cursor.fetchall() result = self.cursor.fetchall()
finally: finally:
lock.release() lock.release()
return result return parser_chatroom_message(result) if username_.__contains__('@chatroom') else result
# result.sort(key=lambda x: x[5]) # result.sort(key=lambda x: x[5])
# return self.add_sender(result) # return self.add_sender(result)
@ -164,7 +228,7 @@ class Msg:
finally: finally:
lock.release() lock.release()
# result.sort(key=lambda x: x[5]) # result.sort(key=lambda x: x[5])
return result return parser_chatroom_message(result) if username_.__contains__('@chatroom') else result
def get_messages_by_type(self, username_, type_, year_='all'): def get_messages_by_type(self, username_, type_, year_='all'):
if not self.open_flag: if not self.open_flag:
@ -629,14 +693,15 @@ if __name__ == '__main__':
msg.init_database() msg.init_database()
wxid = 'wxid_0o18ef858vnu22' wxid = 'wxid_0o18ef858vnu22'
wxid = '24521163022@chatroom' wxid = '24521163022@chatroom'
wxid = 'wxid_vtz9jk9ulzjt22' # si wxid = 'wxid_vtz9jk9ulzjt22' # si
print() print()
from app.util import compress_content from app.util import compress_content
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
msgs = msg.get_messages(wxid) msgs = msg.get_messages(wxid)
for msg in msgs: for msg in msgs:
if msg[2]==49 and msg[3]==5: if msg[2] == 49 and msg[3] == 5:
xml = compress_content.decompress_CompressContent(msg[11]) xml = compress_content.decompress_CompressContent(msg[11])
root = ET.XML(xml) root = ET.XML(xml)
appmsg = root.find('appmsg') appmsg = root.find('appmsg')
@ -658,4 +723,4 @@ if __name__ == '__main__':
print(thumb) print(thumb)
if tmp.field2 == 4: if tmp.field2 == 4:
app_logo = tmp.field2 app_logo = tmp.field2
print('logo',app_logo) print('logo', app_logo)

View File

@ -110,7 +110,6 @@ class PackageMsg:
a[12]: msg_sender, ContactPC ContactDefault 类型这个才是群聊里的信息发送人不是群聊或者自己是发送者没有这个字段 a[12]: msg_sender, ContactPC ContactDefault 类型这个才是群聊里的信息发送人不是群聊或者自己是发送者没有这个字段
''' '''
updated_messages = [] # 用于存储修改后的消息列表 updated_messages = [] # 用于存储修改后的消息列表
chatroom_members = self.get_chatroom_member_list(chatroom_wxid)
messages = msg_db.get_messages(chatroom_wxid) messages = msg_db.get_messages(chatroom_wxid)
for row in messages: for row in messages:
message = list(row) message = list(row)
@ -150,7 +149,7 @@ class PackageMsg:
contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid) contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG) contact.set_avatar(contact.smallHeadImgBLOG)
message.append(contact) message.append(contact)
updated_messages.append(message) updated_messages.append(tuple(message))
return updated_messages return updated_messages
def get_chatroom_member_list(self, strtalker): def get_chatroom_member_list(self, strtalker):

View File

@ -1,11 +1,12 @@
import os.path import os.path
import subprocess
import platform
from PIL import Image
from PyQt5 import QtGui from PyQt5 import QtGui
from PyQt5.QtCore import QSize, pyqtSignal, Qt, QThread from PyQt5.QtCore import QSize, pyqtSignal, Qt, QThread
from PyQt5.QtGui import QPainter, QFont, QColor, QPixmap, QPolygon, QFontMetrics from PyQt5.QtGui import QPainter, QFont, QColor, QPixmap, QPolygon, QFontMetrics
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QVBoxLayout, QSpacerItem, \ from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QVBoxLayout, QSpacerItem, \
QScrollArea, QScrollBar QScrollArea
from app.components.scroll_bar import ScrollBar from app.components.scroll_bar import ScrollBar
@ -83,7 +84,7 @@ class Notice(QLabel):
def __init__(self, text, type_=3, parent=None): def __init__(self, text, type_=3, parent=None):
super().__init__(text, parent) super().__init__(text, parent)
self.type_ = type_ self.type_ = type_
self.setFont(QFont('微软雅黑', 12)) self.setFont(QFont('微软雅黑', 10))
self.setWordWrap(True) self.setWordWrap(True)
self.setTextInteractionFlags(Qt.TextSelectableByMouse) self.setTextInteractionFlags(Qt.TextSelectableByMouse)
self.setAlignment(Qt.AlignCenter) self.setAlignment(Qt.AlignCenter)
@ -100,6 +101,19 @@ class Avatar(QLabel):
self.setFixedSize(QSize(45, 45)) self.setFixedSize(QSize(45, 45))
def open_image_viewer(file_path):
system_platform = platform.system()
if system_platform == "Darwin": # macOS
subprocess.run(["open", file_path])
elif system_platform == "Windows":
subprocess.run(["start", " ", file_path], shell=True)
elif system_platform == "Linux":
subprocess.run(["xdg-open", file_path])
else:
print("Unsupported platform")
class OpenImageThread(QThread): class OpenImageThread(QThread):
def __init__(self, image_path): def __init__(self, image_path):
super().__init__() super().__init__()
@ -107,8 +121,7 @@ class OpenImageThread(QThread):
def run(self) -> None: def run(self) -> None:
if os.path.exists(self.image_path): if os.path.exists(self.image_path):
image = Image.open(self.image_path) open_image_viewer(self.image_path)
image.show()
class ImageMessage(QLabel): class ImageMessage(QLabel):
@ -121,6 +134,9 @@ class ImageMessage(QLabel):
self.image = QLabel(self) self.image = QLabel(self)
self.max_width = max_width self.max_width = max_width
self.max_height = max_height self.max_height = max_height
# self.setFixedSize(self.max_width,self.max_height)
self.setMaximumWidth(self.max_width)
self.setMaximumHeight(self.max_height)
if isinstance(image, str): if isinstance(image, str):
pixmap = QPixmap(image) pixmap = QPixmap(image)
self.image_path = image self.image_path = image
@ -129,8 +145,7 @@ class ImageMessage(QLabel):
self.set_image(pixmap) self.set_image(pixmap)
if image_link: if image_link:
self.image_path = image_link self.image_path = image_link
self.setMaximumWidth(self.max_width)
self.setMaximumHeight(self.max_height)
if is_send: if is_send:
self.setAlignment(Qt.AlignCenter | Qt.AlignRight) self.setAlignment(Qt.AlignCenter | Qt.AlignRight)
# self.setScaledContents(True) # self.setScaledContents(True)
@ -151,7 +166,7 @@ class ImageMessage(QLabel):
class BubbleMessage(QWidget): class BubbleMessage(QWidget):
def __init__(self, str_content, avatar, Type, is_send=False, parent=None): def __init__(self, str_content, avatar, Type,is_send=False, display_name=None, parent=None):
super().__init__(parent) super().__init__(parent)
self.isSend = is_send self.isSend = is_send
# self.set # self.set
@ -173,17 +188,30 @@ class BubbleMessage(QWidget):
self.message = ImageMessage(str_content, is_send) self.message = ImageMessage(str_content, is_send)
else: else:
raise ValueError("未知的消息类型") raise ValueError("未知的消息类型")
if display_name:
label_name = QLabel(display_name,self)
if is_send:
label_name.setAlignment(Qt.AlignRight)
vlayout = QVBoxLayout()
vlayout.setSpacing(0)
vlayout.addWidget(label_name)
vlayout.addWidget(self.message)
self.spacerItem = QSpacerItem(45 + 6, 45, QSizePolicy.Expanding, QSizePolicy.Minimum) self.spacerItem = QSpacerItem(45 + 6, 45, QSizePolicy.Expanding, QSizePolicy.Minimum)
if is_send: if is_send:
layout.addItem(self.spacerItem) layout.addItem(self.spacerItem)
layout.addWidget(self.message, 1) if display_name:
layout.addLayout(vlayout,1)
else:
layout.addWidget(self.message, 1)
layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignLeft) layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignLeft)
layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignLeft) layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignLeft)
else: else:
layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignRight) layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignRight)
layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignRight) layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignRight)
layout.addWidget(self.message, 1) if display_name:
layout.addLayout(vlayout,1)
else:
layout.addWidget(self.message, 1)
layout.addItem(self.spacerItem) layout.addItem(self.spacerItem)
self.setLayout(layout) self.setLayout(layout)
@ -206,8 +234,6 @@ class ScrollArea(QScrollArea):
) )
class ChatWidget(QWidget): class ChatWidget(QWidget):
def __init__(self): def __init__(self):
super().__init__() super().__init__()

View File

@ -47,8 +47,9 @@ class Person:
os.makedirs('./data/avatar', exist_ok=True) os.makedirs('./data/avatar', exist_ok=True)
save_path = os.path.join(f'data/avatar/', self.wxid + '.png') save_path = os.path.join(f'data/avatar/', self.wxid + '.png')
self.avatar_path = save_path self.avatar_path = save_path
self.avatar.save(save_path) if not os.path.exists(save_path):
print('保存头像', save_path) self.avatar.save(save_path)
print('保存头像', save_path)
@singleton @singleton

View File

@ -36,6 +36,8 @@ class ChatInfo(QWidget):
self.setLayout(self.vBoxLayout) self.setLayout(self.vBoxLayout)
def show_chats(self): def show_chats(self):
# Me().save_avatar()
# self.contact.save_avatar()
self.show_chat_thread = ShowChatThread(self.contact) self.show_chat_thread = ShowChatThread(self.contact)
self.show_chat_thread.showSingal.connect(self.add_message) self.show_chat_thread.showSingal.connect(self.add_message)
self.show_chat_thread.finishSingal.connect(self.show_finish) self.show_chat_thread.finishSingal.connect(self.show_finish)
@ -79,6 +81,29 @@ class ChatInfo(QWidget):
return True return True
return False return False
def get_avatar_path(self, is_send, message, is_absolute_path=False) -> str:
if self.contact.is_chatroom:
avatar = message[12].smallHeadImgUrl
else:
avatar = Me().smallHeadImgUrl if is_send else self.contact.smallHeadImgUrl
if is_absolute_path:
if self.contact.is_chatroom:
# message[12].save_avatar()
avatar = message[12].avatar
else:
avatar = Me().avatar if is_send else self.contact.avatar
return avatar
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 = None
return display_name
def add_message(self, message): def add_message(self, message):
try: try:
type_ = message[2] type_ = message[2]
@ -86,7 +111,8 @@ class ChatInfo(QWidget):
str_time = message[8] str_time = message[8]
# print(type_, type(type_)) # print(type_, type(type_))
is_send = message[4] is_send = message[4]
avatar = Me().avatar if is_send else self.contact.avatar avatar = self.get_avatar_path(is_send, message,True)
display_name = self.get_display_name(is_send, message)
timestamp = message[5] timestamp = message[5]
BytesExtra = message[10] BytesExtra = message[10]
if type_ == 1: if type_ == 1:
@ -98,7 +124,8 @@ class ChatInfo(QWidget):
str_content, str_content,
avatar, avatar,
type_, type_,
is_send is_send,
display_name=display_name
) )
self.chat_window.add_message_item(bubble_message, 0) self.chat_window.add_message_item(bubble_message, 0)
elif type_ == 3: elif type_ == 3:
@ -107,7 +134,7 @@ class ChatInfo(QWidget):
time_message = Notice(self.last_str_time) time_message = Notice(self.last_str_time)
self.last_str_time = str_time self.last_str_time = str_time
self.chat_window.add_message_item(time_message, 0) self.chat_window.add_message_item(time_message, 0)
image_path = hard_link_db.get_image(content=str_content,bytesExtra=BytesExtra, thumb=False) image_path = hard_link_db.get_image(content=str_content, bytesExtra=BytesExtra, thumb=False)
image_path = get_abs_path(image_path) image_path = get_abs_path(image_path)
bubble_message = BubbleMessage( bubble_message = BubbleMessage(
image_path, image_path,
@ -132,7 +159,7 @@ class ChatInfo(QWidget):
self.chat_window.add_message_item(bubble_message, 0) self.chat_window.add_message_item(bubble_message, 0)
elif type_ == 10000: elif type_ == 10000:
str_content = str_content.lstrip('<revokemsg>').rstrip('</revokemsg>') str_content = str_content.lstrip('<revokemsg>').rstrip('</revokemsg>')
message = Notice(str_content ) message = Notice(str_content)
self.chat_window.add_message_item(message, 0) self.chat_window.add_message_item(message, 0)
except: except:
print(message) print(message)

View File

@ -79,10 +79,7 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow,QCursorGif):
self.outputThread0 = None self.outputThread0 = None
self.outputThread = None self.outputThread = None
self.setupUi(self) self.setupUi(self)
# 设置忙碌光标图片数组
self.initCursor([':/icons/icons/Cursors/%d.png' %
i for i in range(8)])
self.setCursorTimeout(100)
# self.setWindowIcon(Icon.MainWindow_Icon) # self.setWindowIcon(Icon.MainWindow_Icon)
pixmap = QPixmap(Icon.logo_ico_path) pixmap = QPixmap(Icon.logo_ico_path)
icon = QIcon(pixmap) icon = QIcon(pixmap)
@ -97,6 +94,14 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow,QCursorGif):
self.label = QLabel(self) self.label = QLabel(self)
self.label.setGeometry((self.width() - 300) // 2, (self.height() - 100) // 2, 300, 100) self.label.setGeometry((self.width() - 300) // 2, (self.height() - 100) // 2, 300, 100)
self.label.setPixmap(QPixmap(':/icons/icons/loading.svg')) self.label.setPixmap(QPixmap(':/icons/icons/loading.svg'))
self.menu_output.setIcon(Icon.Output)
self.action_output_CSV.setIcon(Icon.ToCSV)
self.action_output_CSV.triggered.connect(self.output)
self.action_output_contacts.setIcon(Icon.Output)
self.action_output_contacts.triggered.connect(self.output)
self.action_batch_export.setIcon(Icon.Output)
self.action_batch_export.triggered.connect(self.output)
self.action_desc.setIcon(Icon.Help_Icon)
def load_data(self, flag=True): def load_data(self, flag=True):
if os.path.exists('./app/data/info.json'): if os.path.exists('./app/data/info.json'):
@ -119,15 +124,15 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow,QCursorGif):
) )
def init_ui(self): def init_ui(self):
# 设置忙碌光标图片数组
self.initCursor([':/icons/icons/Cursors/%d.png' %
i for i in range(8)])
self.setCursorTimeout(100)
self.startBusy() self.startBusy()
self.menu_output.setIcon(Icon.Output)
self.action_output_CSV.setIcon(Icon.ToCSV)
self.action_output_CSV.triggered.connect(self.output)
self.action_output_contacts.setIcon(Icon.Output)
self.action_output_contacts.triggered.connect(self.output)
self.action_batch_export.setIcon(Icon.Output)
self.action_batch_export.triggered.connect(self.output)
self.action_desc.setIcon(Icon.Help_Icon)
self.action_help_contact.triggered.connect( self.action_help_contact.triggered.connect(
lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5"))) lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5")))
self.action_help_chat.triggered.connect( self.action_help_chat.triggered.connect(

View File

@ -130,7 +130,7 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog, QCursorGif):
return return
if self.info.get('key') == 'None': if self.info.get('key') == 'None':
QMessageBox.critical(self, "错误", QMessageBox.critical(self, "错误",
"密钥错误\n将软件放在桌面上试试\n如果还不可以的话我也我能为力,您可以等待后续版本解决该问题") "密钥错误\n请查看教程解决相关问题")
close_db() close_db()
self.thread2 = DecryptThread(db_dir, self.info['key']) self.thread2 = DecryptThread(db_dir, self.info['key'])
self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum) self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum)
@ -232,11 +232,13 @@ class DecryptThread(QThread):
try: try:
shutil.copy2("app/DataBase/Msg/MSG0.db", target_database) # 使用一个数据库文件作为模板 shutil.copy2("app/DataBase/Msg/MSG0.db", target_database) # 使用一个数据库文件作为模板
except FileNotFoundError: except FileNotFoundError:
logger.error(traceback.format_exc())
self.errorSignal.emit(True) self.errorSignal.emit(True)
# 合并数据库 # 合并数据库
try: try:
merge_databases(source_databases, target_database) merge_databases(source_databases, target_database)
except FileNotFoundError: except FileNotFoundError:
logger.error(traceback.format_exc())
QMessageBox.critical("错误", "数据库不存在\n请检查微信版本是否为最新") QMessageBox.critical("错误", "数据库不存在\n请检查微信版本是否为最新")
# 音频数据库文件 # 音频数据库文件
@ -248,11 +250,13 @@ class DecryptThread(QThread):
try: try:
shutil.copy2("app/DataBase/Msg/MediaMSG0.db", target_database) # 使用一个数据库文件作为模板 shutil.copy2("app/DataBase/Msg/MediaMSG0.db", target_database) # 使用一个数据库文件作为模板
except FileNotFoundError: except FileNotFoundError:
logger.error(traceback.format_exc())
self.errorSignal.emit(True) self.errorSignal.emit(True)
# 合并数据库 # 合并数据库
try: try:
merge_MediaMSG_databases(source_databases, target_database) merge_MediaMSG_databases(source_databases, target_database)
except FileNotFoundError: except FileNotFoundError:
logger.error(traceback.format_exc())
QMessageBox.critical("错误", "数据库不存在\n请检查微信版本是否为最新") QMessageBox.critical("错误", "数据库不存在\n请检查微信版本是否为最新")
self.okSignal.emit('ok') self.okSignal.emit('ok')
# self.signal.emit('100') # self.signal.emit('100')

26
main.py
View File

@ -3,19 +3,6 @@ import sys
import time import time
import traceback import traceback
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from app.DataBase import close_db
from app.log import logger
from app.ui import mainview
from app.ui.tool.pc_decrypt import pc_decrypt
from app.config import version
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
widget = None widget = None
@ -35,6 +22,19 @@ def excepthook(exc_type, exc_value, traceback_):
# 设置 excepthook # 设置 excepthook
sys.excepthook = excepthook sys.excepthook = excepthook
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from app.DataBase import close_db
from app.log import logger
from app.ui import mainview
from app.ui.tool.pc_decrypt import pc_decrypt
from app.config import version
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
class ViewController(QWidget): class ViewController(QWidget):

View File

@ -272,6 +272,7 @@ python main.py
- [STDquantum](https://github.com/STDquantum) - [STDquantum](https://github.com/STDquantum)
- [xuanli](https://github.com/xuanli) - [xuanli](https://github.com/xuanli)
- [无名路人](https://github.com/wumingluren)
如果您提供赞助并希望出现在赞助者名单中,请在提交赞助时提供您的 GitHub 用户名或其他相关信息。 如果您提供赞助并希望出现在赞助者名单中,请在提交赞助时提供您的 GitHub 用户名或其他相关信息。

View File

@ -7,7 +7,6 @@ silk-python
pyaudio pyaudio
fuzzywuzzy fuzzywuzzy
python-Levenshtein python-Levenshtein
Pillow==10.1.0
requests requests
flask==3.0.0 flask==3.0.0
pyecharts==2.0.1 pyecharts==2.0.1