From 5e22cc063a33d3babd73d531dd1c11085a4b3aa5 Mon Sep 17 00:00:00 2001 From: Muzifs Date: Wed, 9 Jul 2025 16:39:41 +0300 Subject: [PATCH 1/2] updaded start.py & config.py --- src/config.py | 25 ++++++++++++++++++++----- src/modules/start.py | 15 +++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/config.py b/src/config.py index 9292fce..8cc4f0d 100644 --- a/src/config.py +++ b/src/config.py @@ -1,9 +1,24 @@ # Директория, где хранятся модули -MODULES_DIR = "modules" +MODULES_DIR = 'modules' # Название файла db sqlite -DATABASE_NAME = "users.db" +DATABASE_NAME = 'users.db' -# Текст для команд -MESSAGE_FOR_START = "Бот-модератор для чата @linux_gaming_ru" -MESSAGE_FOR_HELP = "пусто" \ No newline at end of file +# Сообщения команд +COMMAND_MESSAGES = { + 'start': 'Бот-модератор для чата @linux_gaming_ru', + 'help': 'пусто', + 'manual_ban': ( + 'ℹ️ Использование бана:\n' + '1️⃣ Ответьте на сообщение: /ban\n' + '2️⃣ Укажите тэг: /ban @username\n' + '3️⃣ Укажите ID: /ban 123456789' + ), + 'no_admin_rights': '❌ Только администраторы могут использовать эту команду.', + 'no_restrict_rights': '❌ У вас недостаточно прав.', + 'user_not_found': '❌ Пользователь не найден.', + 'cant_ban_admin': '❌ Невозможно забанить администратора.', + 'banned': '✅ Пользователь успешно забанен.', + 'general_error': '⚠️ Произошла непредвиденная ошибка.' + +} \ No newline at end of file diff --git a/src/modules/start.py b/src/modules/start.py index dd63f8a..64cd4d1 100644 --- a/src/modules/start.py +++ b/src/modules/start.py @@ -1,7 +1,7 @@ from telebot.async_telebot import AsyncTeleBot import logging -from config import MESSAGE_FOR_START +from config import COMMAND_MESSAGES logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля @@ -9,8 +9,15 @@ def register_handlers(bot: AsyncTeleBot): # Регистрирует все об @bot.message_handler(commands=['start']) # Обработчик команды /start async def start_command(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 + try: - logger.info(f"Команда START ({message.from_user.id})") - await bot.send_message(message.chat.id, MESSAGE_FOR_START) + + await send_message(chat_id, COMMAND_MESSAGES['start']) + logger.info(f"Пользователь {message.from_user.id} запустил /start") + except Exception as e: - logger.error(f"Команда START ({message.from_user.id}) {str(e)}") \ No newline at end of file + logger.error(f"Пользователь {message.from_user.id} запустил /start: {str(e)}") \ No newline at end of file From ae134e84454022a2e950e0dbb6bb31fd8be97874 Mon Sep 17 00:00:00 2001 From: Muzifs Date: Wed, 9 Jul 2025 16:52:17 +0300 Subject: [PATCH 2/2] added command ban --- src/database.py | 20 +++++- src/modules/ban.py | 143 +++++++++++++++++++++++++++++++++++++ src/modules/chat_events.py | 21 ++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/modules/ban.py create mode 100644 src/modules/chat_events.py diff --git a/src/database.py b/src/database.py index d19957e..e10ae5e 100644 --- a/src/database.py +++ b/src/database.py @@ -59,7 +59,25 @@ class Database: # Инициализация класса def get_user(self, user_id: int) -> Optional[Tuple]: with self._get_connection() as connect: cursor = connect.cursor() - cursor.execute('''SELECT id, nickname, tag FROM users WHERE id = ?''', (user_id,)) + cursor.execute(''' + SELECT id, nickname, tag + FROM users + WHERE id = ? + ''', (user_id,)) + return cursor.fetchone() + + # Находит пользователя по username (без @) + def get_user_by_username(self, username: str) -> Optional[Tuple]: + if not username: + return None + + with self._get_connection() as connect: + cursor = connect.cursor() + cursor.execute(''' + SELECT id, nickname, tag + FROM users + WHERE LOWER(tag) = LOWER(?) + ''', (username,)) return cursor.fetchone() # Создаем экземпляр базы данных для импорта в других модулях diff --git a/src/modules/ban.py b/src/modules/ban.py new file mode 100644 index 0000000..11b494d --- /dev/null +++ b/src/modules/ban.py @@ -0,0 +1,143 @@ +from telebot.async_telebot import AsyncTeleBot +from telebot.types import Message, User +import asyncio +import logging +from database import db + +from config import COMMAND_MESSAGES + +logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля + +def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики команд + + @bot.message_handler(commands=['ban']) # Обработчик команды /ban + async def ban_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 + + # Разбиваем текст сообщения на части + 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']) + return + + # Проверяем право администратора на бан + if admin_status.status == 'administrator' and not admin_status.can_restrict_members: + await send_message(chat_id, COMMAND_MESSAGES['no_restrict_rights']) + return + + except Exception as e: + await send_message(chat_id, f"⚠️ Ошибка: {str(e)}") + logger.error(f"Ошибка при получении статуса администратора: {str(e)}") + return + + # Случай №1 - Команда используется в ответ на сообщение + if len(parts_msg) == 1: + + # Если банят в теме + if message.is_topic_message: + + # Если без ответа на сообщение + if message.message_thread_id == message.reply_to_message.message_id: + return + + # Если команда правильная + else: + target_user = message.reply_to_message.from_user + + # Если банят в обычном чате + elif message.reply_to_message and message.is_topic_message is None: + target_user = message.reply_to_message.from_user + + # Не выводим сообщение, что команда неправильная + else: + return + + # Случай №2 - Команда с аргументом (/ban @username или /ban 12345) + elif len(parts_msg) == 2: + + # Выводим помощь (/ban help) + if parts_msg[1].strip() in ['help', 'помощь']: + await send_message(chat_id, COMMAND_MESSAGES['manual_ban']) + return + + identifier = parts_msg[1].strip() + + # Поиск по 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 + ) + + # Если пользователь не найден + if not target_user: + await send_message(chat_id, COMMAND_MESSAGES['user_not_found']) + 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_ban_admin']) + return + + except Exception as e: + await send_message(chat_id, f"⚠️ Ошибка: {str(e)}") + logger.error(f"Ошибка при получении статуса пользователя: {str(e)}") + return + + # Выполняем бан + try: + await bot.ban_chat_member(message.chat.id, target_user.id) + await send_message(chat_id, COMMAND_MESSAGES['banned']) + + await asyncio.sleep(5) + await bot.delete_message(message.chat.id, message.message_id) + await bot.delete_message(message.chat.id, message.message_id+2) + logger.info(f"Пользователь {target_user.id} забанен администратором {message.from_user.id}.") + + except Exception as e: + await send_message(chat_id, f"⚠️ Ошибка: {str(e)}") + logger.error(f"Ошибка бана: {str(e)}") + + except Exception as e: + await send_message(chat_id, COMMAND_MESSAGES['general_error']) + logger.error(f"Общая ошибка в ban_command: {str(e)}") \ No newline at end of file diff --git a/src/modules/chat_events.py b/src/modules/chat_events.py new file mode 100644 index 0000000..0c5a9a9 --- /dev/null +++ b/src/modules/chat_events.py @@ -0,0 +1,21 @@ +from telebot.async_telebot import AsyncTeleBot +from telebot.types import Message +import asyncio + +import logging + +logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля + +def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики событий + + @bot.message_handler(content_types=['new_chat_members']) # Обработчик захода + async def handle_new_members(message: Message): + await asyncio.sleep(10) + await bot.delete_message(message.chat.id, message.message_id) + logger.info(f"Пользователь {message.from_user.id} зашёл в чат.") + + @bot.message_handler(content_types=['left_chat_member']) # Обработчик выхода + async def handle_left_members(message: Message): + await asyncio.sleep(10) + await bot.delete_message(message.chat.id, message.message_id) + logger.info(f"Пользователь {message.from_user.id} вышел из чата.") \ No newline at end of file