add: store pranks

This commit is contained in:
2025-07-18 18:05:45 +05:00
parent d52d4dbf75
commit 7e4e2c0bad
7 changed files with 623 additions and 51 deletions

View 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"]
}