群聊显示具体的发送人。
This commit is contained in:
parent
4f68fc4af1
commit
deb90ce151
@ -7,7 +7,7 @@
|
|||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
from .wx_info import BiasAddr,read_info, get_wechat_db,encrypt,batch_decrypt,decrypt
|
from .wx_info import BiasAddr,read_info, get_wechat_db,encrypt,batch_decrypt,decrypt
|
||||||
from .wx_info import merge_copy_db, merge_msg_db, merge_media_msg_db
|
from .wx_info import merge_copy_db, merge_msg_db, merge_media_msg_db
|
||||||
from .analyzer.db_parsing import read_img_dat, read_emoji, decompress_CompressContent, read_audio_buf, read_audio, parse_xml_string
|
from .analyzer.db_parsing import read_img_dat, read_emoji, decompress_CompressContent, read_audio_buf, read_audio, parse_xml_string,read_BytesExtra
|
||||||
from .ui import app_show_chat, get_user_list, export
|
from .ui import app_show_chat, get_user_list, export
|
||||||
|
|
||||||
import os,json
|
import os,json
|
||||||
|
@ -5,4 +5,4 @@
|
|||||||
# Author: xaoyaoo
|
# Author: xaoyaoo
|
||||||
# Date: 2023/09/27
|
# Date: 2023/09/27
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
from .db_parsing import read_img_dat, read_emoji, decompress_CompressContent, read_audio_buf, read_audio, parse_xml_string
|
from .db_parsing import read_img_dat, read_emoji, decompress_CompressContent, read_audio_buf, read_audio, parse_xml_string,read_BytesExtra
|
||||||
|
@ -153,11 +153,13 @@ def decompress_CompressContent(data):
|
|||||||
"""
|
"""
|
||||||
if data is None or not isinstance(data, bytes):
|
if data is None or not isinstance(data, bytes):
|
||||||
return None
|
return None
|
||||||
|
try:
|
||||||
dst = lz4.block.decompress(data, uncompressed_size=len(data) << 8)
|
dst = lz4.block.decompress(data, uncompressed_size=len(data) << 8)
|
||||||
dst.decode().replace('\x00', '') # 已经解码完成后,还含有0x00的部分,要删掉,要不后面ET识别的时候会报错
|
dst.decode().replace(b'\x00', '') # 已经解码完成后,还含有0x00的部分,要删掉,要不后面ET识别的时候会报错
|
||||||
uncompressed_data = dst.encode('utf-8', errors='ignore')
|
uncompressed_data = dst.decode('utf-8', errors='ignore')
|
||||||
return uncompressed_data
|
return uncompressed_data
|
||||||
|
except Exception as e:
|
||||||
|
return data.decode('utf-8', errors='ignore')
|
||||||
|
|
||||||
|
|
||||||
def read_audio_buf(buf_data, is_play=False, is_wave=False, rate=24000):
|
def read_audio_buf(buf_data, is_play=False, is_wave=False, rate=24000):
|
||||||
@ -257,13 +259,13 @@ def read_BytesExtra(BytesExtra):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
DB = sqlite3.connect(r"D:\_code\py_code\test\a2023\b0821wxdb\merge_wfwx_db\kkWxMsg\MSG_all.db")
|
DB = sqlite3.connect(r"D:\_code\py_code\test\a2023\b0821wxdb\merge_wfwx_db\hwfWxMsg\MSG_all.db")
|
||||||
cursor = DB.cursor()
|
cursor = DB.cursor()
|
||||||
sql = "select MsgSvrID,BytesExtra from MSG where BytesExtra is not null and StrTalker='24724392255@chatroom' order by CreateTime desc limit 10"
|
sql = "select MsgSvrID,CompressContent from MSG where MSG.MsgSvrID=5379391128928795712"
|
||||||
DBdata = cursor.execute(sql).fetchall()
|
DBdata = cursor.execute(sql).fetchall()
|
||||||
for i in DBdata:
|
for i in DBdata:
|
||||||
MsgSvrID, BytesExtra = i
|
MsgSvrID, CompressContent = i
|
||||||
data = read_BytesExtra(BytesExtra)
|
data = decompress_CompressContent(CompressContent)
|
||||||
# 提取特定键的信息
|
# 提取特定键的信息
|
||||||
print(MsgSvrID,"\n",data)
|
print(MsgSvrID,"\n",data)
|
||||||
print("-" * 64)
|
print("-" * 64)
|
@ -22,7 +22,7 @@
|
|||||||
{% if msg.is_sender == 1 %}
|
{% if msg.is_sender == 1 %}
|
||||||
<div style="background-color: #f3e9c1;">
|
<div style="background-color: #f3e9c1;">
|
||||||
|
|
||||||
<label style="color:#A13A50">[发][{{msg.type_name}}] {{msg.CreateTime}}</label><br>
|
<label style="color:#A13A50">[{{msg.talker}}][{{msg.type_name}}] {{msg.CreateTime}}</label><br>
|
||||||
|
|
||||||
{% if msg.type_name == '语音' %}
|
{% if msg.type_name == '语音' %}
|
||||||
<audio controls>
|
<audio controls>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div style="background-color: #d3eed3">
|
<div style="background-color: #d3eed3">
|
||||||
<label style="color:#f54f71">[收][{{msg.type_name}}] {{msg.CreateTime}}</label><br>
|
<label style="color:#f54f71">[{{msg.talker}}][{{msg.type_name}}] {{msg.CreateTime}}</label><br>
|
||||||
|
|
||||||
{% if msg.type_name == '语音' %}
|
{% if msg.type_name == '语音' %}
|
||||||
<audio controls>
|
<audio controls>
|
||||||
|
@ -6,12 +6,13 @@
|
|||||||
# Date: 2023/11/10
|
# Date: 2023/11/10
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
import base64
|
import base64
|
||||||
|
import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import hashlib
|
import hashlib
|
||||||
from pywxdump.analyzer import read_img_dat, decompress_CompressContent, read_audio, parse_xml_string
|
from pywxdump.analyzer import read_img_dat, decompress_CompressContent, read_audio, parse_xml_string, read_BytesExtra
|
||||||
|
|
||||||
from flask import Flask, request, render_template, g, Blueprint
|
from flask import Flask, request, render_template, g, Blueprint
|
||||||
|
|
||||||
@ -24,26 +25,31 @@ def get_md5(s):
|
|||||||
|
|
||||||
def get_user_list(MSG_ALL_db_path, MicroMsg_db_path):
|
def get_user_list(MSG_ALL_db_path, MicroMsg_db_path):
|
||||||
users = []
|
users = []
|
||||||
|
|
||||||
# 连接 MSG_ALL.db 数据库,并执行查询
|
# 连接 MSG_ALL.db 数据库,并执行查询
|
||||||
db1 = sqlite3.connect(MSG_ALL_db_path)
|
db1 = sqlite3.connect(MSG_ALL_db_path)
|
||||||
cursor1 = db1.cursor()
|
cursor1 = db1.cursor()
|
||||||
cursor1.execute("SELECT StrTalker, COUNT(*) AS ChatCount FROM MSG GROUP BY StrTalker ORDER BY ChatCount DESC")
|
cursor1.execute("SELECT StrTalker, COUNT(*) AS ChatCount FROM MSG GROUP BY StrTalker ORDER BY ChatCount DESC")
|
||||||
result = cursor1.fetchall()
|
result = cursor1.fetchall()
|
||||||
|
|
||||||
|
dict_user_count = {}
|
||||||
|
# 将结果转换为字典
|
||||||
for row in result:
|
for row in result:
|
||||||
# 获取用户名、昵称、备注和聊天记录数量
|
dict_user_count[row[0]] = row[1]
|
||||||
|
|
||||||
db2 = sqlite3.connect(MicroMsg_db_path)
|
db2 = sqlite3.connect(MicroMsg_db_path)
|
||||||
cursor2 = db2.cursor()
|
cursor2 = db2.cursor()
|
||||||
cursor2.execute("SELECT UserName, NickName, Remark FROM Contact WHERE UserName=?", (row[0],))
|
cursor2.execute("SELECT UserName, NickName, Remark FROM Contact;")
|
||||||
result2 = cursor2.fetchone()
|
result2 = cursor2.fetchall()
|
||||||
if result2:
|
for row in result2:
|
||||||
username, nickname, remark = result2
|
username, nickname, remark = row
|
||||||
chat_count = row[1]
|
|
||||||
|
|
||||||
# 拼接四列数据为元组
|
# 拼接四列数据为元组
|
||||||
row_data = {"username": username, "nickname": nickname, "remark": remark, "chat_count": chat_count,
|
row_data = {"username": username, "nickname": nickname, "remark": remark,
|
||||||
|
"chat_count": dict_user_count.get(username, 0),
|
||||||
"isChatRoom": username.startswith("@chatroom")}
|
"isChatRoom": username.startswith("@chatroom")}
|
||||||
users.append(row_data)
|
users.append(row_data)
|
||||||
|
|
||||||
|
users.sort(key=lambda x: x["chat_count"], reverse=True) # 按照聊天记录数量排序
|
||||||
cursor2.close()
|
cursor2.close()
|
||||||
db2.close()
|
db2.close()
|
||||||
cursor1.close()
|
cursor1.close()
|
||||||
@ -94,7 +100,7 @@ def load_base64_img_data(start_time, end_time, username_md5, FileStorage_path):
|
|||||||
|
|
||||||
|
|
||||||
def load_chat_records(selected_talker, start_index, page_size, user_list, MSG_ALL_db_path, MediaMSG_all_db_path,
|
def load_chat_records(selected_talker, start_index, page_size, user_list, MSG_ALL_db_path, MediaMSG_all_db_path,
|
||||||
FileStorage_path):
|
FileStorage_path, USER_LIST):
|
||||||
username = user_list.get("username", "")
|
username = user_list.get("username", "")
|
||||||
username_md5 = get_md5(username)
|
username_md5 = get_md5(username)
|
||||||
type_name_dict = {
|
type_name_dict = {
|
||||||
@ -116,7 +122,7 @@ def load_chat_records(selected_talker, start_index, page_size, user_list, MSG_AL
|
|||||||
cursor1 = db1.cursor()
|
cursor1 = db1.cursor()
|
||||||
|
|
||||||
cursor1.execute(
|
cursor1.execute(
|
||||||
"SELECT localId, IsSender, StrContent, StrTalker, Sequence, Type, SubType,CreateTime,MsgSvrID,DisplayContent,CompressContent FROM MSG WHERE StrTalker=? ORDER BY CreateTime ASC LIMIT ?,?",
|
"SELECT localId, IsSender, StrContent, StrTalker, Sequence, Type, SubType,CreateTime,MsgSvrID,DisplayContent,CompressContent,BytesExtra FROM MSG WHERE StrTalker=? ORDER BY CreateTime ASC LIMIT ?,?",
|
||||||
(selected_talker, start_index, page_size))
|
(selected_talker, start_index, page_size))
|
||||||
result1 = cursor1.fetchall()
|
result1 = cursor1.fetchall()
|
||||||
|
|
||||||
@ -127,7 +133,7 @@ def load_chat_records(selected_talker, start_index, page_size, user_list, MSG_AL
|
|||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in result1:
|
for row in result1:
|
||||||
localId, IsSender, StrContent, StrTalker, Sequence, Type, SubType, CreateTime, MsgSvrID, DisplayContent, CompressContent = row
|
localId, IsSender, StrContent, StrTalker, Sequence, Type, SubType, CreateTime, MsgSvrID, DisplayContent, CompressContent, BytesExtra = row
|
||||||
CreateTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(CreateTime))
|
CreateTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(CreateTime))
|
||||||
|
|
||||||
type_name = type_name_dict.get(Type, {}).get(SubType, "未知")
|
type_name = type_name_dict.get(Type, {}).get(SubType, "未知")
|
||||||
@ -172,8 +178,28 @@ def load_chat_records(selected_talker, start_index, page_size, user_list, MSG_AL
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
content["msg"] = StrContent
|
content["msg"] = StrContent
|
||||||
|
talker = "未知"
|
||||||
|
if IsSender == 1:
|
||||||
|
talker = "我"
|
||||||
|
else:
|
||||||
|
if StrTalker.endswith("@chatroom"):
|
||||||
|
bytes_extra = read_BytesExtra(BytesExtra)
|
||||||
|
if bytes_extra:
|
||||||
|
try:
|
||||||
|
matched_string = bytes_extra['3'][0]['2'].decode('utf-8', errors='ignore')
|
||||||
|
talker_dicts = list(filter(lambda x: x["username"] == matched_string, USER_LIST))
|
||||||
|
if len(talker_dicts) > 0:
|
||||||
|
talker_dict = talker_dicts[0]
|
||||||
|
room_username = talker_dict.get("username", "")
|
||||||
|
room_nickname = talker_dict.get("nickname", "")
|
||||||
|
room_remark = talker_dict.get("remark", "")
|
||||||
|
talker = room_remark if room_remark else room_nickname if room_nickname else room_username
|
||||||
|
else:
|
||||||
|
talker = matched_string
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
row_data = {"MsgSvrID": MsgSvrID, "type_name": type_name, "is_sender": IsSender,
|
row_data = {"MsgSvrID": MsgSvrID, "type_name": type_name, "is_sender": IsSender, "talker": talker,
|
||||||
"content": content, "CreateTime": CreateTime}
|
"content": content, "CreateTime": CreateTime}
|
||||||
data.append(row_data)
|
data.append(row_data)
|
||||||
return data
|
return data
|
||||||
@ -221,7 +247,9 @@ app_show_chat.debug = False
|
|||||||
@app_show_chat.route('/')
|
@app_show_chat.route('/')
|
||||||
def index():
|
def index():
|
||||||
g.USER_LIST = get_user_list(g.MSG_ALL_db_path, g.MicroMsg_db_path)
|
g.USER_LIST = get_user_list(g.MSG_ALL_db_path, g.MicroMsg_db_path)
|
||||||
return render_template("index.html", users=g.USER_LIST)
|
# 只去前面500个有聊天记录的用户
|
||||||
|
USER_LIST = g.USER_LIST[:500]
|
||||||
|
return render_template("index.html", users=USER_LIST)
|
||||||
|
|
||||||
|
|
||||||
# 获取聊天记录
|
# 获取聊天记录
|
||||||
@ -240,7 +268,7 @@ def get_chat_data():
|
|||||||
page_size = limit
|
page_size = limit
|
||||||
|
|
||||||
data = load_chat_records(username, start_index, page_size, user, g.MSG_ALL_db_path, g.MediaMSG_all_db_path,
|
data = load_chat_records(username, start_index, page_size, user, g.MSG_ALL_db_path, g.MediaMSG_all_db_path,
|
||||||
g.FileStorage_path)
|
g.FileStorage_path, g.USER_LIST)
|
||||||
return render_template("chat.html", msgs=data)
|
return render_template("chat.html", msgs=data)
|
||||||
else:
|
else:
|
||||||
return "error"
|
return "error"
|
||||||
|
@ -194,7 +194,6 @@ def get_key(db_path, addr_len):
|
|||||||
continue
|
continue
|
||||||
if verify_key(key_bytes, MicroMsg_path):
|
if verify_key(key_bytes, MicroMsg_path):
|
||||||
return key_bytes.hex()
|
return key_bytes.hex()
|
||||||
|
|
||||||
return "None"
|
return "None"
|
||||||
|
|
||||||
|
|
||||||
@ -326,7 +325,6 @@ def get_wechat_db(require_list: Union[List[str], str] = "all", msg_dir: str = No
|
|||||||
print(f" {path.replace(user, '')}")
|
print(f" {path.replace(user, '')}")
|
||||||
print("-" * 32)
|
print("-" * 32)
|
||||||
print(f"[+] 共 {len(user_dirs)} 个微信账号")
|
print(f"[+] 共 {len(user_dirs)} 个微信账号")
|
||||||
|
|
||||||
return user_dirs
|
return user_dirs
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user