forked from Muzifs/LGBot
Изменение кэширования сообщений
This commit is contained in:
@@ -92,6 +92,24 @@ class Database: # Инициализация класса
|
|||||||
ON users(tag COLLATE NOCASE)
|
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()
|
connect.commit()
|
||||||
logger.info("База данных и индексы успешно инициализированы")
|
logger.info("База данных и индексы успешно инициализированы")
|
||||||
|
|
||||||
@@ -395,5 +413,52 @@ class Database: # Инициализация класса
|
|||||||
connect.commit()
|
connect.commit()
|
||||||
logger.info(f"Пользователь {from_user_id} поблагодарил {to_user_id} в чате {chat_id}")
|
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()
|
db = Database()
|
@@ -2,7 +2,6 @@ from telebot.async_telebot import AsyncTeleBot
|
|||||||
from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji
|
from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
from database import db
|
from database import db
|
||||||
from thank_words import contains_thank_word
|
from thank_words import contains_thank_word
|
||||||
@@ -11,29 +10,39 @@ from config import THANK_COOLDOWN
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Кэш для хранения message_id -> (user_id, message_thread_id) (последние 1000 сообщений)
|
# Фоновая задача для автоочистки старых сообщений
|
||||||
# Используем OrderedDict для автоматического удаления старых записей
|
_cleanup_task = None
|
||||||
_message_cache = OrderedDict()
|
|
||||||
_MAX_CACHE_SIZE = 1000
|
|
||||||
|
|
||||||
def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None):
|
def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None):
|
||||||
"""Добавляет сообщение в кэш"""
|
"""Добавляет сообщение в кэш БД"""
|
||||||
key = f"{chat_id}:{message_id}"
|
db.cache_message(chat_id, message_id, user_id, message_thread_id)
|
||||||
_message_cache[key] = (user_id, message_thread_id)
|
|
||||||
|
|
||||||
# Удаляем старые записи, если кэш переполнен
|
|
||||||
if len(_message_cache) > _MAX_CACHE_SIZE:
|
|
||||||
_message_cache.popitem(last=False)
|
|
||||||
|
|
||||||
def _get_cached_message(chat_id: int, message_id: int):
|
def _get_cached_message(chat_id: int, message_id: int):
|
||||||
"""Получает (user_id, message_thread_id) из кэша"""
|
"""Получает (user_id, message_thread_id) из кэша БД"""
|
||||||
key = f"{chat_id}:{message_id}"
|
return db.get_cached_message(chat_id, message_id)
|
||||||
return _message_cache.get(key)
|
|
||||||
|
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):
|
def register_handlers(bot: AsyncTeleBot):
|
||||||
"""Регистрирует обработчики для отслеживания благодарностей"""
|
"""Регистрирует обработчики для отслеживания благодарностей"""
|
||||||
logger.info("Регистрация обработчика благодарностей (karma_tracker)")
|
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)
|
@bot.message_reaction_handler(func=lambda m: True)
|
||||||
async def handle_reaction(reaction: MessageReactionUpdated):
|
async def handle_reaction(reaction: MessageReactionUpdated):
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user