Compare commits
	
		
			2 Commits
		
	
	
		
			97e4887a8a
			...
			03298ac1b4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 03298ac1b4 | |||
| af800203e5 | 
| @@ -8,6 +8,12 @@ DATABASE_NAME = 'users.db' | ||||
| COMMAND_MESSAGES = { | ||||
|     'start': 'Бот-модератор для чата @linux_gaming_ru', | ||||
|     'help': 'пусто', | ||||
|     'manual_mute': ( | ||||
|         'ℹ️ Использование мута:\n' | ||||
|         '1️⃣ Ответьте на сообщение: <code>/mute время</code>\n' | ||||
|         '2️⃣ Укажите тэг: <code>/mute @username время</code>\n' | ||||
|         '3️⃣ Укажите ID: <code>/mute 123456789 время</code>\n\n' | ||||
|     ), | ||||
|     'manual_ban': ( | ||||
|         'ℹ️ Использование бана:\n' | ||||
|         '1️⃣ Ответьте на сообщение: <code>/ban</code>\n' | ||||
| @@ -23,7 +29,12 @@ COMMAND_MESSAGES = { | ||||
|     'no_admin_rights': '❌ Только администраторы могут использовать эту команду.', | ||||
|     'no_restrict_rights': '❌ У вас недостаточно прав.', | ||||
|     'user_not_found': '❌ Пользователь не найден.', | ||||
|     'incorrect_time_format': '❌ Неверный формат времени. Используйте: 10м, 1ч, 2д.', | ||||
|     'min_mute': '❌ Минимальное время мута - 1 минута.', | ||||
|     'max_mute': '❌ Максимальное время мута - 30 дней.', | ||||
|     'cant_mute_admin': '❌ Невозможно замутить администратора.', | ||||
|     'cant_ban_admin': '❌ Невозможно забанить администратора.', | ||||
|     'muted': '✅ Пользователь замучен на {time_display}.', | ||||
|     'banned': '✅ Пользователь успешно забанен.', | ||||
|     'unbanned': '✅ Пользователь успешно разбанен.', | ||||
|     'general_error': '⚠️ Произошла непредвиденная ошибка.' | ||||
|   | ||||
							
								
								
									
										343
									
								
								src/modules/mute.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										343
									
								
								src/modules/mute.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,343 @@ | ||||
| from telebot.async_telebot import AsyncTeleBot | ||||
| from telebot.types import Message, User, ChatPermissions | ||||
| import asyncio | ||||
| import logging | ||||
| import time | ||||
| from database import db | ||||
|  | ||||
| from config import COMMAND_MESSAGES | ||||
|  | ||||
| logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля | ||||
|  | ||||
| # Возвращает количество секунд | ||||
| def parse_mute_time(time_str: str) -> int: | ||||
|  | ||||
|     # Парсим строку времени | ||||
|     time_str = time_str.strip().lower() | ||||
|  | ||||
|     # Минуты | ||||
|     if time_str.endswith('m') or time_str.endswith('м'): | ||||
|         try: | ||||
|             minutes = int(time_str[:-1]) | ||||
|             return abs(minutes) * 60 | ||||
|         except: | ||||
|             return None | ||||
|  | ||||
|     # Часы | ||||
|     elif time_str.endswith('h') or time_str.endswith('ч'): | ||||
|         try: | ||||
|             hours = int(time_str[:-1]) | ||||
|             return abs(hours) * 3600 | ||||
|         except: | ||||
|             return None | ||||
|  | ||||
|     # Дни | ||||
|     elif time_str.endswith('d') or time_str.endswith('д'): | ||||
|         try: | ||||
|             days = int(time_str[:-1]) | ||||
|             return abs(days) * 86400 | ||||
|         except: | ||||
|             return None | ||||
|  | ||||
|     # Число без указания единицы (по умолчанию минуты) | ||||
|     elif time_str.isdigit(): | ||||
|         try: | ||||
|             minutes = int(time_str) | ||||
|             return abs(minutes) * 60 | ||||
|         except: | ||||
|             return None | ||||
|  | ||||
|     return None | ||||
|  | ||||
| # Возвращает причину мута | ||||
| def extract_reason(words: str) -> str: | ||||
|  | ||||
|     if words == []: | ||||
|         reason = 'отсутствует' | ||||
|     else: | ||||
|         reason = ' '.join(words) | ||||
|  | ||||
|     return reason | ||||
|  | ||||
| # Форматирует время в нормальный вид | ||||
| def format_time(seconds: int) -> str: | ||||
|  | ||||
|     # Для минут | ||||
|     minutes = seconds // 60 | ||||
|     if minutes < 60: | ||||
|         if minutes % 10 == 1 and minutes % 100 != 11: | ||||
|             return f"{minutes} минута" | ||||
|         elif 2 <= minutes % 10 <= 4 and minutes % 100 not in (12, 13, 14): | ||||
|             return f"{minutes} минуты" | ||||
|         else: | ||||
|             return f"{minutes} минут" | ||||
|  | ||||
|     # Для часов | ||||
|     hours = minutes // 60 | ||||
|     if hours < 24: | ||||
|         if hours % 10 == 1 and hours % 100 != 11: | ||||
|             return f"{hours} час" | ||||
|         elif 2 <= hours % 10 <= 4 and hours % 100 not in (12, 13, 14): | ||||
|             return f"{hours} часа" | ||||
|         else: | ||||
|             return f"{hours} часов" | ||||
|  | ||||
|     # Для дней | ||||
|     days = hours // 24 | ||||
|     if days % 10 == 1 and days % 100 != 11: | ||||
|         return f"{days} день" | ||||
|     elif 2 <= days % 10 <= 4 and days % 100 not in (12, 13, 14): | ||||
|         return f"{days} дня" | ||||
|     else: | ||||
|         return f"{days} дней" | ||||
|  | ||||
| # Удаляет два последних сообщения | ||||
| async def delete_messages(bot: AsyncTeleBot, message: Message, time_sleep: int): | ||||
|     await asyncio.sleep(time_sleep) | ||||
|     await bot.delete_message(message.chat.id, message.message_id) | ||||
|     await bot.delete_message(message.chat.id, message.message_id+1) | ||||
|  | ||||
| def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики команд | ||||
|  | ||||
|     @bot.message_handler(commands=['mute']) # Обработчик команды /mute | ||||
|     async def mute_command(message: Message): | ||||
|  | ||||
|         # Отправка сообщения в тему или обычный чат | ||||
|         send_message = bot.reply_to if message.is_topic_message else bot.send_message | ||||
|         chat_id = message if message.is_topic_message else message.chat.id | ||||
|  | ||||
|         # Определяем целевого пользователя | ||||
|         target_user = None | ||||
|  | ||||
|         # Отпределяем время | ||||
|         time_arg = None | ||||
|  | ||||
|         # Определяем причину | ||||
|         reason = None | ||||
|  | ||||
|         # Разбиваем текст сообщения на части | ||||
|         parts_msg = message.text.split() | ||||
|  | ||||
|         try: | ||||
|             # Проверяем, является ли отправитель администратором | ||||
|             try: | ||||
|                 admin_status = await bot.get_chat_member(message.chat.id, message.from_user.id) | ||||
|  | ||||
|                 # Проверяем статус администратора (создателя) | ||||
|                 if admin_status.status not in ['administrator', 'creator']: | ||||
|                     await send_message(chat_id, COMMAND_MESSAGES['no_admin_rights']) | ||||
|  | ||||
|                     # Удаляем сообщения через 5 секунд | ||||
|                     await delete_messages(bot, message, 5) | ||||
|  | ||||
|                     return | ||||
|  | ||||
|                 # Проверяем право администратора на мут | ||||
|                 if admin_status.status == 'administrator' and not admin_status.can_restrict_members: | ||||
|                     await send_message(chat_id, COMMAND_MESSAGES['no_restrict_rights']) | ||||
|  | ||||
|                     # Удаляем сообщения через 5 секунд | ||||
|                     await delete_messages(bot, message, 5) | ||||
|  | ||||
|                     return | ||||
|  | ||||
|             except Exception as e: | ||||
|                 await send_message(chat_id, f"⚠️ Ошибка: {str(e)}") | ||||
|                 logger.error(f"Ошибка при получении статуса администратора: {str(e)}") | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Выводим помощь | ||||
|             if len(parts_msg) == 2 and parts_msg[1].strip() in ['help', 'помощь']: | ||||
|                 await send_message(chat_id, COMMAND_MESSAGES['manual_mute']) | ||||
|  | ||||
|                 # Удаляем сообщения через 30 секунд | ||||
|                 await delete_messages(bot, message, 30) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Случай №1 - Команда используется в ответ на сообщение | ||||
|             if len(parts_msg) >= 2: | ||||
|  | ||||
|                 # Если мутят в теме | ||||
|                 if message.is_topic_message: | ||||
|  | ||||
|                     # Если без ответа на сообщение | ||||
|                     if message.message_thread_id == message.reply_to_message.message_id: | ||||
|                         await asyncio.sleep(3) | ||||
|                         await bot.delete_message(message.chat.id, message.message_id) | ||||
|                         return | ||||
|  | ||||
|                     # Если с ответом на сообщение | ||||
|                     else: | ||||
|                         target_user = message.reply_to_message.from_user | ||||
|                         time_arg = parts_msg[1] | ||||
|                         reason = extract_reason(parts_msg[2:]) | ||||
|  | ||||
|                 # Если мутят в обычном чате | ||||
|                 elif message.reply_to_message and message.is_topic_message is None: | ||||
|                     target_user = message.reply_to_message.from_user | ||||
|                     time_arg = parts_msg[1] | ||||
|                     reason = extract_reason(parts_msg[2:]) | ||||
|  | ||||
|                 # Не выводим сообщение, что команда неправильная | ||||
|                 else: | ||||
|                     await asyncio.sleep(3) | ||||
|                     await bot.delete_message(message.chat.id, message.message_id) | ||||
|                     return | ||||
|  | ||||
|             # Случай №2 - Команда через тег или ID | ||||
|             elif len(parts_msg) >= 3: | ||||
|  | ||||
|                 identifier = parts_msg[1].strip() | ||||
|                 time_arg = parts_msg[2] | ||||
|                 reason = extract_reason(parts_msg[3:]) | ||||
|  | ||||
|                 # Поиск по ID | ||||
|                 if identifier.isdigit(): | ||||
|  | ||||
|                     # Делаем в int и ищем | ||||
|                     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 asyncio.sleep(3) | ||||
|                 await bot.delete_message(message.chat.id, message.message_id) | ||||
|                 return | ||||
|  | ||||
|             print(reason) | ||||
|  | ||||
|             # Если пользователь не найден | ||||
|             if not target_user: | ||||
|                 await send_message(chat_id, COMMAND_MESSAGES['user_not_found']) | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Парсинг времени мута | ||||
|             mute_seconds = parse_mute_time(time_arg) | ||||
|             if mute_seconds is None: | ||||
|                 await send_message(chat_id, COMMAND_MESSAGES['incorrect_time_format']) | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Минимальный мут 1 минута (60 секунд) | ||||
|             if mute_seconds < 60: | ||||
|                 await send_message(chat_id, COMMAND_MESSAGES['min_mute']) | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Максимальный мут 30 дней (2592000 секунд) | ||||
|             if mute_seconds > 2592000: | ||||
|                 await send_message(chat_id, COMMAND_MESSAGES['max_mute']) | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Проверяем статус целевого пользователя | ||||
|             try: | ||||
|                 target_status = await bot.get_chat_member(message.chat.id, target_user.id) | ||||
|  | ||||
|                 # Проверяем, является ли цель администратором или создателем | ||||
|                 if target_status.status in ['administrator', 'creator']: | ||||
|                     await send_message(chat_id, COMMAND_MESSAGES['cant_mute_admin']) | ||||
|  | ||||
|                     # Удаляем сообщения через 5 секунд | ||||
|                     await delete_messages(bot, message, 5) | ||||
|  | ||||
|                     return | ||||
|  | ||||
|             except Exception as e: | ||||
|                 await send_message(chat_id, f"⚠️ Ошибка: {str(e)}") | ||||
|                 logger.error(f"Ошибка при получении статуса пользователя: {str(e)}") | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|                 return | ||||
|  | ||||
|             # Выполняем мут | ||||
|             try: | ||||
|  | ||||
|                 # Вычисляем время окончания мута | ||||
|                 until_date = int(time.time()) + mute_seconds | ||||
|  | ||||
|                 # Устанавливаем ограничения (только чтение) | ||||
|                 permissions = ChatPermissions( | ||||
|                     can_send_messages=False, | ||||
|                     can_send_media_messages=False, | ||||
|                     can_send_polls=False, | ||||
|                     can_send_other_messages=False, | ||||
|                     can_add_web_page_previews=False, | ||||
|                     can_change_info=False, | ||||
|                     can_invite_users=False, | ||||
|                     can_pin_messages=False, | ||||
|                 ) | ||||
|  | ||||
|                 await bot.restrict_chat_member( | ||||
|                     chat_id=message.chat.id, | ||||
|                     user_id=target_user.id, | ||||
|                     permissions=permissions, | ||||
|                     until_date=until_date | ||||
|                 ) | ||||
|  | ||||
|                 # Форматирование времени | ||||
|                 time_display = format_time(mute_seconds) | ||||
|  | ||||
|                 # Отправляем сообщения, что пользователь получил мут | ||||
|                 await send_message(chat_id, COMMAND_MESSAGES['muted'].format(time_display=time_display)) | ||||
|                 logger.info(f"Пользователь {target_user.id} замучен на {time_display} администратором {message.from_user.id}.") | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|             except Exception as e: | ||||
|                 await send_message(chat_id, f"⚠️ Ошибка: {str(e)}") | ||||
|                 logger.error(f"Ошибка мута: {str(e)}") | ||||
|  | ||||
|                 # Удаляем сообщения через 5 секунд | ||||
|                 await delete_messages(bot, message, 5) | ||||
|  | ||||
|         except Exception as e: | ||||
|             await send_message(chat_id, COMMAND_MESSAGES['general_error']) | ||||
|             logger.error(f"Общая ошибка в mute_command: {str(e)}") | ||||
|  | ||||
|             # Удаляем сообщения через 5 секунд | ||||
|             await delete_messages(bot, message, 5) | ||||
		Reference in New Issue
	
	Block a user