WIP C# stuff

This commit is contained in:
Rory&
2025-12-25 07:07:31 +01:00
parent e141202e5a
commit a01fb6ab39
10 changed files with 358 additions and 51 deletions
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20251207-164820" />
</ItemGroup>
</Project>
@@ -0,0 +1,55 @@
using System.Text.Json.Serialization;
namespace DiscordEmojiConverter;
public class DiscordEmojiJson {
[JsonPropertyName("emojis")]
public List<DiscordEmoji>? Emojis { get; set; }
[JsonPropertyName("emojisByCategory")]
public Dictionary<string, List<int>>? EmojisByCategory { get; set; }
[JsonPropertyName("nameToEmoji")]
public Dictionary<string, int>? NameToEmoji { get; set; }
[JsonPropertyName("surrogateToEmoji")]
public Dictionary<string, int>? SurrogateToEmoji { get; set; }
[JsonPropertyName("numDiversitySprites")]
public int? NumDiversitySprites { get; set; }
[JsonPropertyName("numNonDiversitySprites")]
public int? NumNonDiversitySprites { get; set; }
}
public class DiscordEmoji {
[JsonPropertyName("names")]
public List<string>? Names { get; set; }
[JsonPropertyName("surrogates")]
public string? Surrogates { get; set; }
[JsonPropertyName("unicodeVersion")]
public float? UnicodeVersion { get; set; }
[JsonPropertyName("spriteIndex")]
public int? SpriteIndex { get; set; }
[JsonPropertyName("hasMultiDiversity")]
public bool? HasMultiDiversity { get; set; }
[JsonPropertyName("hasMultiDiversityParent")]
public bool? HasMultiDiversityParent { get; set; }
[JsonPropertyName("hasDiversity")]
public bool? HasDiversity { get; set; }
[JsonPropertyName("hasDiversityParent")]
public bool? HasDiversityParent { get; set; }
[JsonPropertyName("diversityChildren")]
public List<int>? DiversityChildren { get; set; }
[JsonPropertyName("diversity")]
public List<string>? Diversity { get; set; }
}
@@ -0,0 +1,27 @@
// See https://aka.ms/new-console-template for more information
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using ArcaneLibs.Extensions;
using DiscordEmojiConverter;
var emojis = JsonSerializer.Deserialize<DiscordEmojiJson>(File.OpenRead(args[0]),
new JsonSerializerOptions() { UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow });
emojis.SurrogateToEmoji = null;
emojis.NameToEmoji = null;
emojis.NumDiversitySprites = null;
emojis.NumNonDiversitySprites = null;
foreach (var emoji in emojis.Emojis!)
{
emoji.HasDiversity = null;
emoji.HasDiversityParent = null;
emoji.HasMultiDiversity = null;
emoji.HasMultiDiversityParent = null;
emoji.SpriteIndex = null;
emoji.UnicodeVersion = null;
}
Console.WriteLine(emojis.ToJson(ignoreNull: true, indent: false));
+20 -51
View File
@@ -2,63 +2,32 @@
namespace Spacebar.ConfigModel;
public class Config
{
[JsonPropertyName("admin")] public EndpointConfig Admin { get; set; } = null!;
[JsonPropertyName("api")] public EndpointConfig Api { get; set; } = null!;
[JsonPropertyName("gateway")] public EndpointConfig Gateway { get; set; } = null!;
[JsonPropertyName("cdn")] public EndpointConfig Cdn { get; set; } = null!;
public class Config {
[JsonPropertyName("admin")]
public EndpointConfig Admin { get; set; } = null!;
public Config ReadFromKv(Dictionary<string, object?> kv)
{
// to object
[JsonPropertyName("api")]
public EndpointConfig Api { get; set; } = null!;
foreach (var (key, value) in kv)
{
switch (key.Split('_', 2)[0])
{
default:
Console.WriteLine($"Unrecognized config key prefix: {key}");
continue;
}
}
[JsonPropertyName("gateway")]
public EndpointConfig Gateway { get; set; } = null!;
return this;
}
[JsonPropertyName("cdn")]
public EndpointConfig Cdn { get; set; } = null!;
}
public class EndpointConfig
{
[JsonPropertyName("endpointPrivate")] public string? EndpointPrivate { get; set; }
[JsonPropertyName("endpointPublic")] public string? EndpointPublic { get; set; }
public class EndpointConfig {
[JsonPropertyName("endpointPrivate")]
public string? EndpointPrivate { get; set; }
public EndpointConfig ReadFromKv(Dictionary<string, object?> kv, string prefix)
{
foreach (var (key, value) in kv)
{
if (!key.StartsWith(prefix + "_")) continue;
var subKey = key[(prefix + "_").Length..];
switch (subKey)
{
case "ENDPOINT_PRIVATE":
EndpointPrivate = value?.ToString();
break;
case "ENDPOINT_PUBLIC":
EndpointPublic = value?.ToString();
break;
default:
Console.WriteLine($"Unrecognized config key: {key}");
break;
}
}
return this;
}
[JsonPropertyName("endpointPublic")]
public string? EndpointPublic { get; set; }
}
public class ApiConfig : EndpointConfig
{
[JsonPropertyName("activeVersions")] public List<string> ActiveVersions { get; set; } = null!;
[JsonPropertyName("defaultVersion")] public string DefaultVersion { get; set; } = null!;
public class ApiConfig : EndpointConfig {
[JsonPropertyName("activeVersions")]
public List<string> ActiveVersions { get; set; } = null!;
[JsonPropertyName("defaultVersion")]
public string DefaultVersion { get; set; } = null!;
}
@@ -0,0 +1,37 @@
using System.Text.Json.Serialization;
namespace Spacebar.ConfigModel;
public class DefaultsConfiguration
{
[JsonPropertyName("guild")] public GuildDefaults Guild = new GuildDefaults();
[JsonPropertyName("user")] public ChannelDefaults Channel = new ChannelDefaults();
}
public class GuildDefaults
{
[JsonPropertyName("maxPresences")] public int MaxPresences { get; set; } = 250000;
[JsonPropertyName("maxVideoChannelUsers")]
public int MaxVideoChannelUsers { get; set; } = 200;
[JsonPropertyName("afkTimeout")] public int AfkTimeout { get; set; } = 300;
[JsonPropertyName("defaultMessageNotifications")]
public int DefaultMessageNotifications { get; set; } = 1;
[JsonPropertyName("explicitContentFilter")]
public int ExplicitContentFilter { get; set; } = 0;
}
public class ChannelDefaults
{
[JsonPropertyName("premium")]
public bool Premium { get; set; } = true;
[JsonPropertyName("premiumType")]
public int PremiumType { get; set; } = 2;
[JsonPropertyName("verified")]
public bool Verified { get; set; } = true;
}
@@ -0,0 +1,35 @@
using System.Text.Json.Serialization;
namespace Spacebar.ConfigModel;
public class GeneralConfiguration {
[JsonPropertyName("instanceName")]
public string InstanceName { get; set; } = "Spacebar Instance";
[JsonPropertyName("serverName")]
public string? ServerName { get; set; } = null;
[JsonPropertyName("instanceDescription")]
public string InstanceDescription { get; set; } = "This is a Spacebar instance made in the pre-release days";
[JsonPropertyName("frontPage")]
public string? FrontPage { get; set; } = null;
[JsonPropertyName("tosPage")]
public string? TosPage { get; set; } = null;
[JsonPropertyName("correspondenceEmail")]
public string? CorrespondenceEmail { get; set; } = null;
[JsonPropertyName("correspondenceUserID")]
public string? CorrespondenceUserID { get; set; } = null;
[JsonPropertyName("image")]
public string? Image { get; set; } = null;
[JsonPropertyName("instanceId")]
public string InstanceId { get; set; } = null!; // {get;set;}=Snowflake.generate();
[JsonPropertyName("autoCreateBotUsers")]
public bool AutoCreateBotUsers { get; set; } = false;
}
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
namespace Spacebar.ConfigModel;
public class LimitsConfiguration {
[JsonPropertyName("user")] public UserLimits User = new UserLimits();
[JsonPropertyName("guild")] public GuildLimits Guild = new GuildLimits();
[JsonPropertyName("message")] public MessageLimits Message = new MessageLimits();
[JsonPropertyName("channel")] public ChannelLimits Channel = new ChannelLimits();
[JsonPropertyName("rate")] public RateLimits Rate = new RateLimits();
[JsonPropertyName("absoluteRate")] public GlobalRateLimits AbsoluteRate = new GlobalRateLimits();
}
@@ -0,0 +1,26 @@
using System.Text.Json.Serialization;
namespace Spacebar.ConfigModel;
public class SecurityConfiguration
{
[JsonPropertyName("captcha")] public CaptchaConfiguration Captcha = new CaptchaConfiguration();
[JsonPropertyName("twoFactor")] public TwoFactorConfiguration TwoFactor = new TwoFactorConfiguration();
[JsonPropertyName("autoUpdate")] public bool AutoUpdate = true;
[JsonPropertyName("requestSignature")] public string RequestSignature; // = crypto.randomBytes(32).toString("base64");
[JsonPropertyName("jwtSecret")] public string? JwtSecret = null;
[JsonPropertyName("forwardedFor")] public string? ForwardedFor = null;
[JsonPropertyName("trustedProxies")] public string TrustedProxies = null;
[JsonPropertyName("abuseIpDbApiKey")] public string? AbuseIpDbApiKey = null;
[JsonPropertyName("abuseipdbBlacklistRatelimit")] public int AbuseipdbBlacklistRatelimit = 5;
[JsonPropertyName("abuseipdbConfidenceScoreTreshold")] public int AbuseipdbConfidenceScoreTreshold = 50;
[JsonPropertyName("ipdataApiKey")] public string? IpdataApiKey = null;
[JsonPropertyName("mfaBackupCodeCount")] public int MfaBackupCodeCount = 10;
[JsonPropertyName("statsWorldReadable")] public bool StatsWorldReadable = true;
[JsonPropertyName("defaultRegistrationTokenExpiration")] public int DefaultRegistrationTokenExpiration = 1000 * 60 * 60 * 24 * 7;
[JsonPropertyName("cdnSignUrls")] public bool CdnSignUrls = false;
[JsonPropertyName("cdnSignatureKey")] public string CdnSignatureKey = crypto.randomBytes(32).toString("base64");
[JsonPropertyName("cdnSignatureDuration")] public string CdnSignatureDuration = "24h";
[JsonPropertyName("cdnSignatureIncludeIp")] public bool CdnSignatureIncludeIp = true;
[JsonPropertyName("cdnSignatureIncludeUserAgent")] public bool CdnSignatureIncludeUserAgent = true;
}
@@ -0,0 +1,106 @@
using System.Text.Json.Serialization;
namespace Spacebar.ConfigModel;
public class ServerConfiguration {
[JsonPropertyName("admin")] public EndpointConfiguration Admin = new EndpointConfiguration();
[JsonPropertyName("gateway")] public EndpointConfiguration Gateway = new EndpointConfiguration();
[JsonPropertyName("cdn")] public CdnConfiguration Cdn = new CdnConfiguration();
[JsonPropertyName("api")] public ApiConfiguration Api = new ApiConfiguration();
[JsonPropertyName("general")] public GeneralConfiguration General = new GeneralConfiguration();
[JsonPropertyName("limits")] public LimitsConfiguration Limits = new LimitsConfiguration();
[JsonPropertyName("security")] public SecurityConfiguration Security = new SecurityConfiguration();
[JsonPropertyName("login")] public LoginConfiguration Login = new LoginConfiguration();
[JsonPropertyName("register")] public RegisterConfiguration Register = new RegisterConfiguration();
[JsonPropertyName("regions")] public RegionConfiguration Regions = new RegionConfiguration();
[JsonPropertyName("guild")] public GuildConfiguration Guild = new GuildConfiguration();
[JsonPropertyName("gif")] public GifConfiguration Gif = new GifConfiguration();
[JsonPropertyName("rabbitmq")] public RabbitMQConfiguration Rabbitmq = new RabbitMQConfiguration();
[JsonPropertyName("kafka")] public KafkaConfiguration Kafka = new KafkaConfiguration();
[JsonPropertyName("templates")] public TemplateConfiguration Templates = new TemplateConfiguration();
[JsonPropertyName("metrics")] public MetricsConfiguration Metrics = new MetricsConfiguration();
[JsonPropertyName("defaults")] public DefaultsConfiguration Defaults = new DefaultsConfiguration();
[JsonPropertyName("external")] public ExternalTokensConfiguration External = new ExternalTokensConfiguration();
[JsonPropertyName("email")] public EmailConfiguration Email = new EmailConfiguration();
[JsonPropertyName("passwordReset")] public PasswordResetConfiguration PasswordReset = new PasswordResetConfiguration();
[JsonPropertyName("user")] public UserConfiguration User = new UserConfiguration();
}
public class GeneralConfiguration {
[JsonPropertyName("instanceName")] public string InstanceName = "Spacebar Instance";
[JsonPropertyName("instanceDescription")]
public string? InstanceDescription = "This is a Spacebar instance made in the pre-release days";
[JsonPropertyName("frontPage")] public string? FrontPage = null;
[JsonPropertyName("tosPage")] public string? TosPage = null;
[JsonPropertyName("correspondenceEmail")]
public string? CorrespondenceEmail = null;
[JsonPropertyName("correspondenceUserID")]
public string? CorrespondenceUserId = null;
[JsonPropertyName("image")] public string? Image = null;
[JsonPropertyName("instanceId")] public string InstanceId = Snowflake.generate();
[JsonPropertyName("autoCreateBotUsers")]
public bool AutoCreateBotUsers = false;
}
public class EndpointConfiguration {
[JsonPropertyName("endpointPrivate")]
public string? EndpointPrivate { get; set; }
[JsonPropertyName("endpointPublic")]
public string? EndpointPublic { get; set; }
}
public class ApiConfiguration : EndpointConfiguration {
[JsonPropertyName("activeVersions")]
public List<string> ActiveVersions { get; set; } = null!;
[JsonPropertyName("defaultVersion")]
public string DefaultVersion { get; set; } = null!;
}
public class CdnConfiguration : EndpointConfiguration {
[JsonPropertyName("resizeHeightMax")] public int ResizeHeightMax = 1000;
[JsonPropertyName("resizeWidthMax")] public int ResizeWidthMax = 1000;
[JsonPropertyName("imagorServerUrl")] public string? ImagorServerUrl = null;
[JsonPropertyName("proxyCacheHeaderSeconds")]
public int ProxyCacheHeaderSeconds = 60 * 60 * 24;
[JsonPropertyName("maxAttachmentSize")]
public int MaxAttachmentSize = 25 * 1024 * 1024; // 25 MB
// limits: CdnLimitsConfiguration = new CdnLimitsConfiguration();
}
public class CdnLimitsConfiguration {
// ordered by route register order in CDN...
[JsonPropertyName("icon")] public CdnImageLimitsConfiguration Icon = new CdnImageLimitsConfiguration();
[JsonPropertyName("roleIcon")] public CdnImageLimitsConfiguration RoleIcon = new CdnImageLimitsConfiguration();
[JsonPropertyName("emoji")] public CdnImageLimitsConfiguration Emoji = new CdnImageLimitsConfiguration();
[JsonPropertyName("sticker")] public CdnImageLimitsConfiguration Sticker = new CdnImageLimitsConfiguration();
[JsonPropertyName("banner")] public CdnImageLimitsConfiguration Banner = new CdnImageLimitsConfiguration();
[JsonPropertyName("splash")] public CdnImageLimitsConfiguration Splash = new CdnImageLimitsConfiguration();
[JsonPropertyName("avatar")] public CdnImageLimitsConfiguration Avatar = new CdnImageLimitsConfiguration();
[JsonPropertyName("discoverySplash")] public CdnImageLimitsConfiguration DiscoverySplash = new CdnImageLimitsConfiguration();
[JsonPropertyName("appIcon")] public CdnImageLimitsConfiguration AppIcon = new CdnImageLimitsConfiguration();
[JsonPropertyName("discoverSplash")] public CdnImageLimitsConfiguration DiscoverSplash = new CdnImageLimitsConfiguration(); //what even is this?
[JsonPropertyName("teamIcon")] public CdnImageLimitsConfiguration TeamIcon = new CdnImageLimitsConfiguration();
[JsonPropertyName("channelIcon")] public CdnImageLimitsConfiguration ChannelIcon = new CdnImageLimitsConfiguration(); // is this even used?
[JsonPropertyName("guildAvatar")] public CdnImageLimitsConfiguration GuildAvatar = new CdnImageLimitsConfiguration();
}
public class CdnImageLimitsConfiguration {
[JsonPropertyName("maxHeight")] public int MaxHeight = 8192;
[JsonPropertyName("maxWidth")] public int MaxWidth = 8192;
[JsonPropertyName("maxSize")] public int MaxSize = 10 * 1024 * 1024; // 10 MB
// "always" | "never" | "premium"
[JsonPropertyName("allowAnimated")] public string AllowAnimated = "always";
}
@@ -0,0 +1,26 @@
@page "/ServerConfig"
@inject Config Config
@using System.Net.Http.Headers
@using System.Text.Json
@using Spacebar.AdminApi.TestClient.Services
@using Spacebar.ConfigModel.Extensions
<h3>Server Config</h3>
@if (CurrentServerConfig is null) {
<p>Loading server config...</p>
} else {
<pre>@JsonSerializer.Serialize(CurrentServerConfig, new JsonSerializerOptions { WriteIndented = true })</pre>
}
@code {
private Spacebar.ConfigModel.ServerConfiguration? CurrentServerConfig { get; set; } = new();
protected override async Task OnInitializedAsync() {
var hc = new StreamingHttpClient();
hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Config.AccessToken);
var cfgKv = await hc.GetFromJsonAsync<Dictionary<string, string?>>($"{Config.AdminUrl}/_spacebar/admin/config");
var cfg = cfgKv.ToNestedJsonObject();
CurrentServerConfig = cfg.Deserialize<Spacebar.ConfigModel.ServerConfiguration>();
}
}