add: store pranks
This commit is contained in:
55
app/api/pranks.py
Normal file
55
app/api/pranks.py
Normal file
@ -0,0 +1,55 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from app.services.server.prank import PrankService
|
||||
from app.models.server.prank import PrankCommandCreate, PrankCommandUpdate, PrankExecute
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/api/pranks",
|
||||
tags=["Pranks"]
|
||||
)
|
||||
|
||||
prank_service = PrankService()
|
||||
|
||||
@router.get("/commands")
|
||||
async def get_all_prank_commands():
|
||||
"""Получение всех доступных команд-пакостей"""
|
||||
return await prank_service.get_all_prank_commands()
|
||||
|
||||
@router.get("/commands/{command_id}")
|
||||
async def get_prank_command(command_id: str):
|
||||
"""Получение команды-пакости по ID"""
|
||||
return await prank_service.get_prank_command(command_id)
|
||||
|
||||
@router.post("/commands")
|
||||
async def add_prank_command(command: PrankCommandCreate):
|
||||
"""Добавление новой команды-пакости"""
|
||||
return await prank_service.add_prank_command(command)
|
||||
|
||||
@router.put("/commands/{command_id}")
|
||||
async def update_prank_command(command_id: str, update_data: PrankCommandUpdate):
|
||||
"""Обновление команды-пакости"""
|
||||
return await prank_service.update_prank_command(command_id, update_data)
|
||||
|
||||
@router.delete("/commands/{command_id}")
|
||||
async def delete_prank_command(command_id: str):
|
||||
"""Удаление команды-пакости"""
|
||||
return await prank_service.delete_prank_command(command_id)
|
||||
|
||||
@router.get("/servers")
|
||||
async def get_all_servers():
|
||||
"""Получение списка всех доступных серверов"""
|
||||
return await prank_service.get_all_servers()
|
||||
|
||||
@router.get("/servers/{server_id}/players")
|
||||
async def get_server_online_players(server_id: str):
|
||||
"""Получение списка онлайн игроков на сервере"""
|
||||
return await prank_service.get_server_online_players(server_id)
|
||||
|
||||
@router.post("/execute")
|
||||
async def execute_prank(username: str, prank_data: PrankExecute):
|
||||
"""Выполнение пакости (списание монет и выполнение команды)"""
|
||||
return await prank_service.execute_prank(
|
||||
username,
|
||||
prank_data.command_id,
|
||||
prank_data.target_player,
|
||||
prank_data.server_id
|
||||
)
|
@ -5,3 +5,5 @@ class ServerCommand(BaseModel):
|
||||
command: str
|
||||
server_ip: str
|
||||
require_online_player: Optional[bool] = False
|
||||
target_message: Optional[str] = None # Сообщение для цели
|
||||
global_message: Optional[str] = None # Сообщение для остальных
|
||||
|
36
app/models/server/prank.py
Normal file
36
app/models/server/prank.py
Normal file
@ -0,0 +1,36 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional, List
|
||||
|
||||
class PrankCommandCreate(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
price: int
|
||||
command_template: str
|
||||
server_ids: List[str] = Field(
|
||||
default=[],
|
||||
description='Список серверов, где доступна команда. Использование ["*"] означает доступность на всех серверах'
|
||||
)
|
||||
targetDescription: Optional[str] = None # Сообщение для целевого игрока
|
||||
globalDescription: Optional[str] = None # Сообщение для всех остальных
|
||||
|
||||
class PrankCommandUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
price: Optional[int] = None
|
||||
command_template: Optional[str] = None
|
||||
server_ids: Optional[List[str]] = None
|
||||
targetDescription: Optional[str] = None
|
||||
globalDescription: Optional[str] = None
|
||||
|
||||
class PrankCommand(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
description: str
|
||||
price: int
|
||||
command_template: str
|
||||
server_ids: List[str] = []
|
||||
|
||||
class PrankExecute(BaseModel):
|
||||
command_id: str
|
||||
target_player: str
|
||||
server_id: str
|
@ -14,6 +14,8 @@ class CommandService:
|
||||
"command": command_data.command,
|
||||
"server_ip": command_data.server_ip,
|
||||
"require_online_player": command_data.require_online_player,
|
||||
"target_message": command_data.target_message if hasattr(command_data, 'target_message') else None,
|
||||
"global_message": command_data.global_message if hasattr(command_data, 'global_message') else None,
|
||||
"created_at": datetime.now().isoformat()
|
||||
}
|
||||
print(f"[{datetime.now()}] Добавлена команда: {command_data.command} "
|
||||
@ -26,7 +28,13 @@ class CommandService:
|
||||
try:
|
||||
# Получаем команды для указанного сервера
|
||||
commands = [
|
||||
{"id": cmd_id, "command": cmd["command"], "require_online_player": cmd["require_online_player"]}
|
||||
{
|
||||
"id": cmd_id,
|
||||
"command": cmd["command"],
|
||||
"require_online_player": cmd["require_online_player"],
|
||||
"target_message": cmd.get("target_message"),
|
||||
"global_message": cmd.get("global_message")
|
||||
}
|
||||
for cmd_id, cmd in pending_commands.items()
|
||||
if cmd["server_ip"] == server_ip
|
||||
]
|
||||
|
@ -3,68 +3,274 @@ from datetime import datetime
|
||||
import json
|
||||
from app.services.coins import CoinsService
|
||||
from app.models.server.event import PlayerEvent, OnlinePlayersUpdate
|
||||
import uuid
|
||||
|
||||
class EventService:
|
||||
def __init__(self):
|
||||
self.coins_service = CoinsService()
|
||||
|
||||
async def process_event(self, event_data: dict):
|
||||
async def process_event(self, event_data):
|
||||
"""Обработка событий от сервера Minecraft"""
|
||||
try:
|
||||
# Проверяем формат ваших событий (event_type вместо type)
|
||||
event_type = event_data.get("event_type")
|
||||
server_ip = event_data.get("server_ip", "unknown")
|
||||
if not event_type:
|
||||
# Для совместимости со старым форматом
|
||||
event_type = event_data.get("type")
|
||||
|
||||
if not event_type:
|
||||
raise HTTPException(status_code=400, detail="Missing event type")
|
||||
|
||||
if event_type == "player_join":
|
||||
player_name = event_data["player_name"]
|
||||
player_id = event_data["player_id"]
|
||||
print(f"[{datetime.now()}] Игрок вошел: {player_name} (ID: {player_id}) "
|
||||
f"IP сервера: {server_ip}")
|
||||
server_ip = event_data.get("server_ip")
|
||||
if not server_ip:
|
||||
raise HTTPException(status_code=400, detail="Missing server IP")
|
||||
|
||||
# Преобразуем ваши типы событий в нужные форматы
|
||||
if event_type == "online_players_update":
|
||||
# Регистрируем сервер, если его нет
|
||||
await self._register_server(server_ip, event_data)
|
||||
|
||||
# Обновляем данные об онлайн игроках
|
||||
players = event_data.get("players", [])
|
||||
await self._update_online_players(server_ip, players)
|
||||
return {"status": "success"}
|
||||
|
||||
elif event_type == "player_join":
|
||||
player_id = event_data.get("player_id")
|
||||
player_name = event_data.get("player_name")
|
||||
|
||||
if not player_id or not player_name:
|
||||
raise HTTPException(status_code=400, detail="Missing player data")
|
||||
|
||||
# Регистрируем вход игрока
|
||||
await self._register_player_login(server_ip, player_id, player_name)
|
||||
return {"status": "success"}
|
||||
|
||||
elif event_type == "player_quit":
|
||||
player_name = event_data["player_name"]
|
||||
player_id = event_data["player_id"]
|
||||
print(f"[{datetime.now()}] Игрок вышел: {player_name} (ID: {player_id}) "
|
||||
f"IP сервера: {server_ip}")
|
||||
player_id = event_data.get("player_id")
|
||||
player_name = event_data.get("player_name")
|
||||
|
||||
if not player_id or not player_name:
|
||||
raise HTTPException(status_code=400, detail="Missing player data")
|
||||
|
||||
# Регистрируем выход игрока
|
||||
await self._register_player_logout(server_ip, player_id, player_name)
|
||||
return {"status": "success"}
|
||||
|
||||
elif event_type == "player_session":
|
||||
player_name = event_data["player_name"]
|
||||
player_id = event_data["player_id"]
|
||||
duration = event_data["duration"]
|
||||
player_id = event_data.get("player_id")
|
||||
player_name = event_data.get("player_name")
|
||||
duration = event_data.get("duration", 0)
|
||||
|
||||
# Обновляем монеты через выделенный сервис
|
||||
await self.coins_service.update_player_coins(player_id, player_name, duration, server_ip)
|
||||
|
||||
print(f"[{datetime.now()}] Игрок {player_name} провел на сервере: {duration} секунд "
|
||||
f"IP сервера: {server_ip}")
|
||||
|
||||
elif event_type == "online_players_update":
|
||||
players = event_data["players"]
|
||||
print(f"\n[{datetime.now()}] Текущие онлайн-игроки ({len(players)}): "
|
||||
f"IP сервера: {server_ip}")
|
||||
|
||||
# Обрабатываем каждого игрока
|
||||
for player in players:
|
||||
player_id = player["player_id"]
|
||||
player_name = player["player_name"]
|
||||
online_time = player["online_time"]
|
||||
if not player_id or not player_name:
|
||||
raise HTTPException(status_code=400, detail="Missing player data")
|
||||
|
||||
# Обновляем монеты через выделенный сервис
|
||||
await self.coins_service.update_player_coins(
|
||||
player_id, player_name, online_time, server_ip
|
||||
)
|
||||
|
||||
hours, remainder = divmod(online_time, 3600)
|
||||
minutes, seconds = divmod(remainder, 60)
|
||||
print(f" - {player_name} (ID: {player_id}) "
|
||||
f"Онлайн: {hours}ч {minutes}м {seconds}с")
|
||||
print()
|
||||
|
||||
else:
|
||||
print(f"[{datetime.now()}] Неизвестное событие: {json.dumps(event_data, indent=2)}")
|
||||
raise HTTPException(status_code=400, detail="Invalid event type")
|
||||
|
||||
return {"status": "success", "message": "Event processed"}
|
||||
# Обрабатываем информацию о сессии
|
||||
await self._process_player_session(server_ip, player_id, player_name, duration)
|
||||
return {"status": "success"}
|
||||
|
||||
# Если тип события не распознан
|
||||
print(f"[{datetime.now()}] Неизвестное событие: {event_data}")
|
||||
raise HTTPException(status_code=400, detail="Invalid event type")
|
||||
|
||||
except HTTPException as e:
|
||||
print(f"[{datetime.now()}] Ошибка обработки события: {e.status_code}: {e.detail}")
|
||||
print(f"Полученные данные: {event_data}")
|
||||
raise
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now()}] Ошибка обработки события: {str(e)}")
|
||||
print(f"Полученные данные: {json.dumps(event_data, indent=2)}")
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
print(f"[{datetime.now()}] Необработанная ошибка: {str(e)}")
|
||||
print(f"Полученные данные: {event_data}")
|
||||
raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")
|
||||
|
||||
async def _register_server(self, server_ip, event_data):
|
||||
"""Регистрирует сервер, если его нет в базе"""
|
||||
from app.db.database import db
|
||||
import uuid
|
||||
|
||||
game_servers_collection = db.game_servers
|
||||
|
||||
# Проверяем, есть ли уже такой сервер
|
||||
existing_server = await game_servers_collection.find_one({"ip": server_ip})
|
||||
|
||||
if not existing_server:
|
||||
# Создаем новую запись сервера
|
||||
server_data = {
|
||||
"id": str(uuid.uuid4()),
|
||||
"name": f"Server {server_ip}", # Можно улучшить название
|
||||
"ip": server_ip,
|
||||
"port": 25565, # Стандартный порт Minecraft
|
||||
"description": f"Minecraft server {server_ip}",
|
||||
"max_players": 100,
|
||||
"registered_at": datetime.utcnow()
|
||||
}
|
||||
|
||||
await game_servers_collection.insert_one(server_data)
|
||||
print(f"[{datetime.utcnow()}] Зарегистрирован новый сервер: {server_ip}")
|
||||
|
||||
return existing_server or await game_servers_collection.find_one({"ip": server_ip})
|
||||
|
||||
async def _update_online_players(self, server_ip, players_data):
|
||||
"""Обновляет информацию об онлайн игроках"""
|
||||
from app.db.database import db
|
||||
|
||||
online_players_collection = db.online_players
|
||||
|
||||
# Получаем ID сервера
|
||||
server = await self._register_server(server_ip, {})
|
||||
server_id = server["id"]
|
||||
|
||||
# Помечаем всех игроков как оффлайн на этом сервере
|
||||
await online_players_collection.update_many(
|
||||
{"server_id": server_id},
|
||||
{"$set": {"is_online": False}}
|
||||
)
|
||||
|
||||
# Обновляем данные для каждого онлайн игрока
|
||||
now = datetime.utcnow()
|
||||
for player in players_data:
|
||||
player_id = player.get("player_id")
|
||||
player_name = player.get("player_name")
|
||||
online_time = player.get("online_time", 0)
|
||||
|
||||
if not player_id or not player_name:
|
||||
continue
|
||||
|
||||
# Проверяем, существует ли уже запись
|
||||
existing_player = await online_players_collection.find_one({
|
||||
"uuid": player_id,
|
||||
"server_id": server_id
|
||||
})
|
||||
|
||||
if existing_player:
|
||||
# Обновляем существующую запись
|
||||
await online_players_collection.update_one(
|
||||
{"_id": existing_player["_id"]},
|
||||
{"$set": {
|
||||
"username": player_name,
|
||||
"is_online": True,
|
||||
"last_seen": now,
|
||||
"online_duration": online_time
|
||||
}}
|
||||
)
|
||||
else:
|
||||
# Создаем новую запись
|
||||
await online_players_collection.insert_one({
|
||||
"uuid": player_id,
|
||||
"username": player_name,
|
||||
"server_id": server_id,
|
||||
"is_online": True,
|
||||
"login_time": now,
|
||||
"last_seen": now,
|
||||
"online_duration": online_time
|
||||
})
|
||||
|
||||
online_count = len(players_data)
|
||||
print(f"[{now}] Обновлена информация о {online_count} игроках на сервере {server_ip}")
|
||||
|
||||
# Также обновляем информацию о коинах для каждого игрока
|
||||
if players_data:
|
||||
from app.services.coins import CoinsService
|
||||
coins_service = CoinsService()
|
||||
|
||||
for player in players_data:
|
||||
player_id = player.get("player_id")
|
||||
player_name = player.get("player_name")
|
||||
online_time = player.get("online_time", 0)
|
||||
|
||||
if player_id and player_name:
|
||||
await coins_service.update_player_coins(player_id, player_name, online_time, server_ip)
|
||||
|
||||
async def _register_player_login(self, server_ip, player_id, player_name):
|
||||
"""Регистрирует вход игрока на сервер"""
|
||||
from app.db.database import db
|
||||
|
||||
online_players_collection = db.online_players
|
||||
|
||||
server = await self._register_server(server_ip, {})
|
||||
server_id = server["id"]
|
||||
|
||||
now = datetime.utcnow()
|
||||
|
||||
# Проверяем, есть ли уже запись для этого игрока
|
||||
existing_player = await online_players_collection.find_one({
|
||||
"uuid": player_id,
|
||||
"server_id": server_id
|
||||
})
|
||||
|
||||
if existing_player:
|
||||
# Обновляем запись
|
||||
await online_players_collection.update_one(
|
||||
{"_id": existing_player["_id"]},
|
||||
{"$set": {
|
||||
"username": player_name,
|
||||
"is_online": True,
|
||||
"login_time": now,
|
||||
"last_seen": now
|
||||
}}
|
||||
)
|
||||
else:
|
||||
# Создаем новую запись
|
||||
await online_players_collection.insert_one({
|
||||
"uuid": player_id,
|
||||
"username": player_name,
|
||||
"server_id": server_id,
|
||||
"is_online": True,
|
||||
"login_time": now,
|
||||
"last_seen": now,
|
||||
"online_duration": 0
|
||||
})
|
||||
|
||||
print(f"[{now}] Игрок {player_name} зашел на сервер {server_ip}")
|
||||
|
||||
async def _register_player_logout(self, server_ip, player_id, player_name):
|
||||
"""Регистрирует выход игрока с сервера"""
|
||||
from app.db.database import db
|
||||
|
||||
online_players_collection = db.online_players
|
||||
|
||||
server = await self._register_server(server_ip, {})
|
||||
server_id = server["id"]
|
||||
|
||||
now = datetime.utcnow()
|
||||
|
||||
# Ищем запись игрока
|
||||
player = await online_players_collection.find_one({
|
||||
"uuid": player_id,
|
||||
"server_id": server_id
|
||||
})
|
||||
|
||||
if player:
|
||||
# Обновляем запись
|
||||
await online_players_collection.update_one(
|
||||
{"_id": player["_id"]},
|
||||
{"$set": {
|
||||
"is_online": False,
|
||||
"last_seen": now
|
||||
}}
|
||||
)
|
||||
|
||||
print(f"[{now}] Игрок {player_name} вышел с сервера {server_ip}")
|
||||
|
||||
async def _process_player_session(self, server_ip, player_id, player_name, duration):
|
||||
"""Обрабатывает информацию о завершенной сессии игрока"""
|
||||
from app.db.database import db
|
||||
from app.services.coins import CoinsService
|
||||
|
||||
server = await self._register_server(server_ip, {})
|
||||
server_id = server["id"]
|
||||
|
||||
# Обновляем статистику времени игры
|
||||
await db.player_sessions.insert_one({
|
||||
"uuid": player_id,
|
||||
"username": player_name,
|
||||
"server_id": server_id,
|
||||
"server_ip": server_ip,
|
||||
"duration": duration,
|
||||
"session_end": datetime.utcnow()
|
||||
})
|
||||
|
||||
# Начисляем коины за время игры
|
||||
coins_service = CoinsService()
|
||||
await coins_service.update_player_coins(player_id, player_name, duration, server_ip)
|
||||
|
||||
print(f"[{datetime.now()}] Сессия игрока {player_name} завершена, длительность: {duration} сек.")
|
||||
|
264
app/services/server/prank.py
Normal file
264
app/services/server/prank.py
Normal file
@ -0,0 +1,264 @@
|
||||
from fastapi import HTTPException
|
||||
from app.db.database import db, users_collection
|
||||
from app.models.server.prank import PrankCommand, PrankCommandUpdate
|
||||
from datetime import datetime
|
||||
import uuid
|
||||
from app.services.server.command import CommandService
|
||||
|
||||
# Создаем коллекции для хранения пакостей и серверов
|
||||
prank_commands_collection = db.prank_commands
|
||||
game_servers_collection = db.game_servers
|
||||
online_players_collection = db.online_players
|
||||
|
||||
class PrankService:
|
||||
async def add_prank_command(self, command_data):
|
||||
"""Добавление новой команды-пакости"""
|
||||
# Проверяем корректность шаблона команды
|
||||
if "{targetPlayer}" not in command_data.command_template:
|
||||
raise HTTPException(status_code=400,
|
||||
detail="Шаблон команды должен содержать {targetPlayer} для подстановки имени цели")
|
||||
|
||||
prank_id = str(uuid.uuid4())
|
||||
|
||||
# Создаем новую команду в БД
|
||||
prank_command = {
|
||||
"id": prank_id,
|
||||
"name": command_data.name,
|
||||
"description": command_data.description,
|
||||
"price": command_data.price,
|
||||
"command_template": command_data.command_template,
|
||||
"server_ids": command_data.server_ids,
|
||||
"targetDescription": command_data.targetDescription,
|
||||
"globalDescription": command_data.globalDescription, # Добавить это поле
|
||||
"created_at": datetime.utcnow()
|
||||
}
|
||||
|
||||
await prank_commands_collection.insert_one(prank_command)
|
||||
|
||||
return {"status": "success", "id": prank_id}
|
||||
|
||||
async def get_all_prank_commands(self):
|
||||
"""Получение списка всех команд-пакостей"""
|
||||
commands = await prank_commands_collection.find().to_list(1000)
|
||||
result = []
|
||||
|
||||
for cmd in commands:
|
||||
result.append({
|
||||
"id": cmd["id"],
|
||||
"name": cmd["name"],
|
||||
"description": cmd["description"],
|
||||
"price": cmd["price"],
|
||||
"command_template": cmd["command_template"],
|
||||
"server_ids": cmd.get("server_ids", []),
|
||||
"targetDescription": cmd.get("targetDescription"),
|
||||
"globalDescription": cmd.get("globalDescription") # Добавить это поле
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
async def get_prank_command(self, command_id: str):
|
||||
"""Получение конкретной команды по ID"""
|
||||
command = await prank_commands_collection.find_one({"id": command_id})
|
||||
if not command:
|
||||
raise HTTPException(status_code=404, detail="Команда не найдена")
|
||||
|
||||
return {
|
||||
"id": command["id"],
|
||||
"name": command["name"],
|
||||
"description": command["description"],
|
||||
"price": command["price"],
|
||||
"command_template": command["command_template"],
|
||||
"server_ids": command.get("server_ids", []),
|
||||
"targetDescription": command.get("targetDescription"),
|
||||
"globalDescription": command.get("globalDescription") # Добавить это поле
|
||||
}
|
||||
|
||||
async def update_prank_command(self, command_id: str, update_data: PrankCommandUpdate):
|
||||
"""Обновление команды-пакости"""
|
||||
command = await prank_commands_collection.find_one({"id": command_id})
|
||||
if not command:
|
||||
raise HTTPException(status_code=404, detail="Команда не найдена")
|
||||
|
||||
# Готовим данные для обновления
|
||||
update = {}
|
||||
if update_data.name is not None:
|
||||
update["name"] = update_data.name
|
||||
if update_data.description is not None:
|
||||
update["description"] = update_data.description
|
||||
if update_data.price is not None:
|
||||
update["price"] = update_data.price
|
||||
if update_data.command_template is not None:
|
||||
if "{targetPlayer}" not in update_data.command_template:
|
||||
raise HTTPException(status_code=400,
|
||||
detail="Шаблон команды должен содержать {targetPlayer} для подстановки имени цели")
|
||||
update["command_template"] = update_data.command_template
|
||||
if update_data.server_ids is not None:
|
||||
update["server_ids"] = update_data.server_ids
|
||||
if update_data.targetDescription is not None:
|
||||
update["targetDescription"] = update_data.targetDescription
|
||||
if update_data.globalDescription is not None: # Добавить эту проверку
|
||||
update["globalDescription"] = update_data.globalDescription
|
||||
|
||||
if update:
|
||||
result = await prank_commands_collection.update_one(
|
||||
{"id": command_id},
|
||||
{"$set": update}
|
||||
)
|
||||
|
||||
if result.modified_count == 0:
|
||||
raise HTTPException(status_code=500, detail="Ошибка при обновлении команды")
|
||||
|
||||
return {"status": "success"}
|
||||
|
||||
async def delete_prank_command(self, command_id: str):
|
||||
"""Удаление команды-пакости"""
|
||||
command = await prank_commands_collection.find_one({"id": command_id})
|
||||
if not command:
|
||||
raise HTTPException(status_code=404, detail="Команда не найдена")
|
||||
|
||||
result = await prank_commands_collection.delete_one({"id": command_id})
|
||||
if result.deleted_count == 0:
|
||||
raise HTTPException(status_code=500, detail="Ошибка при удалении команды")
|
||||
|
||||
return {"status": "success"}
|
||||
|
||||
async def get_all_servers(self):
|
||||
"""Получение списка всех доступных серверов"""
|
||||
servers = await game_servers_collection.find().to_list(100)
|
||||
|
||||
# Если нет зарегистрированных серверов, вернем пустой список
|
||||
if not servers:
|
||||
return []
|
||||
|
||||
result = []
|
||||
for server in servers:
|
||||
# Получаем количество онлайн игроков
|
||||
online_count = await online_players_collection.count_documents(
|
||||
{"server_id": server["id"], "is_online": True}
|
||||
)
|
||||
|
||||
result.append({
|
||||
"id": server["id"],
|
||||
"name": server["name"],
|
||||
"ip": server.get("ip"),
|
||||
"port": server.get("port"),
|
||||
"description": server.get("description", ""),
|
||||
"online_players": online_count,
|
||||
"max_players": server.get("max_players", 0)
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
async def get_server_online_players(self, server_id: str):
|
||||
"""Получение списка онлайн игроков на конкретном сервере"""
|
||||
server = await game_servers_collection.find_one({"id": server_id})
|
||||
if not server:
|
||||
raise HTTPException(status_code=404, detail="Сервер не найден")
|
||||
|
||||
players = await online_players_collection.find(
|
||||
{"server_id": server_id, "is_online": True}
|
||||
).to_list(1000)
|
||||
|
||||
result = []
|
||||
for player in players:
|
||||
result.append({
|
||||
"username": player["username"],
|
||||
"uuid": player.get("uuid", ""),
|
||||
"online_since": player.get("login_time")
|
||||
})
|
||||
|
||||
return {
|
||||
"server": {
|
||||
"id": server["id"],
|
||||
"name": server["name"]
|
||||
},
|
||||
"online_players": result,
|
||||
"count": len(result)
|
||||
}
|
||||
|
||||
async def execute_prank(self, username: str, command_id: str, target_player: str, server_id: str):
|
||||
"""Выполнение пакости (покупка и выполнение команды)"""
|
||||
# Проверяем пользователя
|
||||
user = await users_collection.find_one({"username": username})
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||
|
||||
# Проверяем команду
|
||||
command = await prank_commands_collection.find_one({"id": command_id})
|
||||
if not command:
|
||||
raise HTTPException(status_code=404, detail="Команда не найдена")
|
||||
|
||||
# Проверяем сервер
|
||||
server = await game_servers_collection.find_one({"id": server_id})
|
||||
if not server:
|
||||
raise HTTPException(status_code=404, detail="Сервер не найден")
|
||||
|
||||
# Проверяем, доступна ли команда на данном сервере
|
||||
if (command.get("server_ids") and
|
||||
"*" not in command.get("server_ids", []) and
|
||||
server_id not in command.get("server_ids", [])):
|
||||
raise HTTPException(status_code=400, detail="Команда недоступна на выбранном сервере")
|
||||
|
||||
# Проверяем, онлайн ли целевой игрок
|
||||
target_online = await online_players_collection.find_one({
|
||||
"username": target_player,
|
||||
"server_id": server_id,
|
||||
"is_online": True
|
||||
})
|
||||
|
||||
if not target_online:
|
||||
raise HTTPException(status_code=400, detail=f"Игрок {target_player} не в сети на этом сервере")
|
||||
|
||||
# Проверяем достаточно ли монет
|
||||
user_coins = user.get("coins", 0)
|
||||
if user_coins < command["price"]:
|
||||
raise HTTPException(status_code=400,
|
||||
detail=f"Недостаточно монет. Требуется: {command['price']}, имеется: {user_coins}")
|
||||
|
||||
# Формируем команду для выполнения
|
||||
actual_command = command["command_template"].replace("{targetPlayer}", target_player)
|
||||
|
||||
# Обрабатываем оба типа сообщений
|
||||
target_desc = None
|
||||
global_desc = None
|
||||
|
||||
if command.get("targetDescription"):
|
||||
target_desc = command.get("targetDescription").replace("{username}", username).replace("{targetPlayer}", target_player)
|
||||
|
||||
if command.get("globalDescription"):
|
||||
global_desc = command.get("globalDescription").replace("{username}", username).replace("{targetPlayer}", target_player)
|
||||
|
||||
# Отправляем команду с обоими сообщениями
|
||||
command_service = CommandService()
|
||||
from app.models.server.command import ServerCommand
|
||||
|
||||
server_command = ServerCommand(
|
||||
command=actual_command,
|
||||
server_ip=server.get("ip", ""),
|
||||
require_online_player=True,
|
||||
target_message=target_desc, # Сообщение для цели
|
||||
global_message=global_desc # Сообщение для всех остальных
|
||||
)
|
||||
|
||||
command_result = await command_service.add_command(server_command)
|
||||
|
||||
# Логируем выполнение пакости
|
||||
log_entry = {
|
||||
"user_id": user["_id"],
|
||||
"username": username,
|
||||
"target_player": target_player,
|
||||
"command_id": command_id,
|
||||
"command_name": command["name"],
|
||||
"server_id": server_id,
|
||||
"price": command["price"],
|
||||
"executed_command": actual_command,
|
||||
"executed_at": datetime.utcnow()
|
||||
}
|
||||
|
||||
await db.prank_executions.insert_one(log_entry)
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"message": f"Команда '{command['name']}' успешно выполнена на игроке {target_player}",
|
||||
"remaining_coins": user_coins - command["price"]
|
||||
}
|
Reference in New Issue
Block a user