增加五个数据统计接口

This commit is contained in:
STDquantum 2023-12-20 18:19:17 +08:00
parent 261ac8ea27
commit 8f12d9a3d0
3 changed files with 176 additions and 21 deletions

View File

@ -10,6 +10,7 @@ import html
import re import re
from app.log import logger from app.log import logger
from app.util.compress_content import parser_reply
db_path = "./app/Database/Msg/MSG.db" db_path = "./app/Database/Msg/MSG.db"
lock = threading.Lock() lock = threading.Lock()
@ -153,7 +154,7 @@ class Msg:
sql = ''' sql = '''
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
from MSG from MSG
where StrTalker=? and Type=? and strftime('%Y',CreateTime,'unixepoch','localtime') = ? where StrTalker=? and Type=? and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?
order by CreateTime order by CreateTime
''' '''
else: else:
@ -323,7 +324,7 @@ class Msg:
from ( from (
SELECT MsgSvrID, CreateTime SELECT MsgSvrID, CreateTime
FROM MSG FROM MSG
where StrTalker = ? and strftime('%Y',CreateTime,'unixepoch','localtime') = ? where StrTalker = ? and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?
) )
group by hours group by hours
''' '''
@ -372,6 +373,155 @@ class Msg:
lock.release() lock.release()
return result return result
def get_send_messages_type_number(self, year_="all") -> list:
"""
统计自己发的各类型消息条数按条数降序精确到subtype\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)]
"""
sql = f"""
SELECT type, subtype, Count(MsgSvrID)
from MSG
where isSender = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
group by type, subtype
order by Count(MsgSvrID) desc
"""
result = None
if not self.open_flag:
return None
try:
lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else [])
result = self.cursor.fetchall()
except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
finally:
lock.release()
return result
def get_chatted_top_contacts(self, year_="all", contain_chatroom=False, top_n=10) -> list:
"""
统计聊天最多的 n 个联系人默认不包含群组按条数降序\n
return [(wxid_1, number_1), (wxid_2, number_2), ...]
"""
sql = f"""
SELECT strtalker, Count(MsgSvrID)
from MSG
where strtalker != "filehelper" and strtalker != "notifymessage" and strtalker not like "gh_%"
{"and strtalker not like '%@chatroom'" if not contain_chatroom else ""}
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
group by strtalker
order by Count(MsgSvrID) desc
limit {top_n}
"""
result = None
if not self.open_flag:
return None
try:
lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else [])
result = self.cursor.fetchall()
except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
finally:
lock.release()
return result
def get_send_messages_length(self, year_="all") -> int:
"""
统计自己总共发消息的字数包含type=1的文本和type=49,subtype=57里面自己发的文本
"""
sql_type_1 = f"""
SELECT sum(length(strContent))
from MSG
where isSender = 1 and type = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
"""
sql_type_49 = f"""
SELECT CompressContent
from MSG
where isSender = 1 and type = 49 and subtype = 57
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
"""
sum_type_1 = None
result_type_49 = None
sum_type_49 = 0
if not self.open_flag:
return None
try:
lock.acquire(True)
self.cursor.execute(sql_type_1, [year_] if year_ != "all" else [])
sum_type_1 = self.cursor.fetchall()[0][0]
self.cursor.execute(sql_type_49, [year_] if year_ != "all" else [])
result_type_49 = self.cursor.fetchall()
for message in result_type_49:
message = message[0]
content = parser_reply(message)
if content["is_error"]:
continue
sum_type_49 += len(content["title"])
except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
finally:
lock.release()
return sum_type_1 + sum_type_49
def get_send_messages_number_sum(self, year_="all") -> int:
"""统计自己总共发了多少条消息"""
sql = f"""
SELECT count(MsgSvrID)
from MSG
where isSender = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
"""
result = None
if not self.open_flag:
return None
try:
lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else [])
result = self.cursor.fetchall()[0][0]
except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
finally:
lock.release()
return result
def get_send_messages_number_by_hour(self, year_="all"):
"""
统计每个小时时段自己总共发了多少消息从最多到最少排序\n
return be like [('23', 9526), ('00', 7890), ('22', 7600), ..., ('05', 29)]
"""
sql = f"""
SELECT strftime('%H', CreateTime, 'unixepoch', 'localtime') as hour,count(MsgSvrID)
from (
SELECT MsgSvrID, CreateTime
FROM MSG
where isSender = 1
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
)
group by hour
order by count(MsgSvrID) desc
"""
result = None
if not self.open_flag:
return None
try:
lock.acquire(True)
self.cursor.execute(sql, [year_] if year_ != "all" else [])
result = self.cursor.fetchall()
except sqlite3.DatabaseError:
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
finally:
lock.release()
return result
def close(self): def close(self):
if self.open_flag: if self.open_flag:
try: try:
@ -386,16 +536,18 @@ class Msg:
if __name__ == '__main__': if __name__ == '__main__':
db_path = "./Msg/MSG.db" db_path = "./app/database/Msg/MSG.db"
msg = Msg() msg = Msg()
msg.init_database() msg.init_database()
result = msg.get_message_by_num('wxid_vtz9jk9ulzjt22', 9999999) print(msg.get_chatted_top_contacts(year_="2023"))
print(result) print(msg.get_chatted_top_contacts(year_="2023", contain_chatroom=True, top_n=20))
result = msg.get_messages_by_type('wxid_vtz9jk9ulzjt22', 49) # result = msg.get_message_by_num("wxid_vtz9jk9ulzjt22", 9999999)
for r in result: # print(result)
type_ = r[2] # result = msg.get_messages_by_type("wxid_vtz9jk9ulzjt22", 49)
sub_type = r[3] # for r in result:
if type_ == 49 and sub_type == 57: # type_ = r[2]
print(r) # sub_type = r[3]
print(r[-1]) # if type_ == 49 and sub_type == 57:
break # print(r)
# print(r[-1])
# break

View File

@ -389,13 +389,13 @@ class ChildThread(QThread):
displayname = MePC().name if is_send else self.contact.remark displayname = MePC().name if is_send else self.contact.remark
displayname = escape_js_and_html(displayname) displayname = escape_js_and_html(displayname)
if self.output_type == Output.HTML: if self.output_type == Output.HTML:
contentText = content.get('title') contentText = escape_js_and_html(content.get('title'))
emojiText = findall(r"(\[.+?\])", contentText) emojiText = findall(r"(\[.+?\])", contentText)
for emoji_text in emojiText: for emoji_text in emojiText:
if emoji_text in emoji: if emoji_text in emoji:
contentText = contentText.replace(emoji_text, emoji[emoji_text]) contentText = contentText.replace(emoji_text, emoji[emoji_text])
if refer_msg: if refer_msg:
referText = f"{refer_msg.get('displayname')}{refer_msg.get('content')}" referText = f"{escape_js_and_html(refer_msg.get('displayname'))}{escape_js_and_html(refer_msg.get('content'))}"
emojiText = findall(r"(\[.+?\])", referText) emojiText = findall(r"(\[.+?\])", referText)
for emoji_text in emojiText: for emoji_text in emojiText:
if emoji_text in emoji: if emoji_text in emoji:

View File

@ -46,7 +46,8 @@ def parser_reply(data: bytes):
'type': '1', 'type': '1',
'content': '引用错误', 'content': '引用错误',
'displayname': '用户名', 'displayname': '用户名',
} },
"is_error": True
} }
try: try:
root = ET.XML(xml_content) root = ET.XML(xml_content)
@ -58,12 +59,13 @@ def parser_reply(data: bytes):
refermsg_displayname = appmsg.find('refermsg').find('displayname').text refermsg_displayname = appmsg.find('refermsg').find('displayname').text
return { return {
'type': msg_type, 'type': msg_type,
'title': escape_js_and_html(title), 'title': title,
'refer': None if refermsg_type != 1 else { 'refer': None if refermsg_type != 1 else {
'type': refermsg_type, 'type': refermsg_type,
'content': escape_js_and_html(refermsg_content.lstrip("\n")), 'content': refermsg_content.lstrip("\n"),
'displayname': escape_js_and_html(refermsg_displayname), 'displayname': refermsg_displayname,
} },
"is_error": False
} }
except: except:
return { return {
@ -73,5 +75,6 @@ def parser_reply(data: bytes):
'type': '1', 'type': '1',
'content': '引用错误', 'content': '引用错误',
'displayname': '用户名', 'displayname': '用户名',
} },
"is_error": True
} }