mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-27 16:09:07 -07:00
Radicade Public Code
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RadicadeServer.DB;
|
||||
using RadicadeServer.Extensions;
|
||||
|
||||
namespace RadicadeServer.API.Rooms
|
||||
{
|
||||
internal static class RoomEconomyPayload
|
||||
{
|
||||
private const string RawKey = "RoomEconomyPayload.Raw";
|
||||
|
||||
public static async Task<JsonElement?> ReadBodyAsync(HttpRequest request)
|
||||
{
|
||||
if (request.HasFormContentType)
|
||||
{
|
||||
try
|
||||
{
|
||||
var form = await request.ReadFormAsync();
|
||||
if (form.Count > 0)
|
||||
{
|
||||
var fields = new Dictionary<string, object?>();
|
||||
foreach (var field in form)
|
||||
fields[field.Key] = field.Value.ToString();
|
||||
foreach (var file in form.Files)
|
||||
fields[file.Name] = file.FileName;
|
||||
return JsonSerializer.SerializeToElement(fields);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
request.HttpContext.Items[RawKey] = $"<form body could not be read: {ex.Message}>";
|
||||
}
|
||||
}
|
||||
|
||||
string raw;
|
||||
using (var reader = new StreamReader(request.Body))
|
||||
raw = await reader.ReadToEndAsync();
|
||||
|
||||
var text = raw.TrimStart('\uFEFF', ' ', '\t', '\r', '\n');
|
||||
if (text.Length == 0) return null;
|
||||
|
||||
if (text[0] is '{' or '[')
|
||||
{
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(text);
|
||||
return doc.RootElement.Clone();
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var pairs = ParsePairs(raw);
|
||||
if (pairs.Count > 0)
|
||||
{
|
||||
request.HttpContext.Items[RawKey] = raw;
|
||||
return JsonSerializer.SerializeToElement(pairs);
|
||||
}
|
||||
|
||||
request.HttpContext.Items[RawKey] = raw;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string RawBody(HttpRequest request) =>
|
||||
request.HttpContext.Items.TryGetValue(RawKey, out var raw) ? raw as string ?? "" : "";
|
||||
|
||||
public static JsonElement? Value(JsonElement? body, params string[] names)
|
||||
{
|
||||
if (body == null) return null;
|
||||
|
||||
var stack = new Stack<JsonElement>();
|
||||
stack.Push(body.Value);
|
||||
var visited = 0;
|
||||
|
||||
while (stack.Count > 0 && visited++ < 2000)
|
||||
{
|
||||
var element = stack.Pop();
|
||||
if (element.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var item in element.EnumerateArray()) stack.Push(item);
|
||||
continue;
|
||||
}
|
||||
if (element.ValueKind != JsonValueKind.Object) continue;
|
||||
|
||||
foreach (var property in element.EnumerateObject())
|
||||
{
|
||||
if (property.Value.ValueKind is JsonValueKind.Object or JsonValueKind.Array)
|
||||
{
|
||||
stack.Push(property.Value);
|
||||
continue;
|
||||
}
|
||||
if (Matches(property.Name, names)) return property.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string? String(JsonElement? body, params string[] names)
|
||||
{
|
||||
var value = Value(body, names);
|
||||
if (value == null) return null;
|
||||
if (value.Value.ValueKind == JsonValueKind.String) return value.Value.GetString();
|
||||
if (value.Value.ValueKind is JsonValueKind.Number or JsonValueKind.True or JsonValueKind.False)
|
||||
return value.Value.ToString();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static long? Long(JsonElement? body, params string[] names)
|
||||
{
|
||||
var value = Value(body, names);
|
||||
if (value == null) return null;
|
||||
if (value.Value.ValueKind == JsonValueKind.Number)
|
||||
{
|
||||
if (value.Value.TryGetInt64(out var number)) return number;
|
||||
if (value.Value.TryGetDouble(out var real)) return (long)real;
|
||||
}
|
||||
if (value.Value.ValueKind == JsonValueKind.String && long.TryParse(value.Value.GetString(), out var parsed))
|
||||
return parsed;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool? Bool(JsonElement? body, params string[] names)
|
||||
{
|
||||
var value = Value(body, names);
|
||||
if (value == null) return null;
|
||||
if (value.Value.ValueKind == JsonValueKind.True) return true;
|
||||
if (value.Value.ValueKind == JsonValueKind.False) return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static long? LongFromRequest(HttpRequest request, params string[] names)
|
||||
{
|
||||
foreach (var pair in request.Query)
|
||||
{
|
||||
if (!Matches(pair.Key, names)) continue;
|
||||
if (long.TryParse(pair.Value.FirstOrDefault(), out var fromQuery)) return fromQuery;
|
||||
}
|
||||
foreach (var pair in request.RouteValues)
|
||||
{
|
||||
if (!Matches(pair.Key, names)) continue;
|
||||
if (long.TryParse(pair.Value?.ToString(), out var fromRoute)) return fromRoute;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Dictionary<string, object?> Fields(JsonElement? body)
|
||||
{
|
||||
var fields = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
|
||||
if (body == null || body.Value.ValueKind != JsonValueKind.Object) return fields;
|
||||
|
||||
foreach (var property in body.Value.EnumerateObject())
|
||||
{
|
||||
fields[property.Name] = property.Value.ValueKind switch
|
||||
{
|
||||
JsonValueKind.String => property.Value.GetString(),
|
||||
JsonValueKind.Number => property.Value.TryGetInt64(out var number) ? number : property.Value.GetDouble(),
|
||||
JsonValueKind.True => true,
|
||||
JsonValueKind.False => false,
|
||||
JsonValueKind.Null => null,
|
||||
_ => property.Value.Clone()
|
||||
};
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
public static async Task<long?> RoomIdAsync(RecDBContext db, HttpRequest request, JsonElement? body, params string[] names)
|
||||
{
|
||||
var roomId = Long(body, names) ?? LongFromRequest(request, names);
|
||||
if (roomId is > 0) return roomId;
|
||||
|
||||
var accountId = request.HttpContext.User.GetUserId();
|
||||
if (accountId is not > 0) return null;
|
||||
var presence = await db.Presences.AsNoTracking()
|
||||
.FirstOrDefaultAsync(item => item.playerId == accountId.Value);
|
||||
if (presence?.roomInstance is not > 0) return null;
|
||||
return await db.RoomInstances.AsNoTracking()
|
||||
.Where(instance => instance.roomInstanceId == presence.roomInstance.Value)
|
||||
.Select(instance => (long?)instance.roomId)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public static string NewId()
|
||||
{
|
||||
var bytes = RandomNumberGenerator.GetBytes(16);
|
||||
return Convert.ToBase64String(bytes).Replace('+', '-').Replace('/', '_').TrimEnd('=');
|
||||
}
|
||||
|
||||
private static Dictionary<string, object?> ParsePairs(string raw)
|
||||
{
|
||||
var pairs = new Dictionary<string, object?>();
|
||||
foreach (var pair in raw.Split('&', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
var at = pair.IndexOf('=');
|
||||
var key = at < 0 ? pair : pair[..at];
|
||||
var value = at < 0 ? "" : pair[(at + 1)..];
|
||||
key = key.Trim();
|
||||
if (key.Length == 0) continue;
|
||||
|
||||
try
|
||||
{
|
||||
pairs[Uri.UnescapeDataString(key.Replace('+', ' '))] =
|
||||
Uri.UnescapeDataString(value.Replace('+', ' '));
|
||||
}
|
||||
catch (UriFormatException)
|
||||
{
|
||||
pairs[key] = value;
|
||||
}
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
private static bool Matches(string name, string[] names)
|
||||
{
|
||||
foreach (var wanted in names)
|
||||
{
|
||||
if (string.Equals(Normalize(name), Normalize(wanted), StringComparison.Ordinal)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string Normalize(string name) =>
|
||||
string.Concat(name.Where(char.IsLetterOrDigit)).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user