Compare commits
20 Commits
c81a37f9ac
...
master
Author | SHA1 | Date | |
---|---|---|---|
51e1d59b12 | |||
a60c6b2ee9 | |||
4cbb60fdf4 | |||
f667ac7085 | |||
853bfcdbb4 | |||
d73c0079f0 | |||
3f23b4c708 | |||
a714e0d05c | |||
40b60baa93 | |||
fc3ef20145 | |||
bc909adf4e | |||
37c596c5c7 | |||
de079a131f | |||
d5c207e1bc | |||
40f75f7ad8 | |||
2648d6f4f1 | |||
c05703c1b1 | |||
a7f9ab26ad | |||
5f38f8c603 | |||
ed4bbacaf1 |
@@ -1 +1,4 @@
|
||||
BOT_TOKEN = "..." # Токен бота получать у @BotFather
|
||||
BOT_TOKEN = "..." # Токен бота получать у @BotFather
|
||||
ADMIN_CHAT_ID = -1001111111111 # ID админ-чата получать у @username_to_id_bot
|
||||
LOG_THREAD_ID = 2 # ID топика, брать из ссылки сообщения
|
||||
ADMIN_IDS = "11111,22222" # ID администраторов получать у @username_to_id_bot
|
18
README.md
18
README.md
@@ -1,21 +1,9 @@
|
||||
<div align="center">
|
||||
<h1 align="center">LGBot</h1>
|
||||
<p align="center">Бот-модератор для @linux_gaming_ru </p>
|
||||
<p align="center">Бот-администратор для @linux_gaming_ru </p>
|
||||
</div>
|
||||
|
||||
## Список дел
|
||||
|
||||
- [X] Команда /start
|
||||
- [ ] Команда /help
|
||||
- [ ] Команда /mute
|
||||
- [ ] Команда /unmute
|
||||
- [X] Команда /ban
|
||||
- [X] Команда /unban
|
||||
- [ ] Фильтрация сообщений
|
||||
- [ ] Удаление сообщений с матом
|
||||
- [ ] Удаление рекламы
|
||||
|
||||
### Установка зависимостей (через pyenv)
|
||||
### Установка зависимостей (pyenv)
|
||||
|
||||
```sh
|
||||
pyenv install 3.11.0
|
||||
@@ -30,7 +18,7 @@ pip install -r requirements.txt
|
||||
|
||||
### Настройка
|
||||
|
||||
Создатите файл **.env** и внесите в него ваш токен, который вы получили у @BotFather.
|
||||
Создайте файл **.env** и внесите в него токен бота, ID админ-чата и топика.
|
||||
|
||||
### Запуск
|
||||
|
||||
|
87
src/action_reporter.py
Normal file
87
src/action_reporter.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
import logging
|
||||
import os
|
||||
from database import db
|
||||
|
||||
# Инициализация
|
||||
class ActionReporter:
|
||||
def __init__(self, bot: AsyncTeleBot, log_chat_id: int, log_thread_id: int):
|
||||
self.bot = bot
|
||||
self.log_chat_id = log_chat_id
|
||||
self.log_thread_id = log_thread_id
|
||||
|
||||
# Получает информацию о пользователе из базы данных
|
||||
async def _get_user_info(self, user_id: int) -> str:
|
||||
user_info = db.get_user(user_id)
|
||||
if user_info:
|
||||
|
||||
# Вытаскиваем данные с кортежа
|
||||
_, nickname, tag = user_info
|
||||
|
||||
# Формируем справку о пользователе
|
||||
text = "👤 <b>Пользователь:</b>\n"
|
||||
if nickname:
|
||||
text += f"• Name: <code>{nickname}</code>\n"
|
||||
if tag:
|
||||
text += f"• Tag: <code>@{tag}</code>\n"
|
||||
text += f"• ID: <code>{user_id}</code>"
|
||||
|
||||
return text
|
||||
|
||||
# Получает информацию об администраторе
|
||||
async def _get_admin_info(self, admin_id: int) -> str:
|
||||
admin_info = db.get_user(admin_id)
|
||||
if admin_info:
|
||||
|
||||
# Вытаскиваем данные с кортежа
|
||||
_, nickname, tag = admin_info
|
||||
|
||||
# Формируем справку об администраторе
|
||||
text = "🛡 <b>Администратор:</b>\n"
|
||||
if nickname:
|
||||
text += f"• Name: <code>{nickname}</code>\n"
|
||||
if tag:
|
||||
text += f"• Tag: <code>@{tag}</code>\n"
|
||||
text += f"• ID: <code>{admin_id}</code>"
|
||||
|
||||
return text
|
||||
|
||||
# Отправляет лог действия в админ-чат
|
||||
async def log_action(self, action: str, user_id: int, admin_id: int, reason: str, duration: str, photo_path: str):
|
||||
try:
|
||||
|
||||
# Получаем информацию о пользователе и администраторе
|
||||
user_info = await self._get_user_info(user_id)
|
||||
admin_info = await self._get_admin_info(admin_id)
|
||||
|
||||
# Формируем сообщение
|
||||
msg = f"⚙️ <b>Действие:</b> {action}\n"
|
||||
|
||||
if duration:
|
||||
msg += f"⏱ <b>Длительность:</b> {duration}\n"
|
||||
|
||||
if reason:
|
||||
msg += f"📝 <b>Причина:</b> <i>{reason}</i>\n"
|
||||
|
||||
msg += f"\n{user_info}\n\n{admin_info}"
|
||||
|
||||
# Отправляем лог с изображением
|
||||
if photo_path and os.path.exists(photo_path):
|
||||
with open(photo_path, 'rb') as photo_file:
|
||||
await self.bot.send_photo(self.log_chat_id, photo_file, caption=msg, message_thread_id=self.log_thread_id)
|
||||
|
||||
# Отправляем лог без изображения
|
||||
else:
|
||||
await self.bot.send_message(self.log_chat_id, msg, message_thread_id=self.log_thread_id)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Ошибка отправки лога: {str(e)}")
|
||||
|
||||
# Создаем глобальный экземпляр для импорта
|
||||
action_reporter = None
|
||||
|
||||
# Инициализирует логгер модерации
|
||||
def init_action_reporter(bot: AsyncTeleBot, log_chat_id: int, log_thread_id: int):
|
||||
global action_reporter
|
||||
action_reporter = ActionReporter(bot, log_chat_id, log_thread_id)
|
@@ -4,27 +4,78 @@ MODULES_DIR = 'modules'
|
||||
# Название файла db sqlite
|
||||
DATABASE_NAME = 'users.db'
|
||||
|
||||
# Название файла для логов
|
||||
LOG_FILE_NAME = 'bot.log'
|
||||
|
||||
# Сообщения команд
|
||||
COMMAND_MESSAGES = {
|
||||
'start': 'Бот-модератор для чата @linux_gaming_ru',
|
||||
'help': 'пусто',
|
||||
'start': 'Бот-администратор для чата @linux_gaming_ru',
|
||||
'help': (
|
||||
"<b>📚 Справочник команд администратора</b>\n\n"
|
||||
"<u>Основные команды:</u>\n"
|
||||
"• <code>/start</code> - Начало работы\n"
|
||||
"• <code>/help</code> - Этот справочник\n\n"
|
||||
"<u>🛠 Команды модерации:</u>\n"
|
||||
"• <code>/mute help</code> - Инструкция по муту\n"
|
||||
"• <code>/unmute help</code> - Снятие мута\n"
|
||||
"• <code>/ban help</code> - Инструкция по бану\n"
|
||||
"• <code>/unban help</code> - Снятие бана\n\n"
|
||||
"<i>ℹ️ Для подробностей по конкретной команде используйте: /команда help</i>"
|
||||
),
|
||||
'manual_mute': (
|
||||
'ℹ️ Использование мута:\n'
|
||||
'1️⃣ Ответьте на сообщение: <code>/mute время</code>\n'
|
||||
'2️⃣ Укажите тэг: <code>/mute @username время</code>\n'
|
||||
'3️⃣ Укажите ID: <code>/mute 123456789 время</code>\n\n'
|
||||
"<b>🔇 Команда /mute</b>\n\n"
|
||||
"<i>Ограничивает права пользователя на указанное время</i>\n\n"
|
||||
"<u>🕒 Форматы времени:</u>\n"
|
||||
"• Минуты: <code>10м</code>, <code>30м</code>\n"
|
||||
"• Часы: <code>1ч</code>, <code>3ч</code>\n"
|
||||
"• Дни: <code>1д</code>, <code>7д</code>\n\n"
|
||||
"<u>🎯 Способы использования:</u>\n"
|
||||
"1. Ответ на сообщение:\n"
|
||||
" <code>/mute 30м причина</code>\n"
|
||||
"2. По тегу пользователя:\n"
|
||||
" <code>/mute @username 1ч спам</code>\n"
|
||||
"3. По ID пользователя:\n"
|
||||
" <code>/mute 123456789 1д нарушение правил</code>\n\n"
|
||||
"<b>⚠️ Максимальный срок: 30 дней</b>\n"
|
||||
"<i>ℹ️ Причину стараться указывать</i>"
|
||||
),
|
||||
'manual_unmute': (
|
||||
"<b>🔊 Команда /unmute</b>\n\n"
|
||||
"<i>Снимает ограничения с пользователя</i>\n\n"
|
||||
"<u>🎯 Способы использования:</u>\n"
|
||||
"1. Ответ на сообщение:\n"
|
||||
" <code>/unmute</code>\n"
|
||||
"2. По тегу пользователя:\n"
|
||||
" <code>/unmute @username</code>\n"
|
||||
"3. По ID пользователя:\n"
|
||||
" <code>/unmute 123456789</code>\n\n"
|
||||
"<i>ℹ️ Работает только для временно замученных пользователей</i>"
|
||||
),
|
||||
'manual_ban': (
|
||||
'ℹ️ Использование бана:\n'
|
||||
'1️⃣ Ответьте на сообщение: <code>/ban</code>\n'
|
||||
'2️⃣ Укажите тэг: <code>/ban @username</code>\n'
|
||||
'3️⃣ Укажите ID: <code>/ban 123456789</code>'
|
||||
"<b>🚫 Команда /ban</b>\n\n"
|
||||
"<i>Навсегда исключает пользователя из чата</i>\n\n"
|
||||
"<u>🎯 Способы использования:</u>\n"
|
||||
"1. Ответ на сообщение:\n"
|
||||
" <code>/ban причина</code>\n"
|
||||
"2. По тегу пользователя:\n"
|
||||
" <code>/ban @username спам</code>\n"
|
||||
"3. По ID пользователя:\n"
|
||||
" <code>/ban 123456789 нарушение правил</code>\n\n"
|
||||
"<b>⚠️ Добавляет в ЧС</b>\n"
|
||||
"<i>ℹ️ Для разбана используйте /unban</i>"
|
||||
),
|
||||
'manual_unban': (
|
||||
'ℹ️ Использование разбана:\n'
|
||||
'1️⃣ Ответьте на сообщение: <code>/unban</code>\n'
|
||||
'2️⃣ Укажите тэг: <code>/unban @username</code>\n'
|
||||
'3️⃣ Укажите ID: <code>/unban 123456789</code>'
|
||||
"<b>✅ Команда /unban</b>\n\n"
|
||||
"<i>Снимает бан с пользователя</i>\n\n"
|
||||
"<u>🎯 Способы использования:</u>\n"
|
||||
"1. Ответ на сообщение:\n"
|
||||
" <code>/unban</code>\n"
|
||||
"2. По тегу пользователя:\n"
|
||||
" <code>/unban @username</code>\n"
|
||||
"3. По ID пользователя:\n"
|
||||
" <code>/unban 123456789</code>\n\n"
|
||||
"<b>⚠️ Работает только для забаненных через /ban</b>\n"
|
||||
"<i>ℹ️ Пользователь сможет снова присоединиться</i>"
|
||||
),
|
||||
'no_admin_rights': '❌ Только администраторы могут использовать эту команду.',
|
||||
'no_restrict_rights': '❌ У вас недостаточно прав.',
|
||||
@@ -35,8 +86,10 @@ COMMAND_MESSAGES = {
|
||||
'cant_mute_admin': '❌ Невозможно замутить администратора.',
|
||||
'cant_ban_admin': '❌ Невозможно забанить администратора.',
|
||||
'muted': '✅ Пользователь замучен на {time_display}.',
|
||||
'unmuted': '✅ Пользователь размучен.',
|
||||
'banned': '✅ Пользователь успешно забанен.',
|
||||
'unbanned': '✅ Пользователь успешно разбанен.',
|
||||
'error': '⚠️ Ошибка: {e}',
|
||||
'general_error': '⚠️ Произошла непредвиденная ошибка.'
|
||||
|
||||
}
|
@@ -2,6 +2,8 @@ import logging
|
||||
import time
|
||||
import os
|
||||
|
||||
from config import LOG_FILE_NAME
|
||||
|
||||
class ColoredFormatter(logging.Formatter): # Цветные логи (для терминала)
|
||||
LEVEL_COLORS = {
|
||||
logging.INFO: '\033[92m',
|
||||
@@ -38,6 +40,13 @@ class UncoloredFormatter(logging.Formatter): # Бесцветные логи (д
|
||||
return f"[{time_str}] [{date_str}] [{level_name}] {record.getMessage()}"
|
||||
|
||||
def setup_logging(): # Инициализирует систему логирования
|
||||
|
||||
# Добавляем разделитель для нового сеанса
|
||||
if os.path.exists(LOG_FILE_NAME):
|
||||
with open(LOG_FILE_NAME, "a", encoding="utf-8") as f:
|
||||
f.write("\n" + "=" * 60 + "\n")
|
||||
f.write(f"{'ЗАПУЩЕН НОВЫЙ СЕАНС':^60}\n")
|
||||
f.write("=" * 60 + "\n\n")
|
||||
|
||||
# Создаем корневой логгер
|
||||
logger = logging.getLogger()
|
||||
@@ -49,7 +58,7 @@ def setup_logging(): # Инициализирует систему логиро
|
||||
console_handler.setFormatter(ColoredFormatter())
|
||||
|
||||
# Сохраняем логи в файл
|
||||
file_handler = logging.FileHandler("bot.log", encoding='utf-8')
|
||||
file_handler = logging.FileHandler(LOG_FILE_NAME, encoding='utf-8')
|
||||
file_handler.setFormatter(UncoloredFormatter())
|
||||
|
||||
logger.addHandler(console_handler)
|
||||
|
72
src/main.py
72
src/main.py
@@ -12,13 +12,21 @@ from logger import setup_logging
|
||||
|
||||
from database import db
|
||||
|
||||
from action_reporter import init_action_reporter
|
||||
|
||||
from config import MODULES_DIR
|
||||
|
||||
load_dotenv() # Загружаем токен бота из .env
|
||||
# Загружаем токен бота из .env
|
||||
load_dotenv()
|
||||
bot = AsyncTeleBot(os.getenv("BOT_TOKEN"), parse_mode="html")
|
||||
|
||||
logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля
|
||||
# Загружаем ID админ-чата из .env и инициализируемся для логов в чат
|
||||
init_action_reporter(bot, os.getenv("ADMIN_CHAT_ID"), os.getenv("LOG_THREAD_ID"))
|
||||
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Middleware для автоматического обновления информации о пользователях в базе данных
|
||||
class UserUpdateMiddleware(BaseMiddleware):
|
||||
def __init__(self, db):
|
||||
super().__init__()
|
||||
@@ -27,6 +35,7 @@ class UserUpdateMiddleware(BaseMiddleware):
|
||||
self.update_types = ['message', 'chat_member']
|
||||
self.db = db
|
||||
|
||||
# Обработчик, вызываемый ДО обработки сообщения основными хэндлерами
|
||||
async def pre_process(self, message, data):
|
||||
|
||||
# Обработка пользователей, отправившие сообщение
|
||||
@@ -47,43 +56,78 @@ class UserUpdateMiddleware(BaseMiddleware):
|
||||
)
|
||||
return data
|
||||
|
||||
# Обработчик, вызываемый ПОСЛЕ обработки сообщения основными хэндлерами
|
||||
async def post_process(self, message, data, exception):
|
||||
pass
|
||||
|
||||
# Регистрируем middleware
|
||||
bot.setup_middleware(UserUpdateMiddleware(db))
|
||||
|
||||
async def load_modules(): # Загружает все модули из директории /modules
|
||||
# Загружает все модули из директории /modules
|
||||
async def load_modules():
|
||||
|
||||
setup_logging() # Инициализация логирования
|
||||
# Инициализация логирования
|
||||
setup_logging()
|
||||
|
||||
loaded_count = 0 # Переменная для подсчёта модулей
|
||||
modules_path = os.path.join(os.path.dirname(__file__), MODULES_DIR) # Импортируем относительный путь проекта
|
||||
# Переменная для подсчёта модулей
|
||||
loaded_count = 0
|
||||
|
||||
# Импортируем относительный путь проекта
|
||||
modules_path = os.path.join(os.path.dirname(__file__), MODULES_DIR)
|
||||
|
||||
for filename in os.listdir(modules_path):
|
||||
|
||||
# Если файл содержит в конце .py (кроме __init__.py)
|
||||
if filename.endswith(".py") and filename != "__init__.py":
|
||||
module_name = filename[:-3] # Убираем расширение .py
|
||||
|
||||
# Убираем расширение .py
|
||||
module_name = filename[:-3]
|
||||
|
||||
try:
|
||||
|
||||
# Импортируем модуль (modules.start)
|
||||
module = importlib.import_module(f"{MODULES_DIR}.{module_name}")
|
||||
|
||||
# Если присутствует register_handlers
|
||||
if hasattr(module, "register_handlers"):
|
||||
|
||||
module.register_handlers(bot)
|
||||
loaded_count += 1
|
||||
logger.info(f"Модуль {module_name} успешно загружен")
|
||||
logger.info(f"Модуль {module_name} успешно загружен.")
|
||||
|
||||
# Если нет register_handlers
|
||||
else:
|
||||
logger.warning(f"Модуль {module_name} не содержит функцию register_handlers")
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.warning(f"Модуль {module_name} не содержит функцию register_handlers.")
|
||||
|
||||
except Exception as e:
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка при загрузке модуля {module_name}: {str(e)}")
|
||||
|
||||
# Записываем отчет о модулях в логи
|
||||
logger.info(f"Загружено модулей: {loaded_count} шт. Бот запущен.")
|
||||
|
||||
async def main():
|
||||
os.system('clear') # Очищаем терминал
|
||||
|
||||
# Очищаем терминал
|
||||
os.system('clear')
|
||||
|
||||
try:
|
||||
await load_modules() # Проверяем и загружаем модули
|
||||
await bot.infinity_polling() # Запускаем бота
|
||||
except (KeyboardInterrupt, asyncio.CancelledError):
|
||||
logger.info("Бот остановлен.")
|
||||
|
||||
# Проверяем и загружаем модули
|
||||
await load_modules()
|
||||
|
||||
# Запускаем бота
|
||||
await bot.infinity_polling()
|
||||
|
||||
except Exception as e:
|
||||
|
||||
# Записываем критическую ошибку в логи
|
||||
logger.critical(f"Критическая ошибка: {str(e)}")
|
||||
|
||||
# Завершаем скрипт с критической ошибкой
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@@ -4,232 +4,246 @@ import asyncio
|
||||
import logging
|
||||
from database import db
|
||||
|
||||
from action_reporter import action_reporter
|
||||
from utils import (
|
||||
delete_messages,
|
||||
check_admin_status,
|
||||
check_target_status,
|
||||
)
|
||||
|
||||
from config import COMMAND_MESSAGES
|
||||
|
||||
logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля
|
||||
|
||||
# Возвращает причину бана
|
||||
def extract_reason(words: str) -> str:
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
if words == []:
|
||||
reason = 'отсутствует'
|
||||
else:
|
||||
reason = ' '.join(words)
|
||||
# Обработчик команды /ban
|
||||
@bot.message_handler(commands=['ban'])
|
||||
async def _ban_command_wrapper(message: Message):
|
||||
await ban_command(bot, message)
|
||||
|
||||
return reason
|
||||
# Основная функция команды /ban
|
||||
async def ban_command(bot: AsyncTeleBot, message: Message, photo_path: str = None):
|
||||
|
||||
# Удаляет два последних сообщения
|
||||
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)
|
||||
# Определяем целевого пользователя
|
||||
target_user = None
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики команд
|
||||
# Определяем причину
|
||||
reason = None
|
||||
|
||||
@bot.message_handler(commands=['ban']) # Обработчик команды /ban
|
||||
async def ban_command(message: Message):
|
||||
# Разбиваем текст сообщения на части
|
||||
parts_msg = message.text.split()
|
||||
|
||||
# Отправка сообщения в тему или обычный чат
|
||||
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
|
||||
# Команда /ban help
|
||||
if len(parts_msg) == 2 and parts_msg[1].strip() in ('help', 'помощь'):
|
||||
|
||||
# Определяем целевого пользователя
|
||||
target_user = None
|
||||
# Отправляем инструкцию
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['manual_ban'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Определяем причину
|
||||
reason = None
|
||||
# Удаляем сообщения через 30 секунд
|
||||
await delete_messages(bot, message, time_sleep=30, number_message=2)
|
||||
return
|
||||
|
||||
# Разбиваем текст сообщения на части
|
||||
parts_msg = message.text.split()
|
||||
try:
|
||||
|
||||
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'])
|
||||
# Проверяем, является ли отправитель администратором
|
||||
if await check_admin_status(bot, message) == 1:
|
||||
return
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, 5)
|
||||
# Команда через ответ на сообщение, если одно слово (/ban)
|
||||
if len(parts_msg) == 1:
|
||||
|
||||
# Если это топик
|
||||
if message.is_topic_message:
|
||||
|
||||
# Если без ответа на сообщение
|
||||
if message.message_thread_id == message.reply_to_message.message_id:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
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)
|
||||
# Если с ответом на сообщение
|
||||
else:
|
||||
|
||||
return
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
reason = 'отсутствует'
|
||||
|
||||
# Если это General (обычный чат)
|
||||
elif message.reply_to_message and message.is_topic_message is None:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
reason = 'отсутствует'
|
||||
message.message_thread_id = None
|
||||
|
||||
except Exception as e:
|
||||
await send_message(chat_id, f"⚠️ Ошибка: {str(e)}")
|
||||
logger.error(f"Ошибка при получении статуса администратора: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, 5)
|
||||
|
||||
# Если команда неправильная
|
||||
else:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Выводим помощь (/ban help)
|
||||
if len(parts_msg) == 2 and parts_msg[1].strip() in ['help', 'помощь']:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['manual_ban'])
|
||||
# В сообщении больше одного слова
|
||||
else:
|
||||
|
||||
# Если второе слово это тег или ID
|
||||
if parts_msg[1].strip().isdigit() or parts_msg[1].startswith('@'):
|
||||
|
||||
# Собираем данные
|
||||
identifier = parts_msg[1].strip()
|
||||
reason = ' '.join(parts_msg[2:]) if parts_msg[2:] != [] else 'отсутствует'
|
||||
|
||||
# Делаем поиск по ID
|
||||
if identifier.isdigit():
|
||||
|
||||
# Удаляем сообщения через 30 секунд
|
||||
await delete_messages(bot, message, 30)
|
||||
# Ищем пользователя в базе данных
|
||||
user_info = db.get_user(int(identifier))
|
||||
|
||||
return
|
||||
# Если нашли пользователя
|
||||
if user_info:
|
||||
|
||||
# Если одно слово, то ответом на сообщение
|
||||
if len(parts_msg) == 1:
|
||||
# Создаем объект пользователя
|
||||
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:
|
||||
|
||||
# Если это топик
|
||||
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)
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Если с ответом на сообщение
|
||||
else:
|
||||
target_user = message.reply_to_message.from_user
|
||||
reason = extract_reason(parts_msg[1:])
|
||||
|
||||
# Если это обычный чат
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
reason = ' '.join(parts_msg[1:])
|
||||
|
||||
# Если это General (обычный чат)
|
||||
elif message.reply_to_message and message.is_topic_message is None:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
reason = extract_reason(parts_msg[1:])
|
||||
reason = ' '.join(parts_msg[1:])
|
||||
message.message_thread_id = None
|
||||
|
||||
# Удаляем сообщение, если команда неправильная
|
||||
# Если команда неправильная
|
||||
else:
|
||||
await asyncio.sleep(3)
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
else:
|
||||
|
||||
# Если второе слово это тег или ID
|
||||
if parts_msg[1].strip().isdigit() or parts_msg[1].startswith('@'):
|
||||
|
||||
identifier = parts_msg[1].strip()
|
||||
reason = extract_reason(parts_msg[2:])
|
||||
|
||||
# Поиск по ID
|
||||
if identifier.isdigit():
|
||||
# Если пользователь не найден в базе данных
|
||||
if not target_user:
|
||||
|
||||
# Делаем в 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:
|
||||
|
||||
# Если это тема
|
||||
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
|
||||
reason = extract_reason(parts_msg[1:])
|
||||
|
||||
# Если это обычный чат
|
||||
elif message.reply_to_message and message.is_topic_message is None:
|
||||
target_user = message.reply_to_message.from_user
|
||||
reason = extract_reason(parts_msg[1:])
|
||||
|
||||
# Удаляем сообщение, если команда неправильная
|
||||
else:
|
||||
await asyncio.sleep(3)
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
||||
return
|
||||
|
||||
# Если пользователь не найден
|
||||
if not target_user:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['user_not_found'])
|
||||
|
||||
# Удаляем сообщения через 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_ban_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:
|
||||
await bot.ban_chat_member(message.chat.id, target_user.id)
|
||||
|
||||
# Отправляем сообщения, что пользователь получил бан
|
||||
await send_message(chat_id, COMMAND_MESSAGES['banned'])
|
||||
logger.info(f"Пользователь {target_user.id} забанен администратором {message.from_user.id}.")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
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)
|
||||
|
||||
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"Общая ошибка в ban_command: {str(e)}")
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['user_not_found'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, 5)
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Проверяем статус целевого пользователя
|
||||
if await check_target_status(bot, message, target_user) == 1:
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
# Выполняем бан
|
||||
await bot.ban_chat_member(
|
||||
chat_id=message.chat.id,
|
||||
user_id=target_user.id,
|
||||
)
|
||||
|
||||
# Отправляем лог в админ-чат
|
||||
await action_reporter.log_action(
|
||||
action="БАН",
|
||||
user_id=target_user.id,
|
||||
admin_id=message.from_user.id,
|
||||
reason=reason,
|
||||
duration=None,
|
||||
photo_path=photo_path,
|
||||
)
|
||||
|
||||
# Отправляем сообщения, что пользователь получил бан
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['banned'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {target_user.id} забанен администратором {message.from_user.id}.")
|
||||
|
||||
# Удаляем сообщения через 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['error'].format(e=str(e)),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка бана: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 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"Общая ошибка в ban_command: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
67
src/modules/botdata.py
Normal file
67
src/modules/botdata.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from utils import delete_messages
|
||||
|
||||
from config import COMMAND_MESSAGES, DATABASE_NAME, LOG_FILE_NAME
|
||||
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Загружаем id администраторов из .env
|
||||
ADMIN_IDS = [int(id_str.strip()) for id_str in os.getenv('ADMIN_IDS').split(',')]
|
||||
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
# Обработчик команды /botdata
|
||||
@bot.message_handler(commands=['botdata'])
|
||||
async def botdata_command(message: Message):
|
||||
|
||||
try:
|
||||
|
||||
# Если id администратора совпадает
|
||||
if message.from_user.id in ADMIN_IDS:
|
||||
|
||||
# Отправляем базу данных
|
||||
await bot.send_document(
|
||||
chat_id=message.chat.id,
|
||||
document=open(DATABASE_NAME, 'rb')
|
||||
)
|
||||
|
||||
# Отправляем файл с логами
|
||||
await bot.send_document(
|
||||
chat_id=message.chat.id,
|
||||
document=open(LOG_FILE_NAME, 'rb')
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Администратор {message.from_user.id} запустил /botdata.")
|
||||
|
||||
# Если id администратора не совпадает
|
||||
else:
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['no_admin_rights'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {message.from_user.id} запустил /botdata.")
|
||||
|
||||
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"Общая ошибка в botdata_command: {str(e)}")
|
@@ -10,13 +10,13 @@ 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)
|
||||
for new_member in message.new_chat_members:
|
||||
logger.info(f"Пользователь {new_member.id} зашёл в чат.")
|
||||
await asyncio.sleep(10)
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
||||
|
||||
@bot.message_handler(content_types=['left_chat_member']) # Обработчик выхода
|
||||
async def handle_left_members(message: Message):
|
||||
logger.info(f"Пользователь {message.left_chat_member.id} вышел из чата.")
|
||||
await asyncio.sleep(10)
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
||||
logger.info(f"Пользователь {message.left_chat_member.id} вышел из чата.")
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
70
src/modules/content_filter.py
Normal file
70
src/modules/content_filter.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
import logging
|
||||
from database import db
|
||||
|
||||
# Импортируем обработчики команд
|
||||
from modules.mute import mute_command
|
||||
from modules.ban import ban_command
|
||||
|
||||
logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики событий
|
||||
|
||||
# Обработчик изображений
|
||||
@bot.message_handler(content_types=['photo'])
|
||||
async def message_photo(message: Message):
|
||||
|
||||
# Определяем путь к изображению
|
||||
photo_path = None
|
||||
|
||||
try:
|
||||
|
||||
# Проверяем, есть ли подпись
|
||||
if not message.caption:
|
||||
return
|
||||
|
||||
# Разделяем подпись на части
|
||||
parts = message.caption.split()
|
||||
|
||||
# Определяем команду (первое слово в подписи)
|
||||
command = parts[0].lower()
|
||||
|
||||
# Поддерживаемые команды
|
||||
supported_commands = {
|
||||
'/mute': mute_command,
|
||||
'/ban': ban_command
|
||||
}
|
||||
|
||||
# Проверяем, является ли первое слово командой
|
||||
if command not in supported_commands:
|
||||
return
|
||||
|
||||
# Скачиваем изображение
|
||||
file_info = await bot.get_file(message.photo[-1].file_id)
|
||||
os.makedirs("tmp", exist_ok=True)
|
||||
photo_path = f"tmp/{file_info.file_id}.jpg"
|
||||
downloaded_file = await bot.download_file(file_info.file_path)
|
||||
|
||||
with open(photo_path, 'wb') as new_file:
|
||||
new_file.write(downloaded_file)
|
||||
|
||||
# Переносим caption в text
|
||||
message.text = message.caption
|
||||
|
||||
# Вызываем обработчик команды
|
||||
handler = supported_commands[command]
|
||||
await handler(bot, message, photo_path=photo_path)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка обработки команды с изображением: {str(e)}")
|
||||
|
||||
finally:
|
||||
if photo_path and os.path.exists(photo_path):
|
||||
try:
|
||||
os.remove(photo_path)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка удаления временного изображения: {str(e)}")
|
48
src/modules/help.py
Normal file
48
src/modules/help.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from utils import delete_messages
|
||||
|
||||
from config import COMMAND_MESSAGES
|
||||
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
# Обработчик команды /help
|
||||
@bot.message_handler(commands=['help'])
|
||||
async def help_command(message: Message):
|
||||
|
||||
try:
|
||||
|
||||
# Отправляем сообщение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['help'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {message.from_user.id} запустил /help.")
|
||||
|
||||
# Если пользователь писал в чат
|
||||
if message.chat.id != message.from_user.id:
|
||||
|
||||
# Удаляем сообщения через 30 секунд
|
||||
await delete_messages(bot, message, time_sleep=30, 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"Общая ошибка в help_command: {str(e)}")
|
@@ -5,339 +5,329 @@ import logging
|
||||
import time
|
||||
from database import db
|
||||
|
||||
from action_reporter import action_reporter
|
||||
from utils import (
|
||||
delete_messages,
|
||||
check_admin_status,
|
||||
check_target_status,
|
||||
parse_mute_time,
|
||||
format_mute_time,
|
||||
)
|
||||
|
||||
from config import COMMAND_MESSAGES
|
||||
|
||||
logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Возвращает количество секунд
|
||||
def parse_mute_time(time_str: str) -> int:
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
# Парсим строку времени
|
||||
time_str = time_str.strip().lower()
|
||||
# Обработчик команды /mute
|
||||
@bot.message_handler(commands=['mute'])
|
||||
async def _mute_command_wrapper(message: Message):
|
||||
await mute_command(bot, message)
|
||||
|
||||
# Минуты
|
||||
if time_str.endswith('m') or time_str.endswith('м'):
|
||||
try:
|
||||
minutes = int(time_str[:-1])
|
||||
return abs(minutes) * 60
|
||||
except:
|
||||
return None
|
||||
# Основная функция команды /mute
|
||||
async def mute_command(bot: AsyncTeleBot, message: Message, photo_path: str = None):
|
||||
|
||||
# Часы
|
||||
elif time_str.endswith('h') or time_str.endswith('ч'):
|
||||
try:
|
||||
hours = int(time_str[:-1])
|
||||
return abs(hours) * 3600
|
||||
except:
|
||||
return None
|
||||
# Определяем целевого пользователя
|
||||
target_user = None
|
||||
|
||||
# Дни
|
||||
elif time_str.endswith('d') or time_str.endswith('д'):
|
||||
try:
|
||||
days = int(time_str[:-1])
|
||||
return abs(days) * 86400
|
||||
except:
|
||||
return None
|
||||
# Отпределяем время
|
||||
time_arg = None
|
||||
|
||||
# Число без указания единицы (по умолчанию минуты)
|
||||
elif time_str.isdigit():
|
||||
try:
|
||||
minutes = int(time_str)
|
||||
return abs(minutes) * 60
|
||||
except:
|
||||
return None
|
||||
# Определяем причину
|
||||
reason = None
|
||||
|
||||
return None
|
||||
# Разбиваем текст сообщения на части
|
||||
parts_msg = message.text.split()
|
||||
|
||||
# Возвращает причину мута
|
||||
def extract_reason(words: str) -> str:
|
||||
# Команда /mute help
|
||||
if len(parts_msg) == 2 and parts_msg[1].strip() in ('help', 'помощь'):
|
||||
|
||||
if words == []:
|
||||
reason = 'отсутствует'
|
||||
else:
|
||||
reason = ' '.join(words)
|
||||
# Отправляем инструкцию
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['manual_mute'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
return reason
|
||||
# Удаляем сообщения через 30 секунд
|
||||
await delete_messages(bot, message, time_sleep=30, number_message=2)
|
||||
return
|
||||
|
||||
# Форматирует время в нормальный вид
|
||||
def format_time(seconds: int) -> str:
|
||||
try:
|
||||
|
||||
# Для минут
|
||||
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} минут"
|
||||
# Проверяем, является ли отправитель администратором
|
||||
if await check_admin_status(bot, message) == 1:
|
||||
return
|
||||
|
||||
# Для часов
|
||||
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} часов"
|
||||
# Если одно слово (/mute)
|
||||
if len(parts_msg) == 1:
|
||||
|
||||
# Для дней
|
||||
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} дней"
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Удаляет два последних сообщения
|
||||
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)
|
||||
# Команда через ответ на сообщение, если два слова (/mute 2m)
|
||||
elif len(parts_msg) == 2:
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики команд
|
||||
# Если это топик
|
||||
if message.is_topic_message:
|
||||
|
||||
@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)
|
||||
# Если без ответа на сообщение
|
||||
if message.message_thread_id == message.reply_to_message.message_id:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Проверяем право администратора на мут
|
||||
if admin_status.status == 'administrator' and not admin_status.can_restrict_members:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['no_restrict_rights'])
|
||||
# Если с ответом на сообщение
|
||||
else:
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, 5)
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
time_arg = parts_msg[1]
|
||||
reason = 'отсутствует'
|
||||
|
||||
return
|
||||
# Если это General (обычный чат)
|
||||
elif message.reply_to_message and message.is_topic_message is None:
|
||||
|
||||
except Exception as e:
|
||||
await send_message(chat_id, f"⚠️ Ошибка: {str(e)}")
|
||||
logger.error(f"Ошибка при получении статуса администратора: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, 5)
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
time_arg = parts_msg[1]
|
||||
reason = 'отсутствует'
|
||||
message.message_thread_id = None
|
||||
|
||||
# Если команда неправильная
|
||||
else:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Выводим помощь
|
||||
if len(parts_msg) == 2 and parts_msg[1].strip() in ['help', 'помощь']:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['manual_mute'])
|
||||
# В сообщении больше двух слов
|
||||
else:
|
||||
|
||||
# Удаляем сообщения через 30 секунд
|
||||
await delete_messages(bot, message, 30)
|
||||
# Если второе слово это тег или ID
|
||||
if parts_msg[1].strip().isdigit() or parts_msg[1].startswith('@'):
|
||||
|
||||
return
|
||||
# Собираем данные
|
||||
identifier = parts_msg[1].strip()
|
||||
time_arg = parts_msg[2]
|
||||
reason = ' '.join(parts_msg[3:]) if parts_msg[3:] != [] else 'отсутствует'
|
||||
|
||||
# Случай №1 - Команда используется в ответ на сообщение
|
||||
if len(parts_msg) >= 2:
|
||||
# Делаем поиск по 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:
|
||||
|
||||
# Если это топик
|
||||
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)
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Если с ответом на сообщение
|
||||
else:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
time_arg = parts_msg[1]
|
||||
reason = extract_reason(parts_msg[2:])
|
||||
reason = ' '.join(parts_msg[2:])
|
||||
|
||||
# Если мутят в обычном чате
|
||||
# Если это General (обычный чат)
|
||||
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:])
|
||||
|
||||
# Не выводим сообщение, что команда неправильная
|
||||
reason = ' '.join(parts_msg[2:])
|
||||
message.message_thread_id = None
|
||||
|
||||
# Если команда неправильная
|
||||
else:
|
||||
await asyncio.sleep(3)
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Случай №2 - Команда через тег или ID
|
||||
elif len(parts_msg) >= 3:
|
||||
# Если пользователь не найден в базе данных
|
||||
if not target_user:
|
||||
|
||||
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)}")
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['user_not_found'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, 5)
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Парсинг времени мута
|
||||
mute_seconds = parse_mute_time(time_arg)
|
||||
|
||||
# Если не указали время
|
||||
if mute_seconds is None:
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['incorrect_time_format'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Минимальное время мута - 1 минута (60 секунд)
|
||||
if mute_seconds < 60:
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['min_mute'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Максимальное время мута - 30 дней (2592000 секунд)
|
||||
if mute_seconds > 2592000:
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['max_mute'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Проверяем статус целевого пользователя
|
||||
if await check_target_status(bot, message, target_user) == 1:
|
||||
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_mute_time(mute_seconds)
|
||||
|
||||
# Отправляем сообщение-лог в админ-чат
|
||||
await action_reporter.log_action(
|
||||
action="МУТ",
|
||||
user_id=target_user.id,
|
||||
admin_id=message.from_user.id,
|
||||
reason=reason,
|
||||
duration=time_display,
|
||||
photo_path=photo_path,
|
||||
)
|
||||
|
||||
# Отправляем сообщение, что пользователь получил мут
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['muted'].format(time_display=time_display),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {target_user.id} получил мут на {time_display} от администратора {message.from_user.id}.")
|
||||
|
||||
# Удаляем сообщения через 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['error'].format(e=str(e)),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка мута: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 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"Общая ошибка в mute_command: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
@@ -1,24 +1,48 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from utils import delete_messages
|
||||
|
||||
from config import COMMAND_MESSAGES
|
||||
|
||||
logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики команд
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
@bot.message_handler(commands=['start']) # Обработчик команды /start
|
||||
# Обработчик команды /start
|
||||
@bot.message_handler(commands=['start'])
|
||||
async def start_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
|
||||
|
||||
try:
|
||||
|
||||
await send_message(chat_id, COMMAND_MESSAGES['start'])
|
||||
# Отправляем сообщение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['start'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {message.from_user.id} запустил /start.")
|
||||
|
||||
# Если пользователь писал в чат
|
||||
if message.chat.id != message.from_user.id:
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Пользователь {message.from_user.id} запустил /start: {str(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"Общая ошибка в start_command: {str(e)}")
|
@@ -1,88 +1,103 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message, User
|
||||
from telebot.types import Message, User, ChatPermissions
|
||||
import asyncio
|
||||
import logging
|
||||
from database import db
|
||||
|
||||
from action_reporter import action_reporter
|
||||
from utils import (
|
||||
delete_messages,
|
||||
check_admin_status,
|
||||
check_target_status,
|
||||
)
|
||||
|
||||
from config import COMMAND_MESSAGES
|
||||
|
||||
logger = logging.getLogger(__name__) # Получаем логгер для текущего модуля
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def register_handlers(bot: AsyncTeleBot): # Регистрирует все обработчики команд
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
@bot.message_handler(commands=['unban']) # Обработчик команды /unban
|
||||
# Обработчик команды /unban
|
||||
@bot.message_handler(commands=['unban'])
|
||||
async def unban_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
|
||||
# Команда /unban help
|
||||
if len(parts_msg) == 2 and parts_msg[1].strip() in ('help', 'помощь'):
|
||||
|
||||
except Exception as e:
|
||||
await send_message(chat_id, f"⚠️ Ошибка: {str(e)}")
|
||||
logger.error(f"Ошибка при получении статуса администратора: {str(e)}")
|
||||
# Отправляем инструкцию
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['manual_unban'],
|
||||
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
|
||||
|
||||
# Случай №1 - Команда используется в ответ на сообщение
|
||||
# Команда через ответ на сообщение, если одно слово (/unban)
|
||||
if len(parts_msg) == 1:
|
||||
|
||||
# Если банят в теме
|
||||
# Если это топик
|
||||
if message.is_topic_message:
|
||||
|
||||
# Если без ответа на сообщение
|
||||
if message.message_thread_id == message.reply_to_message.message_id:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Если команда правильная
|
||||
# Если с ответом на сообщение
|
||||
else:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
|
||||
# Если банят в обычном чате
|
||||
# Если это General (обычный чат)
|
||||
elif message.reply_to_message and message.is_topic_message is None:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
message.message_thread_id = None
|
||||
|
||||
# Не выводим сообщение, что команда неправильная
|
||||
# Удаляем сообщение, если команда неправильная
|
||||
else:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Случай №2 - Команда с аргументом (/unban @username или /unban 12345)
|
||||
# Команда через тег или ID, если два слова
|
||||
elif len(parts_msg) == 2:
|
||||
|
||||
# Выводим помощь (/unban help)
|
||||
if parts_msg[1].strip() in ['help', 'помощь']:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['manual_unban'])
|
||||
return
|
||||
|
||||
# Собираем данные
|
||||
identifier = parts_msg[1].strip()
|
||||
|
||||
# Поиск по ID
|
||||
# Делаем поиск по 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],
|
||||
@@ -90,14 +105,16 @@ def register_handlers(bot: AsyncTeleBot): # Регистрирует все об
|
||||
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],
|
||||
@@ -105,25 +122,81 @@ def register_handlers(bot: AsyncTeleBot): # Регистрирует все об
|
||||
is_bot=False
|
||||
)
|
||||
|
||||
# Если пользователь не найден
|
||||
# Если пользователь не найден в базе данных
|
||||
if not target_user:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['user_not_found'])
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['user_not_found'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Проверяем статус целевого пользователя
|
||||
if await check_target_status(bot, message, target_user) == 1:
|
||||
return
|
||||
|
||||
# Выполняем разбан
|
||||
try:
|
||||
await bot.unban_chat_member(message.chat.id, target_user.id)
|
||||
await send_message(chat_id, COMMAND_MESSAGES['unbanned'])
|
||||
|
||||
# Выполняем разбан
|
||||
await bot.unban_chat_member(
|
||||
chat_id=message.chat.id,
|
||||
user_id=target_user.id,
|
||||
)
|
||||
|
||||
# Отправляем лог в админ-чат
|
||||
await action_reporter.log_action(
|
||||
action="РАЗБАН",
|
||||
user_id=target_user.id,
|
||||
admin_id=message.from_user.id,
|
||||
reason=None,
|
||||
duration=None,
|
||||
photo_path=None,
|
||||
)
|
||||
|
||||
await asyncio.sleep(5)
|
||||
await bot.delete_message(message.chat.id, message.message_id)
|
||||
await bot.delete_message(message.chat.id, message.message_id+1)
|
||||
# Отправляем сообщения, что пользователь получил разбан
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['unbanned'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {target_user.id} разбанен администратором {message.from_user.id}.")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
|
||||
except Exception as e:
|
||||
await send_message(chat_id, f"⚠️ Ошибка: {str(e)}")
|
||||
logger.error(f"Ошибка разбана: {str(e)}")
|
||||
|
||||
# Отправляем ошибку
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['error'].format(e=str(e)),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка размута: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
|
||||
except Exception as e:
|
||||
await send_message(chat_id, COMMAND_MESSAGES['general_error'])
|
||||
logger.error(f"Общая ошибка в unban_command: {str(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"Общая ошибка в unban_command: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
215
src/modules/unmute.py
Normal file
215
src/modules/unmute.py
Normal file
@@ -0,0 +1,215 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message, User, ChatPermissions
|
||||
import asyncio
|
||||
import logging
|
||||
from database import db
|
||||
|
||||
from action_reporter import action_reporter
|
||||
from utils import (
|
||||
delete_messages,
|
||||
check_admin_status,
|
||||
check_target_status,
|
||||
)
|
||||
|
||||
from config import COMMAND_MESSAGES
|
||||
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Регистрирует все обработчики команд
|
||||
def register_handlers(bot: AsyncTeleBot):
|
||||
|
||||
# Обработчик команды /unmute
|
||||
@bot.message_handler(commands=['unmute'])
|
||||
async def unmute_command(message: Message):
|
||||
|
||||
# Определяем целевого пользователя
|
||||
target_user = None
|
||||
|
||||
# Разбиваем текст сообщения на части
|
||||
parts_msg = message.text.split()
|
||||
|
||||
# Команда /unmute 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['manual_unmute'],
|
||||
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
|
||||
|
||||
# Команда через ответ на сообщение, если одно слово (/unmute)
|
||||
if len(parts_msg) == 1:
|
||||
|
||||
# Если это топик
|
||||
if message.is_topic_message:
|
||||
|
||||
# Если без ответа на сообщение
|
||||
if message.message_thread_id == message.reply_to_message.message_id:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Если с ответом на сообщение
|
||||
else:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
|
||||
# Если это General (обычный чат)
|
||||
elif message.reply_to_message and message.is_topic_message is None:
|
||||
|
||||
# Собираем данные
|
||||
target_user = message.reply_to_message.from_user
|
||||
message.message_thread_id = None
|
||||
|
||||
# Удаляем сообщение, если команда неправильная
|
||||
else:
|
||||
|
||||
# Удаляем сообщение через 3 секунды
|
||||
await delete_messages(bot, message, time_sleep=3, number_message=1)
|
||||
return
|
||||
|
||||
# Команда через тег или ID, если два слова
|
||||
elif len(parts_msg) == 2:
|
||||
|
||||
# Собираем данные
|
||||
identifier = parts_msg[1].strip()
|
||||
|
||||
# Делаем поиск по 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
|
||||
)
|
||||
|
||||
# Если пользователь не найден в базе данных
|
||||
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,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Проверяем статус целевого пользователя
|
||||
if await check_target_status(bot, message, target_user) == 1:
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
# Убираем ограничения (можно писать в чат)
|
||||
permissions = ChatPermissions(
|
||||
can_send_messages=True,
|
||||
can_send_media_messages=True,
|
||||
can_send_polls=True,
|
||||
can_send_other_messages=True,
|
||||
can_add_web_page_previews=True,
|
||||
can_change_info=False,
|
||||
can_invite_users=True,
|
||||
can_pin_messages=False
|
||||
)
|
||||
|
||||
# Выполняем размут
|
||||
await bot.restrict_chat_member(
|
||||
chat_id=message.chat.id,
|
||||
user_id=target_user.id,
|
||||
permissions=permissions,
|
||||
)
|
||||
|
||||
# Отправляем лог в админ-чат
|
||||
await action_reporter.log_action(
|
||||
action="РАЗМУТ",
|
||||
user_id=target_user.id,
|
||||
admin_id=message.from_user.id,
|
||||
reason=None,
|
||||
duration=None,
|
||||
photo_path=None,
|
||||
)
|
||||
|
||||
# Отправляем сообщения, что пользователь получил размут
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['unmuted'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем действие в логи
|
||||
logger.info(f"Пользователь {target_user.id} получил размут от администратора {message.from_user.id}.")
|
||||
|
||||
# Удаляем сообщения через 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['error'].format(e=str(e)),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка размута: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 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"Общая ошибка в unmute_command: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
177
src/utils.py
Normal file
177
src/utils.py
Normal file
@@ -0,0 +1,177 @@
|
||||
from telebot.async_telebot import AsyncTeleBot
|
||||
from telebot.types import Message
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
# Получаем логгер для текущего модуля
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Удаляет определённое количество сообщения
|
||||
async def delete_messages(bot: AsyncTeleBot, message: Message, time_sleep: int, number_message: int):
|
||||
await asyncio.sleep(time_sleep)
|
||||
for i in range(number_message):
|
||||
await bot.delete_message(message.chat.id, message.message_id+i)
|
||||
|
||||
# Проверяет, является ли отправитель администратором
|
||||
async def check_admin_status(bot: AsyncTeleBot, message: Message):
|
||||
|
||||
if message.reply_to_message and message.is_topic_message is None:
|
||||
message.message_thread_id = None
|
||||
|
||||
try:
|
||||
|
||||
# Получаем статус отправителя
|
||||
admin_status = await bot.get_chat_member(message.chat.id, message.from_user.id)
|
||||
|
||||
# Проверка наличия прав администратора/создателя
|
||||
if admin_status.status not in ('administrator', 'creator'):
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['no_admin_rights'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return 1
|
||||
|
||||
# Проверка права на ограничение участников
|
||||
if admin_status.status == 'administrator' and not admin_status.can_restrict_members:
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['no_restrict_rights'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return 1
|
||||
|
||||
except Exception as e:
|
||||
|
||||
# Отправляем ошибку
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['error'].format(e=str(e)),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка при получении статуса администратора: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return 1
|
||||
|
||||
# Проверяет статус целевого пользователя
|
||||
async def check_target_status(bot: AsyncTeleBot, message: Message, target_user):
|
||||
|
||||
if message.reply_to_message and message.is_topic_message is None:
|
||||
message.message_thread_id = None
|
||||
|
||||
try:
|
||||
|
||||
# Получаем статус пользователя
|
||||
target_status = await bot.get_chat_member(
|
||||
chat_id=message.chat.id,
|
||||
user_id=target_user.id,
|
||||
)
|
||||
|
||||
# Проверяем, является ли цель администратором или создателем
|
||||
if target_status.status in ('administrator', 'creator'):
|
||||
|
||||
# Отправляем предупреждение
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['cant_mute_admin'],
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
|
||||
# Отправляем ошибку
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=COMMAND_MESSAGES['error'].format(e=str(e)),
|
||||
message_thread_id=message.message_thread_id,
|
||||
)
|
||||
|
||||
# Записываем ошибку в логи
|
||||
logger.error(f"Ошибка при получении статуса пользователя: {str(e)}")
|
||||
|
||||
# Удаляем сообщения через 5 секунд
|
||||
await delete_messages(bot, message, time_sleep=5, number_message=2)
|
||||
return
|
||||
|
||||
# Возвращает количество секунд
|
||||
def parse_mute_time(time_str: str) -> int | None:
|
||||
|
||||
# Нормализация входной строки
|
||||
normalized = time_str.strip().lower()
|
||||
|
||||
# Словарь для конвертации единиц времени в секунды
|
||||
time_units = {
|
||||
'm': 60, 'м': 60, # минуты
|
||||
'h': 3600, 'ч': 3600, # часы
|
||||
'd': 86400, 'д': 86400 # дни
|
||||
}
|
||||
|
||||
# Проверям, существует ли строка
|
||||
if not normalized:
|
||||
return None
|
||||
|
||||
# Проверяем последний символ (единица измерения)
|
||||
unit = normalized[-1]
|
||||
if unit not in time_units:
|
||||
return None
|
||||
|
||||
# Парсим числовую часть
|
||||
try:
|
||||
value = int(normalized[:-1])
|
||||
if value <= 0:
|
||||
return None
|
||||
|
||||
return value * time_units[unit]
|
||||
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
|
||||
# Форматирует время в нормальный вид
|
||||
def format_mute_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 < 10 or minutes % 100 >= 20):
|
||||
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 < 10 or hours % 100 >= 20):
|
||||
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 < 10 or days % 100 >= 20):
|
||||
return f"{days} дня"
|
||||
else:
|
||||
return f"{days} дней"
|
Reference in New Issue
Block a user