forked from Muzifs/LGBot
Compare commits
21 Commits
6b41e61d7e
...
master
Author | SHA1 | Date | |
---|---|---|---|
0bd399f121 | |||
c257c6c1a2 | |||
c7b2961ae1 | |||
8af2f128a7 | |||
4aba68d242 | |||
8bf512e509 | |||
459ed66e9a | |||
de1c82c267 | |||
4a2aa00eb7 | |||
c4400fc244 | |||
b7f09ae719 | |||
1619e82df1 | |||
0ee7cb3bd4 | |||
9b11f21bc1 | |||
2b9e819944 | |||
58daea0492 | |||
63ac924a3d | |||
be64915e9b | |||
61e9d31a75 | |||
6bdf996ca4 | |||
c07a082694 |
File diff suppressed because it is too large
Load Diff
27
.gitignore
vendored
27
.gitignore
vendored
@@ -1,6 +1,33 @@
|
|||||||
|
# Python
|
||||||
.venv/
|
.venv/
|
||||||
.env
|
.env
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
|
# IDE
|
||||||
.idea/
|
.idea/
|
||||||
|
.gigaide/
|
||||||
|
.claude/
|
||||||
|
.vscode/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# Build
|
||||||
|
target/
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Logs
|
||||||
bot.log
|
bot.log
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Databases
|
||||||
users.db
|
users.db
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
@@ -126,7 +126,7 @@ def normalize_text(text: str) -> str:
|
|||||||
Убирает:
|
Убирает:
|
||||||
- Звездочки, точки, подчеркивания между буквами (х*й, х.у.й, х_у_й → хуй)
|
- Звездочки, точки, подчеркивания между буквами (х*й, х.у.й, х_у_й → хуй)
|
||||||
- Повторяющиеся символы (хууууууй → хуй)
|
- Повторяющиеся символы (хууууууй → хуй)
|
||||||
- Пробелы между буквами (х у й → хуй)
|
- ОДИНОЧНЫЕ пробелы между ОДИНОЧНЫМИ буквами (х у й → хуй, но "не бу" остаётся "не бу")
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
text: Исходный текст
|
text: Исходный текст
|
||||||
@@ -140,9 +140,22 @@ def normalize_text(text: str) -> str:
|
|||||||
# Приводим к нижнему регистру
|
# Приводим к нижнему регистру
|
||||||
normalized = text.lower()
|
normalized = text.lower()
|
||||||
|
|
||||||
# Убираем распространенные символы обфускации между буквами
|
# Циклически убираем обфускацию, пока что-то меняется
|
||||||
# Заменяем последовательности: буква + [*._ ]+ + буква на буква+буква
|
max_iterations = 10
|
||||||
normalized = re.sub(r'([а-яё])[\*\.\-_\s]+([а-яё])', r'\1\2', normalized)
|
for _ in range(max_iterations):
|
||||||
|
before = normalized
|
||||||
|
|
||||||
|
# Убираем звёздочки, точки, дефисы, подчёркивания между буквами
|
||||||
|
# х*й, х.у.й, х_у_й → хуй
|
||||||
|
normalized = re.sub(r'([а-яё])[\*\.\-_]+([а-яё])', r'\1\2', normalized)
|
||||||
|
|
||||||
|
# Убираем ОДИНОЧНЫЕ пробелы между ОДИНОЧНЫМИ буквами (обфускация)
|
||||||
|
# "х у й" → "хуй", но "не бу" → "не бу" (не склеиваем обычные слова)
|
||||||
|
# Паттерн: одиночная буква + пробелы + одиночная буква
|
||||||
|
normalized = re.sub(r'\b([а-яё])\s+([а-яё])\b', r'\1\2', normalized)
|
||||||
|
|
||||||
|
if before == normalized:
|
||||||
|
break
|
||||||
|
|
||||||
# Убираем повторяющиеся буквы (более 2 подряд)
|
# Убираем повторяющиеся буквы (более 2 подряд)
|
||||||
# хууууууй → хуй, пииииздец → пиздец
|
# хууууууй → хуй, пииииздец → пиздец
|
||||||
|
@@ -187,10 +187,23 @@ COMMAND_MESSAGES = {
|
|||||||
"3. Ответ на сообщение:\n"
|
"3. Ответ на сообщение:\n"
|
||||||
" Ответьте на сообщение: <code>/karma</code>\n\n"
|
" Ответьте на сообщение: <code>/karma</code>\n\n"
|
||||||
"<b>💡 Как начислить карму?</b>\n"
|
"<b>💡 Как начислить карму?</b>\n"
|
||||||
"Ответьте на сообщение пользователя словами благодарности:\n"
|
"<u>Способ 1: Ответить на сообщение</u>\n"
|
||||||
"• спасибо\n"
|
"• спасибо → +1 карма\n"
|
||||||
"• благодарю\n"
|
"• благодарю → +1 карма\n"
|
||||||
"• спс, сенкс, thanks и др.\n\n"
|
"• спс, сенкс, thanks и др. → +1 карма\n\n"
|
||||||
|
"<u>Способ 2: Поставить реакцию (работает как переключатель)</u>\n"
|
||||||
|
"• Поставил 👍 → +1 карма | Убрал 👍 → -1 карма\n"
|
||||||
|
"• Поставил 👎 → -1 карма | Убрал 👎 → +1 карма\n"
|
||||||
|
"• Поставил 🔥 → +2 кармы | Убрал 🔥 → -2 кармы\n"
|
||||||
|
"• Поставил ❤ → +5 кармы | Убрал ❤ → -5 кармы\n"
|
||||||
|
"• Поставил ❤🔥 → +10 кармы | Убрал ❤🔥 → -10 кармы\n"
|
||||||
|
"• Нет ограничений по времени для реакций!\n\n"
|
||||||
|
"<b>🔥 БОНУС: Благодарность с восклицательным знаком даёт x2 кармы!</b>\n"
|
||||||
|
"• спасибо! → +2 кармы 👍👍\n"
|
||||||
|
"• thanks! → +2 кармы 👍👍\n\n"
|
||||||
|
"<b>⚠️ Снятие кармы:</b>\n"
|
||||||
|
"• Предупреждение (/warn): -5 кармы\n"
|
||||||
|
"• Мут (/mute или автомут): -10 кармы\n\n"
|
||||||
"<i>⏱ Одному пользователю можно давать карму раз в час</i>"
|
"<i>⏱ Одному пользователю можно давать карму раз в час</i>"
|
||||||
),
|
),
|
||||||
'top_karma_help': (
|
'top_karma_help': (
|
||||||
@@ -199,6 +212,22 @@ COMMAND_MESSAGES = {
|
|||||||
"<u>🎯 Использование:</u>\n"
|
"<u>🎯 Использование:</u>\n"
|
||||||
" <code>/top</code>\n\n"
|
" <code>/top</code>\n\n"
|
||||||
"<i>💡 Система кармы поощряет активных и полезных участников чата!</i>"
|
"<i>💡 Система кармы поощряет активных и полезных участников чата!</i>"
|
||||||
|
),
|
||||||
|
'setkarma_help': (
|
||||||
|
"<b>🎚 Команда /setkarma</b>\n\n"
|
||||||
|
"<i>Устанавливает карму пользователя в указанное значение (только для администраторов)</i>\n\n"
|
||||||
|
"<u>🎯 Способы использования:</u>\n"
|
||||||
|
"1. Ответ на сообщение:\n"
|
||||||
|
" <code>/setkarma 100</code>\n"
|
||||||
|
"2. По тегу пользователя:\n"
|
||||||
|
" <code>/setkarma @username 50</code>\n"
|
||||||
|
"3. По ID пользователя:\n"
|
||||||
|
" <code>/setkarma 123456789 -10</code>\n\n"
|
||||||
|
"<b>💡 Примеры:</b>\n"
|
||||||
|
"• Установить карму на 0: <code>/setkarma @user 0</code>\n"
|
||||||
|
"• Установить отрицательную карму: <code>/setkarma @user -50</code>\n"
|
||||||
|
"• Установить высокую карму: <code>/setkarma @user 1000</code>\n\n"
|
||||||
|
"<i>⚠️ Команда доступна только администраторам с правами ограничения</i>"
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
@@ -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("База данных и индексы успешно инициализированы")
|
||||||
|
|
||||||
@@ -287,6 +305,31 @@ class Database: # Инициализация класса
|
|||||||
connect.commit()
|
connect.commit()
|
||||||
logger.info(f"Пользователю {user_id} добавлено {amount} кармы в чате {chat_id}")
|
logger.info(f"Пользователю {user_id} добавлено {amount} кармы в чате {chat_id}")
|
||||||
|
|
||||||
|
# Устанавливает карму пользователя в указанное значение
|
||||||
|
def set_karma(self, user_id: int, chat_id: int, karma_value: int):
|
||||||
|
with self._get_connection() as connect:
|
||||||
|
cursor = connect.cursor()
|
||||||
|
# Проверяем существование записи
|
||||||
|
cursor.execute('SELECT karma_points FROM karma WHERE user_id = ? AND chat_id = ?', (user_id, chat_id))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
|
||||||
|
if result:
|
||||||
|
# Обновляем существующую карму
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE karma
|
||||||
|
SET karma_points = ?
|
||||||
|
WHERE user_id = ? AND chat_id = ?
|
||||||
|
''', (karma_value, user_id, chat_id))
|
||||||
|
else:
|
||||||
|
# Создаем новую запись
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO karma (user_id, chat_id, karma_points)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
''', (user_id, chat_id, karma_value))
|
||||||
|
|
||||||
|
connect.commit()
|
||||||
|
logger.info(f"Карма пользователя {user_id} установлена на {karma_value} в чате {chat_id}")
|
||||||
|
|
||||||
# Получает карму пользователя
|
# Получает карму пользователя
|
||||||
def get_karma(self, user_id: int, chat_id: int) -> int:
|
def get_karma(self, user_id: int, chat_id: int) -> int:
|
||||||
with self._get_connection() as connect:
|
with self._get_connection() as connect:
|
||||||
@@ -370,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()
|
0
src/lgbot.db
Normal file
0
src/lgbot.db
Normal file
25
src/main.py
25
src/main.py
@@ -65,6 +65,11 @@ class UserUpdateMiddleware(BaseMiddleware):
|
|||||||
|
|
||||||
# Обработчик, вызываемый ДО обработки сообщения основными хэндлерами
|
# Обработчик, вызываемый ДО обработки сообщения основными хэндлерами
|
||||||
async def pre_process(self, message, data):
|
async def pre_process(self, message, data):
|
||||||
|
# Проверяем, что это действительно сообщение (а не ChatMemberUpdated)
|
||||||
|
if not hasattr(message, 'content_type'):
|
||||||
|
# Это не Message объект (например ChatMemberUpdated), пропускаем
|
||||||
|
return data
|
||||||
|
|
||||||
# Логируем ВСЕ входящие сообщения для отладки
|
# Логируем ВСЕ входящие сообщения для отладки
|
||||||
logger.info(f"[MIDDLEWARE] Получено сообщение от {message.from_user.id}, тип: {message.content_type}, текст: {message.text if hasattr(message, 'text') else 'N/A'}")
|
logger.info(f"[MIDDLEWARE] Получено сообщение от {message.from_user.id}, тип: {message.content_type}, текст: {message.text if hasattr(message, 'text') else 'N/A'}")
|
||||||
|
|
||||||
@@ -80,8 +85,20 @@ class UserUpdateMiddleware(BaseMiddleware):
|
|||||||
# Это позволяет auto_mute работать независимо от karma_tracker
|
# Это позволяет auto_mute работать независимо от karma_tracker
|
||||||
await self._check_profanity(message)
|
await self._check_profanity(message)
|
||||||
|
|
||||||
|
# ВАЖНО: Кэшируем ВСЕ сообщения для обработки реакций (не только текстовые!)
|
||||||
|
# Пользователи могут ставить реакции на фото, видео, стикеры и т.д.
|
||||||
|
try:
|
||||||
|
karma_module = importlib.import_module("modules.0_karma_tracker")
|
||||||
|
if message.chat.type in ['group', 'supergroup']:
|
||||||
|
# Передаём message_thread_id для правильной отправки уведомлений в топики
|
||||||
|
thread_id = getattr(message, 'message_thread_id', None)
|
||||||
|
karma_module._cache_message(message.chat.id, message.message_id, message.from_user.id, thread_id)
|
||||||
|
logger.info(f"[CACHE] Сообщение {message.message_id} от {message.from_user.id} добавлено в кэш, chat_id={message.chat.id}, thread_id={thread_id}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка кэширования сообщения: {e}", exc_info=True)
|
||||||
|
|
||||||
# Обработка новых участников группы
|
# Обработка новых участников группы
|
||||||
elif message.content_type == 'new_chat_members':
|
if message.content_type == 'new_chat_members':
|
||||||
for new_member in message.new_chat_members:
|
for new_member in message.new_chat_members:
|
||||||
self.db.add_or_update_user(
|
self.db.add_or_update_user(
|
||||||
user_id=new_member.id,
|
user_id=new_member.id,
|
||||||
@@ -180,6 +197,7 @@ async def setup_bot_commands():
|
|||||||
BotCommand("botdata", "Получить данные бота (только для админов)"),
|
BotCommand("botdata", "Получить данные бота (только для админов)"),
|
||||||
BotCommand("karma", "Просмотр кармы пользователя"),
|
BotCommand("karma", "Просмотр кармы пользователя"),
|
||||||
BotCommand("top", "Топ-10 пользователей по карме"),
|
BotCommand("top", "Топ-10 пользователей по карме"),
|
||||||
|
BotCommand("setkarma", "Установить карму пользователя. Использование: /setkarma help"),
|
||||||
]
|
]
|
||||||
|
|
||||||
await bot.set_my_commands(commands)
|
await bot.set_my_commands(commands)
|
||||||
@@ -200,8 +218,9 @@ async def main():
|
|||||||
# Устанавливаем команды бота
|
# Устанавливаем команды бота
|
||||||
await setup_bot_commands()
|
await setup_bot_commands()
|
||||||
|
|
||||||
# Запускаем бота
|
# Запускаем бота с обработкой реакций
|
||||||
await bot.infinity_polling()
|
logger.info("Запуск бота с allowed_updates: message, message_reaction, chat_member")
|
||||||
|
await bot.infinity_polling(allowed_updates=['message', 'message_reaction', 'chat_member'])
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
from telebot.async_telebot import AsyncTeleBot
|
from telebot.async_telebot import AsyncTeleBot
|
||||||
from telebot.types import Message
|
from telebot.types import Message, MessageReactionUpdated, ReactionTypeEmoji
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -10,10 +10,233 @@ from config import THANK_COOLDOWN
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Фоновая задача для автоочистки старых сообщений
|
||||||
|
_cleanup_task = None
|
||||||
|
|
||||||
|
def _cache_message(chat_id: int, message_id: int, user_id: int, message_thread_id: int = None):
|
||||||
|
"""Добавляет сообщение в кэш БД"""
|
||||||
|
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) из кэша БД"""
|
||||||
|
return db.get_cached_message(chat_id, message_id)
|
||||||
|
|
||||||
|
async def _cleanup_old_cache():
|
||||||
|
"""Фоновая задача для очистки старых сообщений из кэша каждые 6 часов"""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
await asyncio.sleep(21600) # Ждём 6 часов
|
||||||
|
deleted = db.cleanup_old_messages(max_age_seconds=604800) # Удаляем старше 7 дней
|
||||||
|
cache_size = db.get_cache_size()
|
||||||
|
logger.info(f"[CACHE CLEANUP] Удалено: {deleted}, размер кэша: {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)
|
||||||
|
async def handle_reaction(reaction: MessageReactionUpdated):
|
||||||
|
"""
|
||||||
|
Обрабатывает реакции на сообщения.
|
||||||
|
Реакции работают как переключатель:
|
||||||
|
- Поставил 👍 → +1 карма | Убрал 👍 → -1 карма
|
||||||
|
- Поставил 👎 → -1 карма | Убрал 👎 → +1 карма
|
||||||
|
- Поставил 🔥 → +2 кармы | Убрал 🔥 → -2 кармы
|
||||||
|
- Поставил ❤ → +5 кармы | Убрал ❤ → -5 кармы
|
||||||
|
- Поставил ❤🔥 → +10 кармы | Убрал ❤🔥 → -10 кармы
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info(f"[KARMA] Получена реакция от {reaction.user.id}")
|
||||||
|
|
||||||
|
# Проверяем, что это групповой чат
|
||||||
|
if reaction.chat.type not in ['group', 'supergroup']:
|
||||||
|
logger.info(f"[KARMA] Пропуск реакции - не групповой чат")
|
||||||
|
return
|
||||||
|
|
||||||
|
from_user = reaction.user
|
||||||
|
chat_id = reaction.chat.id
|
||||||
|
|
||||||
|
# Получаем автора сообщения и топик из кэша
|
||||||
|
cached_data = _get_cached_message(chat_id, reaction.message_id)
|
||||||
|
if not cached_data:
|
||||||
|
logger.warning(f"[KARMA] Сообщение {reaction.message_id} не найдено в кэше")
|
||||||
|
return
|
||||||
|
|
||||||
|
to_user_id, message_thread_id = cached_data
|
||||||
|
|
||||||
|
# Защита от самооценки
|
||||||
|
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
|
||||||
|
|
||||||
|
# Примечание: мы не проверяем является ли to_user_id ботом, т.к.:
|
||||||
|
# 1. Сообщения ботов не кэшируются (только пользовательские)
|
||||||
|
# 2. Если бот все же попал в кэш, это исключительный случай и не критично
|
||||||
|
|
||||||
|
# Проверяем старые реакции
|
||||||
|
old_thumbs_up = False
|
||||||
|
old_thumbs_down = False
|
||||||
|
old_heart = False
|
||||||
|
old_fire_heart = False
|
||||||
|
old_fire = False
|
||||||
|
if reaction.old_reaction:
|
||||||
|
for react in reaction.old_reaction:
|
||||||
|
if isinstance(react, ReactionTypeEmoji):
|
||||||
|
if react.emoji == "👍":
|
||||||
|
old_thumbs_up = True
|
||||||
|
elif react.emoji == "👎":
|
||||||
|
old_thumbs_down = True
|
||||||
|
elif react.emoji == "❤":
|
||||||
|
old_heart = True
|
||||||
|
elif react.emoji == "❤🔥":
|
||||||
|
old_fire_heart = True
|
||||||
|
elif react.emoji == "🔥":
|
||||||
|
old_fire = True
|
||||||
|
|
||||||
|
# Проверяем новые реакции
|
||||||
|
new_thumbs_up = False
|
||||||
|
new_thumbs_down = False
|
||||||
|
new_heart = False
|
||||||
|
new_fire_heart = False
|
||||||
|
new_fire = False
|
||||||
|
if reaction.new_reaction:
|
||||||
|
for react in reaction.new_reaction:
|
||||||
|
if isinstance(react, ReactionTypeEmoji):
|
||||||
|
if react.emoji == "👍":
|
||||||
|
new_thumbs_up = True
|
||||||
|
elif react.emoji == "👎":
|
||||||
|
new_thumbs_down = True
|
||||||
|
elif react.emoji == "❤":
|
||||||
|
new_heart = True
|
||||||
|
elif react.emoji == "❤🔥":
|
||||||
|
new_fire_heart = True
|
||||||
|
elif react.emoji == "🔥":
|
||||||
|
new_fire = True
|
||||||
|
|
||||||
|
# Определяем изменение кармы (накапливаем все изменения)
|
||||||
|
karma_change = 0
|
||||||
|
actions = [] # Список всех действий для логирования
|
||||||
|
|
||||||
|
# Логика изменения кармы - проверяем ВСЕ реакции (не elif!)
|
||||||
|
# Это важно, т.к. пользователь может менять реакции (убрать 👍 и поставить 🔥)
|
||||||
|
|
||||||
|
# Проверяем 👍
|
||||||
|
if new_thumbs_up and not old_thumbs_up:
|
||||||
|
karma_change += 1
|
||||||
|
actions.append("поставил 👍 (+1)")
|
||||||
|
elif old_thumbs_up and not new_thumbs_up:
|
||||||
|
karma_change -= 1
|
||||||
|
actions.append("убрал 👍 (-1)")
|
||||||
|
|
||||||
|
# Проверяем 👎
|
||||||
|
if new_thumbs_down and not old_thumbs_down:
|
||||||
|
karma_change -= 1
|
||||||
|
actions.append("поставил 👎 (-1)")
|
||||||
|
elif old_thumbs_down and not new_thumbs_down:
|
||||||
|
karma_change += 1
|
||||||
|
actions.append("убрал 👎 (+1)")
|
||||||
|
|
||||||
|
# Проверяем ❤
|
||||||
|
if new_heart and not old_heart:
|
||||||
|
karma_change += 5
|
||||||
|
actions.append("поставил ❤ (+5)")
|
||||||
|
elif old_heart and not new_heart:
|
||||||
|
karma_change -= 5
|
||||||
|
actions.append("убрал ❤ (-5)")
|
||||||
|
|
||||||
|
# Проверяем ❤🔥
|
||||||
|
if new_fire_heart and not old_fire_heart:
|
||||||
|
karma_change += 10
|
||||||
|
actions.append("поставил ❤🔥 (+10)")
|
||||||
|
elif old_fire_heart and not new_fire_heart:
|
||||||
|
karma_change -= 10
|
||||||
|
actions.append("убрал ❤🔥 (-10)")
|
||||||
|
|
||||||
|
# Проверяем 🔥
|
||||||
|
if new_fire and not old_fire:
|
||||||
|
karma_change += 2
|
||||||
|
actions.append("поставил 🔥 (+2)")
|
||||||
|
elif old_fire and not new_fire:
|
||||||
|
karma_change -= 2
|
||||||
|
actions.append("убрал 🔥 (-2)")
|
||||||
|
|
||||||
|
# Если нет изменений - выходим
|
||||||
|
if karma_change == 0:
|
||||||
|
logger.info(f"[KARMA] Нет изменений в реакциях")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Формируем текст действий для логирования
|
||||||
|
action_text = ", ".join(actions)
|
||||||
|
logger.info(f"[KARMA] {action_text} от {from_user.id} для {to_user_id}, итоговое изменение кармы: {karma_change}")
|
||||||
|
|
||||||
|
# Изменяем карму
|
||||||
|
db.add_karma(to_user_id, chat_id, karma_change)
|
||||||
|
|
||||||
|
# Получаем новую карму
|
||||||
|
new_karma = db.get_karma(to_user_id, chat_id)
|
||||||
|
|
||||||
|
# Формируем имя пользователя (из БД: id, nickname, tag)
|
||||||
|
to_user_display = f"@{to_user_info[2]}" if to_user_info[2] else to_user_info[1]
|
||||||
|
|
||||||
|
# Формируем эмодзи для уведомления (берем первое действие или дефолтное)
|
||||||
|
notification_emoji = "⭐"
|
||||||
|
if "👍" in action_text:
|
||||||
|
notification_emoji = "👍"
|
||||||
|
elif "👎" in action_text:
|
||||||
|
notification_emoji = "👎"
|
||||||
|
elif "🔥" in action_text and "❤🔥" not in action_text:
|
||||||
|
notification_emoji = "🔥"
|
||||||
|
elif "❤🔥" in action_text:
|
||||||
|
notification_emoji = "❤🔥"
|
||||||
|
elif "❤" in action_text:
|
||||||
|
notification_emoji = "❤"
|
||||||
|
|
||||||
|
# Отправляем уведомление
|
||||||
|
karma_sign = f"+{karma_change}" if karma_change > 0 else str(karma_change)
|
||||||
|
change_word = "увеличена" if karma_change > 0 else "уменьшена"
|
||||||
|
response = f"{notification_emoji} Карма пользователя {to_user_display} {change_word} ({karma_sign})! Текущая карма: {new_karma}"
|
||||||
|
logger.info(f"[KARMA] Отправка уведомления в чат {chat_id}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
sent_message = await bot.send_message(
|
||||||
|
chat_id,
|
||||||
|
response,
|
||||||
|
message_thread_id=message_thread_id
|
||||||
|
)
|
||||||
|
logger.info(f"[KARMA] Уведомление отправлено успешно, message_id={sent_message.message_id}")
|
||||||
|
|
||||||
|
# Удаляем уведомление через 10 секунд В ФОНЕ (не блокируя обработку других реакций)
|
||||||
|
async def delete_notification():
|
||||||
|
try:
|
||||||
|
await asyncio.sleep(10)
|
||||||
|
await bot.delete_message(chat_id, sent_message.message_id)
|
||||||
|
logger.info(f"[KARMA] Уведомление удалено")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Не удалось удалить уведомление о карме: {e}")
|
||||||
|
|
||||||
|
# Запускаем удаление в фоне
|
||||||
|
asyncio.create_task(delete_notification())
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка отправки уведомления о карме: {e}", exc_info=True)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка при обработке реакции: {e}", exc_info=True)
|
||||||
|
|
||||||
@bot.message_handler(func=lambda message: message.reply_to_message is not None and message.text and not message.text.startswith('/'))
|
@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):
|
async def handle_thank_message(message: Message):
|
||||||
"""
|
"""
|
||||||
@@ -28,6 +251,12 @@ def register_handlers(bot: AsyncTeleBot):
|
|||||||
logger.info(f"[KARMA] Пропуск - не групповой чат: {message.chat.type}")
|
logger.info(f"[KARMA] Пропуск - не групповой чат: {message.chat.type}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# ВАЖНО: В топиках каждое сообщение технически является reply на первое сообщение топика
|
||||||
|
# Проверяем, что это реальный reply на сообщение пользователя, а не просто сообщение в топике
|
||||||
|
if message.is_topic_message and message.reply_to_message.message_id == message.message_thread_id:
|
||||||
|
logger.info(f"[KARMA] Пропуск - это сообщение в топике (не reply на пользователя)")
|
||||||
|
return
|
||||||
|
|
||||||
# Проверяем наличие благодарственных слов
|
# Проверяем наличие благодарственных слов
|
||||||
if not contains_thank_word(message.text):
|
if not contains_thank_word(message.text):
|
||||||
logger.info(f"[KARMA] Нет слов благодарности в: {message.text[:50]}")
|
logger.info(f"[KARMA] Нет слов благодарности в: {message.text[:50]}")
|
||||||
@@ -61,8 +290,11 @@ def register_handlers(bot: AsyncTeleBot):
|
|||||||
# Молча игнорируем, чтобы не спамить
|
# Молча игнорируем, чтобы не спамить
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Определяем количество кармы: x2 если есть восклицательный знак
|
||||||
|
karma_amount = 2 if '!' in message.text else 1
|
||||||
|
|
||||||
# Начисляем карму (благодарность уже записана атомарно выше)
|
# Начисляем карму (благодарность уже записана атомарно выше)
|
||||||
db.add_karma(to_user.id, chat_id, 1)
|
db.add_karma(to_user.id, chat_id, karma_amount)
|
||||||
|
|
||||||
# Получаем новую карму пользователя
|
# Получаем новую карму пользователя
|
||||||
new_karma = db.get_karma(to_user.id, chat_id)
|
new_karma = db.get_karma(to_user.id, chat_id)
|
||||||
@@ -74,19 +306,27 @@ def register_handlers(bot: AsyncTeleBot):
|
|||||||
else:
|
else:
|
||||||
to_user_display = to_user_name
|
to_user_display = to_user_name
|
||||||
|
|
||||||
# Отправляем уведомление
|
# Отправляем уведомление с указанием количества кармы
|
||||||
response = f"👍 Карма пользователя {to_user_display} увеличена! Текущая карма: {new_karma}"
|
karma_emoji = "👍👍" if karma_amount == 2 else "👍"
|
||||||
|
karma_change = f"+{karma_amount}"
|
||||||
|
response = f"{karma_emoji} Карма пользователя {to_user_display} увеличена ({karma_change})! Текущая карма: {new_karma}"
|
||||||
|
|
||||||
sent_message = await bot.reply_to(message, response)
|
|
||||||
|
|
||||||
logger.info(f"Пользователь {from_user.id} поблагодарил {to_user.id}, карма: {new_karma}")
|
|
||||||
|
|
||||||
# Удаляем уведомление через 5 секунд
|
|
||||||
await asyncio.sleep(5)
|
|
||||||
try:
|
try:
|
||||||
await bot.delete_message(chat_id, sent_message.message_id)
|
sent_message = await bot.reply_to(message, response)
|
||||||
|
logger.info(f"Пользователь {from_user.id} поблагодарил {to_user.id}, карма: {new_karma}")
|
||||||
|
|
||||||
|
# Удаляем уведомление через 25 секунд В ФОНЕ
|
||||||
|
async def delete_thank_notification():
|
||||||
|
try:
|
||||||
|
await asyncio.sleep(25)
|
||||||
|
await bot.delete_message(chat_id, sent_message.message_id)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Не удалось удалить уведомление о карме: {e}")
|
||||||
|
|
||||||
|
# Запускаем удаление в фоне
|
||||||
|
asyncio.create_task(delete_thank_notification())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Не удалось удалить уведомление о карме: {e}")
|
logger.error(f"Ошибка отправки уведомления о благодарности: {e}", exc_info=True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при обработке благодарности: {e}", exc_info=True)
|
logger.error(f"Ошибка при обработке благодарности: {e}", exc_info=True)
|
@@ -90,6 +90,10 @@ async def apply_mute(bot: AsyncTeleBot, message: Message, user_id: int, duration
|
|||||||
until_date=until_date
|
until_date=until_date
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Снимаем карму за автомут
|
||||||
|
db.add_karma(user_id, message.chat.id, -10)
|
||||||
|
logger.info(f"Снято 10 кармы пользователю {user_id} за автомут")
|
||||||
|
|
||||||
# Удаляем сообщение с матом
|
# Удаляем сообщение с матом
|
||||||
try:
|
try:
|
||||||
await bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
|
await bot.delete_message(chat_id=message.chat.id, message_id=message.message_id)
|
||||||
|
@@ -52,6 +52,7 @@ def register_handlers(bot: AsyncTeleBot):
|
|||||||
user_data = db.get_user_by_username(username)
|
user_data = db.get_user_by_username(username)
|
||||||
if user_data:
|
if user_data:
|
||||||
target_user_id = user_data[0]
|
target_user_id = user_data[0]
|
||||||
|
logger.info(f"[KARMA CMD] Найден пользователь по username '{username}': id={user_data[0]}, nickname={user_data[1]}, tag={user_data[2]}")
|
||||||
target_user = type('User', (), {
|
target_user = type('User', (), {
|
||||||
'id': user_data[0],
|
'id': user_data[0],
|
||||||
'first_name': user_data[1],
|
'first_name': user_data[1],
|
||||||
@@ -75,6 +76,8 @@ def register_handlers(bot: AsyncTeleBot):
|
|||||||
else:
|
else:
|
||||||
user_display = target_user.first_name
|
user_display = target_user.first_name
|
||||||
|
|
||||||
|
logger.info(f"[KARMA CMD] Показываем карму: user_id={target_user_id}, username={getattr(target_user, 'username', None)}, display={user_display}, karma={karma}")
|
||||||
|
|
||||||
# Определяем эмодзи в зависимости от кармы
|
# Определяем эмодзи в зависимости от кармы
|
||||||
if karma == 0:
|
if karma == 0:
|
||||||
emoji = "😐"
|
emoji = "😐"
|
||||||
|
@@ -279,6 +279,10 @@ async def mute_command(bot: AsyncTeleBot, message: Message, photo_path: str = No
|
|||||||
until_date=until_date
|
until_date=until_date
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Снимаем карму за мут
|
||||||
|
db.add_karma(target_user.id, message.chat.id, -10)
|
||||||
|
logger.info(f"Снято 10 кармы пользователю {target_user.id} за мут")
|
||||||
|
|
||||||
# Форматируем время в удобный формат
|
# Форматируем время в удобный формат
|
||||||
time_display = format_mute_time(mute_seconds)
|
time_display = format_mute_time(mute_seconds)
|
||||||
|
|
||||||
|
198
src/modules/setkarma.py
Normal file
198
src/modules/setkarma.py
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
from telebot.async_telebot import AsyncTeleBot
|
||||||
|
from telebot.types import Message, User
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from database import db
|
||||||
|
from action_reporter import action_reporter
|
||||||
|
from utils import delete_messages, check_admin_status
|
||||||
|
|
||||||
|
from config import COMMAND_MESSAGES
|
||||||
|
|
||||||
|
# Получаем логгер для текущего модуля
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Регистрирует обработчик команды
|
||||||
|
def register_handlers(bot: AsyncTeleBot):
|
||||||
|
|
||||||
|
# Обработчик команды /setkarma
|
||||||
|
@bot.message_handler(commands=['setkarma'])
|
||||||
|
async def _setkarma_command_wrapper(message: Message):
|
||||||
|
await setkarma_command(bot, message)
|
||||||
|
|
||||||
|
# Основная функция команды /setkarma
|
||||||
|
async def setkarma_command(bot: AsyncTeleBot, message: Message):
|
||||||
|
"""Устанавливает карму пользователя в указанное значение"""
|
||||||
|
|
||||||
|
# Определяем целевого пользователя
|
||||||
|
target_user = None
|
||||||
|
|
||||||
|
# Определяем новое значение кармы
|
||||||
|
new_karma_value = None
|
||||||
|
|
||||||
|
# Разбиваем текст сообщения на части
|
||||||
|
parts_msg = message.text.split()
|
||||||
|
|
||||||
|
# Команда /setkarma help
|
||||||
|
if len(parts_msg) == 2 and parts_msg[1].strip() in ('help', 'помощь'):
|
||||||
|
# Отправляем инструкцию
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text=COMMAND_MESSAGES['setkarma_help'],
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Удаляем сообщения через 30 секунд
|
||||||
|
await delete_messages(bot, message, time_sleep=30, number_message=2)
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Проверяем, является ли отправитель администратором
|
||||||
|
if await check_admin_status(bot, message) == 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Проверяем, что это групповой чат
|
||||||
|
if message.chat.type not in ['group', 'supergroup']:
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text="❌ Эта команда работает только в групповых чатах.",
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Если недостаточно аргументов
|
||||||
|
if len(parts_msg) < 2:
|
||||||
|
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Команда через ответ на сообщение: /setkarma 100
|
||||||
|
if message.reply_to_message and (not message.is_topic_message or message.message_thread_id != message.reply_to_message.message_id):
|
||||||
|
if len(parts_msg) >= 2:
|
||||||
|
target_user = message.reply_to_message.from_user
|
||||||
|
try:
|
||||||
|
new_karma_value = int(parts_msg[1])
|
||||||
|
except ValueError:
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text="❌ Неверный формат кармы. Укажите целое число.",
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Команда с указанием пользователя: /setkarma @username 100 или /setkarma 123456789 100
|
||||||
|
elif len(parts_msg) >= 3 and (parts_msg[1].strip().isdigit() or parts_msg[1].startswith('@')):
|
||||||
|
identifier = parts_msg[1].strip()
|
||||||
|
try:
|
||||||
|
new_karma_value = int(parts_msg[2])
|
||||||
|
except ValueError:
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text="❌ Неверный формат кармы. Укажите целое число.",
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Поиск по ID
|
||||||
|
if identifier.isdigit():
|
||||||
|
user_info = db.get_user(int(identifier))
|
||||||
|
if user_info:
|
||||||
|
target_user = User(
|
||||||
|
id=user_info[0],
|
||||||
|
first_name=user_info[1],
|
||||||
|
username=user_info[2],
|
||||||
|
is_bot=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Поиск по тегу
|
||||||
|
elif identifier.startswith('@'):
|
||||||
|
user_info = db.get_user_by_username(identifier[1:])
|
||||||
|
if user_info:
|
||||||
|
target_user = User(
|
||||||
|
id=user_info[0],
|
||||||
|
first_name=user_info[1],
|
||||||
|
username=user_info[2],
|
||||||
|
is_bot=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# Если команда неправильная
|
||||||
|
else:
|
||||||
|
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Если пользователь не найден
|
||||||
|
if not target_user:
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text=COMMAND_MESSAGES['user_not_found'],
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Проверяем, не пытается ли установить карму себе
|
||||||
|
if message.from_user.id == target_user.id:
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text="❌ Нельзя устанавливать карму самому себе.",
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Получаем текущую карму
|
||||||
|
old_karma = db.get_karma(target_user.id, message.chat.id)
|
||||||
|
|
||||||
|
# Устанавливаем новую карму
|
||||||
|
db.set_karma(target_user.id, message.chat.id, new_karma_value)
|
||||||
|
|
||||||
|
# Формируем имя пользователя для отображения
|
||||||
|
target_user_display = f"@{target_user.username}" if target_user.username else target_user.first_name
|
||||||
|
|
||||||
|
# Вычисляем разницу
|
||||||
|
karma_diff = new_karma_value - old_karma
|
||||||
|
diff_sign = "+" if karma_diff > 0 else ""
|
||||||
|
|
||||||
|
# Отправляем сообщение-лог в админ-чат
|
||||||
|
await action_reporter.log_action(
|
||||||
|
action="УСТАНОВКА КАРМЫ",
|
||||||
|
user_id=target_user.id,
|
||||||
|
admin_id=message.from_user.id,
|
||||||
|
reason=f"Карма изменена: {old_karma} → {new_karma_value} ({diff_sign}{karma_diff})",
|
||||||
|
duration=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Отправляем сообщение в чат
|
||||||
|
response = (
|
||||||
|
f"✅ Карма пользователя {target_user_display} установлена на <b>{new_karma_value}</b>\n"
|
||||||
|
f"Было: {old_karma} → Стало: {new_karma_value} ({diff_sign}{karma_diff})"
|
||||||
|
)
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text=response,
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Записываем действие в логи
|
||||||
|
logger.info(
|
||||||
|
f"Администратор {message.from_user.id} установил карму пользователя {target_user.id} "
|
||||||
|
f"на {new_karma_value} (было {old_karma})"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Удаляем сообщения через 5 секунд
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# Отправляем ошибку
|
||||||
|
await bot.send_message(
|
||||||
|
chat_id=message.chat.id,
|
||||||
|
text=COMMAND_MESSAGES['general_error'],
|
||||||
|
message_thread_id=message.message_thread_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Записываем ошибку в логи
|
||||||
|
logger.error(f"Общая ошибка в setkarma_command: {str(e)}")
|
||||||
|
|
||||||
|
# Удаляем сообщения через 5 секунд
|
||||||
|
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
@@ -144,6 +144,10 @@ async def warn_command(bot: AsyncTeleBot, message: Message):
|
|||||||
admin_id=message.from_user.id
|
admin_id=message.from_user.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Снимаем карму за предупреждение
|
||||||
|
db.add_karma(target_user.id, message.chat.id, -5)
|
||||||
|
logger.info(f"Снято 5 кармы пользователю {target_user.id} за предупреждение")
|
||||||
|
|
||||||
# Импортируем константы времени
|
# Импортируем константы времени
|
||||||
from config import ONE_WEEK, TWO_WEEKS
|
from config import ONE_WEEK, TWO_WEEKS
|
||||||
|
|
||||||
|
17
src/utils.py
17
src/utils.py
@@ -8,14 +8,21 @@ from config import COMMAND_MESSAGES
|
|||||||
# Получаем логгер для текущего модуля
|
# Получаем логгер для текущего модуля
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Удаляет определённое количество сообщения
|
# Удаляет определённое количество сообщения В ФОНЕ (не блокирует обработку других событий)
|
||||||
async def delete_messages(bot: AsyncTeleBot, message: Message, time_sleep: int, number_message: int):
|
async def delete_messages(bot: AsyncTeleBot, message: Message, time_sleep: int, number_message: int):
|
||||||
await asyncio.sleep(time_sleep)
|
async def _delete_task():
|
||||||
for i in range(number_message):
|
|
||||||
try:
|
try:
|
||||||
await bot.delete_message(message.chat.id, message.message_id+i)
|
await asyncio.sleep(time_sleep)
|
||||||
|
for i in range(number_message):
|
||||||
|
try:
|
||||||
|
await bot.delete_message(message.chat.id, message.message_id+i)
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Не удалось удалить сообщение {message.message_id+i}: {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Не удалось удалить сообщение {message.message_id+i}: {e}")
|
logger.error(f"Ошибка в задаче удаления сообщений: {e}")
|
||||||
|
|
||||||
|
# Запускаем удаление в фоне
|
||||||
|
asyncio.create_task(_delete_task())
|
||||||
|
|
||||||
# Проверяет, является ли отправитель администратором
|
# Проверяет, является ли отправитель администратором
|
||||||
async def check_admin_status(bot: AsyncTeleBot, message: Message, check_restrict_rights: bool = True):
|
async def check_admin_status(bot: AsyncTeleBot, message: Message, check_restrict_rights: bool = True):
|
||||||
|
Reference in New Issue
Block a user