Files
telegram-helper-bot/helper_bot/handlers/admin/services.py
2026-02-02 00:13:33 +03:00

197 lines
8.0 KiB
Python

from datetime import datetime
from typing import List, Optional
from helper_bot.handlers.admin.exceptions import (
InvalidInputError,
UserAlreadyBannedError,
)
from helper_bot.utils.helper_func import (
add_days_to_date,
get_banned_users_buttons,
get_banned_users_list,
)
# Local imports - metrics
from helper_bot.utils.metrics import track_errors, track_time
from logs.custom_logger import logger
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],
ban_author_id: 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, ban_author=ban_author_id
)
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