Files
malenia/services/user_service.py

119 lines
3.8 KiB
Python

import logging
from aiogram.types import Message
from remnawave import RemnawaveSDK
from sqlalchemy.ext.asyncio import AsyncSession
from db.models.tickets import TicketStatus
from db.models.users import User
from misc import utils
from repositories import UserRepository
from repositories.tickets import TicketRepository
from schemas.users import NewUserDTO, TicketCreator
from services.rw import RWUserInfo, get_user_by_telegram_id
from texts import (
NO_SUBSCRIPTION,
NOTHING_PLACEHOLDER,
SUBSCRIPTION_INFORMATION,
TICKET_STATUS_EMOJIS,
)
logger = logging.getLogger(__name__)
class UserServiceError(Exception): ...
class UserService:
def __init__(
self, user_repository: UserRepository, ticket_repository: TicketRepository
) -> None:
self.user_repository = user_repository
self.ticket_repository = ticket_repository
@staticmethod
def format_ticket_name(
creator: TicketCreator,
status: TicketStatus | None = TicketStatus.OPEN,
ticket_id: int | None = None,
):
return (
TICKET_STATUS_EMOJIS[status.value]
+ (f" T-{ticket_id:0>3}" if ticket_id else "")
+ " | "
+ (f"@{creator.username}" if creator.username else str(creator.id))
)
@staticmethod
def format_subscription_message(
rw_user: RWUserInfo | None,
link: str | None = None,
):
if rw_user is None:
# Пользователь не найден в Remnawave
return NO_SUBSCRIPTION
status_icon, status_text = utils.format_status(rw_user.status)
expire_date = rw_user.expire_at.strftime("%d.%m.%Y")
days_left = utils.format_days_left(rw_user.expire_at)
used_traffic = utils.format_traffic(rw_user.used_traffic_bytes, rw_user.traffic_limit_bytes)
hwid_limit = utils.format_hwid_limit(rw_user.hwid_device_limit)
link = link or NOTHING_PLACEHOLDER
return SUBSCRIPTION_INFORMATION.format(
status_icon=status_icon,
status=status_text,
expire_date=expire_date,
days_left=days_left,
used_traffic=used_traffic,
hwid_limit=hwid_limit,
link=link,
)
async def add_user(
self,
session: AsyncSession,
user_id: int,
rw_sdk: RemnawaveSDK,
referal: int | None = None,
) -> User:
user = await self.user_repository.get_user_by_id(session, user_id)
if user:
return user
rw_user = await get_user_by_telegram_id(rw_sdk, user_id)
link = utils.get_subscription_link(rw_user.short_uuid) if rw_user else None
referal = int(referal) if str(referal).isdigit() and user_id != int(referal) else None
model = NewUserDTO(id=user_id, referal=referal, link=link)
return await self.user_repository.create_user(session, model)
async def update_user_link(
self, session: AsyncSession, user_id: int, rw_sdk: RemnawaveSDK
) -> User:
rw_user = await get_user_by_telegram_id(rw_sdk, user_id)
user = await self.user_repository.get_user_by_id(session, user_id)
if not rw_user:
return user
link = utils.get_subscription_link(rw_user.short_uuid)
user = await self.user_repository.update_user_link(session, user_id, link)
return user
async def send_promotion_to_users(self, session: AsyncSession, msg: Message) -> list[User]:
users = await self.user_repository.get_users(session)
sent: list[User] = []
for user in users:
try:
await msg.copy_to(user.id)
sent.append(user)
except Exception:
logger.critical("failed to send a message to user %d.", user.id, exc_info=True)
return sent