fix
This commit is contained in:
parent
bd4a880d7a
commit
d0e75a9f15
@ -65,6 +65,140 @@ class MsgHandler(DatabaseBase):
|
||||
msg_count.update({row[0]: row[1] for row in result})
|
||||
return msg_count
|
||||
|
||||
@db_error
|
||||
def get_msg_list(self, wxid="", start_index=0, page_size=500, msg_type: str = "", msg_sub_type: str = "",
|
||||
start_createtime=None, end_createtime=None):
|
||||
"""
|
||||
获取聊天记录列表
|
||||
:param wxid: wxid
|
||||
:param start_index: 起始索引
|
||||
:param page_size: 页大小
|
||||
:param msg_type: 消息类型
|
||||
:param msg_sub_type: 消息子类型
|
||||
:param start_createtime: 开始时间
|
||||
:param end_createtime: 结束时间
|
||||
:return: 聊天记录列表 {"id": _id, "MsgSvrID": str(MsgSvrID), "type_name": type_name, "is_sender": IsSender,
|
||||
"talker": talker, "room_name": StrTalker, "msg": msg, "src": src, "extra": {},
|
||||
"CreateTime": CreateTime, }
|
||||
"""
|
||||
if not self.tables_exist("MSG"):
|
||||
return [], []
|
||||
|
||||
param = ()
|
||||
sql_wxid, param = ("AND StrTalker=? ", param + (wxid,)) if wxid else ("", param)
|
||||
sql_type, param = ("AND Type=? ", param + (msg_type,)) if msg_type else ("", param)
|
||||
sql_sub_type, param = ("AND SubType=? ", param + (msg_sub_type,)) if msg_type and msg_sub_type else ("", param)
|
||||
sql_start_createtime, param = ("AND CreateTime>=? ", param + (start_createtime,)) if start_createtime else (
|
||||
"", param)
|
||||
sql_end_createtime, param = ("AND CreateTime<=? ", param + (end_createtime,)) if end_createtime else ("", param)
|
||||
|
||||
sql = (
|
||||
"SELECT localId,TalkerId,MsgSvrID,Type,SubType,CreateTime,IsSender,Sequence,StatusEx,FlagEx,Status,"
|
||||
"MsgSequence,StrContent,MsgServerSeq,StrTalker,DisplayContent,Reserved0,Reserved1,Reserved3,"
|
||||
"Reserved4,Reserved5,Reserved6,CompressContent,BytesExtra,BytesTrans,Reserved2,"
|
||||
"ROW_NUMBER() OVER (ORDER BY CreateTime ASC) AS id "
|
||||
"FROM MSG WHERE 1=1 "
|
||||
f"{sql_wxid}"
|
||||
f"{sql_type}"
|
||||
f"{sql_sub_type}"
|
||||
f"{sql_start_createtime}"
|
||||
f"{sql_end_createtime}"
|
||||
f"ORDER BY CreateTime ASC LIMIT ?,?"
|
||||
)
|
||||
param = param + (start_index, page_size)
|
||||
result = self.execute(sql, param)
|
||||
if not result:
|
||||
return [], []
|
||||
|
||||
result_data = (self.get_msg_detail(row) for row in result)
|
||||
rdata = list(result_data) # 转为列表
|
||||
wxid_list = {d['talker'] for d in rdata} # 创建一个无重复的 wxid 列表
|
||||
|
||||
return rdata, list(wxid_list)
|
||||
|
||||
@db_error
|
||||
def get_date_count(self, wxid='', start_time: int = 0, end_time: int = 0, time_format='%Y-%m-%d'):
|
||||
"""
|
||||
获取每日聊天记录数量,包括发送者数量、接收者数量和总数。
|
||||
"""
|
||||
if not self.tables_exist("MSG"):
|
||||
return {}
|
||||
if isinstance(start_time, str) and start_time.isdigit():
|
||||
start_time = int(start_time)
|
||||
if isinstance(end_time, str) and end_time.isdigit():
|
||||
end_time = int(end_time)
|
||||
|
||||
# if start_time or end_time is not an integer and not a float, set both to 0
|
||||
if not (isinstance(start_time, (int, float)) and isinstance(end_time, (int, float))):
|
||||
start_time = 0
|
||||
end_time = 0
|
||||
params = ()
|
||||
|
||||
sql_wxid = "AND StrTalker = ? " if wxid else ""
|
||||
params = params + (wxid,) if wxid else params
|
||||
|
||||
sql_time = "AND CreateTime BETWEEN ? AND ? " if start_time and end_time else ""
|
||||
params = params + (start_time, end_time) if start_time and end_time else params
|
||||
|
||||
sql = (f"SELECT strftime('{time_format}', CreateTime, 'unixepoch', 'localtime') AS date, "
|
||||
" COUNT(*) AS total_count ,"
|
||||
" SUM(CASE WHEN IsSender = 1 THEN 1 ELSE 0 END) AS sender_count, "
|
||||
" SUM(CASE WHEN IsSender = 0 THEN 1 ELSE 0 END) AS receiver_count "
|
||||
"FROM MSG "
|
||||
"WHERE StrTalker NOT LIKE '%chatroom%' "
|
||||
f"{sql_wxid} {sql_time} "
|
||||
f"GROUP BY date ORDER BY date ASC;")
|
||||
result = self.execute(sql, params)
|
||||
|
||||
if not result:
|
||||
return {}
|
||||
# 将查询结果转换为字典
|
||||
result_dict = {}
|
||||
for row in result:
|
||||
date, total_count, sender_count, receiver_count = row
|
||||
result_dict[date] = {
|
||||
"sender_count": sender_count,
|
||||
"receiver_count": receiver_count,
|
||||
"total_count": total_count
|
||||
}
|
||||
return result_dict
|
||||
|
||||
@db_error
|
||||
def get_top_talker_count(self, top: int = 10, start_time: int = 0, end_time: int = 0):
|
||||
"""
|
||||
获取聊天记录数量最多的联系人,他们聊天记录数量
|
||||
"""
|
||||
if not self.tables_exist("MSG"):
|
||||
return {}
|
||||
if isinstance(start_time, str) and start_time.isdigit():
|
||||
start_time = int(start_time)
|
||||
if isinstance(end_time, str) and end_time.isdigit():
|
||||
end_time = int(end_time)
|
||||
|
||||
# if start_time or end_time is not an integer and not a float, set both to 0
|
||||
if not (isinstance(start_time, (int, float)) and isinstance(end_time, (int, float))):
|
||||
start_time = 0
|
||||
end_time = 0
|
||||
|
||||
sql_time = f"AND CreateTime BETWEEN {start_time} AND {end_time} " if start_time and end_time else ""
|
||||
sql = (
|
||||
"SELECT StrTalker, COUNT(*) AS count,"
|
||||
"SUM(CASE WHEN IsSender = 1 THEN 1 ELSE 0 END) AS sender_count, "
|
||||
"SUM(CASE WHEN IsSender = 0 THEN 1 ELSE 0 END) AS receiver_count "
|
||||
"FROM MSG "
|
||||
"WHERE StrTalker NOT LIKE '%chatroom%' "
|
||||
f"{sql_time} "
|
||||
"GROUP BY StrTalker ORDER BY count DESC "
|
||||
f"LIMIT {top};"
|
||||
)
|
||||
result = self.execute(sql)
|
||||
if not result:
|
||||
return {}
|
||||
# 将查询结果转换为字典
|
||||
result_dict = {row[0]: {"total_count": row[1], "sender_count": row[2], "receiver_count": row[3]} for row in
|
||||
result}
|
||||
return result_dict
|
||||
|
||||
# 单条消息处理
|
||||
@db_error
|
||||
def get_msg_detail(self, row):
|
||||
@ -250,140 +384,6 @@ class MsgHandler(DatabaseBase):
|
||||
"CreateTime": CreateTime, }
|
||||
return row_data
|
||||
|
||||
@db_error
|
||||
def get_msg_list(self, wxid="", start_index=0, page_size=500, msg_type: str = "", msg_sub_type: str = "",
|
||||
start_createtime=None, end_createtime=None):
|
||||
"""
|
||||
获取聊天记录列表
|
||||
:param wxid: wxid
|
||||
:param start_index: 起始索引
|
||||
:param page_size: 页大小
|
||||
:param msg_type: 消息类型
|
||||
:param msg_sub_type: 消息子类型
|
||||
:param start_createtime: 开始时间
|
||||
:param end_createtime: 结束时间
|
||||
:return: 聊天记录列表 {"id": _id, "MsgSvrID": str(MsgSvrID), "type_name": type_name, "is_sender": IsSender,
|
||||
"talker": talker, "room_name": StrTalker, "msg": msg, "src": src, "extra": {},
|
||||
"CreateTime": CreateTime, }
|
||||
"""
|
||||
if not self.tables_exist("MSG"):
|
||||
return [], []
|
||||
|
||||
param = ()
|
||||
sql_wxid, param = ("AND StrTalker=? ", param + (wxid,)) if wxid else ("", param)
|
||||
sql_type, param = ("AND Type=? ", param + (msg_type,)) if msg_type else ("", param)
|
||||
sql_sub_type, param = ("AND SubType=? ", param + (msg_sub_type,)) if msg_type and msg_sub_type else ("", param)
|
||||
sql_start_createtime, param = ("AND CreateTime>=? ", param + (start_createtime,)) if start_createtime else (
|
||||
"", param)
|
||||
sql_end_createtime, param = ("AND CreateTime<=? ", param + (end_createtime,)) if end_createtime else ("", param)
|
||||
|
||||
sql = (
|
||||
"SELECT localId,TalkerId,MsgSvrID,Type,SubType,CreateTime,IsSender,Sequence,StatusEx,FlagEx,Status,"
|
||||
"MsgSequence,StrContent,MsgServerSeq,StrTalker,DisplayContent,Reserved0,Reserved1,Reserved3,"
|
||||
"Reserved4,Reserved5,Reserved6,CompressContent,BytesExtra,BytesTrans,Reserved2,"
|
||||
"ROW_NUMBER() OVER (ORDER BY CreateTime ASC) AS id "
|
||||
"FROM MSG WHERE 1=1 "
|
||||
f"{sql_wxid}"
|
||||
f"{sql_type}"
|
||||
f"{sql_sub_type}"
|
||||
f"{sql_start_createtime}"
|
||||
f"{sql_end_createtime}"
|
||||
f"ORDER BY CreateTime ASC LIMIT ?,?"
|
||||
)
|
||||
param = param + (start_index, page_size)
|
||||
result = self.execute(sql, param)
|
||||
if not result:
|
||||
return [], []
|
||||
|
||||
result_data = (self.get_msg_detail(row) for row in result)
|
||||
rdata = list(result_data) # 转为列表
|
||||
wxid_list = {d['talker'] for d in rdata} # 创建一个无重复的 wxid 列表
|
||||
|
||||
return rdata, list(wxid_list)
|
||||
|
||||
@db_error
|
||||
def get_date_count(self, wxid='', start_time: int = 0, end_time: int = 0, time_format='%Y-%m-%d'):
|
||||
"""
|
||||
获取每日聊天记录数量,包括发送者数量、接收者数量和总数。
|
||||
"""
|
||||
if not self.tables_exist("MSG"):
|
||||
return {}
|
||||
if isinstance(start_time, str) and start_time.isdigit():
|
||||
start_time = int(start_time)
|
||||
if isinstance(end_time, str) and end_time.isdigit():
|
||||
end_time = int(end_time)
|
||||
|
||||
# if start_time or end_time is not an integer and not a float, set both to 0
|
||||
if not (isinstance(start_time, (int, float)) and isinstance(end_time, (int, float))):
|
||||
start_time = 0
|
||||
end_time = 0
|
||||
params = ()
|
||||
|
||||
sql_wxid = "AND StrTalker = ? " if wxid else ""
|
||||
params = params + (wxid,) if wxid else params
|
||||
|
||||
sql_time = "AND CreateTime BETWEEN ? AND ? " if start_time and end_time else ""
|
||||
params = params + (start_time, end_time) if start_time and end_time else params
|
||||
|
||||
sql = (f"SELECT strftime('{time_format}', CreateTime, 'unixepoch', 'localtime') AS date, "
|
||||
" COUNT(*) AS total_count ,"
|
||||
" SUM(CASE WHEN IsSender = 1 THEN 1 ELSE 0 END) AS sender_count, "
|
||||
" SUM(CASE WHEN IsSender = 0 THEN 1 ELSE 0 END) AS receiver_count "
|
||||
"FROM MSG "
|
||||
"WHERE StrTalker NOT LIKE '%chatroom%' "
|
||||
f"{sql_wxid} {sql_time} "
|
||||
f"GROUP BY date ORDER BY date ASC;")
|
||||
result = self.execute(sql, params)
|
||||
|
||||
if not result:
|
||||
return {}
|
||||
# 将查询结果转换为字典
|
||||
result_dict = {}
|
||||
for row in result:
|
||||
date, total_count, sender_count, receiver_count = row
|
||||
result_dict[date] = {
|
||||
"sender_count": sender_count,
|
||||
"receiver_count": receiver_count,
|
||||
"total_count": total_count
|
||||
}
|
||||
return result_dict
|
||||
|
||||
@db_error
|
||||
def get_top_talker_count(self, top: int = 10, start_time: int = 0, end_time: int = 0):
|
||||
"""
|
||||
获取聊天记录数量最多的联系人,他们聊天记录数量
|
||||
"""
|
||||
if not self.tables_exist("MSG"):
|
||||
return {}
|
||||
if isinstance(start_time, str) and start_time.isdigit():
|
||||
start_time = int(start_time)
|
||||
if isinstance(end_time, str) and end_time.isdigit():
|
||||
end_time = int(end_time)
|
||||
|
||||
# if start_time or end_time is not an integer and not a float, set both to 0
|
||||
if not (isinstance(start_time, (int, float)) and isinstance(end_time, (int, float))):
|
||||
start_time = 0
|
||||
end_time = 0
|
||||
|
||||
sql_time = f"AND CreateTime BETWEEN {start_time} AND {end_time} " if start_time and end_time else ""
|
||||
sql = (
|
||||
"SELECT StrTalker, COUNT(*) AS count,"
|
||||
"SUM(CASE WHEN IsSender = 1 THEN 1 ELSE 0 END) AS sender_count, "
|
||||
"SUM(CASE WHEN IsSender = 0 THEN 1 ELSE 0 END) AS receiver_count "
|
||||
"FROM MSG "
|
||||
"WHERE StrTalker NOT LIKE '%chatroom%' "
|
||||
f"{sql_time} "
|
||||
"GROUP BY StrTalker ORDER BY count DESC "
|
||||
f"LIMIT {top};"
|
||||
)
|
||||
result = self.execute(sql)
|
||||
if not result:
|
||||
return {}
|
||||
# 将查询结果转换为字典
|
||||
result_dict = {row[0]: {"total_count": row[1], "sender_count": row[2], "receiver_count": row[3]} for row in
|
||||
result}
|
||||
return result_dict
|
||||
|
||||
|
||||
@db_error
|
||||
def decompress_CompressContent(data):
|
||||
|
@ -1,22 +1,61 @@
|
||||
# -*- coding: utf-8 -*-#
|
||||
# -------------------------------------------------------------------------------
|
||||
# Name: Sns.py
|
||||
# Description: 负责处理朋友圈相关数据
|
||||
# Description: 负责处理朋友圈相关数据 软件只能看到在电脑微信浏览过的朋友圈记录
|
||||
# Author: xaoyaoo
|
||||
# Date: 2024/04/15
|
||||
# -------------------------------------------------------------------------------
|
||||
from .dbbase import DatabaseBase
|
||||
from .utils import silk2audio
|
||||
import json
|
||||
|
||||
from .dbbase import DatabaseBase
|
||||
from .utils import silk2audio, xml2dict, timestamp2str
|
||||
|
||||
|
||||
# FeedsV20:朋友圈的XML数据
|
||||
# CommentV20:朋友圈点赞或评论记录
|
||||
# NotificationV7:朋友圈通知
|
||||
# SnsConfigV20:一些配置信息,能读懂的是其中有你的朋友圈背景图
|
||||
# SnsGroupInfoV5:猜测是旧版微信朋友圈可见范围的可见或不可见名单
|
||||
|
||||
class SnsHandler(DatabaseBase):
|
||||
_class_name = "Sns"
|
||||
Media_required_tables = ["AdFeedsV8", "FeedsV20", "CommentV20", "NotificationV7", "SnsConfigV20", "SnsFailureV5",
|
||||
"SnsGroupInfoV5", "SnsNoNotifyV5"]
|
||||
"""
|
||||
FeedsV20:朋友圈的XML数据
|
||||
CommentV20:朋友圈点赞或评论记录
|
||||
NotificationV7:朋友圈通知
|
||||
SnsConfigV20:一些配置信息,能读懂的是其中有你的朋友圈背景图
|
||||
SnsGroupInfoV5:猜测是旧版微信朋友圈可见范围的可见或不可见名单
|
||||
"""
|
||||
|
||||
def get_sns_feed(self):
|
||||
"""
|
||||
获取朋友圈数据
|
||||
"""
|
||||
sql = ("SELECT FeedId, CreateTime, FaultId, Type, UserName, Status, ExtFlag, PrivFlag, StringId, Content, "
|
||||
"Reserved1, Reserved2, Reserved3, Reserved4, Reserved5, Reserved6, ExtraBuf, Reserved7 "
|
||||
"FROM FeedsV20 "
|
||||
"ORDER BY CreateTime DESC")
|
||||
FeedsV20 = self.execute(sql)
|
||||
for row in FeedsV20[2:]:
|
||||
(FeedId, CreateTime, FaultId, Type, UserName, Status, ExtFlag, PrivFlag, StringId, Content,
|
||||
Reserved1, Reserved2, Reserved3, Reserved4, Reserved5, Reserved6, ExtraBuf, Reserved7) = row
|
||||
|
||||
Content = xml2dict(Content) if Content and Content.startswith("<") else Content
|
||||
CreateTime = timestamp2str(CreateTime)
|
||||
print(f""
|
||||
f"{FeedId=}\n"
|
||||
f"{CreateTime=}\n"
|
||||
f"{FaultId=}\n"
|
||||
f"{Type=}\n"
|
||||
f"{UserName=}\n"
|
||||
f"{Status=}\n"
|
||||
f"{ExtFlag=}\n"
|
||||
f"{PrivFlag=}\n"
|
||||
f"{StringId=}\n\n"
|
||||
f"{json.dumps(Content,indent=4,ensure_ascii=False)}\n\n"
|
||||
f"{ExtraBuf=}\n"
|
||||
f"{Reserved1=}\n"
|
||||
f"{Reserved2=}\n"
|
||||
f"{Reserved3=}\n"
|
||||
f"{Reserved4=}\n"
|
||||
f"{Reserved5=}\n"
|
||||
f"{Reserved6=}\n"
|
||||
f"{Reserved7=}\n"
|
||||
)
|
||||
|
||||
break
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user