forked from Muzifs/LGBot
Добавление кармы за реакцию большого пальца
This commit is contained in:
@@ -187,10 +187,12 @@ COMMAND_MESSAGES = {
|
||||
"3. Ответ на сообщение:\n"
|
||||
" Ответьте на сообщение: <code>/karma</code>\n\n"
|
||||
"<b>💡 Как начислить карму?</b>\n"
|
||||
"Ответьте на сообщение пользователя словами благодарности:\n"
|
||||
"<u>Способ 1: Ответить на сообщение</u>\n"
|
||||
"• спасибо → +1 карма\n"
|
||||
"• благодарю → +1 карма\n"
|
||||
"• спс, сенкс, thanks и др. → +1 карма\n\n"
|
||||
"<u>Способ 2: Поставить реакцию 👍</u>\n"
|
||||
"• Нажмите на сообщение и выберите 👍 → +1 карма\n\n"
|
||||
"<b>🔥 БОНУС: Благодарность с восклицательным знаком даёт x2 кармы!</b>\n"
|
||||
"• спасибо! → +2 кармы 👍👍\n"
|
||||
"• thanks! → +2 кармы 👍👍\n\n"
|
||||
|
@@ -200,8 +200,8 @@ async def main():
|
||||
# Устанавливаем команды бота
|
||||
await setup_bot_commands()
|
||||
|
||||
# Запускаем бота
|
||||
await bot.infinity_polling()
|
||||
# Запускаем бота с обработкой реакций
|
||||
await bot.infinity_polling(allowed_updates=['message', 'message_reaction', 'chat_member'])
|
||||
|
||||
except Exception as e:
|
||||
|
||||
|
@@ -1,7 +1,8 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
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
|
||||
@@ -10,10 +11,126 @@ from config import THANK_COOLDOWN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Кэш для хранения message_id -> user_id (последние 1000 сообщений)
|
||||
# Используем OrderedDict для автоматического удаления старых записей
|
||||
_message_cache = OrderedDict()
|
||||
_MAX_CACHE_SIZE = 1000
|
||||
|
||||
def _cache_message(chat_id: int, message_id: int, user_id: int):
|
||||
"""Добавляет сообщение в кэш"""
|
||||
key = f"{chat_id}:{message_id}"
|
||||
_message_cache[key] = user_id
|
||||
|
||||
# Удаляем старые записи, если кэш переполнен
|
||||
if len(_message_cache) > _MAX_CACHE_SIZE:
|
||||
_message_cache.popitem(last=False)
|
||||
|
||||
def _get_cached_user(chat_id: int, message_id: int) -> int:
|
||||
"""Получает user_id из кэша"""
|
||||
key = f"{chat_id}:{message_id}"
|
||||
return _message_cache.get(key)
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
"""Регистрирует обработчики для отслеживания благодарностей"""
|
||||
logger.info("Регистрация обработчика благодарностей (karma_tracker)")
|
||||
|
||||
@bot.message_reaction_handler(func=lambda reaction: True)
|
||||
async def handle_reaction(reaction: MessageReactionUpdated):
|
||||
"""
|
||||
Обрабатывает реакции на сообщения.
|
||||
Если пользователь поставил 👍, начисляет карму автору сообщения.
|
||||
"""
|
||||
try:
|
||||
logger.info(f"[KARMA] Получена реакция от {reaction.user.id}")
|
||||
|
||||
# Проверяем, что это групповой чат
|
||||
if reaction.chat.type not in ['group', 'supergroup']:
|
||||
logger.info(f"[KARMA] Пропуск реакции - не групповой чат")
|
||||
return
|
||||
|
||||
# Проверяем, что есть новые реакции (не удаление)
|
||||
if not reaction.new_reaction:
|
||||
logger.info(f"[KARMA] Пропуск - удаление реакции")
|
||||
return
|
||||
|
||||
# Ищем реакцию 👍 среди новых реакций
|
||||
thumbs_up_found = False
|
||||
for react in reaction.new_reaction:
|
||||
if isinstance(react, ReactionTypeEmoji) and react.emoji == "👍":
|
||||
thumbs_up_found = True
|
||||
break
|
||||
|
||||
if not thumbs_up_found:
|
||||
logger.info(f"[KARMA] Нет реакции 👍")
|
||||
return
|
||||
|
||||
logger.info(f"[KARMA] Обнаружена реакция 👍 от {reaction.user.id}")
|
||||
|
||||
from_user = reaction.user
|
||||
chat_id = reaction.chat.id
|
||||
|
||||
# Получаем автора сообщения из кэша
|
||||
to_user_id = _get_cached_user(chat_id, reaction.message_id)
|
||||
if not to_user_id:
|
||||
logger.warning(f"[KARMA] Сообщение {reaction.message_id} не найдено в кэше")
|
||||
return
|
||||
|
||||
# Защита от самоблагодарности
|
||||
if from_user.id == to_user_id:
|
||||
logger.info(f"Пользователь {from_user.id} попытался поблагодарить сам себя реакцией")
|
||||
return
|
||||
|
||||
# Получаем информацию о пользователе из БД
|
||||
to_user_info = db.get_user(to_user_id)
|
||||
if not to_user_info:
|
||||
logger.warning(f"[KARMA] Пользователь {to_user_id} не найден в БД")
|
||||
return
|
||||
|
||||
# Атомарно проверяем кулдаун и записываем благодарность
|
||||
if not db.try_add_karma_thank(from_user.id, to_user_id, chat_id, THANK_COOLDOWN):
|
||||
logger.info(f"Пользователь {from_user.id} уже благодарил {to_user_id} недавно (реакция)")
|
||||
return
|
||||
|
||||
# Начисляем +1 карму за реакцию
|
||||
db.add_karma(to_user_id, chat_id, 1)
|
||||
|
||||
# Получаем новую карму
|
||||
new_karma = db.get_karma(to_user_id, chat_id)
|
||||
|
||||
logger.info(f"Пользователь {from_user.id} поблагодарил {to_user_id} реакцией 👍, карма: {new_karma}")
|
||||
|
||||
# Формируем имя пользователя (из БД: id, nickname, tag)
|
||||
to_user_display = f"@{to_user_info[2]}" if to_user_info[2] else to_user_info[1]
|
||||
|
||||
response = f"👍 Карма пользователя {to_user_display} увеличена (+1)! Текущая карма: {new_karma}"
|
||||
sent_message = await bot.send_message(
|
||||
chat_id,
|
||||
response,
|
||||
message_thread_id=getattr(reaction, 'message_thread_id', None)
|
||||
)
|
||||
|
||||
# Удаляем уведомление через 15 секунд
|
||||
await asyncio.sleep(15)
|
||||
try:
|
||||
await bot.delete_message(chat_id, sent_message.message_id)
|
||||
except Exception as e:
|
||||
logger.error(f"Не удалось удалить уведомление о карме: {e}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при обработке реакции: {e}", exc_info=True)
|
||||
|
||||
# Обработчик всех текстовых сообщений для кэширования
|
||||
@bot.message_handler(content_types=['text'])
|
||||
async def cache_messages(message: Message):
|
||||
"""Кэширует все текстовые сообщения для возможности обработки реакций"""
|
||||
try:
|
||||
# Кэшируем только сообщения в групповых чатах
|
||||
if message.chat.type in ['group', 'supergroup']:
|
||||
_cache_message(message.chat.id, message.message_id, message.from_user.id)
|
||||
logger.debug(f"[CACHE] Сообщение {message.message_id} от {message.from_user.id} добавлено в кэш")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка кэширования сообщения: {e}")
|
||||
|
||||
@bot.message_handler(func=lambda message: message.reply_to_message is not None and message.text and not message.text.startswith('/'))
|
||||
async def handle_thank_message(message: Message):
|
||||
"""
|
||||
|
Reference in New Issue
Block a user