Files
vpn-control-panel/app/services/server.py
smolkik-code 7c7c88621d Initial commit: VPN Control Panel
- FastAPI REST API with JWT auth
- aiogram 3 Telegram bot with admin middleware
- APScheduler daily tasks (expiry, reminders, revoke, sync)
- SQLAlchemy 2 async ORM with Alembic migrations
- Jinja2 admin panel (Dashboard, Users, Payments, Servers, Tariffs)
- VPN provider abstraction with MockProvider
- Stats service with revenue/subscription analytics
- Docker Compose (PostgreSQL + Redis + app)
- Healthcheck endpoint
2026-07-05 17:50:11 +07:00

72 lines
2.4 KiB
Python

from datetime import datetime, timezone
from loguru import logger
from app.models.server import Server, ServerProtocol
from app.repositories.server import ServerRepository
class ServerService:
def __init__(self, server_repo: ServerRepository):
self.server_repo = server_repo
async def create(
self,
name: str,
host: str,
port: int,
protocol: ServerProtocol,
location: str,
country_code: str,
max_users: int = 100,
) -> Server:
existing = await self.server_repo.get_by_name(name)
if existing is not None:
raise ValueError(f"Server already exists: {name}")
server = await self.server_repo.create(
name=name,
host=host,
port=port,
protocol=protocol,
location=location,
country_code=country_code.upper(),
max_users=max_users,
)
logger.info("Server created: id={} name={} proto={}", server.id, name, protocol.value)
return server
async def get_by_id(self, server_id: int) -> Server | None:
return await self.server_repo.get(server_id)
async def get_active(self) -> list[Server]:
return await self.server_repo.get_active()
async def get_by_protocol(self, protocol: ServerProtocol) -> list[Server]:
return await self.server_repo.get_by_protocol(protocol)
async def get_least_loaded(self, protocol: ServerProtocol) -> Server | None:
return await self.server_repo.get_least_loaded(protocol)
async def update_load(self, server_id: int, load_percent: int) -> Server | None:
load = max(0, min(100, load_percent))
return await self.server_repo.update(server_id, load_percent=load)
async def mark_online(self, server_id: int) -> Server | None:
return await self.server_repo.update(server_id, is_active=True)
async def mark_offline(self, server_id: int) -> Server | None:
server = await self.server_repo.update(server_id, is_active=False)
if server:
logger.warning("Server marked offline: id={} name={}", server_id, server.name)
return server
async def update(
self, server_id: int, **kwargs
) -> Server | None:
return await self.server_repo.update(server_id, **kwargs)
async def get_count(self) -> int:
return await self.server_repo.count_active()