feat: Полный рефакторинг с модульной архитектурой
Some checks reported errors
continuous-integration/drone/push Build encountered an error
Some checks reported errors
continuous-integration/drone/push Build encountered an error
- Исправлены критические ошибки callback обработки - Реализована модульная архитектура с применением SOLID принципов - Добавлена система dependency injection - Создана новая структура: interfaces, repositories, components, controllers - Исправлены проблемы с базой данных (добавлены отсутствующие столбцы) - Заменены заглушки на полную функциональность управления розыгрышами - Добавлены отчеты о проделанной работе и документация Архитектура готова для production и легко масштабируется
This commit is contained in:
177
src/controllers/bot_controller.py
Normal file
177
src/controllers/bot_controller.py
Normal file
@@ -0,0 +1,177 @@
|
||||
from aiogram.types import Message, CallbackQuery
|
||||
from aiogram import F
|
||||
import logging
|
||||
|
||||
from src.interfaces.base import IBotController, ILotteryService, IUserService, IKeyboardBuilder, IMessageFormatter
|
||||
from src.interfaces.base import ILotteryRepository, IParticipationRepository
|
||||
from src.core.config import ADMIN_IDS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BotController(IBotController):
|
||||
"""Основной контроллер бота"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
lottery_service: ILotteryService,
|
||||
user_service: IUserService,
|
||||
keyboard_builder: IKeyboardBuilder,
|
||||
message_formatter: IMessageFormatter,
|
||||
lottery_repo: ILotteryRepository,
|
||||
participation_repo: IParticipationRepository
|
||||
):
|
||||
self.lottery_service = lottery_service
|
||||
self.user_service = user_service
|
||||
self.keyboard_builder = keyboard_builder
|
||||
self.message_formatter = message_formatter
|
||||
self.lottery_repo = lottery_repo
|
||||
self.participation_repo = participation_repo
|
||||
|
||||
def is_admin(self, user_id: int) -> bool:
|
||||
"""Проверить, является ли пользователь администратором"""
|
||||
return user_id in ADMIN_IDS
|
||||
|
||||
async def handle_start(self, message: Message):
|
||||
"""Обработать команду /start"""
|
||||
user = await self.user_service.get_or_create_user(
|
||||
telegram_id=message.from_user.id,
|
||||
username=message.from_user.username,
|
||||
first_name=message.from_user.first_name,
|
||||
last_name=message.from_user.last_name
|
||||
)
|
||||
|
||||
welcome_text = f"👋 Добро пожаловать, {user.first_name or 'дорогой пользователь'}!\n\n"
|
||||
welcome_text += "🎲 Это бот для участия в розыгрышах.\n\n"
|
||||
|
||||
if user.is_registered:
|
||||
welcome_text += "✅ Вы уже зарегистрированы в системе!"
|
||||
else:
|
||||
welcome_text += "📝 Для участия в розыгрышах необходимо зарегистрироваться."
|
||||
|
||||
keyboard = self.keyboard_builder.get_main_keyboard(self.is_admin(message.from_user.id))
|
||||
|
||||
await message.answer(
|
||||
welcome_text,
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
async def handle_admin_panel(self, callback: CallbackQuery):
|
||||
"""Обработать админ панель"""
|
||||
if not self.is_admin(callback.from_user.id):
|
||||
await callback.answer("❌ Недостаточно прав", show_alert=True)
|
||||
return
|
||||
|
||||
text = "⚙️ **Панель администратора**\n\n"
|
||||
text += "Выберите раздел для управления:"
|
||||
|
||||
keyboard = self.keyboard_builder.get_admin_keyboard()
|
||||
|
||||
await callback.message.edit_text(
|
||||
text,
|
||||
reply_markup=keyboard,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
|
||||
async def handle_lottery_management(self, callback: CallbackQuery):
|
||||
"""Обработать управление розыгрышами"""
|
||||
if not self.is_admin(callback.from_user.id):
|
||||
await callback.answer("❌ Недостаточно прав", show_alert=True)
|
||||
return
|
||||
|
||||
text = "🎯 **Управление розыгрышами**\n\n"
|
||||
text += "Выберите действие:"
|
||||
|
||||
keyboard = self.keyboard_builder.get_lottery_management_keyboard()
|
||||
|
||||
await callback.message.edit_text(
|
||||
text,
|
||||
reply_markup=keyboard,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
|
||||
async def handle_conduct_lottery_admin(self, callback: CallbackQuery):
|
||||
"""Обработать выбор розыгрыша для проведения"""
|
||||
if not self.is_admin(callback.from_user.id):
|
||||
await callback.answer("❌ Недостаточно прав", show_alert=True)
|
||||
return
|
||||
|
||||
# Получаем активные розыгрыши
|
||||
lotteries = await self.lottery_service.get_active_lotteries()
|
||||
|
||||
if not lotteries:
|
||||
await callback.answer("❌ Нет активных розыгрышей", show_alert=True)
|
||||
return
|
||||
|
||||
text = "🎯 **Выберите розыгрыш для проведения:**\n\n"
|
||||
|
||||
for lottery in lotteries:
|
||||
participants_count = await self.participation_repo.get_count_by_lottery(lottery.id)
|
||||
text += f"🎲 {lottery.title} ({participants_count} участников)\n"
|
||||
|
||||
keyboard = self.keyboard_builder.get_conduct_lottery_keyboard(lotteries)
|
||||
|
||||
await callback.message.edit_text(
|
||||
text,
|
||||
reply_markup=keyboard,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
|
||||
async def handle_active_lotteries(self, callback: CallbackQuery):
|
||||
"""Показать активные розыгрыши"""
|
||||
lotteries = await self.lottery_service.get_active_lotteries()
|
||||
|
||||
if not lotteries:
|
||||
await callback.answer("❌ Нет активных розыгрышей", show_alert=True)
|
||||
return
|
||||
|
||||
text = "🎲 **Активные розыгрыши:**\n\n"
|
||||
|
||||
for lottery in lotteries:
|
||||
participants_count = await self.participation_repo.get_count_by_lottery(lottery.id)
|
||||
lottery_info = self.message_formatter.format_lottery_info(lottery, participants_count)
|
||||
text += lottery_info + "\n" + "="*30 + "\n\n"
|
||||
|
||||
keyboard = self.keyboard_builder.get_main_keyboard(self.is_admin(callback.from_user.id))
|
||||
|
||||
await callback.message.edit_text(
|
||||
text,
|
||||
reply_markup=keyboard,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
|
||||
async def handle_conduct_lottery(self, callback: CallbackQuery):
|
||||
"""Провести конкретный розыгрыш"""
|
||||
if not self.is_admin(callback.from_user.id):
|
||||
await callback.answer("❌ Недостаточно прав", show_alert=True)
|
||||
return
|
||||
|
||||
try:
|
||||
lottery_id = int(callback.data.split("_")[1])
|
||||
except (ValueError, IndexError):
|
||||
await callback.answer("❌ Неверный формат данных", show_alert=True)
|
||||
return
|
||||
|
||||
# Проводим розыгрыш
|
||||
results = await self.lottery_service.conduct_draw(lottery_id)
|
||||
|
||||
if not results:
|
||||
await callback.answer("❌ Не удалось провести розыгрыш", show_alert=True)
|
||||
return
|
||||
|
||||
# Форматируем результаты
|
||||
text = "🎉 **Розыгрыш завершен!**\n\n"
|
||||
|
||||
winners = [result['winner'] for result in results.values()]
|
||||
winners_text = self.message_formatter.format_winners_list(winners)
|
||||
text += winners_text
|
||||
|
||||
keyboard = self.keyboard_builder.get_admin_keyboard()
|
||||
|
||||
await callback.message.edit_text(
|
||||
text,
|
||||
reply_markup=keyboard,
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
|
||||
await callback.answer("✅ Розыгрыш успешно проведен!", show_alert=True)
|
||||
Reference in New Issue
Block a user