Skip to content
This repository was archived by the owner on May 23, 2025. It is now read-only.

Commit 3841e84

Browse files
committed
feat: 保存消息到数据库,3天定时删除
1 parent 7b3bba0 commit 3841e84

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed

database/messsagDB.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import asyncio
22
import logging
33
import tomllib
4-
from datetime import datetime
4+
from datetime import datetime, timedelta
55
from typing import Optional, List
66

77
from pydantic import validate_arguments
8-
from sqlalchemy import Column, String, Integer, DateTime, Text, Boolean
8+
from sqlalchemy import Column, String, Integer, DateTime, Text, Boolean, delete
99
from sqlalchemy import select
1010
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_scoped_session
1111
from sqlalchemy.orm import declarative_base, sessionmaker
@@ -20,7 +20,7 @@ class Message(DeclarativeBase):
2020
__tablename__ = 'messages'
2121

2222
id = Column(Integer, primary_key=True, autoincrement=True)
23-
msg_id = Column(Integer, unique=True, index=True, comment='消息唯一ID(整型)')
23+
msg_id = Column(Integer, index=True, comment='消息唯一ID(整型)')
2424
sender_wxid = Column(String(40), index=True, comment='消息发送人wxid')
2525
from_wxid = Column(String(40), index=True, comment='消息来源wxid')
2626
msg_type = Column(Integer, comment='消息类型(整型编码)')
@@ -123,7 +123,26 @@ async def close(self):
123123
"""关闭数据库连接"""
124124
await self.engine.dispose()
125125

126+
async def cleanup_messages(self):
127+
"""每三天清理旧消息"""
128+
while True:
129+
async with self._async_session_factory() as session:
130+
try:
131+
# 计算三天前的时间
132+
three_days_ago = datetime.now() - timedelta(days=3)
133+
# 删除三天前的消息
134+
await session.execute(
135+
delete(Message).where(Message.timestamp < three_days_ago)
136+
)
137+
await session.commit()
138+
except Exception as e:
139+
logging.error(f"清理消息失败: {str(e)}")
140+
await session.rollback()
141+
await asyncio.sleep(259200) # 每三天(259200秒)执行一次
142+
126143
async def __aenter__(self):
144+
# 启动清理消息的定时任务
145+
asyncio.create_task(self.cleanup_messages())
127146
return self
128147

129148
async def __aexit__(self, exc_type, exc_val, exc_tb):

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ pymediainfo~=7.0.1
1818
matplotlib~=3.10.0
1919
numpy~=1.26.4
2020
requests~=2.32.3
21-
pillow~=10.4.0
21+
pillow~=10.4.0
22+
pydantic~=2.10.5

utils/xybot.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from WechatAPI import WechatAPIClient
88
from WechatAPI.Client.protect import protector
9+
from database.messsagDB import MessageDB
910
from utils.event_manager import EventManager
1011

1112

@@ -26,6 +27,8 @@ def __init__(self, bot_client: WechatAPIClient):
2627
self.whitelist = main_config.get("XYBot", {}).get("whitelist", [])
2728
self.blacklist = main_config.get("XYBot", {}).get("blacklist", [])
2829

30+
self.msg_db = MessageDB()
31+
2932

3033
def update_profile(self, wxid: str, nickname: str, alias: str, phone: str):
3134
"""更新机器人信息"""
@@ -117,6 +120,16 @@ async def process_text_message(self, message: Dict[str, Any]):
117120
ats = []
118121
message["Ats"] = ats if ats and ats[0] != "" else []
119122

123+
# 保存消息到数据库
124+
await self.msg_db.save_message(
125+
msg_id=int(message["MsgId"]),
126+
sender_wxid=message["SenderWxid"],
127+
from_wxid=message["FromWxid"],
128+
msg_type=int(message["MsgType"]),
129+
content=message["Content"],
130+
is_group=message["IsGroup"]
131+
)
132+
120133
if self.wxid in ats:
121134
logger.info("收到被@消息: 消息ID:{} 来自:{} 发送人:{} @:{} 内容:{}",
122135
message["MsgId"],
@@ -171,6 +184,15 @@ async def process_image_message(self, message: Dict[str, Any]):
171184
message["SenderWxid"],
172185
message["Content"])
173186

187+
await self.msg_db.save_message(
188+
msg_id=int(message["MsgId"]),
189+
sender_wxid=message["SenderWxid"],
190+
from_wxid=message["FromWxid"],
191+
msg_type=int(message["MsgType"]),
192+
content=message["MsgSource"],
193+
is_group=message["IsGroup"]
194+
)
195+
174196
# 解析图片消息
175197
aeskey, cdnmidimgurl = None, None
176198
try:
@@ -219,6 +241,15 @@ async def process_voice_message(self, message: Dict[str, Any]):
219241
message["SenderWxid"],
220242
message["Content"])
221243

244+
await self.msg_db.save_message(
245+
msg_id=int(message["MsgId"]),
246+
sender_wxid=message["SenderWxid"],
247+
from_wxid=message["FromWxid"],
248+
msg_type=int(message["MsgType"]),
249+
content=message["Content"],
250+
is_group=message["IsGroup"]
251+
)
252+
222253
if message["IsGroup"] or not message.get("ImgBuf", {}).get("buffer", ""):
223254
# 解析语音消息
224255
voiceurl, length = None, None
@@ -265,6 +296,15 @@ async def process_xml_message(self, message: Dict[str, Any]):
265296
message["FromWxid"] = message["ToWxid"]
266297
message["IsGroup"] = False
267298

299+
await self.msg_db.save_message(
300+
msg_id=int(message["MsgId"]),
301+
sender_wxid=message["SenderWxid"],
302+
from_wxid=message["FromWxid"],
303+
msg_type=int(message["MsgType"]),
304+
content=message["Content"],
305+
is_group=message["IsGroup"]
306+
)
307+
268308
try:
269309
root = ET.fromstring(message["Content"])
270310
type = int(root.find("appmsg").find("type").text)
@@ -413,6 +453,15 @@ async def process_video_message(self, message):
413453
message["SenderWxid"],
414454
str(message["Content"]).replace("\n", ""))
415455

456+
await self.msg_db.save_message(
457+
msg_id=int(message["MsgId"]),
458+
sender_wxid=message["SenderWxid"],
459+
from_wxid=message["FromWxid"],
460+
msg_type=int(message["MsgType"]),
461+
content=message["Content"],
462+
is_group=message["IsGroup"]
463+
)
464+
416465
message["Video"] = await self.bot.download_video(message["MsgId"])
417466

418467
if self.ignore_check(message["FromWxid"], message["SenderWxid"]):
@@ -441,6 +490,15 @@ async def process_file_message(self, message: Dict[str, Any]):
441490
message["SenderWxid"],
442491
message["Content"])
443492

493+
await self.msg_db.save_message(
494+
msg_id=int(message["MsgId"]),
495+
sender_wxid=message["SenderWxid"],
496+
from_wxid=message["FromWxid"],
497+
msg_type=int(message["MsgType"]),
498+
content=message["Content"],
499+
is_group=message["IsGroup"]
500+
)
501+
444502
message["File"] = await self.bot.download_attach(attach_id)
445503

446504
if self.ignore_check(message["FromWxid"], message["SenderWxid"]):
@@ -507,6 +565,15 @@ async def process_pat_message(self, message: Dict[str, Any]):
507565
message["Patted"],
508566
message["PatSuffix"])
509567

568+
await self.msg_db.save_message(
569+
msg_id=int(message["MsgId"]),
570+
sender_wxid=message["SenderWxid"],
571+
from_wxid=message["FromWxid"],
572+
msg_type=int(message["MsgType"]),
573+
content=f"{message['Patter']} 拍了拍 {message['Patted']} {message['PatSuffix']}",
574+
is_group=message["IsGroup"]
575+
)
576+
510577
if self.ignore_check(message["FromWxid"], message["SenderWxid"]):
511578
if self.ignore_protection or not protector.check(14400):
512579
await EventManager.emit("pat_message", self.bot, message)

0 commit comments

Comments
 (0)