群聊显示具体的发送人。

This commit is contained in:
xaoyaoo 2023-12-06 19:29:46 +08:00
parent 4f68fc4af1
commit deb90ce151
6 changed files with 64 additions and 36 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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>

View File

@ -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"

View File

@ -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