diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 6917363..252c68f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,6 +6,7 @@ labels: '' assignees: '' --- +**是否检查过issues没有相同问题** **bug描述** A clear and concise description of what the bug is. diff --git a/app/DataBase/msg.py b/app/DataBase/msg.py index 9afc005..75f7cc7 100644 --- a/app/DataBase/msg.py +++ b/app/DataBase/msg.py @@ -104,7 +104,6 @@ class Msg: lock.release() return result[0] - def get_message_by_num(self, username_, local_id): sql = ''' select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime @@ -205,7 +204,7 @@ class Msg: finally: lock.release() return result - + def get_messages_by_month(self, username_, year_='2023'): sql = ''' SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID) @@ -226,7 +225,6 @@ class Msg: lock.release() # result.sort(key=lambda x: x[5]) return result - def get_first_time_of_message(self, username_): if not self.open_flag: @@ -271,4 +269,4 @@ if __name__ == '__main__': pprint(msg.get_message_by_num('wxid_0o18ef858vnu22', local_id)) print(msg.get_messages_by_keyword(wxid, '干嘛')) pprint(msg.get_messages_by_keyword(wxid, '干嘛')[0]) - print(msg.get_first_time_of_message('wxid_0o18ef858vnu22')) \ No newline at end of file + print(msg.get_first_time_of_message('wxid_0o18ef858vnu22')) diff --git a/app/DataBase/output_pc.py b/app/DataBase/output_pc.py index 76dc719..2934e38 100644 --- a/app/DataBase/output_pc.py +++ b/app/DataBase/output_pc.py @@ -3,8 +3,9 @@ import html import os from PyQt5.QtCore import pyqtSignal, QThread +from PyQt5.QtWidgets import QFileDialog -from . import msg_db +from . import msg_db, micro_msg_db from .package_msg import PackageMsg from ..DataBase import hard_link_db from ..person_pc import MePC @@ -14,7 +15,7 @@ os.makedirs('./data/聊天记录', exist_ok=True) def makedirs(path): - os.makedirs(path,exist_ok=True) + 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) @@ -52,6 +53,7 @@ class Output(QThread): DOCX = 1 HTML = 2 CSV_ALL = 3 + CONTACT_CSV = 4 def __init__(self, contact, parent=None, type_=DOCX): super().__init__(parent) @@ -71,12 +73,15 @@ class Output(QThread): def to_csv_all(self): origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/" os.makedirs(origin_docx_path, exist_ok=True) - filename = f"{os.path.abspath('.')}/data/聊天记录/messages.csv" + filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(),'messages.csv'), "csv files (*.csv);;all files(*.*)") + if not filename: + return + filename = filename[0] # columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"] columns = ['localId', 'TalkerId', 'Type', 'SubType', 'IsSender', 'CreateTime', 'Status', 'StrContent', 'StrTime', 'Remark', 'NickName', 'Sender'] - # messages = msg_db.get_messages_all() + packagemsg = PackageMsg() messages = packagemsg.get_package_message_all() # 写入CSV文件 @@ -87,11 +92,29 @@ class Output(QThread): writer.writerows(messages) self.okSignal.emit(1) + def contact_to_csv(self): + filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(),'contacts.csv'), "csv files (*.csv);;all files(*.*)") + if not filename: + return + filename = filename[0] + # columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"] + columns = ['UserName','Alias', 'Type', 'Remark', 'NickName', 'PYInitial', 'RemarkPYInitial', 'smallHeadImgUrl', 'bigHeadImgUrl'] + contacts = micro_msg_db.get_contact() + # 写入CSV文件 + with open(filename, mode='w', newline='', encoding='utf-8') as file: + writer = csv.writer(file) + writer.writerow(columns) + # 写入数据 + writer.writerows(contacts) + self.okSignal.emit(1) + def run(self): if self.output_type == self.DOCX: return elif self.output_type == self.CSV_ALL: self.to_csv_all() + elif self.output_type == self.CONTACT_CSV: + self.contact_to_csv() else: self.Child = ChildThread(self.contact, type_=self.output_type) self.Child.progressSignal.connect(self.progress) diff --git a/app/analysis/analysis.py b/app/analysis/analysis.py index c96b209..87d5cad 100644 --- a/app/analysis/analysis.py +++ b/app/analysis/analysis.py @@ -6,10 +6,8 @@ import sys sys.path.append('.') from app.DataBase import msg_db, MsgType -from app.person_pc import ContactPC -import jieba from pyecharts import options as opts -from pyecharts.charts import Pie, WordCloud, Calendar, Bar, Line, Timeline, Grid +from pyecharts.charts import WordCloud, Calendar, Bar from app.resources import resource_rc var = resource_rc.qt_resource_name diff --git a/app/ui_pc/mainview.py b/app/ui_pc/mainview.py index 82db6d7..f6d8e89 100644 --- a/app/ui_pc/mainview.py +++ b/app/ui_pc/mainview.py @@ -102,6 +102,8 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow): 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_desc.setIcon(Icon.Help_Icon) self.action_help_contact.triggered.connect( lambda: QDesktopServices.openUrl(QUrl("https://blog.lc044.love/post/5"))) @@ -192,7 +194,12 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow): if self.sender() == self.action_output_CSV: self.outputThread = Output(None, type_=Output.CSV_ALL) self.outputThread.okSignal.connect( - lambda x: self.message('聊天记录导出成功\n./data/聊天记录/messages.csv')) + lambda x: self.message('聊天记录导出成功')) + self.outputThread.start() + elif self.sender() == self.action_output_contacts: + self.outputThread = Output(None, type_=Output.CONTACT_CSV) + self.outputThread.okSignal.connect( + lambda x: self.message('联系人导出成功')) self.outputThread.start() def message(self, msg): diff --git a/app/ui_pc/mainwindow.py b/app/ui_pc/mainwindow.py index a970c2f..20e242c 100644 --- a/app/ui_pc/mainwindow.py +++ b/app/ui_pc/mainwindow.py @@ -16,31 +16,31 @@ class Ui_MainWindow(object): MainWindow.setObjectName("MainWindow") MainWindow.resize(1280, 779) MainWindow.setStyleSheet("\n" - " /*去掉item虚线边框*/\n" - " QListWidget, QListView, QTreeWidget, QTreeView {\n" - " outline: 0px;\n" - " }\n" - " /*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/\n" - " QListWidget {\n" - " min-width: 120px;\n" - " max-width: 120px;\n" - " color: black;\n" - " background: white;\n" - " border:none;\n" - " }\n" - " QListWidget::item{\n" - " height:80;\n" - " }\n" - " /*被选中时的背景颜色和左边框颜色*/\n" - " QListWidget::item:selected {\n" - " background: rgb(204, 204, 204);\n" - " border-left: 4px solid rgb(9, 187, 7);\n" - " }\n" - " /*鼠标悬停颜色*/\n" - " HistoryPanel::item:hover {\n" - " background: rgb(52, 52, 52);\n" - " }\n" - " ") +" /*去掉item虚线边框*/\n" +" QListWidget, QListView, QTreeWidget, QTreeView {\n" +" outline: 0px;\n" +" }\n" +" /*设置左侧选项的最小最大宽度,文字颜色和背景颜色*/\n" +" QListWidget {\n" +" min-width: 120px;\n" +" max-width: 120px;\n" +" color: black;\n" +" background: white;\n" +" border:none;\n" +" }\n" +" QListWidget::item{\n" +" height:80;\n" +" }\n" +" /*被选中时的背景颜色和左边框颜色*/\n" +" QListWidget::item:selected {\n" +" background: rgb(204, 204, 204);\n" +" border-left: 4px solid rgb(9, 187, 7);\n" +" }\n" +" /*鼠标悬停颜色*/\n" +" HistoryPanel::item:hover {\n" +" background: rgb(52, 52, 52);\n" +" }\n" +" ") self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) @@ -124,12 +124,15 @@ class Ui_MainWindow(object): self.action_help_contact.setObjectName("action_help_contact") self.action_output_CSV = QtWidgets.QAction(MainWindow) self.action_output_CSV.setObjectName("action_output_CSV") + self.action_output_contacts = QtWidgets.QAction(MainWindow) + self.action_output_contacts.setObjectName("action_output_contacts") self.menu_F.addSeparator() self.menu_F.addSeparator() self.menu_F.addAction(self.action_3) self.menu_F.addAction(self.action_4) self.menu_output.addAction(self.action_output_CSV) self.menu_data.addAction(self.menu_output.menuAction()) + self.menu_data.addAction(self.action_output_contacts) self.menu_2.addAction(self.action_help_decrypt) self.menu_2.addAction(self.action_help_chat) self.menu_2.addAction(self.action_help_contact) @@ -173,3 +176,4 @@ class Ui_MainWindow(object): self.action_help_chat.setText(_translate("MainWindow", "聊天相关")) self.action_help_contact.setText(_translate("MainWindow", "好友相关")) self.action_output_CSV.setText(_translate("MainWindow", "CSV")) + self.action_output_contacts.setText(_translate("MainWindow", "导出联系人")) diff --git a/app/ui_pc/mainwindow.ui b/app/ui_pc/mainwindow.ui index 358342e..45f1ad3 100644 --- a/app/ui_pc/mainwindow.ui +++ b/app/ui_pc/mainwindow.ui @@ -1,20 +1,20 @@ - MainWindow - - - - 0 - 0 - 1280 - 779 - - - - MainWindow - - - + MainWindow + + + + 0 + 0 + 1280 + 779 + + + + MainWindow + + + /*去掉item虚线边框*/ QListWidget, QListView, QTreeWidget, QTreeView { outline: 0px; @@ -40,233 +40,239 @@ background: rgb(52, 52, 52); } + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 80 + 500 + + + + + 80 + 16777215 + + + + background-color:rgb(240,240,240) + + + QFrame::NoFrame + + + QFrame::Plain + + + + + 10 + 40 + 60 + 60 + + + + avatar + + + + + + 0 + 230 + 120 + 331 + + + + + 120 + 0 + + + + + 120 + 16777215 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustIgnored + + + + 新建项目 - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 80 - 500 - - - - - 80 - 16777215 - - - - background-color:rgb(240,240,240) - - - QFrame::NoFrame - - - QFrame::Plain - - - - - 10 - 40 - 60 - 60 - - - - avatar - - - - - - 0 - 230 - 120 - 331 - - - - - 120 - 0 - - - - - 120 - 16777215 - - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustIgnored - - - - 新建项目 - - - - - 新建项目 - - - - - 新建项目 - - - - - 新建项目 - - - - - 新建项目 - - - - - - - - - - 微软雅黑 - 50 - false - - - - - - - - - - 0 - 0 - 1280 - 23 - - - - - 文件(F) - - - - - - - - - - 微软雅黑 - - - - 数据 - - - - 导出聊天记录(全部) - - - - - - - - 帮助 - - - - - - - - 关于 - - - - - - 不显示或者显示异常请重启应用、没反应那就多等一会儿 - - - - - - - - - - - - 保存 - - - - - 退出 - - - - - 解密教程 - - - - Microsoft YaHei UI - - - - - - 说明 - - - - - 聊天相关 - - - - - 好友相关 - - - - - CSV - - + + + + 新建项目 + + + + + 新建项目 + + + + + 新建项目 + + + + + 新建项目 + + + + + + + + + + 微软雅黑 + 50 + false + + + + + + + + + + 0 + 0 + 1280 + 23 + + + + + 文件(F) + + + + + + + + + + 微软雅黑 + + + + 数据 + + + + 导出聊天记录(全部) + + - - + + + + + + 帮助 + + + + + + + + 关于 + + + + + + 不显示或者显示异常请重启应用、没反应那就多等一会儿 + + + + + + + + + + + + 保存 + + + + + 退出 + + + + + 解密教程 + + + + Microsoft YaHei UI + + + + + + 说明 + + + + + 聊天相关 + + + + + 好友相关 + + + + + CSV + + + + + 导出联系人 + + + + + diff --git a/app/web_ui/web.py b/app/web_ui/web.py index 5a5c7a6..1f48924 100644 --- a/app/web_ui/web.py +++ b/app/web_ui/web.py @@ -1,11 +1,8 @@ -import json import os import sys from flask import Flask, render_template, send_file -from pyecharts import options as opts -from pyecharts.charts import Bar -from pyecharts.globals import ThemeType + from app.DataBase import msg_db from app.analysis import analysis @@ -19,25 +16,8 @@ contact: ContactPC = None @app.route("/") def index(): - # 创建一个简单的柱状图 - bar = ( - Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)) - .add_xaxis(["A", "B", "C", "D", "E"]) - .add_yaxis("Series", [5, 20, 36, 10, 75]) - .set_global_opts(title_opts=opts.TitleOpts(title="Flask and Pyecharts Interaction")) - ) - - # 将图表转换成 HTML - chart_html = bar.render_embed() - # 渲染模板,并传递图表的 HTML 到模板中 - return render_template("index.html", chart_html=chart_html) - - -@app.route("/index") -def index0(): - return render_template("index1.html") - + return render_template("index.html") @app.route('/home') def home():