mirror of
https://github.com/LC044/WeChatMsg
synced 2025-04-19 02:08:05 +08:00
147 lines
5.1 KiB
Python
147 lines
5.1 KiB
Python
|
#!/usr/bin/env python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
|
|||
|
"""
|
|||
|
@Time : 2025/2/17 21:43
|
|||
|
@Author : SiYuan
|
|||
|
@Email : 863909694@qq.com
|
|||
|
@File : MemoTrace-open_im_msg.py
|
|||
|
@Description :
|
|||
|
"""
|
|||
|
|
|||
|
import os.path
|
|||
|
import sqlite3
|
|||
|
import threading
|
|||
|
import traceback
|
|||
|
import concurrent
|
|||
|
import hashlib
|
|||
|
import threading
|
|||
|
from collections import defaultdict
|
|||
|
from concurrent.futures import ThreadPoolExecutor
|
|||
|
from datetime import datetime, date
|
|||
|
from typing import Tuple
|
|||
|
|
|||
|
from wxManager.merge import increase_data, increase_update_data
|
|||
|
from wxManager.log import logger
|
|||
|
from wxManager.model import DataBaseBase
|
|||
|
from wxManager.parser.util.protocbuf.msg_pb2 import MessageBytesExtra
|
|||
|
|
|||
|
|
|||
|
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])
|
|||
|
|
|||
|
|
|||
|
class OpenIMMsgDB(DataBaseBase):
|
|||
|
|
|||
|
def _get_messages_by_num(self, cursor, username_, start_sort_seq, msg_num):
|
|||
|
"""
|
|||
|
|
|||
|
@param cursor:
|
|||
|
@param username_:
|
|||
|
@param start_sort_seq:
|
|||
|
@param msg_num:
|
|||
|
@return:
|
|||
|
"""
|
|||
|
sql = '''
|
|||
|
select localId,TalkerId,Type,statusEx,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,'',Reserved1
|
|||
|
from ChatCRMsg
|
|||
|
where StrTalker = ? and CreateTime < ?
|
|||
|
order by CreateTime desc
|
|||
|
limit ?
|
|||
|
'''
|
|||
|
cursor.execute(sql, [username_, start_sort_seq, msg_num])
|
|||
|
result = cursor.fetchall()
|
|||
|
if result:
|
|||
|
return result
|
|||
|
else:
|
|||
|
return []
|
|||
|
|
|||
|
def get_messages_by_num(self, username, start_sort_seq, msg_num=20):
|
|||
|
results = [self._get_messages_by_num(self.DB.cursor(), username, start_sort_seq, msg_num)]
|
|||
|
self.commit()
|
|||
|
return results
|
|||
|
|
|||
|
def _get_messages_by_username(self, cursor, username: str,
|
|||
|
time_range: Tuple[int | float | str | date, int | float | str | date] = None, ):
|
|||
|
if time_range:
|
|||
|
start_time, end_time = convert_to_timestamp(time_range)
|
|||
|
sql = f'''
|
|||
|
select localId,TalkerId,Type,statusEx,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,'',Reserved1
|
|||
|
from ChatCRMsg
|
|||
|
where StrTalker=?
|
|||
|
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
|||
|
order by CreateTime
|
|||
|
'''
|
|||
|
cursor.execute(sql, [username])
|
|||
|
result = cursor.fetchall()
|
|||
|
if result:
|
|||
|
return result
|
|||
|
else:
|
|||
|
return []
|
|||
|
|
|||
|
def get_messages_by_username(self, username: str,
|
|||
|
time_range: Tuple[int | float | str | date, int | float | str | date] = None, ):
|
|||
|
result = self._get_messages_by_username(self.DB.cursor(), username, time_range)
|
|||
|
return [result]
|
|||
|
|
|||
|
def get_message_by_server_id(self, username, server_id):
|
|||
|
"""
|
|||
|
获取小于start_sort_seq的msg_num个消息
|
|||
|
@param username:
|
|||
|
@param server_id:
|
|||
|
@return: messages, 最后一条消息的start_sort_seq
|
|||
|
"""
|
|||
|
sql = f'''
|
|||
|
select localId,TalkerId,Type,statusEx,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,'',Reserved1
|
|||
|
from ChatCRMsg
|
|||
|
where MsgSvrID=?
|
|||
|
'''
|
|||
|
for db in self.DB:
|
|||
|
cursor = db.cursor()
|
|||
|
cursor.execute(sql, [server_id])
|
|||
|
result = cursor.fetchone()
|
|||
|
if result:
|
|||
|
return result
|
|||
|
|
|||
|
return None
|
|||
|
|
|||
|
def merge(self, db_path):
|
|||
|
if not (os.path.exists(db_path) or os.path.isfile(db_path)):
|
|||
|
print(f'{db_path} 不存在')
|
|||
|
return
|
|||
|
try:
|
|||
|
# 获取列名
|
|||
|
increase_update_data(db_path, self.cursor, self.DB, 'ChatCRMsg', 'MsgSvrID', 1, exclude_first_column=True)
|
|||
|
except:
|
|||
|
print(f"数据库操作错误: {traceback.format_exc()}")
|
|||
|
self.DB.rollback()
|