diff --git a/extra/admin-api/ConfigTest/ConfigTest.csproj b/extra/admin-api/ConfigTest/ConfigTest.csproj deleted file mode 100644 index 7eea9a8..0000000 --- a/extra/admin-api/ConfigTest/ConfigTest.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - net10.0 - enable - enable - dotnet-ConfigTest-18d89c0e-df5d-447b-8429-7d526a35ab13 - - - - - - - - - - - - - diff --git a/extra/admin-api/ConfigTest/Program.cs b/extra/admin-api/ConfigTest/Program.cs deleted file mode 100644 index 5945bcf..0000000 --- a/extra/admin-api/ConfigTest/Program.cs +++ /dev/null @@ -1,14 +0,0 @@ -using ConfigTest; -using Microsoft.EntityFrameworkCore; -using Spacebar.Db.Contexts; - -var builder = Host.CreateApplicationBuilder(args); -builder.Services.AddHostedService(); -builder.Services.AddDbContext(options => { - options - .UseNpgsql(builder.Configuration.GetConnectionString("Spacebar")) - .EnableDetailedErrors(); -}, ServiceLifetime.Singleton); - -var host = builder.Build(); -host.Run(); diff --git a/extra/admin-api/ConfigTest/Properties/launchSettings.json b/extra/admin-api/ConfigTest/Properties/launchSettings.json deleted file mode 100644 index c355f36..0000000 --- a/extra/admin-api/ConfigTest/Properties/launchSettings.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "ConfigTest": { - "commandName": "Project", - "dotnetRunMessages": true, - "environmentVariables": { - "DOTNET_ENVIRONMENT": "Development" - } - } - } -} diff --git a/extra/admin-api/ConfigTest/Worker.cs b/extra/admin-api/ConfigTest/Worker.cs deleted file mode 100644 index dd3ef77..0000000 --- a/extra/admin-api/ConfigTest/Worker.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Text.Json.Nodes; -using Spacebar.ConfigModel.Extensions; -using Spacebar.Db.Contexts; - -namespace ConfigTest; - -public class Worker(ILogger logger, SpacebarDbContext db) : BackgroundService -{ - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - var config = db.Configs - .OrderBy(x => x.Key) - .ToDictionary(x => x.Key, x => x.Value); - foreach (var (key, value) in config) - { - Console.WriteLine("Config Key: {0}, Value: {1}", key, value ?? "[NULL]"); - } - - var readConfig = config.ToNestedJsonObject(); - Console.WriteLine(readConfig); - var mapped = readConfig.ToFlatKv(); - foreach (var (key, value) in mapped) - { - Console.WriteLine("Mapped Key: {0}, Value: {1}", key, value ?? "[NULL]"); - } - - // check that they're equal - foreach (var (key, value) in config) - { - if (!mapped.ContainsKey(key)) - { - Console.WriteLine("Missing Key in Mapped: {0}", key); - continue; - } - - if (mapped[key] != value) - { - Console.WriteLine("Value Mismatch for Key: {0}, Original: {1}, Mapped: {2}", key, value ?? "[NULL]", mapped[key] ?? "[NULL]"); - } - } - Environment.Exit(0); - } -} \ No newline at end of file diff --git a/extra/admin-api/ConfigTest/appsettings.Development.json b/extra/admin-api/ConfigTest/appsettings.Development.json deleted file mode 100644 index 0324577..0000000 --- a/extra/admin-api/ConfigTest/appsettings.Development.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Trace", //Warning - "Microsoft.AspNetCore.Mvc": "Warning", //Warning - "Microsoft.AspNetCore.HostFiltering": "Warning", //Warning - "Microsoft.AspNetCore.Cors": "Warning", //Warning - // "Microsoft.EntityFrameworkCore": "Warning" - "Microsoft.EntityFrameworkCore.Database.Command": "Debug" - } - }, - "ConnectionStrings": { - "Spacebar": "Host=127.0.0.1; Username=postgres; Database=spacebar; Port=5432; Include Error Detail=true; Maximum Pool Size=1000; Command Timeout=6000; Timeout=600;", - }, - "RabbitMQ": { - "Host": "127.0.0.1", - "Port": 5673, - "Username": "guest", - "Password": "guest" - }, - "SpacebarAdminApi": { - "Enforce2FA": true, - "OverrideUid": null, - "DisableAuthentication": false - } -} diff --git a/extra/admin-api/ConfigTest/appsettings.json b/extra/admin-api/ConfigTest/appsettings.json deleted file mode 100644 index 10f68b8..0000000 --- a/extra/admin-api/ConfigTest/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/extra/admin-api/DiscordEmojiConverter/DiscordEmojiConverter.csproj b/extra/admin-api/DiscordEmojiConverter/DiscordEmojiConverter.csproj deleted file mode 100644 index 72d306b..0000000 --- a/extra/admin-api/DiscordEmojiConverter/DiscordEmojiConverter.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - diff --git a/extra/admin-api/DiscordEmojiConverter/DiscordEmojiJson.cs b/extra/admin-api/DiscordEmojiConverter/DiscordEmojiJson.cs deleted file mode 100644 index 71c4a53..0000000 --- a/extra/admin-api/DiscordEmojiConverter/DiscordEmojiJson.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Text.Json.Serialization; - -namespace DiscordEmojiConverter; - -public class DiscordEmojiJson { - [JsonPropertyName("emojis")] - public List? Emojis { get; set; } - - [JsonPropertyName("emojisByCategory")] - public Dictionary>? EmojisByCategory { get; set; } - - [JsonPropertyName("nameToEmoji")] - public Dictionary? NameToEmoji { get; set; } - - [JsonPropertyName("surrogateToEmoji")] - public Dictionary? SurrogateToEmoji { get; set; } - - [JsonPropertyName("numDiversitySprites")] - public int? NumDiversitySprites { get; set; } - - [JsonPropertyName("numNonDiversitySprites")] - public int? NumNonDiversitySprites { get; set; } -} - -public class DiscordEmoji { - [JsonPropertyName("names")] - public List? 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? DiversityChildren { get; set; } - - [JsonPropertyName("diversity")] - public List? Diversity { get; set; } -} \ No newline at end of file diff --git a/extra/admin-api/DiscordEmojiConverter/Program.cs b/extra/admin-api/DiscordEmojiConverter/Program.cs deleted file mode 100644 index 9659395..0000000 --- a/extra/admin-api/DiscordEmojiConverter/Program.cs +++ /dev/null @@ -1,27 +0,0 @@ -// 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(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)); \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/ApplicationModel.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/ApplicationModel.cs new file mode 100644 index 0000000..5428579 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/ApplicationModel.cs @@ -0,0 +1,33 @@ +namespace Spacebar.Models.AdminApi; + +public class ApplicationModel { + public string Id { get; set; } = null!; + public string Name { get; set; } = null!; + public string? Icon { get; set; } + public string? Description { get; set; } + public string? Summary { get; set; } + public string? Type { get; set; } + public bool Hook { get; set; } + public bool BotPublic { get; set; } + public bool BotRequireCodeGrant { get; set; } + public int Flags { get; set; } + public string? RedirectUris { get; set; } + public int? RpcApplicationState { get; set; } + public int? StoreApplicationState { get; set; } + public int? VerificationState { get; set; } + public string? InteractionsEndpointUrl { get; set; } + public bool? IntegrationPublic { get; set; } + public bool? IntegrationRequireCodeGrant { get; set; } + public int? DiscoverabilityState { get; set; } + public int? DiscoveryEligibilityFlags { get; set; } + public string? Tags { get; set; } + public string? CoverImage { get; set; } + public string? InstallParams { get; set; } + public string? TermsOfServiceUrl { get; set; } + public string? PrivacyPolicyUrl { get; set; } + public string? GuildId { get; set; } + public string? CustomInstallUrl { get; set; } + public string? OwnerId { get; set; } + public string? BotUserId { get; set; } + public string? TeamId { get; set; } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/AsyncActionResult.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/AsyncActionResult.cs new file mode 100644 index 0000000..c306b95 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/AsyncActionResult.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.Models.AdminApi; + +public class AsyncActionResult { + public AsyncActionResult() { } + + public AsyncActionResult(string type, object? data) { + MessageType = type; + Data = data; + } + + [JsonPropertyName("type")] + public string MessageType { get; set; } + + [JsonPropertyName("data")] + public object Data { get; set; } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/FileMetadataModel.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/FileMetadataModel.cs new file mode 100644 index 0000000..56c5eaf --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/FileMetadataModel.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.Models.AdminApi; + +public class FileMetadataModel { + public string UserId { get; set; } = null!; + public string Id { get; set; } = null!; + + [JsonConverter(typeof(JsonStringEnumConverter))] + public FileUploadType Type { get; set; } + + + public enum FileUploadType { + Attachment, + Avatar, + Banner, + GuildIcon, + GuildSplash, + GuildCover, + Emoji, + Sticker + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/ForceJoinRequest.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/ForceJoinRequest.cs new file mode 100644 index 0000000..495e517 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/ForceJoinRequest.cs @@ -0,0 +1,7 @@ +namespace Spacebar.Models.AdminApi; + +public class ForceJoinRequest { + public string? UserId { get; set; } = null!; + public bool MakeAdmin { get; set; } = false; + public bool MakeOwner { get; set; } = false; +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/GuildModel.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/GuildModel.cs new file mode 100644 index 0000000..ae516f1 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/GuildModel.cs @@ -0,0 +1,53 @@ +namespace Spacebar.Models.AdminApi; + +public class GuildModel { + public string Id { get; set; } = null!; + public string? AfkChannelId { get; set; } + public int? AfkTimeout { get; set; } + public string? Banner { get; set; } + public int? DefaultMessageNotifications { get; set; } + public string? Description { get; set; } + public string? DiscoverySplash { get; set; } + public int? ExplicitContentFilter { get; set; } + public string Features { get; set; } = null!; + public string? PrimaryCategoryId { get; set; } + public string? Icon { get; set; } + public bool Large { get; set; } + public int? MaxMembers { get; set; } + public int? MaxPresences { get; set; } + public int? MaxVideoChannelUsers { get; set; } + public int? MemberCount { get; set; } + public int? PresenceCount { get; set; } + public string? TemplateId { get; set; } + public int? MfaLevel { get; set; } + public string Name { get; set; } = null!; + public string? OwnerId { get; set; } + public string? PreferredLocale { get; set; } + public int? PremiumSubscriptionCount { get; set; } + public int PremiumTier { get; set; } + public string? PublicUpdatesChannelId { get; set; } + public string? RulesChannelId { get; set; } + public string? Region { get; set; } + public string? Splash { get; set; } + public string? SystemChannelId { get; set; } + public int? SystemChannelFlags { get; set; } + public bool Unavailable { get; set; } + public int? VerificationLevel { get; set; } + public string WelcomeScreen { get; set; } = null!; + public string? WidgetChannelId { get; set; } + public bool WidgetEnabled { get; set; } + public int? NsfwLevel { get; set; } + public bool Nsfw { get; set; } + public string? Parent { get; set; } + public bool? PremiumProgressBarEnabled { get; set; } + public string ChannelOrdering { get; set; } = null!; + + public int ChannelCount { get; set; } + public int RoleCount { get; set; } + public int EmojiCount { get; set; } + public int StickerCount { get; set; } + public int InviteCount { get; set; } + public int MessageCount { get; set; } + public int BanCount { get; set; } + public int VoiceStateCount { get; set; } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/Rights.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/Rights.cs new file mode 100644 index 0000000..62785f5 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/Rights.cs @@ -0,0 +1,81 @@ +using System.Diagnostics.CodeAnalysis; + +namespace Spacebar.Models.AdminApi; + +public static class SpacebarRights { + [Flags] + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum Rights : ulong { + OPERATOR = 1ul << 0, // has all rights + MANAGE_APPLICATIONS = 1ul << 1, + MANAGE_GUILDS = 1ul << 2, // Manage all guilds instance-wide + MANAGE_MESSAGES = 1ul << 3, // Can't see other messages but delete/edit them in channels that they can see + MANAGE_RATE_LIMITS = 1ul << 4, + MANAGE_ROUTING = 1ul << 5, // can create custom message routes to any channel/guild + MANAGE_TICKETS = 1ul << 6, // can respond to and resolve support tickets + MANAGE_USERS = 1ul << 7, + ADD_MEMBERS = 1ul << 8, // can manually add any members in their guilds + BYPASS_RATE_LIMITS = 1ul << 9, + CREATE_APPLICATIONS = 1ul << 10, + CREATE_CHANNELS = 1ul << 11, // can create guild channels or threads in the guilds that they have permission + CREATE_DMS = 1ul << 12, + CREATE_DM_GROUPS = 1ul << 13, // can create group DMs or custom orphan channels + CREATE_GUILDS = 1ul << 14, + CREATE_INVITES = 1ul << 15, // can create mass invites in the guilds that they have CREATE_INSTANT_INVITE + CREATE_ROLES = 1ul << 16, + CREATE_TEMPLATES = 1ul << 17, + CREATE_WEBHOOKS = 1ul << 18, + JOIN_GUILDS = 1ul << 19, + PIN_MESSAGES = 1ul << 20, + SELF_ADD_REACTIONS = 1ul << 21, + SELF_DELETE_MESSAGES = 1ul << 22, + SELF_EDIT_MESSAGES = 1ul << 23, + SELF_EDIT_NAME = 1ul << 24, + SEND_MESSAGES = 1ul << 25, + USE_ACTIVITIES = 1ul << 26, // use (game) activities in voice channels (e.g. Watch together) + USE_VIDEO = 1ul << 27, + USE_VOICE = 1ul << 28, + INVITE_USERS = 1ul << 29, // can create user-specific invites in the guilds that they have INVITE_USERS + SELF_DELETE_DISABLE = 1ul << 30, // can disable/delete own account + DEBTABLE = 1ul << 31, // can use pay-to-use features + CREDITABLE = 1ul << 32, // can receive money from monetisation related features + KICK_BAN_MEMBERS = 1ul << 33, + + // can kick or ban guild or group DM members in the guilds/groups that they have KICK_MEMBERS, or BAN_MEMBERS + SELF_LEAVE_GROUPS = 1ul << 34, + + // can leave the guilds or group DMs that they joined on their own (one can always leave a guild or group DMs they have been force-added) + PRESENCE = 1ul << 35, + + // inverts the presence confidentiality default (OPERATOR's presence is not routed by default, others' are) for a given user + SELF_ADD_DISCOVERABLE = 1ul << 36, // can mark discoverable guilds that they have permissions to mark as discoverable + MANAGE_GUILD_DIRECTORY = 1ul << 37, // can change anything in the primary guild directory + POGGERS = 1ul << 38, // can send confetti, screenshake, random user mention (@someone) + USE_ACHIEVEMENTS = 1ul << 39, // can use achievements and cheers + INITIATE_INTERACTIONS = 1ul << 40, // can initiate interactions + RESPOND_TO_INTERACTIONS = 1ul << 41, // can respond to interactions + SEND_BACKDATED_EVENTS = 1ul << 42, // can send backdated events + USE_MASS_INVITES = 1ul << 43, // added per @xnacly's request - can accept mass invites + ACCEPT_INVITES = 1ul << 44, // added per @xnacly's request - can accept user-specific invites and DM requests + SELF_EDIT_FLAGS = 1ul << 45, // can modify own flags + EDIT_FLAGS = 1ul << 46, // can set others' flags + MANAGE_GROUPS = 1ul << 47, // can manage others' groups + VIEW_SERVER_STATS = 1ul << 48, // added per @chrischrome's request - can view server stats + RESEND_VERIFICATION_EMAIL = 1ul << 49, // can resend verification emails (/auth/verify/resend) + CREATE_REGISTRATION_TOKENS = 1ul << 50, // can create registration tokens (/auth/generate-registration-tokens) + } + + public static bool HasAllRights(this Rights val, Rights rights) { + if (val.HasFlag(Rights.OPERATOR)) { + return true; + } + + return (val & rights) == rights; + } + + public static void AssertHasAllRights(this Rights val, Rights rights) { + if (!val.HasAllRights(rights)) { + throw new UnauthorizedAccessException("Insufficient rights: missing " + rights); + } + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/Spacebar.Models.AdminApi.csproj b/extra/admin-api/Models/Spacebar.Models.AdminApi/Spacebar.Models.AdminApi.csproj new file mode 100644 index 0000000..d25bf93 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/Spacebar.Models.AdminApi.csproj @@ -0,0 +1,10 @@ + + + + net10.0 + preview + enable + enable + + + diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/StickerModel.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/StickerModel.cs new file mode 100644 index 0000000..0ad81b8 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/StickerModel.cs @@ -0,0 +1,19 @@ +namespace Spacebar.Models.AdminApi; + +public class StickerModel { + public string Id { get; set; } = null!; + public string Name { get; set; } = null!; + public string? Description { get; set; } + public bool? Available { get; set; } + public string? Tags { get; set; } + public string? PackId { get; set; } + public string? GuildId { get; set; } + public string? UserId { get; set; } + public int Type { get; set; } + public int FormatType { get; set; } + // public virtual Guild? Guild { get; set; } + // public virtual StickerPack? Pack { get; set; } + // public virtual ICollection StickerPacks { get; set; } = new List(); + // public virtual User? User { get; set; } + // public virtual ICollection Messages { get; set; } = new List(); +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.AdminApi/UserModel.cs b/extra/admin-api/Models/Spacebar.Models.AdminApi/UserModel.cs new file mode 100644 index 0000000..dd1d483 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.AdminApi/UserModel.cs @@ -0,0 +1,66 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.Models.AdminApi; + +public class UserModel { + public string Id { get; set; } = null!; + public string Username { get; set; } = null!; + public string Discriminator { get; set; } = null!; + public string? Avatar { get; set; } + public int? AccentColor { get; set; } + public string? Banner { get; set; } + public string? ThemeColors { get; set; } + public string? Pronouns { get; set; } + public string? Phone { get; set; } + public bool Desktop { get; set; } + public bool Mobile { get; set; } + public bool Premium { get; set; } + public int PremiumType { get; set; } + public bool Bot { get; set; } + public string Bio { get; set; } = null!; + public bool System { get; set; } + public bool NsfwAllowed { get; set; } + public bool MfaEnabled { get; set; } + public bool WebauthnEnabled { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime? PremiumSince { get; set; } + public bool Verified { get; set; } + public bool Disabled { get; set; } + public bool Deleted { get; set; } + public string? Email { get; set; } + + [JsonNumberHandling(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString)] + public ulong Flags { get; set; } + + [JsonNumberHandling(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString)] + public ulong PublicFlags { get; set; } + + [JsonNumberHandling(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString)] + public ulong Rights { get; set; } + + public ApplicationModel? ApplicationBotUser { get; set; } + public List ConnectedAccounts { get; set; } = new(); + public int GuildCount { get; set; } + public int OwnedGuildCount { get; set; } + public int SessionCount { get; set; } + public int TemplateCount { get; set; } + public int VoiceStateCount { get; set; } + public int MessageCount { get; set; } + + public class ConnectedAccountModel { + public string Id { get; set; } = null!; + public string ExternalId { get; set; } = null!; + public string? UserId { get; set; } + public bool FriendSync { get; set; } + public string Name { get; set; } = null!; + public bool Revoked { get; set; } + public int ShowActivity { get; set; } + public string Type { get; set; } = null!; + public bool Verified { get; set; } + public int Visibility { get; set; } + public string Integrations { get; set; } = null!; + public string? Metadata { get; set; } + public int MetadataVisibility { get; set; } + public bool TwoWayLink { get; set; } + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/Config.cs b/extra/admin-api/Models/Spacebar.Models.Config/Config.cs new file mode 100644 index 0000000..26e9d0f --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/Config.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; + +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 EndpointConfig { + [JsonPropertyName("endpointPrivate")] + public string? EndpointPrivate { get; set; } + + [JsonPropertyName("endpointPublic")] + public string? EndpointPublic { get; set; } +} + +public class ApiConfig : EndpointConfig { + [JsonPropertyName("activeVersions")] + public List ActiveVersions { get; set; } = null!; + + [JsonPropertyName("defaultVersion")] + public string DefaultVersion { get; set; } = null!; +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/DefaultsConfiguration.cs b/extra/admin-api/Models/Spacebar.Models.Config/DefaultsConfiguration.cs new file mode 100644 index 0000000..3cac4cb --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/DefaultsConfiguration.cs @@ -0,0 +1,37 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.ConfigModel; + +public class DefaultsConfiguration +{ + [JsonPropertyName("guild")] public GuildDefaults Guild = new(); + [JsonPropertyName("user")] public ChannelDefaults Channel = new(); +} + +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; +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/Extensions/JsonExtensions.cs b/extra/admin-api/Models/Spacebar.Models.Config/Extensions/JsonExtensions.cs new file mode 100644 index 0000000..20ae733 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/Extensions/JsonExtensions.cs @@ -0,0 +1,119 @@ +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace Spacebar.ConfigModel.Extensions; + +public static class JsonExtensions +{ + extension(Dictionary kv) + { + public JsonObject ToNestedJsonObject(string path = "$") + { + JsonObject root = new(); + // group by prefix + var groups = kv.GroupBy(kvItem => kvItem.Key.Split('_', 2)[0]); + foreach (var group in groups) + { + var prefix = group.Key; + + if (group.Count() == 1 && !group.First().Key.Contains('_')) + { + root[prefix] = group.First().Value == null ? null : JsonNode.Parse(group.First().Value!); + Console.WriteLine("[CONFIG] Single Key: {0}.{1}, Value: {2}", path, prefix, root[prefix]?.ToJsonString()); + continue; + } + + var nestedValues = group.Where(x => x.Key.Contains('_')).ToDictionary(kvItem => kvItem.Key[(prefix.Length + 1)..], kvItem => kvItem.Value); + + if (nestedValues.All(x => int.TryParse(x.Key.Split('_')[0], out _))) + { + Console.WriteLine("[CONFIG] Array Key Detected: {0}.{1}", path, prefix); + var arr = new JsonArray(); + if (nestedValues.All(x => x.Key.Contains('_'))) + { + var objs = nestedValues.GroupBy(x => x.Key.Split('_', 2)[0]); + foreach (var objGroup in objs.OrderBy(x => int.Parse(x.Key))) + { + var i = objGroup.Key; + var objValues = objGroup.ToDictionary(kvItem => kvItem.Key[(i.Length + 1)..], kvItem => kvItem.Value); + var obj = objValues.ToNestedJsonObject($"{path}.{prefix}[{i}]"); + arr.Add(obj); + Console.WriteLine($" - ${path}.{prefix}[{i}]: {obj.ToJsonString()}"); + } + } + else + foreach (var (i, arrayItem) in nestedValues.OrderBy(x => int.Parse(x.Key))) + { + arr.Add(arrayItem == null ? null : JsonNode.Parse(arrayItem)); + Console.WriteLine($" - {path}.{prefix}[{i}]: {arrayItem}"); + } + + root[prefix] = arr; + } + else + { + root[prefix] = nestedValues.ToNestedJsonObject($"{path}.{prefix}"); + } + } + + return root; + } + } + + extension(JsonObject jo) + { + public Dictionary ToFlatKv(string path = "$") + { + var kv = new Dictionary(); + var jso = new JsonSerializerOptions() + { + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + + foreach (var (key, value) in jo) + { + var currentPath = path == "$" ? key : $"{path}_{key}"; + + switch (value) + { + case JsonObject nestedObj: + var nestedKv = nestedObj.ToFlatKv(currentPath); + foreach (var (nestedKey, nestedValue) in nestedKv) + { + kv[nestedKey] = nestedValue; + } + + break; + case JsonArray arr: + for (int i = 0; i < arr.Count; i++) + { + var item = arr[i]; + var itemPath = $"{currentPath}_{i}"; + switch (item) + { + case JsonObject arrObj: + var arrObjKv = arrObj.ToFlatKv(itemPath); + foreach (var (arrObjKey, arrObjValue) in arrObjKv) + { + kv[arrObjKey] = arrObjValue; + } + + break; + default: + kv[itemPath] = item?.ToJsonString(jso); + break; + } + } + + break; + default: + Console.WriteLine(value?.GetType()); + kv[currentPath] = value?.ToJsonString(jso); + break; + } + } + + return kv; + } + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/GeneralConfiguration.cs b/extra/admin-api/Models/Spacebar.Models.Config/GeneralConfiguration.cs new file mode 100644 index 0000000..1e00675 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/GeneralConfiguration.cs @@ -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; +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/LimitsConfiguration.cs b/extra/admin-api/Models/Spacebar.Models.Config/LimitsConfiguration.cs new file mode 100644 index 0000000..56648bd --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/LimitsConfiguration.cs @@ -0,0 +1,189 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.ConfigModel; + +public class LimitsConfiguration { + [JsonPropertyName("user")] + public UserLimits User { get; set; } = new UserLimits(); + + [JsonPropertyName("guild")] + public GuildLimits Guild { get; set; } = new GuildLimits(); + + [JsonPropertyName("message")] + public MessageLimits Message { get; set; } = new MessageLimits(); + + [JsonPropertyName("channel")] + public ChannelLimits Channel { get; set; } = new ChannelLimits(); + + [JsonPropertyName("rate")] + public RateLimits Rate { get; set; } = new RateLimits(); + + [JsonPropertyName("absoluteRate")] + public GlobalRateLimits AbsoluteRate { get; set; } = new GlobalRateLimits(); +} + +public class GlobalRateLimits { + [JsonPropertyName("register")] + public GlobalRateLimit Register { get; set; } = new() { + Enabled = true, + Count = 25, + Window = 60 * 60 * 1000 + }; + + [JsonPropertyName("sendMessage")] + public GlobalRateLimit SendMessage { get; set; } = new() { + Enabled = true, + Count = 200, + Window = 60 * 1000 + }; + + public class GlobalRateLimit : RateLimits.RateLimitOptions { + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } = true; + } +} + +public class RateLimits { + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } = true; + + [JsonPropertyName("ip")] + public RateLimitOptions Ip { get; set; } = new RateLimitOptions() { + Count = 500, + Window = 5 + }; + + [JsonPropertyName("global")] + public RateLimitOptions Global { get; set; } = new RateLimitOptions() { + Count = 250, + Window = 5 + }; + + [JsonPropertyName("error")] + public RateLimitOptions Error { get; set; } = new RateLimitOptions() { + Count = 50, + Window = 5 + }; + + [JsonPropertyName("routes")] + public RouteRateLimits Routes { get; set; } = new RouteRateLimits(); + + public class RouteRateLimits { + [JsonPropertyName("guild")] + public RateLimitOptions Guild { get; set; } = new RateLimitOptions() { + Count = 5, + Window = 5 + }; + + [JsonPropertyName("webhook")] + public RateLimitOptions Webhook { get; set; } = new RateLimitOptions() { + Count = 10, + Window = 5 + }; + + [JsonPropertyName("channel")] + public RateLimitOptions Channel { get; set; } = new RateLimitOptions() { + Count = 10, + Window = 5 + }; + + [JsonPropertyName("auth")] + public AuthRateLimits Auth { get; set; } = new AuthRateLimits(); + + public class AuthRateLimits { + [JsonPropertyName("login")] + public RateLimitOptions Login { get; set; } = new RateLimitOptions() { + Count = 5, + Window = 60 + }; + + [JsonPropertyName("register")] + public RateLimitOptions Register { get; set; } = new RateLimitOptions() { + Count = 2, + Window = 60 * 60 * 12 + }; + } + } + + public class RateLimitOptions { + [JsonPropertyName("count")] + public int Count { get; set; } + + [JsonPropertyName("window")] + public int Window { get; set; } + + [JsonIgnore] + public TimeSpan WindowTimeSpan => TimeSpan.FromSeconds(Window); + } +} + +public class ChannelLimits { + [JsonPropertyName("maxPins")] + public int MaxPins { get; set; } = 500; + + [JsonPropertyName("maxTopic")] + public int MaxTopic { get; set; } = 1024; + + [JsonPropertyName("maxWebhooks")] + public int MaxWebhooks { get; set; } = 100; +} + +public class MessageLimits { + [JsonPropertyName("maxCharacters")] + public int MaxCharacters { get; set; } = 1048576; + + [JsonPropertyName("maxTTSCharacters")] + public int MaxTTSCharacters { get; set; } = 160; + + [JsonPropertyName("maxReactions")] + public int MaxReactions { get; set; } = 2048; + + [JsonPropertyName("maxAttachmentSize")] + public int MaxAttachmentSize { get; set; } = 1024 * 1024 * 1024; + + [JsonPropertyName("maxBulkDelete")] + public int MaxBulkDelete { get; set; } = 1000; + + [JsonPropertyName("maxEmbedDownloadSize")] + public int MaxEmbedDownloadSize { get; set; } = 1024 * 1024 * 1024; + + [JsonPropertyName("maxPreloadCount")] + public int MaxPreloadCount { get; set; } = 100; +} + +public class GuildLimits { + [JsonPropertyName("maxRoles")] + public int MaxRoles { get; set; } = 1000; + + [JsonPropertyName("maxEmojis")] + public int MaxEmojis { get; set; } = 2000; + + [JsonPropertyName("maxStickers")] + public int MaxStickers { get; set; } = 500; + + [JsonPropertyName("maxMembers")] + public int MaxMembers { get; set; } = 25000000; + + [JsonPropertyName("maxChannels")] + public int MaxChannels { get; set; } = 65535; + + [JsonPropertyName("maxBulkBanUsers")] + public int MaxBulkBanUsers { get; set; } = 200; + + [JsonPropertyName("maxChannelsInCategory")] + public int MaxChannelsInCategory { get; set; } = 65536; +} + +public class UserLimits { + [JsonPropertyName("maxGuilds")] + public int MaxGuilds { get; set; } = 1048576; + + [JsonPropertyName("maxUsername")] + public int MaxUsername { get; set; } = 32; + + [JsonPropertyName("maxFriends")] + public int MaxFriends { get; set; } = 5000; + + [JsonPropertyName("maxBio")] + public int MaxBio { get; set; } = 190; +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/SecurityConfiguration.cs b/extra/admin-api/Models/Spacebar.Models.Config/SecurityConfiguration.cs new file mode 100644 index 0000000..e1592c8 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/SecurityConfiguration.cs @@ -0,0 +1,83 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.ConfigModel; + +public class SecurityConfiguration { + [JsonPropertyName("captcha")] + public CaptchaConfiguration Captcha { get; set; } = new(); + + [JsonPropertyName("twoFactor")] + public TwoFactorConfiguration TwoFactor { get; set; } = new(); + + [JsonPropertyName("autoUpdate")] + public bool AutoUpdate { get; set; } = true; + + [JsonPropertyName("requestSignature")] public string RequestSignature; // {get;set;}=crypto.randomBytes(32).toString("base64"); + + [JsonPropertyName("jwtSecret")] + public string? JwtSecret { get; set; } = null; + + [JsonPropertyName("forwardedFor")] + public string? ForwardedFor { get; set; } = null; + + [JsonPropertyName("trustedProxies")] + public string TrustedProxies { get; set; } = null; + + [JsonPropertyName("abuseIpDbApiKey")] + public string? AbuseIpDbApiKey { get; set; } = null; + + [JsonPropertyName("abuseipdbBlacklistRatelimit")] + public int AbuseipdbBlacklistRatelimit { get; set; } = 5; + + [JsonPropertyName("abuseipdbConfidenceScoreTreshold")] + public int AbuseipdbConfidenceScoreTreshold { get; set; } = 50; + + [JsonPropertyName("ipdataApiKey")] + public string? IpdataApiKey { get; set; } = null; + + [JsonPropertyName("mfaBackupCodeCount")] + public int MfaBackupCodeCount { get; set; } = 10; + + [JsonPropertyName("statsWorldReadable")] + public bool StatsWorldReadable { get; set; } = true; + + [JsonPropertyName("defaultRegistrationTokenExpiration")] + public int DefaultRegistrationTokenExpiration { get; set; } = 1000 * 60 * 60 * 24 * 7; + + [JsonPropertyName("cdnSignUrls")] + public bool CdnSignUrls { get; set; } = false; + + [JsonPropertyName("cdnSignatureKey")] + public string CdnSignatureKey { get; set; } = null!; // crypto.randomBytes(32).toString("base64"); + + [JsonPropertyName("cdnSignatureDuration")] + public string CdnSignatureDuration { get; set; } = "24h"; + + [JsonPropertyName("cdnSignatureIncludeIp")] + public bool CdnSignatureIncludeIp { get; set; } = true; + + [JsonPropertyName("cdnSignatureIncludeUserAgent")] + public bool CdnSignatureIncludeUserAgent { get; set; } = true; +} + +public class CaptchaConfiguration { + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } = false; + + /// + /// One of: null, recaptcha, hcaptcha + /// + [JsonPropertyName("service")] + public string Service { get; set; } = "none"; + + [JsonPropertyName("sitekey")] + public string? SiteKey { get; set; } = null; + + [JsonPropertyName("secret")] + public string? Secret { get; set; } = null; +} + +public class TwoFactorConfiguration { + [JsonPropertyName("generateBackupCodes")] + public bool GenerateBackupCodes { get; set; } = true; +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/ServerConfiguration.cs b/extra/admin-api/Models/Spacebar.Models.Config/ServerConfiguration.cs new file mode 100644 index 0000000..2ea107b --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/ServerConfiguration.cs @@ -0,0 +1,371 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.ConfigModel; + +public class ServerConfiguration { + [JsonPropertyName("admin")] + public EndpointConfiguration Admin { get; set; } = new(); + + [JsonPropertyName("gateway")] + public EndpointConfiguration Gateway { get; set; } = new(); + + [JsonPropertyName("cdn")] + public CdnConfiguration Cdn { get; set; } = new(); + + [JsonPropertyName("api")] + public ApiConfiguration Api { get; set; } = new(); + + [JsonPropertyName("general")] + public GeneralConfiguration General { get; set; } = new(); + + [JsonPropertyName("limits")] + public LimitsConfiguration Limits { get; set; } = new(); + + [JsonPropertyName("security")] + public SecurityConfiguration Security { get; set; } = new(); + + [JsonPropertyName("login")] + public LoginConfiguration Login { get; set; } = new(); + + [JsonPropertyName("register")] + public RegisterConfiguration Register { get; set; } = new RegisterConfiguration(); + + [JsonPropertyName("regions")] + public RegionConfiguration Regions { get; set; } = new(); + + [JsonPropertyName("guild")] + public GuildConfiguration Guild { get; set; } = new(); + + [JsonPropertyName("gif")] + public GifConfiguration Gif { get; set; } = new GifConfiguration(); + + [JsonPropertyName("rabbitmq")] + public RabbitMQConfiguration Rabbitmq { get; set; } = new RabbitMQConfiguration(); + + [JsonPropertyName("templates")] + public TemplateConfiguration Templates { get; set; } = new TemplateConfiguration(); + + [JsonPropertyName("defaults")] + public DefaultsConfiguration Defaults { get; set; } = new(); + + [JsonPropertyName("external")] + public ExternalTokensConfiguration External { get; set; } = new(); + + // TODO: lazy + // [JsonPropertyName("email")] + // public EmailConfiguration Email { get; set; } = new EmailConfiguration(); + + [JsonPropertyName("passwordReset")] + public PasswordResetConfiguration PasswordReset { get; set; } = new PasswordResetConfiguration(); + + [JsonPropertyName("user")] + public UserConfiguration User { get; set; } = new UserConfiguration(); +} + +public class RegisterConfiguration { + [JsonPropertyName("email")] + public RegistrationEmailConfiguration Email { get; set; } = new RegistrationEmailConfiguration(); + + [JsonPropertyName("dateOfBirth")] + public DateOfBirthConfiguration DateOfBirth { get; set; } = new DateOfBirthConfiguration(); + + [JsonPropertyName("password")] + public PasswordConfiguration Password { get; set; } = new PasswordConfiguration(); + + [JsonPropertyName("disabled")] + public bool Disabled { get; set; } = false; + + [JsonPropertyName("requireCaptcha")] + public bool RequireCaptcha { get; set; } = true; + + [JsonPropertyName("requireInvite")] + public bool RequireInvite { get; set; } = false; + + [JsonPropertyName("guestsRequireInvite")] + public bool GuestsRequireInvite { get; set; } = true; + + [JsonPropertyName("allowNewRegistration")] + public bool AllowNewRegistration { get; set; } = true; + + [JsonPropertyName("allowMultipleAccounts")] + public bool AllowMultipleAccounts { get; set; } = true; + + [JsonPropertyName("blockIpDataCoThreatTypes")] + public List BlockIpDataCoThreatTypes { get; set; } = [ + "tor", "icloud_relay", "proxy", "datacenter", "anonymous", "known_attacker", "known_abuser", "threat" + ]; // matching ipdata's threat.is_* fields as of 2025/11/30, minus bogon + + [JsonPropertyName("blockAsnTypes")] + public List BlockAsnTypes { get; set; } = [""]; + + [JsonPropertyName("blockAsns")] + public List BlockAsns { get; set; } = [""]; + + [JsonPropertyName("blockAbuseIpDbAboveScore")] + public int BlockAbuseIpDbAboveScore { get; set; } = 75; // 0 to disable + + [JsonPropertyName("incrementingDiscriminators")] + public bool IncrementingDiscriminators { get; set; } = false; // random otherwise + + [JsonPropertyName("defaultRights")] + public string DefaultRights { get; set; } = "875069521787904"; // See `npm run generate:rights` + + [JsonPropertyName("checkIp")] + public bool CheckIp { get; set; } = true; +} + +public class PasswordConfiguration { + [JsonPropertyName("required")] + public bool Required { get; set; } = true; + + [JsonPropertyName("minLength")] + public int MinLength { get; set; } = 8; + + [JsonPropertyName("minNumbers")] + public int MinNumbers { get; set; } = 2; + + [JsonPropertyName("minUpperCase")] + public int MinUpperCase { get; set; } = 2; + + [JsonPropertyName("minSymbols")] + public int MinSymbols { get; set; } = 0; +} + +public class DateOfBirthConfiguration { + [JsonPropertyName("required")] + public bool Required { get; set; } = true; + + [JsonPropertyName("minimum")] + public int Minimum { get; set; } = 13; +} + +public class RegistrationEmailConfiguration { + [JsonPropertyName("required")] + public bool Required { get; set; } = false; + + [JsonPropertyName("allowlist")] + public bool Allowlist { get; set; } = false; + + [JsonPropertyName("blocklist")] + public bool Blocklist { get; set; } = false; + + [JsonPropertyName("domains")] + public List Domains { get; set; } = []; +} + +public class TemplateConfiguration { + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } = true; + + [JsonPropertyName("allowTemplateCreation")] + public bool AllowTemplateCreation { get; set; } = true; + + [JsonPropertyName("allowDiscordTemplates")] + public bool AllowDiscordTemplates { get; set; } = true; + + [JsonPropertyName("allowRaws")] + public bool AllowRaws { get; set; } = true; +} + +public class PasswordResetConfiguration { + [JsonPropertyName("requireCaptcha")] + public bool RequireCaptcha { get; set; } = false; +} + +public class UserConfiguration { + [JsonPropertyName("blockedContains")] + public List BlockedContains { get; set; } = []; + + [JsonPropertyName("blockedEquals")] + public List BlockedEquals { get; set; } = []; +} + +public class RabbitMQConfiguration { + [JsonPropertyName("host")] + public string? Host { get; set; } = null; +} + +public class GifConfiguration { + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } = true; + + [JsonPropertyName("provider")] + public string Provider { get; set; } = "tenor"; + + [JsonPropertyName("apiKey")] + public string? ApiKey { get; set; } = "LIVDSRZULELA"; +} + +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 ActiveVersions { get; set; } = null!; + + [JsonPropertyName("defaultVersion")] + public string DefaultVersion { get; set; } = null!; +} + +public class CdnConfiguration : EndpointConfiguration { + [JsonPropertyName("resizeHeightMax")] + public int ResizeHeightMax { get; set; } = 1000; + + [JsonPropertyName("resizeWidthMax")] + public int ResizeWidthMax { get; set; } = 1000; + + [JsonPropertyName("imagorServerUrl")] + public string? ImagorServerUrl { get; set; } = null; + + [JsonPropertyName("proxyCacheHeaderSeconds")] + public int ProxyCacheHeaderSeconds { get; set; } = 60 * 60 * 24; + + [JsonPropertyName("maxAttachmentSize")] + public int MaxAttachmentSize { get; set; } = 25 * 1024 * 1024; // 25 MB + + // limits: CdnLimitsConfiguration {get;set;}=new CdnLimitsConfiguration(); +} + +public class CdnLimitsConfiguration { + [JsonPropertyName("icon")] + public CdnImageLimitsConfiguration Icon { get; set; } = new(); + + [JsonPropertyName("roleIcon")] + public CdnImageLimitsConfiguration RoleIcon { get; set; } = new(); + + [JsonPropertyName("emoji")] + public CdnImageLimitsConfiguration Emoji { get; set; } = new(); + + [JsonPropertyName("sticker")] + public CdnImageLimitsConfiguration Sticker { get; set; } = new(); + + [JsonPropertyName("banner")] + public CdnImageLimitsConfiguration Banner { get; set; } = new(); + + [JsonPropertyName("splash")] + public CdnImageLimitsConfiguration Splash { get; set; } = new(); + + [JsonPropertyName("avatar")] + public CdnImageLimitsConfiguration Avatar { get; set; } = new(); + + [JsonPropertyName("discoverySplash")] + public CdnImageLimitsConfiguration DiscoverySplash { get; set; } = new(); + + [JsonPropertyName("appIcon")] + public CdnImageLimitsConfiguration AppIcon { get; set; } = new(); + + [JsonPropertyName("discoverSplash")] + public CdnImageLimitsConfiguration DiscoverSplash { get; set; } = new(); //what even is this? + + [JsonPropertyName("teamIcon")] + public CdnImageLimitsConfiguration TeamIcon { get; set; } = new(); + + [JsonPropertyName("channelIcon")] + public CdnImageLimitsConfiguration ChannelIcon { get; set; } = new(); // is this even used? + + [JsonPropertyName("guildAvatar")] + public CdnImageLimitsConfiguration GuildAvatar { get; set; } = new(); +} + +public class CdnImageLimitsConfiguration { + [JsonPropertyName("maxHeight")] + public int MaxHeight { get; set; } = 8192; + + [JsonPropertyName("maxWidth")] + public int MaxWidth { get; set; } = 8192; + + [JsonPropertyName("maxSize")] + public int MaxSize { get; set; } = 10 * 1024 * 1024; // 10 MB + + // "always" | "never" | "premium" + [JsonPropertyName("allowAnimated")] + public string AllowAnimated { get; set; } = "always"; +} + +public class LoginConfiguration { + [JsonPropertyName("requireCaptcha")] + public bool RequireCaptcha { get; set; } = false; + + [JsonPropertyName("requireVerification")] + public bool RequireVerification { get; set; } = false; +} + +public class RegionConfiguration { + [JsonPropertyName("default")] + public string Default { get; set; } = "spacebar-central"; + + [JsonPropertyName("useDefaultAsOptimal")] + public bool UseDefaultAsOptimal { get; set; } = true; + + [JsonPropertyName("available")] + public List Available { get; set; } = []; + + public class Region { + [JsonPropertyName("id")] + public string Id { get; set; } = null!; + + [JsonPropertyName("name")] + public string Name { get; set; } = null!; + + [JsonPropertyName("endpoint")] + public string Endpoint { get; set; } = null!; + + [JsonPropertyName("vip")] + public bool Vip { get; set; } = false; + + [JsonPropertyName("custom")] + public bool Custom { get; set; } = false; + + [JsonPropertyName("deprecated")] + public bool Deprecated { get; set; } = false; + } +} + +public class ExternalTokensConfiguration { + [JsonPropertyName("twitter")] + public string? Twitter { get; set; } = null; +} + +public class GuildConfiguration { + [JsonPropertyName("defaultFeatures")] + public List DefaultFeatures { get; set; } = []; + + [JsonPropertyName("autoJoin")] + public GuildAutoJoinConfiguration AutoJoin { get; set; } = new(); + + [JsonPropertyName("discovery")] + public GuildDiscoveryConfiguration Discovery { get; set; } = new(); + + public class GuildDiscoveryConfiguration { + [JsonPropertyName("showAllGuilds")] + public bool ShowAllGuilds { get; set; } = false; + + [JsonPropertyName("useRecommendation")] + public bool UseRecommendation { get; set; } = false; + + [JsonPropertyName("offset")] + public int Offset { get; set; } = 0; + + [JsonPropertyName("limit")] + public int Limit { get; set; } = 24; + } + + public class GuildAutoJoinConfiguration { + [JsonPropertyName("enabled")] + public bool Enabled { get; set; } = false; + + [JsonPropertyName("guilds")] + public List Guilds { get; set; } = []; + + [JsonPropertyName("canLeave")] + public bool CanLeave { get; set; } = true; + + [JsonPropertyName("bots")] + public bool Bots { get; set; } = false; + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Config/Spacebar.Models.Config.csproj b/extra/admin-api/Models/Spacebar.Models.Config/Spacebar.Models.Config.csproj new file mode 100644 index 0000000..237d661 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Config/Spacebar.Models.Config.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/extra/admin-api/Models/Spacebar.Models.Db/Contexts/SpacebarDbContext.cs b/extra/admin-api/Models/Spacebar.Models.Db/Contexts/SpacebarDbContext.cs new file mode 100644 index 0000000..716079d --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Db/Contexts/SpacebarDbContext.cs @@ -0,0 +1,699 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Spacebar.Models.Db.Models; +using Stream = Spacebar.Models.Db.Models.Stream; + +namespace Spacebar.Models.Db.Contexts; + +public partial class SpacebarDbContext : DbContext +{ + public SpacebarDbContext(DbContextOptions options) + : base(options) + { + } + + public virtual DbSet Applications { get; set; } + + public virtual DbSet ApplicationCommands { get; set; } + + public virtual DbSet Attachments { get; set; } + + public virtual DbSet AuditLogs { get; set; } + + public virtual DbSet AutomodRules { get; set; } + + public virtual DbSet BackupCodes { get; set; } + + public virtual DbSet Badges { get; set; } + + public virtual DbSet Bans { get; set; } + + public virtual DbSet Categories { get; set; } + + public virtual DbSet Channels { get; set; } + + public virtual DbSet ClientReleases { get; set; } + + public virtual DbSet CloudAttachments { get; set; } + + public virtual DbSet Configs { get; set; } + + public virtual DbSet ConnectedAccounts { get; set; } + + public virtual DbSet ConnectionConfigs { get; set; } + + public virtual DbSet EmbedCaches { get; set; } + + public virtual DbSet Emojis { get; set; } + + public virtual DbSet Guilds { get; set; } + + public virtual DbSet InstanceBans { get; set; } + + public virtual DbSet Invites { get; set; } + + public virtual DbSet Members { get; set; } + + public virtual DbSet Messages { get; set; } + + public virtual DbSet Migrations { get; set; } + + public virtual DbSet Notes { get; set; } + + public virtual DbSet RateLimits { get; set; } + + public virtual DbSet ReadStates { get; set; } + + public virtual DbSet Recipients { get; set; } + + public virtual DbSet Relationships { get; set; } + + public virtual DbSet Roles { get; set; } + + public virtual DbSet SecurityKeys { get; set; } + + public virtual DbSet SecuritySettings { get; set; } + + public virtual DbSet Sessions { get; set; } + + public virtual DbSet Stickers { get; set; } + + public virtual DbSet StickerPacks { get; set; } + + public virtual DbSet Streams { get; set; } + + public virtual DbSet StreamSessions { get; set; } + + public virtual DbSet Teams { get; set; } + + public virtual DbSet TeamMembers { get; set; } + + public virtual DbSet