forked from Muzifs/LGBot
Изменение кэширования сообщений
This commit is contained in:
@@ -92,6 +92,24 @@ class Database: # Инициализация класса
|
||||
ON users(tag COLLATE NOCASE)
|
||||
''')
|
||||
|
||||
# Таблица для кэша сообщений (для обработки реакций)
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS message_cache (
|
||||
chat_id INTEGER NOT NULL,
|
||||
message_id INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
thread_id INTEGER,
|
||||
timestamp INTEGER NOT NULL,
|
||||
PRIMARY KEY (chat_id, message_id)
|
||||
)
|
||||
''')
|
||||
|
||||
# Индекс для быстрой очистки старых записей
|
||||
cursor.execute('''
|
||||
CREATE INDEX IF NOT EXISTS idx_message_cache_timestamp
|
||||
ON message_cache(timestamp)
|
||||
''')
|
||||
|
||||
connect.commit()
|
||||
logger.info("База данных и индексы успешно инициализированы")
|
||||
|
||||
@@ -395,5 +413,52 @@ class Database: # Инициализация класса
|
||||
connect.commit()
|
||||
logger.info(f"Пользователь {from_user_id} поблагодарил {to_user_id} в чате {chat_id}")
|
||||
|
||||
# Добавляет сообщение в кэш
|
||||
def cache_message(self, chat_id: int, message_id: int, user_id: int, thread_id: Optional[int] = None):
|
||||
with self._get_connection() as connect:
|
||||
cursor = connect.cursor()
|
||||
current_time = int(time.time())
|
||||
cursor.execute('''
|
||||
INSERT OR REPLACE INTO message_cache (chat_id, message_id, user_id, thread_id, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
''', (chat_id, message_id, user_id, thread_id, current_time))
|
||||
connect.commit()
|
||||
|
||||
# Получает информацию о сообщении из кэша
|
||||
# Возвращает (user_id, thread_id) или None если не найдено
|
||||
def get_cached_message(self, chat_id: int, message_id: int) -> Optional[Tuple[int, Optional[int]]]:
|
||||
with self._get_connection() as connect:
|
||||
cursor = connect.cursor()
|
||||
cursor.execute('''
|
||||
SELECT user_id, thread_id
|
||||
FROM message_cache
|
||||
WHERE chat_id = ? AND message_id = ?
|
||||
''', (chat_id, message_id))
|
||||
result = cursor.fetchone()
|
||||
return result if result else None
|
||||
|
||||
# Очищает сообщения старше указанного времени (по умолчанию 24 часа)
|
||||
def cleanup_old_messages(self, max_age_seconds: int = 86400):
|
||||
with self._get_connection() as connect:
|
||||
cursor = connect.cursor()
|
||||
cutoff_time = int(time.time()) - max_age_seconds
|
||||
cursor.execute('''
|
||||
DELETE FROM message_cache
|
||||
WHERE timestamp < ?
|
||||
''', (cutoff_time,))
|
||||
deleted_count = cursor.rowcount
|
||||
connect.commit()
|
||||
if deleted_count > 0:
|
||||
logger.info(f"Удалено {deleted_count} старых сообщений из кэша")
|
||||
return deleted_count
|
||||
|
||||
# Получает количество сообщений в кэше
|
||||
def get_cache_size(self) -> int:
|
||||
with self._get_connection() as connect:
|
||||
cursor = connect.cursor()
|
||||
cursor.execute('SELECT COUNT(*) FROM message_cache')
|
||||
result = cursor.fetchone()
|
||||
return result[0] if result else 0
|
||||
|
||||
# Создаем экземпляр базы данных для импорта в других модулях
|
||||
db = Database()
|
@@ -2,7 +2,6 @@ from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji
|
||||
import asyncio
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from database import db
|
||||
from thank_words import contains_thank_word
|
||||
@@ -11,29 +10,39 @@ from config import THANK_COOLDOWN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Кэш для хранения message_id -> (user_id, message_thread_id) (последние 1000 сообщений)
|
||||
# Используем OrderedDict для автоматического удаления старых записей
|
||||
_message_cache = OrderedDict()
|
||||
_MAX_CACHE_SIZE = 1000
|
||||
# Фоновая задача для автоочистки старых сообщений
|
||||
_cleanup_task = None
|
||||
|
||||
def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None):
|
||||
"""Добавляет сообщение в кэш"""
|
||||
key = f"{chat_id}:{message_id}"
|
||||
_message_cache[key] = (user_id, message_thread_id)
|
||||
|
||||
# Удаляем старые записи, если кэш переполнен
|
||||
if len(_message_cache) > _MAX_CACHE_SIZE:
|
||||
_message_cache.popitem(last=False)
|
||||
"""Добавляет сообщение в кэш БД"""
|
||||
db.cache_message(chat_id, message_id, user_id, message_thread_id)
|
||||
|
||||
def _get_cached_message(chat_id: int, message_id: int):
|
||||
"""Получает (user_id, message_thread_id) из кэша"""
|
||||
key = f"{chat_id}:{message_id}"
|
||||
return _message_cache.get(key)
|
||||
"""Получает (user_id, message_thread_id) из кэша БД"""
|
||||
return db.get_cached_message(chat_id, message_id)
|
||||
|
||||
async def _cleanup_old_cache():
|
||||
"""Фоновая задача для очистки старых сообщений из кэша каждый час"""
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(3600) # Ждём 1 час
|
||||
deleted = db.cleanup_old_messages(max_age_seconds=86400) # Удаляем старше 24 часов
|
||||
cache_size = db.get_cache_size()
|
||||
logger.info(f"[CACHE CLEANUP] Размер кэша: {cache_size} сообщений")
|
||||
except Exception as e:
|
||||
logger.error(f"[CACHE CLEANUP] Ошибка очистки кэша: {e}", exc_info=True)
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
"""Регистрирует обработчики для отслеживания благодарностей"""
|
||||
logger.info("Регистрация обработчика благодарностей (karma_tracker)")
|
||||
|
||||
# Запускаем фоновую задачу очистки старых сообщений из кэша
|
||||
global _cleanup_task
|
||||
if _cleanup_task is None or _cleanup_task.done():
|
||||
_cleanup_task = asyncio.create_task(_cleanup_old_cache())
|
||||
cache_size = db.get_cache_size()
|
||||
logger.info(f"[CACHE] Запущена автоочистка кэша. Текущий размер: {cache_size} сообщений")
|
||||
|
||||
@bot.message_reaction_handler(func=lambda m: True)
|
||||
async def handle_reaction(reaction: MessageReactionUpdated):
|
||||
"""
|
||||
|
Reference in New Issue
Block a user