from typing import List, Optional from datetime import datetime from helper_bot.utils.helper_func import add_days_to_date, get_banned_users_buttons, get_banned_users_list from helper_bot.handlers.admin.exceptions import UserAlreadyBannedError, InvalidInputError from logs.custom_logger import logger # Local imports - metrics from helper_bot.utils.metrics import ( track_time, track_errors ) class User: """Модель пользователя""" def __init__(self, user_id: int, username: str, full_name: str): self.user_id = user_id self.username = username self.full_name = full_name class BannedUser: """Модель заблокированного пользователя""" def __init__(self, user_id: int, username: str, reason: str, unban_date: Optional[datetime]): self.user_id = user_id self.username = username self.reason = reason self.unban_date = unban_date class AdminService: """Сервис для административных операций""" def __init__(self, bot_db): self.bot_db = bot_db @track_time("get_last_users", "admin_service") @track_errors("admin_service", "get_last_users") async def get_last_users(self) -> List[User]: """Получить список последних пользователей""" try: users_data = await self.bot_db.get_last_users(30) return [ User( user_id=user[1], username='Неизвестно', full_name=user[0] ) for user in users_data ] except Exception as e: logger.error(f"Ошибка при получении списка последних пользователей: {e}") raise @track_time("get_banned_users", "admin_service") @track_errors("admin_service", "get_banned_users") async def get_banned_users(self) -> List[BannedUser]: """Получить список заблокированных пользователей""" try: banned_users_data = await self.bot_db.get_banned_users_from_db() banned_users = [] for user_data in banned_users_data: user_id, reason, unban_date = user_data # Получаем username и full_name из таблицы users username = await self.bot_db.get_username(user_id) full_name = await self.bot_db.get_full_name_by_id(user_id) user_name = username or full_name or f"User_{user_id}" banned_users.append(BannedUser( user_id=user_id, username=user_name, reason=reason, unban_date=unban_date )) return banned_users except Exception as e: logger.error(f"Ошибка при получении списка заблокированных пользователей: {e}") raise @track_time("get_user_by_username", "admin_service") @track_errors("admin_service", "get_user_by_username") async def get_user_by_username(self, username: str) -> Optional[User]: """Получить пользователя по username""" try: user_id = await self.bot_db.get_user_id_by_username(username) if not user_id: return None full_name = await self.bot_db.get_full_name_by_id(user_id) return User( user_id=user_id, username=username, full_name=full_name or 'Неизвестно' ) except Exception as e: logger.error(f"Ошибка при поиске пользователя по username {username}: {e}") raise @track_time("get_user_by_id", "admin_service") @track_errors("admin_service", "get_user_by_id") async def get_user_by_id(self, user_id: int) -> Optional[User]: """Получить пользователя по ID""" try: user_info = await self.bot_db.get_user_by_id(user_id) if not user_info: return None return User( user_id=user_id, username=user_info.username or 'Неизвестно', full_name=user_info.full_name or 'Неизвестно' ) except Exception as e: logger.error(f"Ошибка при поиске пользователя по ID {user_id}: {e}") raise @track_time("ban_user", "admin_service") @track_errors("admin_service", "ban_user") async def ban_user(self, user_id: int, username: str, reason: str, ban_days: Optional[int]) -> None: """Заблокировать пользователя""" try: # Проверяем, не заблокирован ли уже пользователь if await self.bot_db.check_user_in_blacklist(user_id): raise UserAlreadyBannedError(f"Пользователь {user_id} уже заблокирован") # Рассчитываем дату разблокировки date_to_unban = None if ban_days is not None: date_to_unban = add_days_to_date(ban_days) # Сохраняем в БД (username больше не передается, так как не используется в новой схеме) await self.bot_db.set_user_blacklist(user_id, None, reason, date_to_unban) logger.info(f"Пользователь {user_id} ({username}) заблокирован. Причина: {reason}, срок: {ban_days} дней") except Exception as e: logger.error(f"Ошибка при блокировке пользователя {user_id}: {e}") raise @track_time("unban_user", "admin_service") @track_errors("admin_service", "unban_user") async def unban_user(self, user_id: int) -> None: """Разблокировать пользователя""" try: await self.bot_db.delete_user_blacklist(user_id) logger.info(f"Пользователь {user_id} разблокирован") except Exception as e: logger.error(f"Ошибка при разблокировке пользователя {user_id}: {e}") raise @track_time("validate_user_input", "admin_service") @track_errors("admin_service", "validate_user_input") async def validate_user_input(self, input_text: str) -> int: """Валидация введенного ID пользователя""" try: user_id = int(input_text.strip()) if user_id <= 0: raise InvalidInputError("ID пользователя должен быть положительным числом") return user_id except ValueError: raise InvalidInputError("ID пользователя должен быть числом") @track_time("get_banned_users_for_display", "admin_service") @track_errors("admin_service", "get_banned_users_for_display") async def get_banned_users_for_display(self, page: int = 0) -> tuple[str, list]: """Получить данные заблокированных пользователей для отображения""" try: message_text = await get_banned_users_list(page, self.bot_db) buttons_list = await get_banned_users_buttons(self.bot_db) return message_text, buttons_list except Exception as e: logger.error(f"Ошибка при получении данных заблокированных пользователей: {e}") raise