Files
zhenxun_bot/zhenxun/utils/manager/message_manager.py
T

78 lines
2.3 KiB
Python
Raw Normal View History

2026-04-26 15:50:15 +08:00
from collections import OrderedDict
import time
2024-11-05 15:34:45 +08:00
from typing import ClassVar
class MessageManager:
2026-04-26 15:50:15 +08:00
_MAX_USERS: ClassVar[int] = 4096
_MAX_MESSAGES_PER_USER: ClassVar[int] = 200
_TRIM_MESSAGES_TO: ClassVar[int] = 100
_USER_TTL_SECONDS: ClassVar[float] = 6 * 60 * 60
data: ClassVar[OrderedDict[str, tuple[float, list[str]]]] = OrderedDict()
@classmethod
def _prune(cls, now: float | None = None) -> None:
now = time.monotonic() if now is None else now
stale_before = now - cls._USER_TTL_SECONDS
stale_uids = [
uid for uid, (last_seen, _) in cls.data.items() if last_seen <= stale_before
]
for uid in stale_uids:
cls.data.pop(uid, None)
while len(cls.data) > cls._MAX_USERS:
cls.data.popitem(last=False)
@classmethod
def _touch(cls, uid: str, messages: list[str], now: float | None = None) -> None:
now = time.monotonic() if now is None else now
cls.data[uid] = (now, messages)
cls.data.move_to_end(uid)
2024-11-05 15:34:45 +08:00
@classmethod
def add(cls, uid: str, msg_id: str):
2026-04-26 15:50:15 +08:00
now = time.monotonic()
cls._prune(now)
_, messages = cls.data.get(uid, (now, []))
messages.append(msg_id)
cls._touch(uid, messages, now)
2024-11-05 15:34:45 +08:00
cls.remove_check(uid)
2026-04-26 15:50:15 +08:00
cls._prune(now)
2024-11-05 15:34:45 +08:00
@classmethod
def check(cls, uid: str, msg_id: str) -> bool:
2026-04-26 15:50:15 +08:00
now = time.monotonic()
cls._prune(now)
entry = cls.data.get(uid)
if entry is None:
return False
_, messages = entry
cls._touch(uid, messages, now)
return msg_id in messages
2024-11-05 15:34:45 +08:00
@classmethod
def remove_check(cls, uid: str):
2026-04-26 15:50:15 +08:00
entry = cls.data.get(uid)
if entry is None:
return
_, messages = entry
if len(messages) > cls._MAX_MESSAGES_PER_USER:
messages = messages[-cls._TRIM_MESSAGES_TO :]
cls._touch(uid, messages)
2024-11-05 15:34:45 +08:00
@classmethod
def get(cls, uid: str) -> list[str]:
2026-04-26 15:50:15 +08:00
now = time.monotonic()
cls._prune(now)
entry = cls.data.get(uid)
if entry is None:
return []
_, messages = entry
cls._touch(uid, messages, now)
return list(messages)
@classmethod
def clear_all(cls) -> int:
size = len(cls.data)
cls.data.clear()
return size