2023-11-20 22:30:31 +08:00
|
|
|
|
import json
|
2023-11-12 21:51:33 +08:00
|
|
|
|
import os.path
|
|
|
|
|
import time
|
2023-11-20 19:08:11 +08:00
|
|
|
|
import traceback
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
2023-11-23 22:58:27 +08:00
|
|
|
|
from PyQt5.QtCore import pyqtSignal, QThread, QUrl, QFile, QIODevice, QTextStream
|
2023-11-22 23:14:49 +08:00
|
|
|
|
from PyQt5.QtGui import QDesktopServices
|
2023-11-22 22:31:34 +08:00
|
|
|
|
from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
2023-12-01 22:37:45 +08:00
|
|
|
|
from app.DataBase import msg_db, misc_db
|
2023-11-29 21:23:44 +08:00
|
|
|
|
from app.DataBase.merge import merge_databases
|
2023-11-12 21:51:33 +08:00
|
|
|
|
from app.decrypt import get_wx_info, decrypt
|
2023-11-20 19:08:11 +08:00
|
|
|
|
from app.log import logger
|
2023-11-29 23:41:02 +08:00
|
|
|
|
from app.util import path
|
2023-11-12 21:51:33 +08:00
|
|
|
|
from . import decryptUi
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DecryptControl(QWidget, decryptUi.Ui_Dialog):
|
2023-11-25 00:20:35 +08:00
|
|
|
|
DecryptSignal = pyqtSignal(bool)
|
2023-11-17 23:02:40 +08:00
|
|
|
|
get_wxidSignal = pyqtSignal(str)
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
|
|
|
|
def __init__(self, parent=None):
|
|
|
|
|
super(DecryptControl, self).__init__(parent)
|
|
|
|
|
self.setupUi(self)
|
2023-11-22 23:14:49 +08:00
|
|
|
|
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.pushButton_3.clicked.connect(self.decrypt)
|
|
|
|
|
self.btn_getinfo.clicked.connect(self.get_info)
|
|
|
|
|
self.btn_db_dir.clicked.connect(self.select_db_dir)
|
2023-11-20 00:20:00 +08:00
|
|
|
|
self.lineEdit.returnPressed.connect(self.set_wxid)
|
|
|
|
|
self.lineEdit.textChanged.connect(self.set_wxid_)
|
2023-11-22 23:14:49 +08:00
|
|
|
|
self.btn_help.clicked.connect(self.show_help)
|
2023-12-01 22:37:45 +08:00
|
|
|
|
self.label_tip.setVisible(False)
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.info = {}
|
2023-11-14 22:52:18 +08:00
|
|
|
|
self.lineEdit.setFocus()
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.ready = False
|
|
|
|
|
self.wx_dir = None
|
|
|
|
|
|
2023-11-22 23:14:49 +08:00
|
|
|
|
def show_help(self):
|
|
|
|
|
# 定义网页链接
|
2023-11-27 19:19:37 +08:00
|
|
|
|
url = QUrl("https://blog.lc044.love/post/4")
|
2023-11-22 23:14:49 +08:00
|
|
|
|
# 使用QDesktopServices打开网页
|
|
|
|
|
QDesktopServices.openUrl(url)
|
|
|
|
|
|
2023-11-14 22:52:18 +08:00
|
|
|
|
# @log
|
2023-11-12 21:51:33 +08:00
|
|
|
|
def get_info(self):
|
|
|
|
|
try:
|
2023-11-23 22:58:27 +08:00
|
|
|
|
file = QFile(':/data/version_list.json')
|
|
|
|
|
if file.open(QIODevice.ReadOnly | QIODevice.Text):
|
|
|
|
|
stream = QTextStream(file)
|
|
|
|
|
content = stream.readAll()
|
|
|
|
|
file.close()
|
|
|
|
|
VERSION_LIST = json.loads(content)
|
|
|
|
|
else:
|
|
|
|
|
return
|
|
|
|
|
result = get_wx_info.get_info(VERSION_LIST)
|
2023-11-20 22:30:31 +08:00
|
|
|
|
print(result)
|
2023-11-14 22:52:18 +08:00
|
|
|
|
if result == -1:
|
|
|
|
|
QMessageBox.critical(self, "错误", "请登录微信")
|
|
|
|
|
elif result == -2:
|
|
|
|
|
QMessageBox.critical(self, "错误", "微信版本不匹配\n请更新微信版本为:3.9.8.15")
|
2023-11-20 22:30:31 +08:00
|
|
|
|
elif result == -3:
|
|
|
|
|
QMessageBox.critical(self, "错误", "WeChat WeChatWin.dll Not Found")
|
2023-11-14 22:52:18 +08:00
|
|
|
|
else:
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.ready = True
|
|
|
|
|
self.info = result[0]
|
|
|
|
|
self.label_key.setText(self.info['key'])
|
2023-11-14 22:52:18 +08:00
|
|
|
|
self.lineEdit.setText(self.info['wxid'])
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.label_name.setText(self.info['name'])
|
|
|
|
|
self.label_phone.setText(self.info['mobile'])
|
|
|
|
|
self.label_pid.setText(str(self.info['pid']))
|
|
|
|
|
self.label_version.setText(self.info['version'])
|
2023-11-14 22:52:18 +08:00
|
|
|
|
self.lineEdit.setFocus()
|
2023-11-16 23:56:36 +08:00
|
|
|
|
self.checkBox.setChecked(True)
|
2023-11-17 23:02:40 +08:00
|
|
|
|
self.get_wxidSignal.emit(self.info['wxid'])
|
2023-11-29 23:41:02 +08:00
|
|
|
|
directory = os.path.join(path.wx_path(), self.info['wxid'])
|
|
|
|
|
if os.path.exists(directory):
|
|
|
|
|
self.label_db_dir.setText(directory)
|
|
|
|
|
self.wx_dir = directory
|
|
|
|
|
self.checkBox_2.setChecked(True)
|
|
|
|
|
self.ready = True
|
|
|
|
|
if self.ready:
|
|
|
|
|
self.label_ready.setText('已就绪')
|
2023-11-20 22:30:31 +08:00
|
|
|
|
if self.wx_dir and os.path.exists(os.path.join(self.wx_dir)):
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.label_ready.setText('已就绪')
|
|
|
|
|
except Exception as e:
|
2023-12-03 00:03:00 +08:00
|
|
|
|
QMessageBox.critical(self, "未知错误", "请收集报错信息,发起issue解决问题")
|
2023-11-20 19:08:11 +08:00
|
|
|
|
logger.error(traceback.format_exc())
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
2023-11-20 00:20:00 +08:00
|
|
|
|
def set_wxid_(self):
|
|
|
|
|
self.info['wxid'] = self.lineEdit.text()
|
|
|
|
|
|
|
|
|
|
def set_wxid(self):
|
|
|
|
|
self.info['wxid'] = self.lineEdit.text()
|
|
|
|
|
QMessageBox.information(self, "ok", f"wxid修改成功{self.info['wxid']}")
|
|
|
|
|
|
2023-11-12 21:51:33 +08:00
|
|
|
|
def select_db_dir(self):
|
2023-11-22 22:31:34 +08:00
|
|
|
|
directory = QFileDialog.getExistingDirectory(
|
2023-11-29 22:57:58 +08:00
|
|
|
|
self, "选取微信文件保存目录——能看到Msg文件夹",
|
2023-11-29 23:41:02 +08:00
|
|
|
|
path.wx_path()
|
2023-11-29 22:57:58 +08:00
|
|
|
|
) # 起始路径
|
2023-11-20 22:30:31 +08:00
|
|
|
|
db_dir = os.path.join(directory, 'Msg')
|
|
|
|
|
if not os.path.exists(db_dir):
|
|
|
|
|
QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.label_db_dir.setText(directory)
|
|
|
|
|
self.wx_dir = directory
|
|
|
|
|
self.checkBox_2.setChecked(True)
|
|
|
|
|
if self.ready:
|
|
|
|
|
self.label_ready.setText('已就绪')
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
|
|
|
|
def decrypt(self):
|
|
|
|
|
if not self.ready:
|
|
|
|
|
QMessageBox.critical(self, "错误", "请先获取密钥")
|
|
|
|
|
return
|
2023-11-14 22:52:18 +08:00
|
|
|
|
if not self.wx_dir:
|
|
|
|
|
QMessageBox.critical(self, "错误", "请先选择微信安装路径")
|
|
|
|
|
return
|
|
|
|
|
if self.lineEdit.text() == 'None':
|
|
|
|
|
QMessageBox.critical(self, "错误", "请填入wxid")
|
|
|
|
|
return
|
2023-11-20 22:30:31 +08:00
|
|
|
|
db_dir = os.path.join(self.wx_dir, 'Msg')
|
2023-11-12 21:51:33 +08:00
|
|
|
|
if self.ready:
|
2023-11-20 22:30:31 +08:00
|
|
|
|
if not os.path.exists(db_dir):
|
|
|
|
|
QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾")
|
2023-11-12 21:51:33 +08:00
|
|
|
|
return
|
2023-12-05 20:53:32 +08:00
|
|
|
|
if self.info.get('key') == 'none':
|
|
|
|
|
QMessageBox.critical(self, "错误", "密钥错误\n请检查微信版本是否为最新")
|
2023-12-01 22:37:45 +08:00
|
|
|
|
self.label_tip.setVisible(True)
|
|
|
|
|
self.label_tip.setText('点我之后没有反应那就多等儿吧,不要再点了')
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.thread2 = DecryptThread(db_dir, self.info['key'])
|
|
|
|
|
self.thread2.maxNumSignal.connect(self.setProgressBarMaxNum)
|
|
|
|
|
self.thread2.signal.connect(self.progressBar_view)
|
|
|
|
|
self.thread2.okSignal.connect(self.btnExitClicked)
|
2023-12-05 20:53:32 +08:00
|
|
|
|
self.thread2.errorSignal.connect(
|
|
|
|
|
lambda x: QMessageBox.critical(self, "错误", "密钥错误\n请检查微信版本是否为最新")
|
|
|
|
|
)
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.thread2.start()
|
|
|
|
|
|
|
|
|
|
def btnEnterClicked(self):
|
|
|
|
|
# print("enter clicked")
|
|
|
|
|
# 中间可以添加处理逻辑
|
|
|
|
|
# QMessageBox.about(self, "解密成功", "数据库文件存储在app/DataBase/Msg文件夹下")
|
2023-11-20 22:30:31 +08:00
|
|
|
|
|
2023-11-25 00:20:35 +08:00
|
|
|
|
self.DecryptSignal.emit(True)
|
2023-11-15 20:54:27 +08:00
|
|
|
|
# self.close()
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
|
|
|
|
def setProgressBarMaxNum(self, max_val):
|
|
|
|
|
self.progressBar.setRange(0, max_val)
|
|
|
|
|
|
|
|
|
|
def progressBar_view(self, value):
|
|
|
|
|
"""
|
|
|
|
|
进度条显示
|
|
|
|
|
:param value: 进度0-100
|
|
|
|
|
:return: None
|
|
|
|
|
"""
|
|
|
|
|
self.progressBar.setProperty('value', value)
|
|
|
|
|
# self.btnExitClicked()
|
|
|
|
|
# data.init_database()
|
|
|
|
|
|
|
|
|
|
def btnExitClicked(self):
|
|
|
|
|
# print("Exit clicked")
|
2023-11-20 22:30:31 +08:00
|
|
|
|
dic = {
|
|
|
|
|
'wxid': self.info['wxid'],
|
|
|
|
|
'wx_dir': self.wx_dir,
|
|
|
|
|
'name': self.info['name'],
|
|
|
|
|
'mobile': self.info['mobile']
|
|
|
|
|
}
|
2023-11-22 22:31:34 +08:00
|
|
|
|
try:
|
2023-12-03 00:03:00 +08:00
|
|
|
|
os.makedirs('./app/data', exist_ok=True)
|
2023-11-22 22:31:34 +08:00
|
|
|
|
with open('./app/data/info.json', 'w', encoding='utf-8') as f:
|
|
|
|
|
f.write(json.dumps(dic))
|
|
|
|
|
except:
|
|
|
|
|
with open('./info.json', 'w', encoding='utf-8') as f:
|
|
|
|
|
f.write(json.dumps(dic))
|
2023-11-29 21:23:44 +08:00
|
|
|
|
# 目标数据库文件
|
|
|
|
|
target_database = "app/DataBase/Msg/MSG.db"
|
|
|
|
|
# 源数据库文件列表
|
2023-12-05 20:53:32 +08:00
|
|
|
|
source_databases = [f"app/DataBase/Msg/MSG{i}.db" for i in range(1, 20)]
|
2023-11-29 21:23:44 +08:00
|
|
|
|
import shutil
|
|
|
|
|
shutil.copy("app/DataBase/Msg/MSG0.db", target_database) # 使用一个数据库文件作为模板
|
|
|
|
|
# 合并数据库
|
2023-12-05 20:53:32 +08:00
|
|
|
|
try:
|
|
|
|
|
merge_databases(source_databases, target_database)
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
QMessageBox.critical(self, "错误", "数据库不存在\n请检查微信版本是否为最新")
|
2023-11-25 00:20:35 +08:00
|
|
|
|
self.DecryptSignal.emit(True)
|
2023-11-12 21:51:33 +08:00
|
|
|
|
self.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DecryptThread(QThread):
|
|
|
|
|
signal = pyqtSignal(str)
|
|
|
|
|
maxNumSignal = pyqtSignal(int)
|
|
|
|
|
okSignal = pyqtSignal(str)
|
2023-12-05 20:53:32 +08:00
|
|
|
|
errorSignal = pyqtSignal(bool)
|
2023-11-12 21:51:33 +08:00
|
|
|
|
|
|
|
|
|
def __init__(self, db_path, key):
|
|
|
|
|
super(DecryptThread, self).__init__()
|
|
|
|
|
self.db_path = db_path
|
|
|
|
|
self.key = key
|
|
|
|
|
self.textBrowser = None
|
|
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def run(self):
|
2023-12-01 22:37:45 +08:00
|
|
|
|
misc_db.close()
|
|
|
|
|
msg_db.close()
|
|
|
|
|
# micro_msg_db.close()
|
|
|
|
|
# hard_link_db.close()
|
2023-11-12 21:51:33 +08:00
|
|
|
|
output_dir = 'app/DataBase/Msg'
|
2023-12-03 00:03:00 +08:00
|
|
|
|
os.makedirs(output_dir, exist_ok=True)
|
2023-11-12 21:51:33 +08:00
|
|
|
|
tasks = []
|
|
|
|
|
if os.path.exists(self.db_path):
|
|
|
|
|
for root, dirs, files in os.walk(self.db_path):
|
|
|
|
|
for file in files:
|
|
|
|
|
if '.db' == file[-3:]:
|
2023-12-05 20:53:32 +08:00
|
|
|
|
if 'xInfo.db' == file:
|
|
|
|
|
continue
|
2023-11-12 21:51:33 +08:00
|
|
|
|
inpath = os.path.join(root, file)
|
|
|
|
|
# print(inpath)
|
|
|
|
|
output_path = os.path.join(output_dir, file)
|
|
|
|
|
tasks.append([self.key, inpath, output_path])
|
|
|
|
|
self.maxNumSignal.emit(len(tasks))
|
|
|
|
|
for i, task in enumerate(tasks):
|
2023-12-05 20:53:32 +08:00
|
|
|
|
if decrypt.decrypt(*task) == -1:
|
|
|
|
|
self.errorSignal.emit(True)
|
2023-11-29 23:41:02 +08:00
|
|
|
|
self.signal.emit(str(i))
|
2023-11-12 21:51:33 +08:00
|
|
|
|
# print(self.db_path)
|
|
|
|
|
self.okSignal.emit('ok')
|
|
|
|
|
# self.signal.emit('100')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MyThread(QThread):
|
|
|
|
|
signal = pyqtSignal(str)
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
super(MyThread, self).__init__()
|
|
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
for i in range(100):
|
|
|
|
|
self.signal.emit(str(i))
|
|
|
|
|
time.sleep(0.1)
|