用单例实现数据库操作,弃用全局变量

This commit is contained in:
shuaikangzhou 2023-12-01 22:37:45 +08:00
parent 8dd80d7a6c
commit c713c591bd
17 changed files with 462 additions and 306 deletions

View File

@ -4,7 +4,4 @@
<option name="format" value="PLAIN" /> <option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" /> <option name="myDocStringFormat" value="Plain" />
</component> </component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="py.test" />
</component>
</module> </module>

View File

@ -4,18 +4,24 @@
<option name="autoReloadType" value="SELECTIVE" /> <option name="autoReloadType" value="SELECTIVE" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="修复再次解密数据库时显示msg.db占用问题"> <list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="update readme.md">
<change beforePath="$PROJECT_DIR$/.idea/WeChatMsg.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/WeChatMsg.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/resources/resource.qrc" beforeDir="false" afterPath="$PROJECT_DIR$/app/resources/resource.qrc" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/DataBase/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/resources/resource_rc.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/resources/resource_rc.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/DataBase/hard_link.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/hard_link.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/Icon.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/Icon.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/DataBase/micro_msg.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/micro_msg.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/DataBase/misc.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/misc.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/DataBase/msg.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/msg.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/DataBase/output_pc.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/output_pc.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/chat/chat_info.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/chat/chat_info.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/chat/chat_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/chat/chat_window.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/contact/contact_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/contact/contact_window.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/mainview.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/ui_pc/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/mainview.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.ui" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.ui" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.ui" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.ui" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/toolUI.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/toolUI.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/toolUI.ui" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/toolUI.ui" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/util/path.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/util/path.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/tool_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/tool_window.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/main_pc.py" beforeDir="false" afterPath="$PROJECT_DIR$/main_pc.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/readme.md" beforeDir="false" afterPath="$PROJECT_DIR$/readme.md" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -27,8 +33,8 @@
<list> <list>
<option value="Freeze Requirements File" /> <option value="Freeze Requirements File" />
<option value="Blank Requirements File" /> <option value="Blank Requirements File" />
<option value="HTML File" />
<option value="Python Script" /> <option value="Python Script" />
<option value="HTML File" />
</list> </list>
</option> </option>
</component> </component>
@ -170,7 +176,7 @@
<option name="INPUT_FILE" value="" /> <option name="INPUT_FILE" value="" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="merge" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true"> <configuration name="misc" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="WeChatMsg" /> <module name="WeChatMsg" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" /> <option name="PARENT_ENVS" value="true" />
@ -182,7 +188,28 @@
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/DataBase/merge.py" /> <option name="SCRIPT_NAME" value="D:\Project\Python\WeChatMsg\app\DataBase\misc.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="msg" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="WeChatMsg" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/DataBase" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/DataBase/msg.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" /> <option name="EMULATE_TERMINAL" value="false" />
@ -233,34 +260,13 @@
<option name="INPUT_FILE" value="" /> <option name="INPUT_FILE" value="" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="web" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="WeChatMsg" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/web_ui" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/web_ui/web.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Python.main_pc" /> <item itemvalue="Python.main_pc" />
<item itemvalue="Python.test" />
<item itemvalue="Python.merge" />
<item itemvalue="Python.web" />
<item itemvalue="Python.hard_link" /> <item itemvalue="Python.hard_link" />
<item itemvalue="Python.msg" />
<item itemvalue="Python.misc_db" />
<item itemvalue="Python.test" />
</list> </list>
</recent_temporary> </recent_temporary>
</component> </component>
@ -276,27 +282,6 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1672848140146</updated> <updated>1672848140146</updated>
</task> </task>
<task id="LOCAL-00053" summary="update readme">
<created>1699797862964</created>
<option name="number" value="00053" />
<option name="presentableId" value="LOCAL-00053" />
<option name="project" value="LOCAL" />
<updated>1699797862964</updated>
</task>
<task id="LOCAL-00054" summary="增加日志模块">
<created>1699883702805</created>
<option name="number" value="00054" />
<option name="presentableId" value="LOCAL-00054" />
<option name="project" value="LOCAL" />
<updated>1699883702806</updated>
</task>
<task id="LOCAL-00055" summary="update readme">
<created>1699884085863</created>
<option name="number" value="00055" />
<option name="presentableId" value="LOCAL-00055" />
<option name="project" value="LOCAL" />
<updated>1699884085863</updated>
</task>
<task id="LOCAL-00056" summary="增加PC端微信解密条件的判断"> <task id="LOCAL-00056" summary="增加PC端微信解密条件的判断">
<created>1699973547832</created> <created>1699973547832</created>
<option name="number" value="00056" /> <option name="number" value="00056" />
@ -619,7 +604,28 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1701272464442</updated> <updated>1701272464442</updated>
</task> </task>
<option name="localTasksCounter" value="102" /> <task id="LOCAL-00102" summary="修改部分UI">
<created>1701353500149</created>
<option name="number" value="00102" />
<option name="presentableId" value="LOCAL-00102" />
<option name="project" value="LOCAL" />
<updated>1701353500149</updated>
</task>
<task id="LOCAL-00103" summary="优化wxid获取方式">
<created>1701354905621</created>
<option name="number" value="00103" />
<option name="presentableId" value="LOCAL-00103" />
<option name="project" value="LOCAL" />
<updated>1701354905621</updated>
</task>
<task id="LOCAL-00104" summary="update readme.md">
<created>1701361381301</created>
<option name="number" value="00104" />
<option name="presentableId" value="LOCAL-00104" />
<option name="project" value="LOCAL" />
<updated>1701361381302</updated>
</task>
<option name="localTasksCounter" value="105" />
<servers /> <servers />
</component> </component>
<component name="UnknownFeatures"> <component name="UnknownFeatures">
@ -655,9 +661,6 @@
</option> </option>
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<MESSAGE value="修改聊天记录显示顺序" />
<MESSAGE value="聊天记录从后往前显示" />
<MESSAGE value="聊天消息自适应" />
<MESSAGE value="新版本更新" /> <MESSAGE value="新版本更新" />
<MESSAGE value="修复时间插入位置" /> <MESSAGE value="修复时间插入位置" />
<MESSAGE value="修复第一次启动的显示问题" /> <MESSAGE value="修复第一次启动的显示问题" />
@ -680,7 +683,10 @@
<MESSAGE value="修改初始加载显示页面" /> <MESSAGE value="修改初始加载显示页面" />
<MESSAGE value="修改打开路径的初始位置修复打开404图片闪退问题" /> <MESSAGE value="修改打开路径的初始位置修复打开404图片闪退问题" />
<MESSAGE value="修复再次解密数据库时显示msg.db占用问题" /> <MESSAGE value="修复再次解密数据库时显示msg.db占用问题" />
<option name="LAST_COMMIT_MESSAGE" value="修复再次解密数据库时显示msg.db占用问题" /> <MESSAGE value="修改部分UI" />
<MESSAGE value="优化wxid获取方式" />
<MESSAGE value="update readme.md" />
<option name="LAST_COMMIT_MESSAGE" value="update readme.md" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" /> <option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" /> <option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" />
</component> </component>
@ -702,6 +708,21 @@
<line>103</line> <line>103</line>
<option name="timeStamp" value="9" /> <option name="timeStamp" value="9" />
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/app/DataBase/msg.py</url>
<line>104</line>
<option name="timeStamp" value="12" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/app/DataBase/misc.py</url>
<line>64</line>
<option name="timeStamp" value="14" />
</line-breakpoint>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py</url>
<line>201</line>
<option name="timeStamp" value="15" />
</line-breakpoint>
</breakpoints> </breakpoints>
<default-breakpoints> <default-breakpoints>
<breakpoint type="python-exception"> <breakpoint type="python-exception">

View File

@ -7,7 +7,15 @@
@Version : Python3.10 @Version : Python3.10
@comment : ··· @comment : ···
""" """
from .hard_link import HardLink
from .micro_msg import MicroMsg
# from . import data # from . import data
# from . import output # from . import output
from .misc import Misc
from .msg import Msg
__all__ = ["data", 'output'] misc_db = Misc()
msg_db = Msg()
micro_msg_db = MicroMsg()
hard_link_db = HardLink()
__all__ = ["data", 'output', 'misc_db', 'micro_msg_db', 'msg_db', 'hard_link_db']

View File

@ -11,23 +11,52 @@ DB = None
cursor = None cursor = None
db_path = "./app/Database/Msg/HardLinkImage.db" db_path = "./app/Database/Msg/HardLinkImage.db"
root_path = 'FileStorage/MsgAttach/' root_path = 'FileStorage/MsgAttach/'
@log
def get_md5_from_xml(content):
# 解析XML
root = ET.fromstring(content)
# 提取md5的值
md5_value = root.find(".//img").get("md5")
# print(md5_value)
return md5_value
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class HardLink:
def __init__(self):
self.DB = None
self.cursor = None
self.open_flag = False
self.init_database()
def init_database(self):
if not self.open_flag:
if os.path.exists(db_path): if os.path.exists(db_path):
DB = sqlite3.connect(db_path, check_same_thread=False) self.DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标''' # '''创建游标'''
cursor = DB.cursor() self.cursor = self.DB.cursor()
self.open_flag = True
if lock.locked():
lock.release()
def get_image_by_md5(self, md5: bytes):
def init_database(): if not md5:
global DB return None
global cursor if not self.open_flag:
if not DB: return None
if os.path.exists(db_path):
DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def get_image_by_md5(md5: bytes):
sql = ''' sql = '''
select Md5Hash,MD5,FileName,HardLinkImageID.Dir as DirName1,HardLinkImageID2.Dir as DirName2 select Md5Hash,MD5,FileName,HardLinkImageID.Dir as DirName1,HardLinkImageID2.Dir as DirName2
from HardLinkImageAttribute from HardLinkImageAttribute
@ -38,32 +67,22 @@ def get_image_by_md5(md5: bytes):
try: try:
lock.acquire(True) lock.acquire(True)
try: try:
cursor.execute(sql, [md5]) self.cursor.execute(sql, [md5])
except AttributeError: except AttributeError:
init_database() self.init_database()
finally: finally:
cursor.execute(sql, [md5]) self.cursor.execute(sql, [md5])
result = cursor.fetchone() result = self.cursor.fetchone()
return result return result
finally: finally:
lock.release() lock.release()
def get_image(self, content, thumb=False):
def get_md5_from_xml(content):
# 解析XML
root = ET.fromstring(content)
# 提取md5的值
md5_value = root.find(".//img").get("md5")
# print(md5_value)
return md5_value
@log
def get_image(content, thumb=False):
md5 = get_md5_from_xml(content) md5 = get_md5_from_xml(content)
result = get_image_by_md5(binascii.unhexlify(md5)) if not md5:
return None
result = self.get_image_by_md5(binascii.unhexlify(md5))
if result: if result:
# print(result)
dir1 = result[3] dir1 = result[3]
dir2 = result[4] dir2 = result[4]
data_image = result[2] data_image = result[2]
@ -71,10 +90,17 @@ def get_image(content, thumb=False):
dat_image = os.path.join(root_path, dir1, dir0, dir2, data_image) dat_image = os.path.join(root_path, dir1, dir0, dir2, data_image)
return dat_image return dat_image
def close(self):
if self.open_flag:
try:
lock.acquire(True)
self.open_flag = False
self.DB.close()
finally:
lock.release()
def close(): def __del__(self):
if DB: self.close()
DB.close()
# 6b02292eecea118f06be3a5b20075afc_t # 6b02292eecea118f06be3a5b20075afc_t
@ -82,9 +108,10 @@ def close():
if __name__ == '__main__': if __name__ == '__main__':
msg_root_path = './Msg/' msg_root_path = './Msg/'
db_path = "./Msg/HardLinkImage.db" db_path = "./Msg/HardLinkImage.db"
init_database() hard_link_db = HardLink()
hard_link_db.init_database()
content = '''<?xml version="1.0"?><msg>\n\t<img aeskey="bc37a58c32cb203ee9ac587b068e5853" encryver="1" cdnthumbaeskey="bc37a58c32cb203ee9ac587b068e5853" cdnthumburl="3057020100044b30490201000204d181705002032f5405020428a7b4de02046537869d042462313532363539632d663930622d343463302d616636662d333837646434633061626534020401150a020201000405004c4c6d00" cdnthumblength="3097" cdnthumbheight="120" cdnthumbwidth="68" cdnmidheight="0" cdnmidwidth="0" cdnhdheight="0" cdnhdwidth="0" cdnmidimgurl="3057020100044b30490201000204d181705002032f5405020428a7b4de02046537869d042462313532363539632d663930622d343463302d616636662d333837646434633061626534020401150a020201000405004c4c6d00" length="57667" md5="6844b812d5d514eb6878657e0bf4cdbb" originsourcemd5="1dfdfa24922270ea1cb5daba103f45ca" />\n\t<platform_signature></platform_signature>\n\t<imgdatahash></imgdatahash>\n</msg>\n''' content = '''<?xml version="1.0"?><msg>\n\t<img aeskey="bc37a58c32cb203ee9ac587b068e5853" encryver="1" cdnthumbaeskey="bc37a58c32cb203ee9ac587b068e5853" cdnthumburl="3057020100044b30490201000204d181705002032f5405020428a7b4de02046537869d042462313532363539632d663930622d343463302d616636662d333837646434633061626534020401150a020201000405004c4c6d00" cdnthumblength="3097" cdnthumbheight="120" cdnthumbwidth="68" cdnmidheight="0" cdnmidwidth="0" cdnhdheight="0" cdnhdwidth="0" cdnmidimgurl="3057020100044b30490201000204d181705002032f5405020428a7b4de02046537869d042462313532363539632d663930622d343463302d616636662d333837646434633061626534020401150a020201000405004c4c6d00" length="57667" md5="6844b812d5d514eb6878657e0bf4cdbb" originsourcemd5="1dfdfa24922270ea1cb5daba103f45ca" />\n\t<platform_signature></platform_signature>\n\t<imgdatahash></imgdatahash>\n</msg>\n'''
print(get_image(content)) print(hard_link_db.get_image(content))
print(get_image(content, thumb=False)) print(hard_link_db.get_image(content, thumb=False))
result = get_md5_from_xml(content) result = get_md5_from_xml(content)
print(result) print(result)

View File

@ -5,28 +5,45 @@ import threading
lock = threading.Lock() lock = threading.Lock()
DB = None DB = None
cursor = None cursor = None
micromsg_path = "./app/Database/Msg/MicroMsg.db" db_path = "./app/Database/Msg/MicroMsg.db"
if os.path.exists(micromsg_path):
DB = sqlite3.connect(micromsg_path, check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def init_database(): def singleton(cls):
global DB _instance = {}
global cursor
if not DB: def inner():
if os.path.exists(micromsg_path): if cls not in _instance:
DB = sqlite3.connect(micromsg_path, check_same_thread=False) _instance[cls] = cls()
# '''创建游标''' return _instance[cls]
cursor = DB.cursor()
return inner
def is_database_exist(): def is_database_exist():
return os.path.exists(micromsg_path) return os.path.exists(db_path)
def get_contact(): @singleton
class MicroMsg:
def __init__(self):
self.DB = None
self.cursor = None
self.open_flag = False
self.init_database()
def init_database(self):
if not self.open_flag:
if os.path.exists(db_path):
self.DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标'''
self.cursor = self.DB.cursor()
self.open_flag = True
if lock.locked():
lock.release()
def get_contact(self):
if not self.open_flag:
return None
try: try:
lock.acquire(True) lock.acquire(True)
sql = '''select UserName,Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl.bigHeadImgUrl sql = '''select UserName,Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl.bigHeadImgUrl
@ -34,19 +51,25 @@ def get_contact():
where Type%2=1 and Alias is not null where Type%2=1 and Alias is not null
order by PYInitial order by PYInitial
''' '''
cursor.execute(sql) self.cursor.execute(sql)
result = cursor.fetchall() result = self.cursor.fetchall()
finally: finally:
lock.release() lock.release()
# DB.commit()
return result return result
def close(self):
if self.open_flag:
try:
lock.acquire(True)
self.open_flag = False
self.DB.close()
finally:
lock.release()
def close(): def __del__(self):
global DB self.close()
if DB:
DB.close()
if __name__ == '__main__': if __name__ == '__main__':
get_contact() pass
# get_contact()

View File

@ -1,45 +1,59 @@
import os.path import os.path
import sqlite3 import sqlite3
import threading import threading
import time
lock = threading.Lock() lock = threading.Lock()
DB = None DB = None
cursor = None cursor = None
db_path = "./app/Database/Msg/Misc.db" db_path = "./app/Database/Msg/Misc.db"
# misc_path = './Msg/Misc.db'
# db_path = './Msg/Misc.db'
def singleton(cls):
_instance = {}
def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class Misc:
def __init__(self):
self.DB = None
self.cursor = None
self.open_flag = False
self.init_database()
def init_database(self):
if not self.open_flag:
if os.path.exists(db_path): if os.path.exists(db_path):
DB = sqlite3.connect(db_path, check_same_thread=False) self.DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标''' # '''创建游标'''
cursor = DB.cursor() self.cursor = self.DB.cursor()
self.open_flag = True
if lock.locked():
lock.release()
def get_avatar_buffer(self, userName):
def init_database(): if not self.open_flag:
global DB return None
global cursor
if not DB:
if os.path.exists(db_path):
DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def get_avatar_buffer(userName):
sql = ''' sql = '''
select smallHeadBuf select smallHeadBuf
from ContactHeadImg1 from ContactHeadImg1
where usrName=?; where usrName=?;
''' '''
if not self.open_flag:
self.init_database()
try: try:
lock.acquire(True) lock.acquire(True)
try: self.cursor.execute(sql, [userName])
cursor.execute(sql, [userName]) result = self.cursor.fetchall()
except:
time.sleep(0.5)
init_database()
finally:
cursor.execute(sql, [userName])
result = cursor.fetchall()
# print(result[0][0]) # print(result[0][0])
if result: if result:
return result[0][0] return result[0][0]
@ -47,12 +61,19 @@ def get_avatar_buffer(userName):
lock.release() lock.release()
return None return None
def close(self):
if self.open_flag:
try:
lock.acquire(True)
self.open_flag = False
self.DB.close()
finally:
lock.release()
def close(): def __del__(self):
global DB self.close()
if DB:
DB.close()
if __name__ == '__main__': if __name__ == '__main__':
get_avatar_buffer('wxid_al2oan01b6fn11') Misc()
print(Misc().get_avatar_buffer('wxid_al2oan01b6fn11'))

View File

@ -1,35 +1,53 @@
import os.path import os.path
import sqlite3 import sqlite3
import threading import threading
import traceback
from pprint import pprint from pprint import pprint
from app.log import logger
DB = None DB = None
cursor = None cursor = None
db_path = "./app/Database/Msg/MSG.db" db_path = "./app/Database/Msg/MSG.db"
lock = threading.Lock() lock = threading.Lock()
# misc_path = './Msg/Misc.db'
if os.path.exists(db_path):
DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标'''
cursor = DB.cursor()
def is_database_exist(): def is_database_exist():
return os.path.exists(db_path) return os.path.exists(db_path)
def init_database(): def singleton(cls):
global DB _instance = {}
global cursor
if not DB: def inner():
if cls not in _instance:
_instance[cls] = cls()
return _instance[cls]
return inner
@singleton
class Msg:
def __init__(self):
self.DB = None
self.cursor = None
self.open_flag = False
self.init_database()
def init_database(self):
if not self.open_flag:
if os.path.exists(db_path): if os.path.exists(db_path):
DB = sqlite3.connect(db_path, check_same_thread=False) self.DB = sqlite3.connect(db_path, check_same_thread=False)
# '''创建游标''' # '''创建游标'''
cursor = DB.cursor() self.cursor = self.DB.cursor()
self.open_flag = True
if lock.locked():
lock.release()
def get_messages(self, username_):
def get_messages(username_): if not self.open_flag:
return None
sql = ''' sql = '''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime
from MSG from MSG
@ -38,31 +56,31 @@ def get_messages(username_):
''' '''
try: try:
lock.acquire(True) lock.acquire(True)
cursor.execute(sql, [username_]) self.cursor.execute(sql, [username_])
result = cursor.fetchall() result = self.cursor.fetchall()
finally: finally:
lock.release() lock.release()
result.sort(key=lambda x: x[5]) result.sort(key=lambda x: x[5])
return result return result
def get_messages_all(self):
def get_messages_all():
sql = ''' sql = '''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime
from MSG from MSG
order by CreateTime order by CreateTime
''' '''
if not self.open_flag:
return None
try: try:
lock.acquire(True) lock.acquire(True)
cursor.execute(sql) self.cursor.execute(sql)
result = cursor.fetchall() result = self.cursor.fetchall()
finally: finally:
lock.release() lock.release()
result.sort(key=lambda x: x[5]) result.sort(key=lambda x: x[5])
return result return result
def get_message_by_num(self, username_, local_id):
def get_message_by_num(username_, local_id):
sql = ''' sql = '''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime
from MSG from MSG
@ -70,27 +88,39 @@ def get_message_by_num(username_, local_id):
order by CreateTime desc order by CreateTime desc
limit 10 limit 10
''' '''
result = None
if not self.open_flag:
return None
try: try:
lock.acquire(True) lock.acquire(True)
cursor.execute(sql, [username_, local_id]) self.cursor.execute(sql, [username_, local_id])
result = cursor.fetchall() result = self.cursor.fetchall()
except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
finally: finally:
lock.release() lock.release()
# result.sort(key=lambda x: x[5]) # result.sort(key=lambda x: x[5])
return result return result
def close(self):
if self.open_flag:
try:
lock.acquire(True)
self.open_flag = False
self.DB.close()
finally:
lock.release()
def close(): def __del__(self):
global DB self.close()
if DB:
DB.close()
if __name__ == '__main__': if __name__ == '__main__':
msg_root_path = './Msg/' db_path = "./Msg/MSG.db"
init_database() msg = Msg()
result = get_message_by_num('wxid_0o18ef858vnu22', 9999999) msg.init_database()
result = msg.get_message_by_num('wxid_0o18ef858vnu22', 9999999)
print(result) print(result)
print(result[-1][0]) print(result[-1][0])
local_id = result[-1][0] local_id = result[-1][0]
pprint(get_message_by_num('wxid_0o18ef858vnu22', local_id)) pprint(msg.get_message_by_num('wxid_0o18ef858vnu22', local_id))

View File

@ -4,8 +4,8 @@ import os
from PyQt5.QtCore import pyqtSignal, QThread from PyQt5.QtCore import pyqtSignal, QThread
from . import msg from . import msg_db
from ..DataBase import hard_link from ..DataBase import hard_link_db
from ..person_pc import MePC from ..person_pc import MePC
from ..util import get_abs_path from ..util import get_abs_path
@ -152,7 +152,7 @@ class ChildThread(QThread):
columns = ['localId', 'TalkerId', 'Type', 'SubType', columns = ['localId', 'TalkerId', 'Type', 'SubType',
'IsSender', 'CreateTime', 'Status', 'StrContent', 'IsSender', 'CreateTime', 'Status', 'StrContent',
'StrTime'] 'StrTime']
messages = msg.get_messages(self.contact.wxid) messages = msg_db.get_messages(self.contact.wxid)
# 写入CSV文件 # 写入CSV文件
with open(filename, mode='w', newline='', encoding='utf-8') as file: with open(filename, mode='w', newline='', encoding='utf-8') as file:
writer = csv.writer(file) writer = csv.writer(file)
@ -170,7 +170,7 @@ class ChildThread(QThread):
columns = ['localId', 'TalkerId', 'Type', 'SubType', columns = ['localId', 'TalkerId', 'Type', 'SubType',
'IsSender', 'CreateTime', 'Status', 'StrContent', 'IsSender', 'CreateTime', 'Status', 'StrContent',
'StrTime'] 'StrTime']
messages = msg.get_messages_all() messages = msg_db.get_messages_all()
# 写入CSV文件 # 写入CSV文件
with open(filename, mode='w', newline='', encoding='utf-8') as file: with open(filename, mode='w', newline='', encoding='utf-8') as file:
writer = csv.writer(file) writer = csv.writer(file)
@ -183,7 +183,7 @@ class ChildThread(QThread):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
if not os.path.exists(origin_docx_path): if not os.path.exists(origin_docx_path):
os.mkdir(origin_docx_path) os.mkdir(origin_docx_path)
messages = msg.get_messages(self.contact.wxid) 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"
f = open(filename, 'w', encoding='utf-8') f = open(filename, 'w', encoding='utf-8')
html_head = ''' html_head = '''
@ -441,7 +441,7 @@ class ChildThread(QThread):
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}" origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
if not os.path.exists(origin_docx_path): if not os.path.exists(origin_docx_path):
os.mkdir(origin_docx_path) os.mkdir(origin_docx_path)
messages = msg.get_messages(self.contact.wxid) 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"
f = open(filename, 'w', encoding='utf-8') f = open(filename, 'w', encoding='utf-8')
html_head = ''' html_head = '''
@ -738,7 +738,7 @@ const chatMessages = [
if match: if match:
continue continue
image_path = hard_link.get_image(content=str_content, thumb=False) image_path = hard_link_db.get_image(content=str_content, thumb=False)
image_path = get_abs_path(image_path) image_path = get_abs_path(image_path)
image_path = image_path.replace('\\', '/') image_path = image_path.replace('\\', '/')
# print(f"tohtml:---{image_path}") # print(f"tohtml:---{image_path}")

View File

@ -3,7 +3,7 @@ import traceback
from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout
from app.DataBase import msg, hard_link from app.DataBase import msg_db, hard_link_db
from app.components.bubble_message import BubbleMessage, ChatWidget, Notice from app.components.bubble_message import BubbleMessage, ChatWidget, Notice
from app.person_pc import MePC from app.person_pc import MePC
from app.util import get_abs_path from app.util import get_abs_path
@ -106,7 +106,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.get_image(content=str_content, thumb=False) image_path = hard_link_db.get_image(content=str_content, 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,
@ -146,7 +146,7 @@ class ShowChatThread(QThread):
self.wxid = contact.wxid self.wxid = contact.wxid
def run(self) -> None: def run(self) -> None:
messages = msg.get_message_by_num(self.wxid, self.last_message_id) messages = msg_db.get_message_by_num(self.wxid, self.last_message_id)
if messages: if messages:
self.last_message_id = messages[-1][0] self.last_message_id = messages[-1][0]
for message in messages: for message in messages:

View File

@ -1,7 +1,7 @@
from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit
from app.DataBase import micro_msg, misc, msg from app.DataBase import micro_msg_db, misc_db, msg_db
from app.components import ContactQListWidgetItem from app.components import ContactQListWidgetItem
from app.person_pc import ContactPC from app.person_pc import ContactPC
from app.ui_pc.Icon import Icon from app.ui_pc.Icon import Icon
@ -72,9 +72,9 @@ class ChatWindow(QWidget, Ui_Form):
def show_chats(self): def show_chats(self):
if self.ok_flag: if self.ok_flag:
return return
msg.init_database() msg_db.init_database()
micro_msg.init_database() micro_msg_db.init_database()
if not msg.is_database_exist(): if not msg_db.open_flag:
QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库") QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库")
self.show_thread = ShowThread() self.show_thread = ShowThread()
self.show_thread.load_finish_signal.connect(self.load_finish_signal) self.show_thread.load_finish_signal.connect(self.load_finish_signal)
@ -127,7 +127,7 @@ class ShowContactThread(QThread):
super().__init__() super().__init__()
def run(self) -> None: def run(self) -> None:
contact_info_lists = micro_msg.get_contact() contact_info_lists = micro_msg_db.get_contact()
for contact_info_list in contact_info_lists: for contact_info_list in contact_info_lists:
# UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl # UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
contact_info = { contact_info = {
@ -139,7 +139,7 @@ class ShowContactThread(QThread):
'smallHeadImgUrl': contact_info_list[7] 'smallHeadImgUrl': contact_info_list[7]
} }
contact = ContactPC(contact_info) contact = ContactPC(contact_info)
contact.smallHeadImgBLOG = misc.get_avatar_buffer(contact.wxid) contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG) contact.set_avatar(contact.smallHeadImgBLOG)
self.showSingal.emit(contact) self.showSingal.emit(contact)
# pprint(contact.__dict__) # pprint(contact.__dict__)

View File

@ -1,7 +1,7 @@
from PyQt5.QtCore import QThread, pyqtSignal from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QLineEdit
from app.DataBase import micro_msg, misc from app.DataBase import micro_msg_db, misc_db
from app.components import ContactQListWidgetItem from app.components import ContactQListWidgetItem
from app.person_pc import ContactPC from app.person_pc import ContactPC
from app.ui_pc.Icon import Icon from app.ui_pc.Icon import Icon
@ -72,14 +72,15 @@ class ContactWindow(QWidget, Ui_Form):
def show_contacts(self): def show_contacts(self):
if self.ok_flag: if self.ok_flag:
return return
micro_msg.init_database() micro_msg_db.init_database()
if not micro_msg.is_database_exist(): if not micro_msg_db.open_flag:
QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库") QMessageBox.critical(self, "错误", "数据库不存在\n请先解密数据库")
self.show_thread = ShowThread() self.show_thread = ShowThread()
self.show_thread.showSingal.connect(self.show_contact) self.show_thread.showSingal.connect(self.show_contact)
self.show_thread.load_finish_signal.connect(self.load_finish_signal) self.show_thread.load_finish_signal.connect(self.load_finish_signal)
self.show_thread.start() self.show_thread.start()
return return
self.show_thread = ShowContactThread() self.show_thread = ShowContactThread()
self.show_thread.showSingal.connect(self.show_contact) self.show_thread.showSingal.connect(self.show_contact)
self.show_thread.load_finish_signal.connect(self.load_finish_signal) self.show_thread.load_finish_signal.connect(self.load_finish_signal)
@ -116,7 +117,7 @@ class ShowContactThread(QThread):
super().__init__() super().__init__()
def run(self) -> None: def run(self) -> None:
contact_info_lists = micro_msg.get_contact() contact_info_lists = micro_msg_db.get_contact()
for contact_info_list in contact_info_lists: for contact_info_list in contact_info_lists:
# UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl # UserName, Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
contact_info = { contact_info = {
@ -128,7 +129,7 @@ class ShowContactThread(QThread):
'smallHeadImgUrl': contact_info_list[7] 'smallHeadImgUrl': contact_info_list[7]
} }
contact = ContactPC(contact_info) contact = ContactPC(contact_info)
contact.smallHeadImgBLOG = misc.get_avatar_buffer(contact.wxid) contact.smallHeadImgBLOG = misc_db.get_avatar_buffer(contact.wxid)
contact.set_avatar(contact.smallHeadImgBLOG) contact.set_avatar(contact.smallHeadImgBLOG)
self.showSingal.emit(contact) self.showSingal.emit(contact)
# pprint(contact.__dict__) # pprint(contact.__dict__)

View File

@ -15,7 +15,7 @@ from PyQt5.QtGui import QPixmap, QFont, QDesktopServices
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from app import config from app import config
from app.DataBase import msg, misc, micro_msg, hard_link from app.DataBase import msg_db, misc_db, micro_msg_db, hard_link_db
from app.ui_pc.Icon import Icon from app.ui_pc.Icon import Icon
from . import mainwindow from . import mainwindow
from .chat import ChatWindow from .chat import ChatWindow
@ -119,7 +119,7 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
myinfo_item = QListWidgetItem(Icon.Home_Icon, '我的', self.listWidget) myinfo_item = QListWidgetItem(Icon.Home_Icon, '我的', self.listWidget)
tool_window = ToolWindow() tool_window = ToolWindow()
tool_window.get_info_signal.connect(self.set_my_info) tool_window.get_info_signal.connect(self.set_my_info)
tool_window.decrypt_success_signal.connect(self.load_data) tool_window.decrypt_success_signal.connect(self.decrypt_success)
tool_window.load_finish_signal.connect(self.loading) tool_window.load_finish_signal.connect(self.loading)
self.stackedWidget.addWidget(tool_window) self.stackedWidget.addWidget(tool_window)
self.chat_window = ChatWindow() self.chat_window = ChatWindow()
@ -153,9 +153,11 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
def set_my_info(self, wxid): def set_my_info(self, wxid):
self.avatar = QPixmap() self.avatar = QPixmap()
try: try:
img_bytes = misc.get_avatar_buffer(wxid) img_bytes = misc_db.get_avatar_buffer(wxid)
except AttributeError: except AttributeError:
return return
if not img_bytes:
return
if img_bytes[:4] == b'\x89PNG': if img_bytes[:4] == b'\x89PNG':
self.avatar.loadFromData(img_bytes, format='PNG') self.avatar.loadFromData(img_bytes, format='PNG')
else: else:
@ -206,14 +208,18 @@ class MainWinController(QMainWindow, mainwindow.Ui_MainWindow):
''' '''
) )
def decrypt_success(self):
QMessageBox.about(self, "解密成功", "请重新启动")
self.close()
def close(self) -> bool: def close(self) -> bool:
del self.listWidget super().close()
del self.stackedWidget misc_db.close()
misc.close() msg_db.close()
msg.close() micro_msg_db.close()
micro_msg.close() hard_link_db.close()
hard_link.close()
self.contact_window.close() self.contact_window.close()
self.exitSignal.emit(True)
class LoadWindowThread(QThread): class LoadWindowThread(QThread):

View File

@ -146,6 +146,9 @@ class Ui_Dialog(object):
self.pushButton_3.setMaximumSize(QtCore.QSize(100, 16777215)) self.pushButton_3.setMaximumSize(QtCore.QSize(100, 16777215))
self.pushButton_3.setObjectName("pushButton_3") self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout_2.addWidget(self.pushButton_3) self.horizontalLayout_2.addWidget(self.pushButton_3)
self.label_tip = QtWidgets.QLabel(Dialog)
self.label_tip.setObjectName("label_tip")
self.horizontalLayout_2.addWidget(self.label_tip)
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem5) self.horizontalLayout_2.addItem(spacerItem5)
self.verticalLayout.addLayout(self.horizontalLayout_2) self.verticalLayout.addLayout(self.horizontalLayout_2)
@ -185,4 +188,5 @@ class Ui_Dialog(object):
self.btn_getinfo.setText(_translate("Dialog", "获取信息")) self.btn_getinfo.setText(_translate("Dialog", "获取信息"))
self.btn_db_dir.setText(_translate("Dialog", "设置微信路径")) self.btn_db_dir.setText(_translate("Dialog", "设置微信路径"))
self.pushButton_3.setText(_translate("Dialog", "开始解密")) self.pushButton_3.setText(_translate("Dialog", "开始解密"))
self.label_tip.setText(_translate("Dialog", "TextLabel"))
self.label_ready.setText(_translate("Dialog", "未就绪")) self.label_ready.setText(_translate("Dialog", "未就绪"))

View File

@ -319,6 +319,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label_tip">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_2"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">

View File

@ -7,7 +7,7 @@ from PyQt5.QtCore import pyqtSignal, QThread, QUrl, QFile, QIODevice, QTextStrea
from PyQt5.QtGui import QDesktopServices from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog
from app.DataBase import msg, micro_msg, misc, hard_link from app.DataBase import msg_db, misc_db
from app.DataBase.merge import merge_databases from app.DataBase.merge import merge_databases
from app.decrypt import get_wx_info, decrypt from app.decrypt import get_wx_info, decrypt
from app.log import logger from app.log import logger
@ -29,6 +29,7 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog):
self.lineEdit.returnPressed.connect(self.set_wxid) self.lineEdit.returnPressed.connect(self.set_wxid)
self.lineEdit.textChanged.connect(self.set_wxid_) self.lineEdit.textChanged.connect(self.set_wxid_)
self.btn_help.clicked.connect(self.show_help) self.btn_help.clicked.connect(self.show_help)
self.label_tip.setVisible(False)
self.info = {} self.info = {}
self.lineEdit.setFocus() self.lineEdit.setFocus()
self.ready = False self.ready = False
@ -125,7 +126,8 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog):
if not os.path.exists(db_dir): if not os.path.exists(db_dir):
QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾") QMessageBox.critical(self, "错误", "文件夹选择错误\n一般以wxid_xxx结尾")
return return
self.label_tip.setVisible(True)
self.label_tip.setText('点我之后没有反应那就多等儿吧,不要再点了')
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)
self.thread2.signal.connect(self.progressBar_view) self.thread2.signal.connect(self.progressBar_view)
@ -196,12 +198,10 @@ class DecryptThread(QThread):
pass pass
def run(self): def run(self):
misc.close() misc_db.close()
msg.close() msg_db.close()
micro_msg.close() # micro_msg_db.close()
hard_link.close() # hard_link_db.close()
QThread.sleep(1)
# data.decrypt(self.db_path, self.key)
output_dir = 'app/DataBase/Msg' output_dir = 'app/DataBase/Msg'
try: try:
if not os.path.exists(output_dir): if not os.path.exists(output_dir):

View File

@ -24,7 +24,7 @@ def wx_path():
## 获取当前用户名 ## 获取当前用户名
users = os.path.expandvars('$HOMEPATH') users = os.path.expandvars('$HOMEPATH')
## 找到3ebffe94.ini配置文件 ## 找到3ebffe94.ini配置文件
f = open(r'C:' + users + '\\AppData\\Roaming\\Tencent\\WeChat\\All Users\\config\\3ebffe94.ini') f = open(r'C:' + users + '\\AppData\\Roaming\\Tencent\\WeChat\\All Users\\config\\3ebffe94.ini', encoding='utf-8')
txt = f.read() txt = f.read()
f.close() f.close()
# 打开Windows注册表 # 打开Windows注册表

View File

@ -1,10 +1,12 @@
import ctypes import ctypes
import sys import sys
import time import time
import traceback
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from app.log import logger
from app.ui_pc import mainview from app.ui_pc import mainview
from app.ui_pc.tool.pc_decrypt import pc_decrypt from app.ui_pc.tool.pc_decrypt import pc_decrypt
@ -37,11 +39,16 @@ class ViewController(QWidget):
username = '' username = ''
start = time.time() start = time.time()
self.viewMainWIndow = mainview.MainWinController(username=username) self.viewMainWIndow = mainview.MainWinController(username=username)
self.viewMainWIndow.exitSignal.connect(self.close)
try:
self.viewMainWIndow.setWindowTitle("Chat") self.viewMainWIndow.setWindowTitle("Chat")
self.viewMainWIndow.show() self.viewMainWIndow.show()
end = time.time() end = time.time()
print('ok', end - start) print('ok', end - start)
self.viewMainWIndow.init_ui() self.viewMainWIndow.init_ui()
except Exception as e:
print(f"Exception: {e}")
logger.error(traceback.print_exc())
def show_success(self): def show_success(self):
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下") QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
@ -50,8 +57,12 @@ class ViewController(QWidget):
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication(sys.argv) app = QApplication(sys.argv)
view = ViewController() view = ViewController()
try:
# view.loadPCDecryptView() # view.loadPCDecryptView()
view.loadMainWinView() view.loadMainWinView()
# view.show() # view.show()
# view.show_success() # view.show_success()
sys.exit(app.exec_()) sys.exit(app.exec_())
except Exception as e:
print(f"Exception: {e}")
logger.error(traceback.print_exc())