2026-10-01 11:52:31 +02:00
|
|
|
using Microsoft.AspNetCore.Http.Features;
|
|
|
|
|
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
|
|
|
|
|
namespace PrivaPub.Api.Mastodon.Infrastructure
|
|
|
|
|
{
|
|
|
|
|
public sealed class MastodonParams
|
|
|
|
|
{
|
|
|
|
|
readonly Dictionary<string, List<string>> _values;
|
|
|
|
|
|
|
|
|
|
MastodonParams(Dictionary<string, List<string>> values)
|
|
|
|
|
{
|
|
|
|
|
_values = values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<MastodonParams> Read(HttpRequest request, CancellationToken token)
|
|
|
|
|
{
|
|
|
|
|
var values = new Dictionary<string, List<string>>(StringComparer.Ordinal);
|
|
|
|
|
foreach (var pair in request.Query)
|
|
|
|
|
foreach (var value in pair.Value)
|
|
|
|
|
Add(values, pair.Key, value);
|
|
|
|
|
|
|
|
|
|
if (request.HasFormContentType)
|
|
|
|
|
{
|
|
|
|
|
var form = await request.ReadFormAsync(token);
|
|
|
|
|
foreach (var pair in form)
|
|
|
|
|
foreach (var value in pair.Value)
|
|
|
|
|
Add(values, pair.Key, value);
|
|
|
|
|
}
|
|
|
|
|
else if (request.ContentType?.Contains("json", StringComparison.OrdinalIgnoreCase) == true && request.ContentLength != 0)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
using var document = await JsonDocument.ParseAsync(request.Body, cancellationToken: token);
|
|
|
|
|
Flatten(values, default, document.RootElement);
|
|
|
|
|
}
|
|
|
|
|
catch (JsonException)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return new MastodonParams(values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static MastodonParams From(IEnumerable<KeyValuePair<string, string>> pairs)
|
|
|
|
|
{
|
|
|
|
|
var values = new Dictionary<string, List<string>>(StringComparer.Ordinal);
|
|
|
|
|
foreach (var pair in pairs)
|
|
|
|
|
Add(values, pair.Key, pair.Value);
|
|
|
|
|
return new MastodonParams(values);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Has(string name) => _values.ContainsKey(name);
|
|
|
|
|
|
|
|
|
|
public string Get(string name) => _values.TryGetValue(name, out var list) && list.Count > 0 ? list[^1] : default;
|
|
|
|
|
|
|
|
|
|
public IReadOnlyList<string> List(string name) => _values.TryGetValue(name, out var list) ? list : (IReadOnlyList<string>)Array.Empty<string>();
|
|
|
|
|
|
|
|
|
|
public bool? Bool(string name) => Get(name)?.ToLowerInvariant() switch
|
|
|
|
|
{
|
|
|
|
|
"true" or "1" or "on" or "yes" => true,
|
|
|
|
|
"false" or "0" or "off" or "no" or "" => false,
|
2026-10-01 12:05:58 +02:00
|
|
|
_ => (bool?)null
|
2026-10-01 11:52:31 +02:00
|
|
|
};
|
|
|
|
|
|
2026-10-01 12:05:58 +02:00
|
|
|
public int? Int(string name) => int.TryParse(Get(name), out var value) ? value : (int?)null;
|
2026-10-01 11:52:31 +02:00
|
|
|
|
|
|
|
|
static void Add(Dictionary<string, List<string>> values, string key, string value)
|
|
|
|
|
{
|
|
|
|
|
key = key.EndsWith("[]", StringComparison.Ordinal) ? key[..^2] : key;
|
|
|
|
|
if (!values.TryGetValue(key, out var list))
|
|
|
|
|
values[key] = list = new List<string>();
|
|
|
|
|
list.Add(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void Flatten(Dictionary<string, List<string>> values, string prefix, JsonElement element)
|
|
|
|
|
{
|
|
|
|
|
switch (element.ValueKind)
|
|
|
|
|
{
|
|
|
|
|
case JsonValueKind.Object:
|
|
|
|
|
foreach (var property in element.EnumerateObject())
|
|
|
|
|
Flatten(values, prefix == default ? property.Name : $"{prefix}[{property.Name}]", property.Value);
|
|
|
|
|
break;
|
|
|
|
|
case JsonValueKind.Array:
|
|
|
|
|
foreach (var item in element.EnumerateArray())
|
|
|
|
|
{
|
|
|
|
|
if (item.ValueKind is JsonValueKind.Object or JsonValueKind.Array)
|
|
|
|
|
Flatten(values, prefix + "[]", item);
|
|
|
|
|
else
|
|
|
|
|
Add(values, prefix, Scalar(item));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case JsonValueKind.Null or JsonValueKind.Undefined:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (prefix != default)
|
|
|
|
|
Add(values, prefix, Scalar(element));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static string Scalar(JsonElement element) => element.ValueKind switch
|
|
|
|
|
{
|
|
|
|
|
JsonValueKind.String => element.GetString(),
|
|
|
|
|
JsonValueKind.True => "true",
|
|
|
|
|
JsonValueKind.False => "false",
|
|
|
|
|
_ => element.GetRawText()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|