Files
Radicade/Server/Rooms/RoomKeysAPI.cs
T
2026-10-16 23:33:13 -07:00

121 lines
4.0 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RadicadeServer.API.Rooms;
using RadicadeServer.DB;
using RadicadeServer.Extensions;
using RadicadeServer.RecNet.Config;
using RadicadeServer.RecNet.Rooms;
namespace RadicadeServer.API.Rooms.Keys.V1
{
[Route("api/roomkeys/v1")]
[Route("econ/api/roomkeys/v1")]
public class RoomKeysAPI : Controller
{
private const int DefaultMaxKeysPerRoom = 500;
RecDBContext db;
public RoomKeysAPI(RecDBContext context) {
this.db = context;
}
[HttpGet("room")]
public IActionResult GetRoomKeysForRoom(long? roomId)
{
if (roomId is not > 0)
return Ok(Array.Empty<RoomKey>());
return Ok(
db.RoomKeys.Where(roomKey => roomKey.RoomId == roomId.Value).ToList()
);
}
[HttpGet("mine")]
public async Task<IActionResult> GetOwnedRoomkeys([FromQuery] long? roomId)
{
var userId = User.GetUserId();
if (roomId == null || userId == null) return Ok(Array.Empty<object>());
var ownedIds = (await db.Unlocks.AsNoTracking()
.FirstOrDefaultAsync(unlocks => unlocks.AccountId == userId.Value))?.RoomKeys
.FromJson<List<long>>() ?? new List<long>();
var keys = await db.RoomKeys.AsNoTracking()
.Where(key => key.RoomId == roomId.Value && ownedIds.Contains(key.RoomKeyId))
.ToListAsync();
return Ok(keys);
}
[HttpGet("purchased/{roomKeyId:long}")]
public async Task<IActionResult> IsRoomKeyPurchased(long roomKeyId)
{
var userId = User.GetUserId();
if (userId == null || roomKeyId <= 0) return Ok(false);
var roomKey = await db.RoomKeys.AsNoTracking()
.FirstOrDefaultAsync(key => key.RoomKeyId == roomKeyId);
if (roomKey == null) return Ok(false);
var unlocks = await db.Unlocks.AsNoTracking()
.FirstOrDefaultAsync(row => row.AccountId == userId.Value);
var ownedIds = unlocks?.RoomKeys.FromJson<List<long>>() ?? new List<long>();
return Ok(ownedIds.Contains(roomKeyId));
}
[HttpPost("create")]
[HttpPost("create/{roomId}")]
public async Task<IActionResult> CreateRoomKey()
{
var body = await RoomEconomyPayload.ReadBodyAsync(Request);
var roomId = await RoomEconomyPayload.RoomIdAsync(db, Request, body, "roomId", "roomKeyRoomId")
?? ReadRoomIdFromReferrer();
if (roomId is not > 0) return BadRequest(new { Message = "roomId is required." });
var key = new RoomKey
{
RoomId = roomId.Value,
Name = RoomEconomyPayload.String(body, "name", "keyName") ?? "Room Key",
Description = RoomEconomyPayload.String(body, "description") ?? string.Empty,
Price = (int)(RoomEconomyPayload.Long(body, "price", "tokenPrice", "cost") ?? 0),
ReplicationId = RoomEconomyPayload.String(body, "replicationId") ?? Guid.NewGuid().ToString()
};
var maxKeys = await MaxKeysPerRoomAsync();
var existing = await db.RoomKeys.CountAsync(existing => existing.RoomId == roomId.Value);
if (existing >= maxKeys)
{
return BadRequest(new { Message = $"A room can have at most {maxKeys} keys." });
}
await db.RoomKeys.AddAsync(key);
await db.SaveChangesAsync();
return Ok(key);
}
private long? ReadRoomIdFromReferrer()
{
var referer = Request.Headers.Referer.FirstOrDefault();
if (!Uri.TryCreate(referer, UriKind.Absolute, out var uri)) return null;
var parts = uri.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
for (var index = parts.Length - 1; index >= 0; index--)
if (long.TryParse(parts[index], out var roomId) && roomId > 0) return roomId;
return null;
}
private string Describe(System.Text.Json.JsonElement? body)
{
var raw = RoomEconomyPayload.RawBody(Request);
if (raw.Length == 0 && body == null) return "(empty)";
if (raw.Length == 0) raw = body?.ToString() ?? "";
return raw.Length <= 1000 ? raw : raw[..1000] + "...";
}
private async Task<int> MaxKeysPerRoomAsync()
{
var config = await db.Config.FirstOrDefaultAsync();
var limit = config?.RoomKeyConfig?.FromJson<RoomKeyConfig>()?.MaxKeysPerRoom ?? 0;
return limit > 0 ? limit : DefaultMaxKeysPerRoom;
}
}
}