Files
2025-12-16 00:15:29 +05:00

96 lines
3.7 KiB
Python
Raw Permalink 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.

from datetime import datetime
from uuid import uuid4
from fastapi import HTTPException
from app.db.database import db
player_inventory_collection = db.player_inventory
marketplace_operations_collection = db.marketplace_operations
def _serialize_mongodb_doc(doc):
"""Преобразует MongoDB документ для JSON сериализации"""
if doc is None:
return None
# Добавить проверку на список
if isinstance(doc, list):
return [_serialize_mongodb_doc(item) for item in doc]
result = {}
for key, value in doc.items():
# Обработка ObjectId
if key == "_id":
result["_id"] = str(value)
continue
# Обработка ISODate
if isinstance(value, datetime):
result[key] = value.isoformat()
# Обработка вложенных словарей
elif isinstance(value, dict):
if "$date" in value:
# Это ISODate
result[key] = datetime.fromisoformat(value["$date"].replace("Z", "+00:00")).isoformat()
else:
result[key] = _serialize_mongodb_doc(value)
# Обработка списков
elif isinstance(value, list):
result[key] = [_serialize_mongodb_doc(item) if isinstance(item, dict) else item for item in value]
else:
result[key] = value
return result
class InventoryService:
async def list_items(self, username: str, server_ip: str, page: int = 1, limit: int = 20):
q = {"username": username, "server_ip": server_ip, "status": {"$in": ["stored", "withdrawing"]}}
skip = max(page - 1, 0) * limit
items = await player_inventory_collection.find(q) \
.sort("created_at", -1) \
.skip(skip) \
.limit(limit) \
.to_list(length=limit)
serialized_items = _serialize_mongodb_doc(items)
total = await player_inventory_collection.count_documents(q)
return {"items": serialized_items, "page": page, "limit": limit, "total": total}
async def withdraw_item(self, username: str, item_id: str, server_ip: str):
item = await player_inventory_collection.find_one({"id": item_id})
if not item:
raise HTTPException(status_code=404, detail="Item not found")
if item["username"] != username:
raise HTTPException(status_code=403, detail="Not your item")
if item["server_ip"] != server_ip:
raise HTTPException(status_code=400, detail="Wrong server_ip for this item")
if item.get("status") != "stored":
raise HTTPException(status_code=400, detail="Item is not available for withdraw")
# создаём операцию выдачи НА СЕРВЕР (тип оставляем case_reward)
op_id = str(uuid4())
operation = {
"id": op_id,
"type": "case_reward",
"player_name": username,
"item_data": item["item_data"],
"server_ip": server_ip,
"status": "pending",
"created_at": datetime.utcnow(),
# важно: связка с инвентарём, чтобы confirm мог отметить delivered
"inventory_item_id": item_id,
"source": item.get("source"),
}
await marketplace_operations_collection.insert_one(operation)
# помечаем предмет как withdrawing
await player_inventory_collection.update_one(
{"id": item_id},
{"$set": {"status": "withdrawing", "withdraw_operation_id": op_id}}
)
return {"ok": True, "operation_id": op_id, "item_id": item_id}