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})
|
msg_count.update({row[0]: row[1] for row in result})
|
||||||
return msg_count
|
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
|
@db_error
|
||||||
def get_msg_detail(self, row):
|
def get_msg_detail(self, row):
|
||||||
@ -250,140 +384,6 @@ class MsgHandler(DatabaseBase):
|
|||||||
"CreateTime": CreateTime, }
|
"CreateTime": CreateTime, }
|
||||||
return row_data
|
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
|
@db_error
|
||||||
def decompress_CompressContent(data):
|
def decompress_CompressContent(data):
|
||||||
|
@ -1,22 +1,61 @@
|
|||||||
# -*- coding: utf-8 -*-#
|
# -*- coding: utf-8 -*-#
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
# Name: Sns.py
|
# Name: Sns.py
|
||||||
# Description: 负责处理朋友圈相关数据
|
# Description: 负责处理朋友圈相关数据 软件只能看到在电脑微信浏览过的朋友圈记录
|
||||||
# Author: xaoyaoo
|
# Author: xaoyaoo
|
||||||
# Date: 2024/04/15
|
# Date: 2024/04/15
|
||||||
# -------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------
|
||||||
from .dbbase import DatabaseBase
|
import json
|
||||||
from .utils import silk2audio
|
|
||||||
|
|
||||||
|
from .dbbase import DatabaseBase
|
||||||
|
from .utils import silk2audio, xml2dict, timestamp2str
|
||||||
|
|
||||||
|
|
||||||
|
# FeedsV20:朋友圈的XML数据
|
||||||
|
# CommentV20:朋友圈点赞或评论记录
|
||||||
|
# NotificationV7:朋友圈通知
|
||||||
|
# SnsConfigV20:一些配置信息,能读懂的是其中有你的朋友圈背景图
|
||||||
|
# SnsGroupInfoV5:猜测是旧版微信朋友圈可见范围的可见或不可见名单
|
||||||
|
|
||||||
class SnsHandler(DatabaseBase):
|
class SnsHandler(DatabaseBase):
|
||||||
_class_name = "Sns"
|
_class_name = "Sns"
|
||||||
Media_required_tables = ["AdFeedsV8", "FeedsV20", "CommentV20", "NotificationV7", "SnsConfigV20", "SnsFailureV5",
|
Media_required_tables = ["AdFeedsV8", "FeedsV20", "CommentV20", "NotificationV7", "SnsConfigV20", "SnsFailureV5",
|
||||||
"SnsGroupInfoV5", "SnsNoNotifyV5"]
|
"SnsGroupInfoV5", "SnsNoNotifyV5"]
|
||||||
"""
|
|
||||||
FeedsV20:朋友圈的XML数据
|
def get_sns_feed(self):
|
||||||
CommentV20:朋友圈点赞或评论记录
|
"""
|
||||||
NotificationV7:朋友圈通知
|
获取朋友圈数据
|
||||||
SnsConfigV20:一些配置信息,能读懂的是其中有你的朋友圈背景图
|
"""
|
||||||
SnsGroupInfoV5:猜测是旧版微信朋友圈可见范围的可见或不可见名单
|
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