launcher/src/api/server_api.py
2025-01-14 23:59:08 +07:00

118 lines
4.7 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.

import asyncio
import aiomysql
from dataclasses import dataclass
from typing import Optional, Tuple
import time
@dataclass
class ServerStatus:
auth_online: bool
world_online: bool
players_online: int
max_players: int = 1000
realm_name: str = "WotLK Server"
uptime: str = "Unknown"
class ServerAPI:
def __init__(self):
"""Инициализация API для проверки статуса серверов"""
# Настройки серверов
self.auth_address = ('192.168.1.114', 3724)
self.world_address = ('192.168.1.114', 8085)
# Настройки БД (только чтение)
self.db_config = {
'host': '192.168.1.42',
'port': 3306,
'user': 'launcher_ro', # Пользователь для чтения
'password': 'rPIisIhn46',
'db': 'acore_characters'
}
# Кэш
self._last_check = None
self._cache_timeout = 10
self._players_cache = None
self._players_cache_time = None
self._players_cache_timeout = 30
async def get_players_count(self) -> int:
"""Получает количество игроков через БД"""
try:
async with aiomysql.connect(**self.db_config) as conn:
async with conn.cursor() as cur:
# Запрос согласно структуре БД AzerothCore
await cur.execute("""
SELECT COUNT(*) as count
FROM characters
WHERE online > 0
""")
result = await cur.fetchone()
count = result[0] if result else 0
print(f"Current online players: {count}") # Отладочный вывод
# Обновляем кэш
self._players_cache = count
self._players_cache_time = time.time()
return count
except Exception as e:
print(f"Error getting players count: {e}")
return self._players_cache if self._players_cache is not None else 0
async def check_server(self, host: str, port: int) -> bool:
"""Проверяет доступность сервера"""
try:
# Создаем футуру с таймаутом в 2 секунды
reader, writer = await asyncio.wait_for(
asyncio.open_connection(host, port),
timeout=2.0
)
writer.close()
await writer.wait_closed()
print(f"Server {host}:{port} is online")
return True
except (ConnectionRefusedError, asyncio.TimeoutError):
print(f"Server {host}:{port} is offline")
return False
except Exception as e:
print(f"Error checking server {host}:{port}: {e}")
return False
async def get_server_status(self) -> ServerStatus:
"""Получает статус серверов"""
# Проверяем кэш
if self._last_check:
if (asyncio.get_event_loop().time() - self._last_check[0]) < self._cache_timeout:
return self._last_check[1]
try:
# Проверяем оба сервера параллельно
auth_check, world_check = await asyncio.gather(
self.check_server(self.auth_address[0], self.auth_address[1]),
self.check_server(self.world_address[0], self.world_address[1])
)
# Если world сервер онлайн, получаем количество игроков
players_online = 0
if world_check:
try:
players_online = await self.get_players_count()
except Exception as e:
print(f"Error getting players count: {e}")
print(f"Status: auth={auth_check}, world={world_check}, players={players_online}")
status = ServerStatus(
auth_online=auth_check,
world_online=world_check,
players_online=players_online
)
# Сохраняем результат в кэш
self._last_check = (asyncio.get_event_loop().time(), status)
return status
except Exception as e:
print(f"Error in get_server_status: {e}")
return ServerStatus(
auth_online=False,
world_online=False,
players_online=0
)