feat: auto delete server if it is inactive for more than 5 minutes, minor fix
This commit is contained in:
@ -2,6 +2,8 @@ from fastapi import APIRouter
|
|||||||
from app.services.server.command import CommandService
|
from app.services.server.command import CommandService
|
||||||
from app.services.server.event import EventService
|
from app.services.server.event import EventService
|
||||||
from app.models.server.command import ServerCommand
|
from app.models.server.command import ServerCommand
|
||||||
|
from datetime import datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/api/server",
|
prefix="/api/server",
|
||||||
@ -10,12 +12,29 @@ router = APIRouter(
|
|||||||
|
|
||||||
@router.post("/events")
|
@router.post("/events")
|
||||||
async def receive_server_event(event_data: dict):
|
async def receive_server_event(event_data: dict):
|
||||||
|
# Обновляем активность сервера
|
||||||
|
server_ip = event_data.get("server_ip")
|
||||||
|
if server_ip:
|
||||||
|
await update_server_activity(server_ip)
|
||||||
return await EventService().process_event(event_data)
|
return await EventService().process_event(event_data)
|
||||||
|
|
||||||
@router.post("/commands")
|
@router.post("/commands")
|
||||||
async def add_server_command(command_data: ServerCommand):
|
async def add_server_command(command_data: ServerCommand):
|
||||||
|
# Обновляем last_activity для сервера
|
||||||
|
await CommandService()._update_server_activity(command_data.server_ip)
|
||||||
return await CommandService().add_command(command_data)
|
return await CommandService().add_command(command_data)
|
||||||
|
|
||||||
@router.get("/commands")
|
@router.get("/commands")
|
||||||
async def get_server_commands(server_ip: str):
|
async def get_server_commands(server_ip: str):
|
||||||
return await CommandService().get_commands(server_ip)
|
return await CommandService().get_commands(server_ip)
|
||||||
|
|
||||||
|
async def update_server_activity(server_ip):
|
||||||
|
"""Обновляет время последней активности сервера"""
|
||||||
|
from app.db.database import db
|
||||||
|
game_servers_collection = db.game_servers
|
||||||
|
|
||||||
|
await game_servers_collection.update_one(
|
||||||
|
{"ip": server_ip},
|
||||||
|
{"$set": {"last_activity": datetime.utcnow()}},
|
||||||
|
upsert=False
|
||||||
|
)
|
||||||
|
@ -54,3 +54,8 @@ async def get_user_purchased_capes(username: str):
|
|||||||
async def activate_purchased_cape(username: str, cape_id: str):
|
async def activate_purchased_cape(username: str, cape_id: str):
|
||||||
"""Активация приобретенного плаща"""
|
"""Активация приобретенного плаща"""
|
||||||
return await store_cape_service.activate_purchased_cape(username, cape_id)
|
return await store_cape_service.activate_purchased_cape(username, cape_id)
|
||||||
|
|
||||||
|
@router.post("/user/{username}/capes/deactivate/{cape_id}")
|
||||||
|
async def deactivate_purchased_cape(username: str, cape_id: str):
|
||||||
|
"""Деактивация приобретенного плаща"""
|
||||||
|
return await store_cape_service.deactivate_purchased_cape(username, cape_id)
|
||||||
|
@ -20,6 +20,10 @@ class CommandService:
|
|||||||
}
|
}
|
||||||
print(f"[{datetime.now()}] Добавлена команда: {command_data.command} "
|
print(f"[{datetime.now()}] Добавлена команда: {command_data.command} "
|
||||||
f"для сервера {command_data.server_ip}")
|
f"для сервера {command_data.server_ip}")
|
||||||
|
|
||||||
|
# Обновляем last_activity для сервера
|
||||||
|
await self._update_server_activity(command_data.server_ip)
|
||||||
|
|
||||||
return {"status": "success", "command_id": command_id}
|
return {"status": "success", "command_id": command_id}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=str(e))
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
@ -47,3 +51,14 @@ class CommandService:
|
|||||||
return {"status": "success", "commands": commands}
|
return {"status": "success", "commands": commands}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise HTTPException(status_code=400, detail=str(e))
|
raise HTTPException(status_code=400, detail=str(e))
|
||||||
|
|
||||||
|
async def _update_server_activity(self, server_ip):
|
||||||
|
"""Обновляет время последней активности для сервера"""
|
||||||
|
from app.db.database import db
|
||||||
|
game_servers_collection = db.game_servers
|
||||||
|
|
||||||
|
await game_servers_collection.update_one(
|
||||||
|
{"ip": server_ip},
|
||||||
|
{"$set": {"last_activity": datetime.utcnow()}},
|
||||||
|
upsert=False # Не создаем новый сервер, только обновляем существующий
|
||||||
|
)
|
||||||
|
@ -101,11 +101,18 @@ class EventService:
|
|||||||
"port": 25565, # Стандартный порт Minecraft
|
"port": 25565, # Стандартный порт Minecraft
|
||||||
"description": f"Minecraft server {server_ip}",
|
"description": f"Minecraft server {server_ip}",
|
||||||
"max_players": 100,
|
"max_players": 100,
|
||||||
"registered_at": datetime.utcnow()
|
"registered_at": datetime.utcnow(),
|
||||||
|
"last_activity": datetime.utcnow() # Добавляем поле last_activity
|
||||||
}
|
}
|
||||||
|
|
||||||
await game_servers_collection.insert_one(server_data)
|
await game_servers_collection.insert_one(server_data)
|
||||||
print(f"[{datetime.utcnow()}] Зарегистрирован новый сервер: {server_ip}")
|
print(f"[{datetime.utcnow()}] Зарегистрирован новый сервер: {server_ip}")
|
||||||
|
else:
|
||||||
|
# Обновляем активность существующего сервера
|
||||||
|
await game_servers_collection.update_one(
|
||||||
|
{"ip": server_ip},
|
||||||
|
{"$set": {"last_activity": datetime.utcnow()}}
|
||||||
|
)
|
||||||
|
|
||||||
return existing_server or await game_servers_collection.find_one({"ip": server_ip})
|
return existing_server or await game_servers_collection.find_one({"ip": server_ip})
|
||||||
|
|
||||||
@ -114,11 +121,18 @@ class EventService:
|
|||||||
from app.db.database import db
|
from app.db.database import db
|
||||||
|
|
||||||
online_players_collection = db.online_players
|
online_players_collection = db.online_players
|
||||||
|
game_servers_collection = db.game_servers
|
||||||
|
|
||||||
# Получаем ID сервера
|
# Получаем ID сервера
|
||||||
server = await self._register_server(server_ip, {})
|
server = await self._register_server(server_ip, {})
|
||||||
server_id = server["id"]
|
server_id = server["id"]
|
||||||
|
|
||||||
|
# Обновляем время активности сервера
|
||||||
|
await game_servers_collection.update_one(
|
||||||
|
{"id": server_id},
|
||||||
|
{"$set": {"last_activity": datetime.utcnow()}}
|
||||||
|
)
|
||||||
|
|
||||||
# Помечаем всех игроков как оффлайн на этом сервере
|
# Помечаем всех игроков как оффлайн на этом сервере
|
||||||
await online_players_collection.update_many(
|
await online_players_collection.update_many(
|
||||||
{"server_id": server_id},
|
{"server_id": server_id},
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
from app.db.database import db, users_collection
|
from app.db.database import db, users_collection
|
||||||
from app.models.server.prank import PrankCommand, PrankCommandUpdate
|
from app.models.server.prank import PrankCommand, PrankCommandUpdate
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
import uuid
|
import uuid
|
||||||
from app.services.server.command import CommandService
|
from app.services.server.command import CommandService
|
||||||
|
|
||||||
@ -124,6 +124,29 @@ class PrankService:
|
|||||||
|
|
||||||
async def get_all_servers(self):
|
async def get_all_servers(self):
|
||||||
"""Получение списка всех доступных серверов"""
|
"""Получение списка всех доступных серверов"""
|
||||||
|
# Проверяем и удаляем неактивные серверы (более 5 минут без данных)
|
||||||
|
current_time = datetime.utcnow()
|
||||||
|
inactive_threshold = 5 * 60 # 5 минут в секундах
|
||||||
|
|
||||||
|
# Находим серверы, которые не отправляли данные больше 5 минут
|
||||||
|
# Учитываем, что у некоторых серверов может не быть поля last_activity
|
||||||
|
inactive_servers = await game_servers_collection.find({
|
||||||
|
"last_activity": {
|
||||||
|
"$exists": True,
|
||||||
|
"$lt": current_time - timedelta(seconds=inactive_threshold)
|
||||||
|
}
|
||||||
|
}).to_list(100)
|
||||||
|
|
||||||
|
# Удаляем неактивные серверы
|
||||||
|
if inactive_servers:
|
||||||
|
server_ids = [server["id"] for server in inactive_servers]
|
||||||
|
await game_servers_collection.delete_many({"id": {"$in": server_ids}})
|
||||||
|
|
||||||
|
# Опционально: логирование удаленных серверов
|
||||||
|
for server in inactive_servers:
|
||||||
|
print(f"Удален неактивный сервер: {server['name']} (ID: {server['id']})")
|
||||||
|
|
||||||
|
# Получаем актуальный список серверов
|
||||||
servers = await game_servers_collection.find().to_list(100)
|
servers = await game_servers_collection.find().to_list(100)
|
||||||
|
|
||||||
# Если нет зарегистрированных серверов, вернем пустой список
|
# Если нет зарегистрированных серверов, вернем пустой список
|
||||||
@ -144,7 +167,8 @@ class PrankService:
|
|||||||
"port": server.get("port"),
|
"port": server.get("port"),
|
||||||
"description": server.get("description", ""),
|
"description": server.get("description", ""),
|
||||||
"online_players": online_count,
|
"online_players": online_count,
|
||||||
"max_players": server.get("max_players", 0)
|
"max_players": server.get("max_players", 0),
|
||||||
|
"last_activity": server.get("last_activity")
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -131,10 +131,23 @@ class StoreCapeService:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Ошибка при удалении файла: {e}")
|
print(f"Ошибка при удалении файла: {e}")
|
||||||
|
|
||||||
# Удаляем из БД
|
# Удаляем из БД плащей магазина
|
||||||
result = await store_capes_collection.delete_one({"id": cape_id})
|
result = await store_capes_collection.delete_one({"id": cape_id})
|
||||||
if result.deleted_count == 0:
|
if result.deleted_count == 0:
|
||||||
raise HTTPException(status_code=500, detail="Ошибка при удалении из БД")
|
raise HTTPException(status_code=500, detail="Ошибка при удалении из БД")
|
||||||
|
|
||||||
|
# Удаляем из БД купленных плащей
|
||||||
|
purchases_collection = db.purchases
|
||||||
|
purchases = await purchases_collection.find_one({"cape_id": cape_id})
|
||||||
|
if purchases:
|
||||||
|
await purchases_collection.delete_one({"cape_id": cape_id})
|
||||||
|
|
||||||
|
# Удаляем плащ из массива purchased_capes всех пользователей
|
||||||
|
users_collection = db.users
|
||||||
|
await users_collection.update_many(
|
||||||
|
{"purchased_capes.cape_id": cape_id},
|
||||||
|
{"$pull": {"purchased_capes": {"cape_id": cape_id}}}
|
||||||
|
)
|
||||||
|
|
||||||
return {"status": "success"}
|
return {"status": "success"}
|
||||||
|
|
||||||
@ -189,6 +202,7 @@ class StoreCapeService:
|
|||||||
"purchased_capes": {
|
"purchased_capes": {
|
||||||
"cape_id": cape_id,
|
"cape_id": cape_id,
|
||||||
"cape_name": cape["name"],
|
"cape_name": cape["name"],
|
||||||
|
"cape_description": cape["description"],
|
||||||
"file_name": cape_filename,
|
"file_name": cape_filename,
|
||||||
"purchased_at": datetime.utcnow()
|
"purchased_at": datetime.utcnow()
|
||||||
}
|
}
|
||||||
@ -233,6 +247,7 @@ class StoreCapeService:
|
|||||||
result.append({
|
result.append({
|
||||||
"cape_id": cape.get("cape_id"),
|
"cape_id": cape.get("cape_id"),
|
||||||
"cape_name": cape.get("cape_name"),
|
"cape_name": cape.get("cape_name"),
|
||||||
|
"cape_description": cape.get("cape_description"),
|
||||||
"image_url": f"{FILES_URL}/capes/{cape.get('file_name')}",
|
"image_url": f"{FILES_URL}/capes/{cape.get('file_name')}",
|
||||||
"purchased_at": cape.get("purchased_at"),
|
"purchased_at": cape.get("purchased_at"),
|
||||||
"is_active": user.get("cloak_url") == f"{FILES_URL}/capes/{cape.get('file_name')}"
|
"is_active": user.get("cloak_url") == f"{FILES_URL}/capes/{cape.get('file_name')}"
|
||||||
@ -267,4 +282,33 @@ class StoreCapeService:
|
|||||||
return {
|
return {
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"message": f"Плащ '{selected_cape.get('cape_name')}' активирован"
|
"message": f"Плащ '{selected_cape.get('cape_name')}' активирован"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def deactivate_purchased_cape(self, username: str, cape_id: str):
|
||||||
|
"""Деактивация приобретенного плаща"""
|
||||||
|
user = await users_collection.find_one({"username": username})
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||||
|
|
||||||
|
# Проверяем, что плащ был приобретен
|
||||||
|
purchased_capes = user.get("purchased_capes", [])
|
||||||
|
selected_cape = None
|
||||||
|
|
||||||
|
for cape in purchased_capes:
|
||||||
|
if cape.get("cape_id") == cape_id:
|
||||||
|
selected_cape = cape
|
||||||
|
break
|
||||||
|
|
||||||
|
if not selected_cape:
|
||||||
|
raise HTTPException(status_code=404, detail="Плащ не найден среди приобретенных")
|
||||||
|
|
||||||
|
# Устанавливаем выбранный плащ
|
||||||
|
await users_collection.update_one(
|
||||||
|
{"username": username},
|
||||||
|
{"$set": {"cloak_url": None}}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": "success",
|
||||||
|
"message": f"Плащ '{selected_cape.get('cape_name')}' деактивирован"
|
||||||
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 122 KiB |
Reference in New Issue
Block a user