Files
AnonBot/services/business/user_service.py

211 lines
9.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Сервис для управления пользователями
"""
from datetime import datetime
from typing import Optional, Tuple
from aiogram.types import User as TelegramUser
from models.user import User
from services.infrastructure.database import DatabaseService
from services.utils import UtilsService
from services.infrastructure.logger import get_logger
from services.infrastructure.metrics import get_metrics_service
from services.infrastructure.logging_decorators import log_function_call, log_business_event
from services.infrastructure.logging_utils import log_user_created, log_user_blocked
logger = get_logger(__name__)
class UserService:
"""Сервис для управления пользователями"""
def __init__(self, database: DatabaseService, utils: UtilsService):
self.database = database
self.utils = utils
self.metrics = get_metrics_service()
@log_business_event("create_or_update_user", log_params=True, log_result=True)
async def create_or_update_user(self, telegram_user: TelegramUser, chat_id: int) -> User:
"""
Создание или обновление пользователя
Args:
telegram_user: Объект пользователя из Telegram
chat_id: ID чата
Returns:
Объект пользователя
"""
try:
# Проверяем, существует ли пользователь
existing_user = await self.database.get_user(telegram_user.id)
if existing_user:
# Обновляем существующего пользователя
logger.info(f"👤 Обновление существующего пользователя {telegram_user.id}")
self.metrics.increment_users("updated")
return await self._update_existing_user(existing_user, telegram_user, chat_id)
else:
# Создаем нового пользователя
logger.info(f"👤 Создание нового пользователя {telegram_user.id}")
self.metrics.increment_users("created")
return await self._create_new_user(telegram_user, chat_id)
except Exception as e:
logger.error(f"Ошибка при создании/обновлении пользователя {telegram_user.id}: {e}")
raise
@log_function_call(log_params=True, log_result=True)
async def _update_existing_user(self, existing_user: User, telegram_user: TelegramUser, chat_id: int) -> User:
"""Обновление существующего пользователя"""
existing_user.username = telegram_user.username
existing_user.first_name = telegram_user.first_name or "Пользователь"
existing_user.last_name = telegram_user.last_name
existing_user.chat_id = chat_id
existing_user.update_timestamp()
return await self.database.update_user(existing_user)
@log_function_call(log_params=True, log_result=True)
async def _create_new_user(self, telegram_user: TelegramUser, chat_id: int) -> User:
"""Создание нового пользователя"""
user = User(
telegram_id=telegram_user.id,
username=telegram_user.username,
first_name=telegram_user.first_name or "Пользователь",
last_name=telegram_user.last_name,
chat_id=chat_id,
profile_link=self.utils.generate_anonymous_id(),
is_active=True,
is_superuser=False, # Явно устанавливаем False для новых пользователей
created_at=datetime.now(),
updated_at=datetime.now()
)
logger.info(f"👤 Создание нового пользователя {telegram_user.id} с is_superuser={user.is_superuser}")
return await self.database.create_user(user)
@log_function_call(log_params=True, log_result=True)
async def get_user_by_profile_link(self, profile_link: str) -> Optional[User]:
"""
Получение пользователя по ссылке профиля
Args:
profile_link: Ссылка профиля
Returns:
Объект пользователя или None
"""
try:
return await self.database.get_user_by_profile_link(profile_link)
except Exception as e:
logger.error(f"Ошибка при получении пользователя по ссылке {profile_link}: {e}")
return None
@log_function_call(log_params=True, log_result=True)
async def get_user_by_telegram_id(self, telegram_id: int) -> Optional[User]:
"""
Получение пользователя по Telegram ID
Args:
telegram_id: ID пользователя в Telegram
Returns:
Объект пользователя или None
"""
try:
return await self.database.get_user(telegram_id)
except Exception as e:
logger.error(f"Ошибка при получении пользователя {telegram_id}: {e}")
return None
@log_function_call(log_params=True, log_result=True)
def generate_referral_link(self, bot_username: str, user: User) -> str:
"""
Генерация реферальной ссылки для пользователя
Args:
bot_username: Имя бота
user: Объект пользователя
Returns:
Реферальная ссылка
"""
return self.utils.generate_referral_link(bot_username, user.profile_link)
@log_function_call(log_params=True, log_result=True)
async def is_user_blocked(self, blocker_id: int, blocked_id: int) -> bool:
"""
Проверка, заблокирован ли пользователь
Args:
blocker_id: ID пользователя, который блокирует
blocked_id: ID пользователя, которого блокируют
Returns:
True если заблокирован, False иначе
"""
try:
return await self.database.is_user_blocked(blocker_id, blocked_id)
except Exception as e:
logger.error(f"Ошибка при проверке блокировки {blocker_id} -> {blocked_id}: {e}")
return False
@log_business_event("block_user", log_params=True, log_result=True)
async def block_user(self, blocker_id: int, blocked_id: int) -> bool:
"""
Блокировка пользователя
Args:
blocker_id: ID пользователя, который блокирует
blocked_id: ID пользователя, которого блокируют
Returns:
True если успешно заблокирован
"""
try:
await self.database.block_user(blocker_id, blocked_id)
logger.info(f"Пользователь {blocked_id} заблокирован пользователем {blocker_id}")
return True
except Exception as e:
logger.error(f"Ошибка при блокировке пользователя {blocked_id}: {e}")
return False
@log_business_event("unblock_user", log_params=True, log_result=True)
async def unblock_user(self, blocker_id: int, blocked_id: int) -> bool:
"""
Разблокировка пользователя
Args:
blocker_id: ID пользователя, который разблокирует
blocked_id: ID пользователя, которого разблокируют
Returns:
True если успешно разблокирован
"""
try:
result = await self.database.unblock_user(blocker_id, blocked_id)
if result:
logger.info(f"Пользователь {blocked_id} разблокирован пользователем {blocker_id}")
return result
except Exception as e:
logger.error(f"Ошибка при разблокировке пользователя {blocked_id}: {e}")
return False
@log_function_call(log_params=True, log_result=True)
async def get_blocked_users(self, user_id: int) -> list:
"""
Получение списка заблокированных пользователей
Args:
user_id: ID пользователя
Returns:
Список ID заблокированных пользователей
"""
try:
return await self.database.user_blocks.get_blocked_users(user_id)
except Exception as e:
logger.error(f"Ошибка при получении заблокированных пользователей для {user_id}: {e}")
return []