修改消息查找的时间范围参数

This commit is contained in:
SiYuan 2024-02-07 22:52:05 +08:00
parent cf8ebec645
commit ad0482e856

View File

@ -3,6 +3,8 @@ import random
import sqlite3 import sqlite3
import threading import threading
import traceback import traceback
from datetime import datetime, date
from typing import Tuple
from app.log import logger from app.log import logger
from app.util.compress_content import parser_reply from app.util.compress_content import parser_reply
@ -16,6 +18,40 @@ def is_database_exist():
return os.path.exists(db_path) return os.path.exists(db_path)
def convert_to_timestamp_(time_input) -> int:
if isinstance(time_input, (int, float)):
# 如果输入是时间戳,直接返回
return int(time_input)
elif isinstance(time_input, str):
# 如果输入是格式化的时间字符串,将其转换为时间戳
try:
dt_object = datetime.strptime(time_input, '%Y-%m-%d %H:%M:%S')
return int(dt_object.timestamp())
except ValueError:
# 如果转换失败,可能是其他格式的字符串,可以根据需要添加更多的处理逻辑
print("Error: Unsupported date format")
return -1
elif isinstance(time_input, date):
# 如果输入是datetime.date对象将其转换为时间戳
dt_object = datetime.combine(time_input, datetime.min.time())
return int(dt_object.timestamp())
else:
print("Error: Unsupported input type")
return -1
def convert_to_timestamp(time_range) -> Tuple[int, int]:
"""
将时间转换成时间戳
@param time_range:
@return:
"""
if not time_range:
return 0, 0
else:
return convert_to_timestamp_(time_range[0]), convert_to_timestamp_(time_range[1])
def parser_chatroom_message(messages): def parser_chatroom_message(messages):
from app.DataBase import micro_msg_db, misc_db from app.DataBase import micro_msg_db, misc_db
from app.util.protocbuf.msg_pb2 import MessageBytesExtra from app.util.protocbuf.msg_pb2 import MessageBytesExtra
@ -61,7 +97,7 @@ def parser_chatroom_message(messages):
updated_messages.append(tuple(message)) updated_messages.append(tuple(message))
continue continue
# todo 解析还是有问题,会出现这种带:的东西 # todo 解析还是有问题,会出现这种带:的东西
if ':' in wxid: # wxid_ewi8gfgpp0eu22:25319:1 if ':' in wxid: # wxid_ewi8gfgpp0eu22:25319:1
wxid = wxid.split(':')[0] wxid = wxid.split(':')[0]
contact_info_list = micro_msg_db.get_contact_by_username(wxid) contact_info_list = micro_msg_db.get_contact_by_username(wxid)
if contact_info_list is None: # 群聊中已退群的联系人不会保存在数据库里 if contact_info_list is None: # 群聊中已退群的联系人不会保存在数据库里
@ -143,7 +179,11 @@ class Msg:
new_messages.append(new_message) new_messages.append(new_message)
return new_messages return new_messages
def get_messages(self, username_, time_range=None): def get_messages(
self,
username_,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
):
""" """
return list return list
a[0]: localId, a[0]: localId,
@ -164,7 +204,7 @@ class Msg:
if not self.open_flag: if not self.open_flag:
return None return None
if time_range: if time_range:
start_time, end_time = time_range start_time, end_time = convert_to_timestamp(time_range)
sql = f''' sql = f'''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent,DisplayContent select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent,DisplayContent
from MSG from MSG
@ -239,7 +279,13 @@ class Msg:
# result.sort(key=lambda x: x[5]) # result.sort(key=lambda x: x[5])
return parser_chatroom_message(result) if username_.__contains__('@chatroom') else result return parser_chatroom_message(result) if username_.__contains__('@chatroom') else result
def get_messages_by_type(self, username_, type_, year_='all', time_range=None): def get_messages_by_type(
self,
username_,
type_,
year_='all',
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
):
""" """
@param username_: @param username_:
@param type_: @param type_:
@ -250,7 +296,7 @@ class Msg:
if not self.open_flag: if not self.open_flag:
return None return None
if time_range: if time_range:
start_time, end_time = time_range start_time, end_time = convert_to_timestamp(time_range)
if year_ == 'all': if year_ == 'all':
sql = f''' sql = f'''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent,DisplayContent select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent,DisplayContent
@ -379,12 +425,16 @@ class Msg:
lock.release() lock.release()
return [date[0] for date in result] return [date[0] for date in result]
def get_messages_by_days(self, username_, time_range=None): def get_messages_by_days(
self,
username_,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
):
result = None result = None
if not self.open_flag: if not self.open_flag:
return None return None
if time_range: if time_range:
start_time, end_time = time_range start_time, end_time = convert_to_timestamp(time_range)
sql = f''' sql = f'''
SELECT strftime('%Y-%m-%d',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID) SELECT strftime('%Y-%m-%d',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
from ( from (
@ -406,12 +456,16 @@ class Msg:
lock.release() lock.release()
return result return result
def get_messages_by_month(self, username_, time_range=None): def get_messages_by_month(
self,
username_,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
):
result = None result = None
if not self.open_flag: if not self.open_flag:
return None return None
if time_range: if time_range:
start_time, end_time = time_range start_time, end_time = convert_to_timestamp(time_range)
sql = f''' sql = f'''
SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID) SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
from ( from (
@ -474,32 +528,33 @@ class Msg:
result = self.cursor.fetchall() result = self.cursor.fetchall()
return result return result
def get_first_time_of_message(self, username_): def get_first_time_of_message(self, username_=''):
if not self.open_flag: if not self.open_flag:
return None return None
sql = ''' sql = f'''
select StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime select StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime
from MSG from MSG
where StrTalker=? {'where StrTalker=?' if username_ else ''}
order by CreateTime order by CreateTime
limit 1 limit 1
''' '''
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql, [username_]) self.cursor.execute(sql, [username_] if username_ else [])
result = self.cursor.fetchone() result = self.cursor.fetchone()
finally: finally:
lock.release() lock.release()
return result return result
def get_latest_time_of_message(self, username_, year_='all'): def get_latest_time_of_message(self, username_='', year_='all'):
if not self.open_flag: if not self.open_flag:
return None return None
sql = f''' sql = f'''
SELECT isSender,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime, SELECT isSender,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,
strftime('%H:%M:%S', CreateTime,'unixepoch','localtime') as hour strftime('%H:%M:%S', CreateTime,'unixepoch','localtime') as hour
FROM MSG FROM MSG
WHERE StrTalker = ? AND Type=1 AND WHERE Type=1 AND
{'StrTalker = ? AND ' if username_ else f"'{username_}'=? AND "}
hour BETWEEN '00:00:00' AND '05:00:00' hour BETWEEN '00:00:00' AND '05:00:00'
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
ORDER BY hour DESC ORDER BY hour DESC
@ -524,18 +579,22 @@ class Msg:
break break
return res return res
def get_send_messages_type_number(self, year_="all") -> list: def get_send_messages_type_number(
self,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
) -> list:
""" """
统计自己发的各类型消息条数按条数降序精确到subtype\n 统计自己发的各类型消息条数按条数降序精确到subtype\n
return [(type_1, subtype_1, number_1), (type_2, subtype_2, number_2), ...]\n return [(type_1, subtype_1, number_1), (type_2, subtype_2, number_2), ...]\n
be like [(1, 0, 71481), (3, 0, 6686), (49, 57, 3887), ..., (10002, 0, 1)] be like [(1, 0, 71481), (3, 0, 6686), (49, 57, 3887), ..., (10002, 0, 1)]
""" """
if time_range:
start_time, end_time = convert_to_timestamp(time_range)
sql = f""" sql = f"""
SELECT type, subtype, Count(MsgSvrID) SELECT type, subtype, Count(MsgSvrID)
from MSG from MSG
where isSender = 1 where isSender = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
group by type, subtype group by type, subtype
order by Count(MsgSvrID) desc order by Count(MsgSvrID) desc
""" """
@ -544,7 +603,7 @@ class Msg:
return None return None
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else []) self.cursor.execute(sql)
result = self.cursor.fetchall() result = self.cursor.fetchall()
except sqlite3.DatabaseError: except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试') logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
@ -552,20 +611,28 @@ class Msg:
lock.release() lock.release()
return result return result
def get_messages_number(self, username_, time_range=None) -> int: def get_messages_number(
self,
username_,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
) -> int:
"""
统计好友聊天消息的数量
@param username_:
@param time_range:
@return:
"""
if time_range: if time_range:
start_time, end_time = time_range start_time, end_time = convert_to_timestamp(time_range)
sql = f""" sql = f"""
SELECT Count(MsgSvrID) SELECT Count(MsgSvrID)
from MSG from MSG
where StrTalker = ? where StrTalker = ?
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
group by type, subtype
order by Count(MsgSvrID) desc
""" """
result = None result = 0
if not self.open_flag: if not self.open_flag:
return None return 0
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql, [username_]) self.cursor.execute(sql, [username_])
@ -576,18 +643,24 @@ class Msg:
lock.release() lock.release()
return result[0] if result else 0 return result[0] if result else 0
def get_chatted_top_contacts(self, year_="all", contain_chatroom=False, top_n=10) -> list: def get_chatted_top_contacts(
self,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
contain_chatroom=False,
top_n=10
) -> list:
""" """
统计聊天最多的 n 个联系人默认不包含群组按条数降序\n 统计聊天最多的 n 个联系人默认不包含群组按条数降序\n
return [(wxid_1, number_1), (wxid_2, number_2), ...] return [(wxid_1, number_1), (wxid_2, number_2), ...]
""" """
if time_range:
start_time, end_time = convert_to_timestamp(time_range)
sql = f""" sql = f"""
SELECT strtalker, Count(MsgSvrID) SELECT strtalker, Count(MsgSvrID)
from MSG from MSG
where strtalker != "filehelper" and strtalker != "notifymessage" and strtalker not like "gh_%" where strtalker != "filehelper" and strtalker != "notifymessage" and strtalker not like "gh_%"
{"and strtalker not like '%@chatroom'" if not contain_chatroom else ""} {"and strtalker not like '%@chatroom'" if not contain_chatroom else ""}
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
group by strtalker group by strtalker
order by Count(MsgSvrID) desc order by Count(MsgSvrID) desc
limit {top_n} limit {top_n}
@ -597,7 +670,7 @@ class Msg:
return None return None
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else []) self.cursor.execute(sql)
result = self.cursor.fetchall() result = self.cursor.fetchall()
except sqlite3.DatabaseError: except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试') logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
@ -605,22 +678,26 @@ class Msg:
lock.release() lock.release()
return result return result
def get_send_messages_length(self, year_="all") -> int: def get_send_messages_length(
self,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
) -> int:
""" """
统计自己总共发消息的字数包含type=1的文本和type=49,subtype=57里面自己发的文本 统计自己总共发消息的字数包含type=1的文本和type=49,subtype=57里面自己发的文本
""" """
if time_range:
start_time, end_time = convert_to_timestamp(time_range)
sql_type_1 = f""" sql_type_1 = f"""
SELECT sum(length(strContent)) SELECT sum(length(strContent))
from MSG from MSG
where isSender = 1 and type = 1 where isSender = 1 and type = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
""" """
sql_type_49 = f""" sql_type_49 = f"""
SELECT CompressContent SELECT CompressContent
from MSG from MSG
where isSender = 1 and type = 49 and subtype = 57 where isSender = 1 and type = 49 and subtype = 57
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
""" """
sum_type_1 = None sum_type_1 = None
result_type_49 = None result_type_49 = None
@ -630,9 +707,9 @@ class Msg:
return None return None
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql_type_1, [year_] if year_ != "all" else []) self.cursor.execute(sql_type_1)
sum_type_1 = self.cursor.fetchall()[0][0] sum_type_1 = self.cursor.fetchall()[0][0]
self.cursor.execute(sql_type_49, [year_] if year_ != "all" else []) self.cursor.execute(sql_type_49)
result_type_49 = self.cursor.fetchall() result_type_49 = self.cursor.fetchall()
for message in result_type_49: for message in result_type_49:
message = message[0] message = message[0]
@ -646,21 +723,25 @@ class Msg:
lock.release() lock.release()
return sum_type_1 + sum_type_49 return sum_type_1 + sum_type_49
def get_send_messages_number_sum(self, year_="all") -> int: def get_send_messages_number_sum(
self,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
) -> int:
"""统计自己总共发了多少条消息""" """统计自己总共发了多少条消息"""
if time_range:
start_time, end_time = convert_to_timestamp(time_range)
sql = f""" sql = f"""
SELECT count(MsgSvrID) SELECT count(MsgSvrID)
from MSG from MSG
where isSender = 1 where isSender = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
""" """
result = None result = None
if not self.open_flag: if not self.open_flag:
return None return None
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else []) self.cursor.execute(sql)
result = self.cursor.fetchall()[0][0] result = self.cursor.fetchall()[0][0]
except sqlite3.DatabaseError: except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试') logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
@ -668,18 +749,23 @@ class Msg:
lock.release() lock.release()
return result return result
def get_send_messages_number_by_hour(self, year_="all"): def get_send_messages_number_by_hour(
self,
time_range: Tuple[int | float | str | date, int | float | str | date] = None,
)->list:
""" """
统计每个小时时段自己总共发了多少消息从最多到最少排序\n 统计每个小时时段自己总共发了多少消息从最多到最少排序\n
return be like [('23', 9526), ('00', 7890), ('22', 7600), ..., ('05', 29)] return be like [('23', 9526), ('00', 7890), ('22', 7600), ..., ('05', 29)]
""" """
if time_range:
start_time, end_time = convert_to_timestamp(time_range)
sql = f""" sql = f"""
SELECT strftime('%H', CreateTime, 'unixepoch', 'localtime') as hour,count(MsgSvrID) SELECT strftime('%H', CreateTime, 'unixepoch', 'localtime') as hour,count(MsgSvrID)
from ( from (
SELECT MsgSvrID, CreateTime SELECT MsgSvrID, CreateTime
FROM MSG FROM MSG
where isSender = 1 where isSender = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""} {'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
) )
group by hour group by hour
order by count(MsgSvrID) desc order by count(MsgSvrID) desc
@ -689,7 +775,7 @@ class Msg:
return None return None
try: try:
lock.acquire(True) lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else []) self.cursor.execute(sql)
result = self.cursor.fetchall() result = self.cursor.fetchall()
except sqlite3.DatabaseError: except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试') logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
@ -718,4 +804,10 @@ if __name__ == '__main__':
wxid = '24521163022@chatroom' wxid = '24521163022@chatroom'
wxid = 'wxid_vtz9jk9ulzjt22' # si wxid = 'wxid_vtz9jk9ulzjt22' # si
print() print()
time_range = ('2023-01-01 00:00:00', '2024-01-01 00:00:00')
print(msg.get_messages_calendar(wxid)) print(msg.get_messages_calendar(wxid))
print(msg.get_first_time_of_message())
print(msg.get_latest_time_of_message())
top_n = msg.get_chatted_top_contacts(time_range=time_range, top_n=9999999)
print(top_n)
print(len(top_n))