diff --git a/extra/admin-api/Models/Spacebar.Models.Api/LoginRequest.cs b/extra/admin-api/Models/Spacebar.Models.Api/LoginRequest.cs new file mode 100644 index 000000000..6971d55e2 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Api/LoginRequest.cs @@ -0,0 +1,79 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.Models.Api; + +public class LoginRequest { + [JsonPropertyName("login")] + public required string Login { get; set; } + + [JsonPropertyName("password")] + public required string Password { get; set; } + + /// + /// Whether to un-delete a self-disabled or self-deleted account + /// + [JsonPropertyName("undelete")] + public bool? Undelete { get; set; } + + /// + /// One of gift, guild_template, guild_invite, dm_invite, friend_invite, role_subscription or role_subscription_setting + /// + [JsonPropertyName("login_source")] + public string? LoginSource { get; set; } + + [JsonPropertyName("gift_code_sku_id")] + public string? GiftCodeSkuId { get; set; } +} + +/// +/// Note: nullable fields missing "if the login was not completed" +/// +public class LoginResponse { + [JsonPropertyName("user_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public ulong UserId { get; set; } + + [JsonPropertyName("token")] + public string? Token { get; set; } + + [JsonPropertyName("user_settings")] + public LoginUserSettings? UserSettings { get; set; } + + /// + /// Values: update_password + /// + [JsonPropertyName("required_actions")] + public List? RequiredActions { get; set; } + + /// + /// MFA ticket + /// + [JsonPropertyName("ticket")] + public string? Ticket { get; set; } + + [JsonPropertyName("login_instance_id")] + public string? LoginInstanceId { get; set; } + + [JsonPropertyName("mfa")] + public bool? Mfa { get; set; } + + [JsonPropertyName("totp")] + public bool? Totp { get; set; } + + [JsonPropertyName("sms")] + public bool? Sms { get; set; } + + [JsonPropertyName("backup")] + public bool? Backup { get; set; } + + [JsonPropertyName("webauthn")] + public string? Webauthn { get; set; } + + + public class LoginUserSettings { + [JsonPropertyName("locale")] + public string Locale { get; set; } + + [JsonPropertyName("theme")] + public string Theme { get; set; } + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Api/Spacebar.Models.Api.csproj b/extra/admin-api/Models/Spacebar.Models.Api/Spacebar.Models.Api.csproj new file mode 100644 index 000000000..237d66167 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Api/Spacebar.Models.Api.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/extra/admin-api/Models/Spacebar.Models.Api/SpacebarApiError.cs b/extra/admin-api/Models/Spacebar.Models.Api/SpacebarApiError.cs new file mode 100644 index 000000000..03bf9264c --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Api/SpacebarApiError.cs @@ -0,0 +1,29 @@ +using System.Text.Json.Nodes; + +namespace Spacebar.Models.Api; + +public class SpacebarApiException : Exception { + public int Code { get; set; } + public string? Request { get; set; } // Spacebar extension + // public Dictionary Errors { get; set; } + public JsonObject? Errors { get; set; } + + public class FieldErrorList { + // public + } + + public SpacebarApiException(string? message) : base(message) { + + } + + // TODO: abstract out to HTTP layer + public static SpacebarApiException FromJson(JsonObject resp) { + var ex = new SpacebarApiException(resp["message"]!.GetValue()) { + Code = resp["code"]!.GetValue(), + Request = resp["request"]?.GetValue(), + Errors = resp["errors"]?.AsObject() + }; + + return ex; + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Gateway/GatewayPayload.cs b/extra/admin-api/Models/Spacebar.Models.Gateway/GatewayPayload.cs new file mode 100644 index 000000000..1a5d2c864 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Gateway/GatewayPayload.cs @@ -0,0 +1,83 @@ +using System.Diagnostics; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.Json.Serialization; + +namespace Spacebar.Models.Gateway; + +public class GatewayPayload { + [JsonPropertyName("op")] + public GatewayOpcode Opcode { get; set; } + + [JsonPropertyName("d")] + public JsonObject? EventData { get; set; } + + [JsonPropertyName("s")] + public int? Sequence { get; set; } + + [JsonPropertyName("t")] + public string? DispatchEventType { get; set; } + + public T? GetData() where T : class { + if (EventData is null) return null; + var sw = Stopwatch.StartNew(); + var jso = new JsonSerializerOptions(); + if (typeof(T) == typeof(ReadyResponse)) { + Console.WriteLine("Adding ReadyResponse sourcegen"); + jso.TypeInfoResolver = new ReadyResponseSerializerContext(); + } + else + Console.WriteLine($"No TypeInfoResolver for {typeof(T).FullName}"); + + var deserialized = EventData.Deserialize(jso); + Console.WriteLine($"Deserialized {typeof(T).FullName} in {sw.Elapsed}"); + return deserialized; + } +} + +public enum GatewayOpcode { + S2CDispatch, + Heartbeat, + C2SIdentify, + C2SPresenceUpdate, + C2SVoiceStateUpdate, + C2SVoiceServerPing, + C2SResume, + S2CReconnect, + C2SRequestGuildMembers, + S2CInvalidSession, + S2CHello, + S2CHeartbeatAck, + C2SGuildSync, + C2SCallConnect, + C2SGuildSubscriptions, + C2SLobbyConnect, + C2SLobbyDisconnect, + C2SLobbyVoiceStates, + C2SStreamCreate, + C2SStreamDelete, + C2SStreamWatch, + C2SStreamPing, + C2SStreamSetPaused, + C2SLfgSubscription, + C2SRequestGuildApplicationCommands, + C2SEmbeddedActivityCreate, + C2SEmbeddedActivityDelete, + C2SEmbeddedActivityUpdate, + C2SRequestForumUnreads, + C2SRemoteCommand, + C2SRequestDeletedEntityIds, + C2SRequestSoundboardSounds, + C2SSpeedTestCreate, + C2SSpeedTestDelete, + C2SRequestLastMessages, + C2SSearchRecentMembers, + C2SRequestChannelStatuses, + C2SGuildSubscriptionsBulk, + C2SGuildChannelsResync, + C2SRequestChannelMemberCount, + C2SQoSHeartbeat, + C2SUpdateTimeSpentSessionId, + C2SLobbyVoiceServerPing, + C2SRequestChannelInfo +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Gateway/IdentifyRequest.cs b/extra/admin-api/Models/Spacebar.Models.Gateway/IdentifyRequest.cs index ee39e292c..f94ebecd7 100644 --- a/extra/admin-api/Models/Spacebar.Models.Gateway/IdentifyRequest.cs +++ b/extra/admin-api/Models/Spacebar.Models.Gateway/IdentifyRequest.cs @@ -3,6 +3,11 @@ using System.Text.Json.Serialization; namespace Spacebar.Models.Gateway; +public class HelloResponse { + [JsonPropertyName("heartbeat_interval")] + public int HeartbeatInterval { get; set; } +} + public class IdentifyRequest { [JsonPropertyName("token")] public string Token { get; set; } @@ -32,6 +37,171 @@ public class IdentifyRequest { public JsonObject? ClientState { get; set; } } +/// +/// This class defines all client properties used by discord +/// This should *not* be used as a schema, as the types are merely conventions, and the structure isn't well-defined. +/// +public class IdentifyClientProperties { + [JsonPropertyName("os")] + public string? OperatingSystem { get; set; } + + [JsonPropertyName("os_version")] + public string? OperatingSystemVersion { get; set; } + + [JsonPropertyName("os_sdk_version")] + public string? OperatingSystemSdkVersion { get; set; } + + [JsonPropertyName("os_arch")] + public string? OperatingSystemArchitecture { get; set; } + + [JsonPropertyName("app_arch")] + public string? ApplicationArchitecture { get; set; } + + [JsonPropertyName("browser")] + public string? Browser { get; set; } + + [JsonPropertyName("browser_user_agent")] + public string? BrowserUserAgent { get; set; } + + [JsonPropertyName("browser_version")] + public string? BrowserVersion { get; set; } + + [JsonPropertyName("client_build_number")] + public int? ClientBuildNumber { get; set; } + + [JsonPropertyName("native_build_number")] + public int? NativeBuildNumber { get; set; } + + [JsonPropertyName("client_version")] + public string? ClientVersion { get; set; } + + [JsonPropertyName("client_event_source")] + public string? ClientEventSource { get; set; } + + [JsonPropertyName("client_app_state")] + public string? ClientAppState { get; set; } + + [JsonPropertyName("client_launch_id")] + public string? ClientLaunchId { get; set; } + + [JsonPropertyName("client_heartbeat_session_id")] + public string? ClientHeartbeatSessionId { get; set; } + + [JsonPropertyName("client_performance_cpu")] + public int? ClientPerformanceCpu { get; set; } + + [JsonPropertyName("client_performance_memory")] + public int? ClientPerformanceMemory { get; set; } + + [JsonPropertyName("cpu_core_count")] + public int? CpuCoreCount { get; set; } + + [JsonPropertyName("release_channel")] + public string? ReleaseChannel { get; set; } + + [JsonPropertyName("system_locale")] + public string? SystemLocale { get; set; } + + [JsonPropertyName("device")] + public string? DeviceModel { get; set; } + + [JsonPropertyName("device_vendor_id")] + public string? DeviceVendorId { get; set; } + + [JsonPropertyName("device_advertiser_id")] + public string? DeviceAdvertiserId { get; set; } + + [JsonPropertyName("design_id")] + public int? DesignId { get; set; } + + [JsonPropertyName("accessibility_support_enabled")] + public string? AccessibilitySupportEnabled { get; set; } + + [JsonPropertyName("accessibility_features")] + public int? AccessibilityFeatures { get; set; } + + [JsonPropertyName("window_manager")] + public string? WindowManager { get; set; } + + [JsonPropertyName("distro")] + public string? Distro { get; set; } + + [JsonPropertyName("runtime_environment")] + public string? RuntimeEnvironment { get; set; } + + [JsonPropertyName("display_server")] + public string? DisplayServer { get; set; } + + [JsonPropertyName("referrer")] + public string? Referrer { get; set; } + + [JsonPropertyName("referrer_current")] + public string? ReferrerCurrent { get; set; } + + [JsonPropertyName("referring_domain")] + public string? ReferringDomain { get; set; } + + [JsonPropertyName("referring_domain_current")] + public string? ReferringDomainCurrent { get; set; } + + [JsonPropertyName("search_engine")] + public string? SearchEngine { get; set; } + + [JsonPropertyName("search_engine_current")] + public string? SearchEngineCurrent { get; set; } + + [JsonPropertyName("mp_keyword")] + public string? MpKeyword { get; set; } + + [JsonPropertyName("mp_keyword_current")] + public string? MpKeywordCurrent { get; set; } + + [JsonPropertyName("utm_campaign")] + public string? UtmCampaign { get; set; } + + [JsonPropertyName("utm_campaign_current")] + public string? UtmCampaignCurrent { get; set; } + + [JsonPropertyName("utm_content")] + public string? UtmContent { get; set; } + + [JsonPropertyName("utm_content_current")] + public string? UtmContentCurrent { get; set; } + + [JsonPropertyName("utm_medium")] + public string? UtmMedium { get; set; } + + [JsonPropertyName("utm_medium_current")] + public string? UtmMediumCurrent { get; set; } + + [JsonPropertyName("utm_source")] + public string? UtmSource { get; set; } + + [JsonPropertyName("utm_source_current")] + public string? UtmSourceCurrent { get; set; } + + [JsonPropertyName("utm_term")] + public string? UtmTerm { get; set; } + + [JsonPropertyName("utm_term_current")] + public string? UtmTermCurrent { get; set; } + + [JsonPropertyName("has_client_mods")] + public bool? HasClientMods { get; set; } + + [JsonPropertyName("launch_signature")] + public string? LaunchSignature { get; set; } + + [JsonPropertyName("installation_id")] + public string? InstallationId { get; set; } + + [JsonPropertyName("is_fast_connect")] + public bool? IsFastConnect { get; set; } + + [JsonPropertyName("version")] + public string? Version { get; set; } +} + [Flags] public enum GatewayIntentFlags : ulong { Guilds = 1, diff --git a/extra/admin-api/Models/Spacebar.Models.Gateway/QoSPayload.cs b/extra/admin-api/Models/Spacebar.Models.Gateway/QoSPayload.cs index efb8dff9f..e470318bd 100644 --- a/extra/admin-api/Models/Spacebar.Models.Gateway/QoSPayload.cs +++ b/extra/admin-api/Models/Spacebar.Models.Gateway/QoSPayload.cs @@ -2,6 +2,16 @@ using System.Text.Json.Serialization; namespace Spacebar.Models.Gateway; +public class HeartbeatRequest { + [JsonPropertyName("seq")] + public required int? Sequence { get; set; } +} + +public class QoSHeartbeatRequest : HeartbeatRequest { + [JsonPropertyName("qos")] + public required QoSPayload QoSPayload { get; set; } +} + public class QoSPayload { [JsonPropertyName("ver")] public int Version { get; set; } diff --git a/extra/admin-api/Models/Spacebar.Models.Gateway/ReadyResponse.cs b/extra/admin-api/Models/Spacebar.Models.Gateway/ReadyResponse.cs index 5573cdb59..d26fecf6d 100644 --- a/extra/admin-api/Models/Spacebar.Models.Gateway/ReadyResponse.cs +++ b/extra/admin-api/Models/Spacebar.Models.Gateway/ReadyResponse.cs @@ -1,3 +1,37 @@ +using System.Text.Json.Serialization; +using Spacebar.Models.Generic; + namespace Spacebar.Models.Gateway; -public class ReadyResponse { } \ No newline at end of file +public class ReadyResponse { + /* TODO: _trace, analytics_token, api_code_version, auth_session_id_hash, connected_accounts, consents, country_code, experiments, friend_suggestion_count, game_relationships, + geo_ordered_rtc_regions, guild_experiments, guild_join_requests*/ + [JsonPropertyName("guilds")] + public required List Guilds { get; set; } + + [JsonPropertyName("merged_members")] + public List> MergedMembers { get; set; } + + // TODO: notification_settings + + [JsonPropertyName("presences")] + public List Presences { get; set; } // TODO: right type? + + [JsonPropertyName("private_channels")] + public List PrivateChannels { get; set; } + + [JsonPropertyName("read_state")] + public object ReadStates { get; set; } // TODO: schemas + + [JsonPropertyName("relationships")] + public List Relationships { get; set; } // TODO: schemas + + [JsonPropertyName("resume_gateway_url")] + public string ResumeGatewayUrl { get; set; } +} + +[JsonSourceGenerationOptions()] +[JsonSerializable(typeof(ReadyResponse))] +public partial class ReadyResponseSerializerContext : JsonSerializerContext +{ +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Generic/Channel.cs b/extra/admin-api/Models/Spacebar.Models.Generic/Channel.cs index 857d2e787..01a91c649 100644 --- a/extra/admin-api/Models/Spacebar.Models.Generic/Channel.cs +++ b/extra/admin-api/Models/Spacebar.Models.Generic/Channel.cs @@ -2,6 +2,10 @@ using System.Text.Json.Serialization; namespace Spacebar.Models.Generic; +public class Channel { + +} + public class ChannelPermissionOverwrite { [JsonPropertyName("id")] public string Id { get; set; } diff --git a/extra/admin-api/Models/Spacebar.Models.Generic/Emoji.cs b/extra/admin-api/Models/Spacebar.Models.Generic/Emoji.cs new file mode 100644 index 000000000..c47d2a787 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Generic/Emoji.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.Models.Generic; + +public class Emoji { + [JsonPropertyName("id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long Id { get; set; } + + [JsonPropertyName("animated")] + public bool Animated { get; set; } + + [JsonPropertyName("available")] + public bool Available { get; set; } + + [JsonPropertyName("groups")] + public object? Groups { get; set; } // TODO: what is this? + + [JsonPropertyName("guild_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long GuildId { get; set; } + + [JsonPropertyName("managed")] + public bool Managed { get; set; } + + [JsonPropertyName("name")] + public required string Name { get; set; } + + [JsonPropertyName("require_colons")] + public bool RequireColons { get; set; } + + [JsonPropertyName("roles")] + public List Roles { get; set; } // TODO: what type was this again? + + [JsonPropertyName("user_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long UserId { get; set; } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Generic/Guild.cs b/extra/admin-api/Models/Spacebar.Models.Generic/Guild.cs new file mode 100644 index 000000000..239fee5df --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Generic/Guild.cs @@ -0,0 +1,133 @@ +using System.Diagnostics; +using System.Text.Json.Serialization; + +namespace Spacebar.Models.Generic; + +[DebuggerDisplay("{Id} ({Name})")] +public class Guild { + [JsonPropertyName("id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long Id { get; set; } + + [JsonPropertyName("afk_channel_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long? AfkChannelId { get; set; } + + [JsonPropertyName("afk_timeout")] + public int AfkTimeout { get; set; } + + [JsonPropertyName("banner")] + public string? Banner { get; set; } + + [JsonPropertyName("channels")] + public List Channels { get; set; } + + [JsonPropertyName("default_message_notifications")] + public int DefaultMessageNotifications { get; set; } // TODO enum + + [JsonPropertyName("description")] + public string? Description { get; set; } + + [JsonPropertyName("discovery_splash")] + public string? DiscoverySplash { get; set; } + + [JsonPropertyName("emojis")] + public List Emojis { get; set; } + + [JsonPropertyName("explicit_content_filter")] + public int ExplicitContentFilter { get; set; } + + [JsonPropertyName("features")] + public List Features { get; set; } + + [JsonPropertyName("guild_scheduled_events")] + public List GuildScheduledEvents { get; set; } // TODO: implement + + [JsonPropertyName("icon")] + public string? Icon { get; set; } + + [JsonPropertyName("joined_at")] + public DateTimeOffset JoinedAt { get; set; } + + [JsonPropertyName("large")] + public bool Large { get; set; } + + [JsonPropertyName("max_members")] + public int MaxMembers { get; set; } + + [JsonPropertyName("max_presences")] + public int MaxPresences { get; set; } + + [JsonPropertyName("max_video_channel_users")] + public int MaxVideoChannelUsers { get; set; } + + [JsonPropertyName("member_count")] + public int MemberCount { get; set; } + + [JsonPropertyName("mfa_level")] + public int MfaLevel { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("nsfw_level")] + public int NsfwLevel { get; set; } + + [JsonPropertyName("owner_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long OwnerId { get; set; } + + [JsonPropertyName("preferred_locale")] + public string PreferredLocale { get; set; } + + [JsonPropertyName("premium_progress_bar_enabled")] + public bool? PremiumProgressBarEnabled { get; set; } + + [JsonPropertyName("premium_subscription_count")] + public int PremiumSubscriptionCount { get; set; } + + [JsonPropertyName("premium_tier")] + public int PremiumTier { get; set; } + + [JsonPropertyName("presences")] + public List Presences { get; set; } // TODO: correct type? + + [JsonPropertyName("public_updates_channel_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public long? PublicUpdatesChannelId { get; set; } + + [JsonPropertyName("region")] + public string Region { get; set; } + + [JsonPropertyName("roles")] + public List Roles { get; set; } + + [JsonPropertyName("rules_channel_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public long? RulesChannelId { get; set; } + + [JsonPropertyName("splash")] + public string? Splash { get; set; } + + [JsonPropertyName("stickers")] + public List Stickers { get; set; } + + [JsonPropertyName("system_channel_flags")] + public int SystemChannelFlags { get; set; } //TODO enum + + [JsonPropertyName("system_channel_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public long? SystemChannelId { get; set; } + + [JsonPropertyName("threads")] + public List Threads { get; set; } + + [JsonPropertyName("verification_level")] + public int VerificationLevel { get; set; } + + [JsonPropertyName("voice_states")] + public List VoiceStates { get; set; } // TODO: models + + [JsonPropertyName("welcome_screen")] + public object WelcomeScreen { get; set; } // TODO: models + + [JsonPropertyName("widget_channel_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public long? WidgetChannelId { get; set; } + + [JsonPropertyName("widget_enabled")] + public bool WidgetEnabled { get; set; } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Generic/Role.cs b/extra/admin-api/Models/Spacebar.Models.Generic/Role.cs new file mode 100644 index 000000000..6c49f85ee --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Generic/Role.cs @@ -0,0 +1,62 @@ +using System.Text.Json.Serialization; +using Spacebar.Models.Generic.Constants; + +namespace Spacebar.Models.Generic; + +public class Role { + [JsonPropertyName("id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long Id { get; set; } + + [JsonPropertyName("color"), Obsolete("See Colors instead")] + public int Color { get; set; } + + [JsonPropertyName("colors")] + public RoleColors Colors { get; set; } + + [JsonPropertyName("flags")] + public int Flags { get; set; } + + [JsonPropertyName("guild_id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long GuildId { get; set; } + + [JsonPropertyName("hoist")] + public bool Hoist { get; set; } + + [JsonPropertyName("icon")] + public string Icon { get; set; } + + [JsonPropertyName("managed")] + public bool Managed { get; set; } + + [JsonPropertyName("mentionable")] + public bool Mentionable { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("permissions"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required ulong RawPermissions { get; set; } + + [JsonIgnore] + public Permissions Permissions { + get => (Permissions)RawPermissions; + set => RawPermissions = (ulong)value; + } + + [JsonPropertyName("position")] + public int Position { get; set; } + + [JsonPropertyName("unicode_emoji")] + public string UnicodeEmoji { get; set; } + + public class RoleColors { + [JsonPropertyName("primary_color")] + public required int PrimaryColor { get; set; } + + [JsonPropertyName("secondary_color")] + public int? SecondaryColor { get; set; } + + [JsonPropertyName("tertiary_color")] + public int? TertiaryColor { get; set; } + } +} \ No newline at end of file diff --git a/extra/admin-api/Models/Spacebar.Models.Generic/Sticker.cs b/extra/admin-api/Models/Spacebar.Models.Generic/Sticker.cs new file mode 100644 index 000000000..28bf4feb7 --- /dev/null +++ b/extra/admin-api/Models/Spacebar.Models.Generic/Sticker.cs @@ -0,0 +1,38 @@ +using System.Text.Json.Serialization; + +namespace Spacebar.Models.Generic; + +public class Sticker { + [JsonPropertyName("id"), JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public required long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("tags")] + public string Tags { get; set; } + + [JsonPropertyName("available")] + public bool Available { get; set; } + + [JsonPropertyName("type")] + public StickerType Type { get; set; } + + [JsonPropertyName("format_type")] + public StickerFormatType FormatType { get; set; } +} + +public enum StickerType { + Standard = 1, + Guild = 2 +} + +public enum StickerFormatType { + Png = 1, + Apng = 2, + Lottie = 3, + Gif = 4 +} \ No newline at end of file diff --git a/extra/admin-api/Spacebar.Offload/Controllers/IdentifyController.cs b/extra/admin-api/Spacebar.Offload/Controllers/IdentifyController.cs index 02bad394c..9865b727a 100644 --- a/extra/admin-api/Spacebar.Offload/Controllers/IdentifyController.cs +++ b/extra/admin-api/Spacebar.Offload/Controllers/IdentifyController.cs @@ -38,7 +38,9 @@ public class IdentifyController(ILogger logger, SpacebarAuth } yield return new ReplicationMessage() { - Payload = new() { }, + Payload = new() { + Guilds = [] + }, }; }