using System.Text.Json.Serialization; namespace KickWsClient.Models; public class KickModels { public class ChatMessageSenderIdentityBadgeModel { /// /// Internal type for badge e.g. moderator /// [JsonPropertyName("type")] public required string Type { get; set; } /// /// Friendly name for badge e.g. Moderator /// [JsonPropertyName("text")] public required string Text { get; set; } /// /// Count (if applicable) for badge (e.g. sub count for gifted subs) /// [JsonPropertyName("count")] public int? Count { get; set; } } public class ChatMessageSenderIdentityModel { /// /// User's hex color /// [JsonPropertyName("color")] public required string Color { get; set; } /// /// Badges a user has /// [JsonPropertyName("badges")] public List Badges = []; } public class ChatMessageSenderModel { /// /// Kick internal user ID /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Kick display name /// [JsonPropertyName("username")] public required string Username { get; set; } /// /// Kick slug (for URLs) /// [JsonPropertyName("slug")] public required string Slug { get; set; } /// /// Identity info for display color and badges /// [JsonPropertyName("identity")] public required ChatMessageSenderIdentityModel Identity { get; set; } } public class ChatMessageMetadataOriginalSenderModel { /// /// Original sender's user ID /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Original sender's username /// [JsonPropertyName("username")] public required string Username { get; set; } } public class ChatMessageMetadataOriginalMessageModel { /// /// ID (GUID) of the original message /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// Content of the original message /// [JsonPropertyName("content")] public required string Content { get; set; } } public class ChatMessageMetadataModel { /// /// Sender of the message that this message is in reply to /// [JsonPropertyName("original_sender")] public required ChatMessageMetadataOriginalSenderModel OriginalSender { get; set; } /// /// Content of the message that this message is in reply to /// [JsonPropertyName("original_message")] public required ChatMessageMetadataOriginalMessageModel OriginalMessage { get; set; } } public class FollowersUpdatedEventModel { /// /// Channel follower count /// [JsonPropertyName("followersCount")] public int FollowersCount { get; set; } /// /// ID to identify what chatroom this event belongs to /// [JsonPropertyName("chatroom_id")] public int ChatroomId { get; set; } /// /// Maybe returns your username if you're auth'd? No idea. Just returned null for me /// [JsonPropertyName("username")] public string? Username { get; set; } /// /// Epoch value that signifies ??? /// [JsonPropertyName("created_at")] public int? CreatedAtEpoch { get; set; } // It returned true even though I'm not signed in which makes no sense, so I'll assume there's a chance it'll // suddenly appear and mark as nullable as it's not really a useful property anyway. /// /// Does it mean we're following? Who knows, returns true even if you're a guest /// [JsonPropertyName("followed")] public bool? Followed { get; set; } } public class ChatMessageEventModel { /// /// Message unique GUID that's referenced for replies and deletions /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// Chatroom ID you can use to differentiate this from other rooms if you sub to multiple at a time /// [JsonPropertyName("chatroom_id")] public int ChatroomId { get; set; } /// /// Content of the message. Emotes are encoded like [emote:161238:russW] which translates to -> https://files.kick.com/emotes/161238/fullsize /// [JsonPropertyName("content")] public required string Content { get; set; } /// /// Regular message is 'message', replies are 'reply' /// [JsonPropertyName("type")] public required string Type { get; set; } // Why created at is an epoch for followers updated but ISO8601 for chat messages is just a mystery /// /// Time message was sent /// [JsonPropertyName("created_at")] public DateTimeOffset CreatedAt { get; set; } /// /// Sender of the message /// [JsonPropertyName("sender")] public required ChatMessageSenderModel Sender { get; set; } /// /// Message metadata which is set for replies only /// [JsonPropertyName("metadata")] public ChatMessageMetadataModel? Metadata { get; set; } } public class ChannelSubscriptionEventModel { /// /// User IDs of subscription recipients /// [JsonPropertyName("user_ids")] public List UserIds { get; set; } = []; /// /// Username of the person who subbed / gifted /// [JsonPropertyName("username")] public required string Username { get; set; } /// /// Channel ID where the sub event occurred /// [JsonPropertyName("channel_id")] public int ChannelId { get; set; } } public class SubscriptionEventModel { /// /// ID of channel where the subscription event occurred /// [JsonPropertyName("chatroom_id")] public int ChatroomId { get; set; } /// /// Username of the person who bought a sub /// [JsonPropertyName("username")] public required string Username { get; set; } /// /// Number of months they've subbed now (e.g. 2 if they bought their 2nd month) /// [JsonPropertyName("months")] public int Months { get; set; } } public class MessageDeletedMessageModel { /// /// ID of the message that was deleted /// [JsonPropertyName("id")] public required string Id { get; set; } } public class MessageDeletedEventModel { /// /// ID of this event (NOT the message to be removed!) /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// Message that was deleted /// [JsonPropertyName("message")] public required MessageDeletedMessageModel Message { get; set; } } public class UserBannedUserModel { /// /// ID of the user. Note it'll be 0 for the janny /// [JsonPropertyName("id")] public int Id { get; set; } /// /// User's username /// [JsonPropertyName("username")] public required string Username { get; set; } /// /// Slug suitable for URLs /// [JsonPropertyName("slug")] public required string Slug { get; set; } } public class UserBannedEventModel { /// /// GUID of the event /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// User who was banished /// [JsonPropertyName("user")] public required UserBannedUserModel User { get; set; } /// /// Janny who did the sweeping /// [JsonPropertyName("banned_by")] public required UserBannedUserModel BannedBy { get; set; } /// /// Datetime that the ban expires. Null for permabans /// [JsonPropertyName("expires_at")] public DateTimeOffset? ExpiresAt { get; set; } } public class UserUnbannedEventModel { /// /// GUID of the event /// [JsonPropertyName("id")] public required string Id { get; set; } /// /// User who was unbanned /// [JsonPropertyName("user")] public required UserBannedUserModel User { get; set; } /// /// Janny who unbanned /// [JsonPropertyName("unbanned_by")] public required UserBannedUserModel UnbannedBy { get; set; } } public class UpdatedLiveStreamCategoryParentModel { /// /// ID representing the category /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Slug representing the category /// [JsonPropertyName("slug")] public required string Slug { get; set; } } public class UpdatedLiveStreamCategoryModel { /// /// ID of the category /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Friendly name of the category /// [JsonPropertyName("name")] public required string Name { get; set; } /// /// Category's slug for forming URls etc. /// [JsonPropertyName("slug")] public required string Slug { get; set; } /// /// Tags for the category /// [JsonPropertyName("tags")] public List Tags { get; set; } = []; /// /// Parent category, if one is present. I think there usually is one, but made it nullable just in case /// [JsonPropertyName("parent_category")] public UpdatedLiveStreamCategoryParentModel? ParentCategory { get; set; } } public class UpdatedLiveStreamEventModel { /// /// ID of the livestream (numeric) /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Livestream slug /// [JsonPropertyName("slug")] public required string Slug { get; set; } /// /// Livestream title /// [JsonPropertyName("session_title")] public required string SessionTitle { get; set; } /// /// Livestream start time /// [JsonPropertyName("created_at")] public DateTimeOffset CreatedAt { get; set; } /// /// Language of the livestream (e.g. English) /// [JsonPropertyName("language")] public string? Language { get; set; } /// /// Whether the stream is marked as for a mature audience /// [JsonPropertyName("is_mature")] public bool IsMature { get; set; } /// /// Number of viewers presently watching /// [JsonPropertyName("viewers")] public int Viewers { get; set; } /// /// Category of the livestream. I believe this is always required but marked it as nullable just in case /// [JsonPropertyName("category")] public UpdatedLiveStreamCategoryModel? Category { get; set; } } public class StopStreamBroadcastLiveStreamChannelModel { /// /// ID of the channel /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Whether the streamer was sent to ban world /// [JsonPropertyName("is_banned")] public bool IsBanned { get; set; } } public class StopStreamBroadcastLiveStreamModel { /// /// Livestream event ID /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Channel that stopped streaming /// [JsonPropertyName("channel")] public required StopStreamBroadcastLiveStreamChannelModel Channel { get; set; } } public class StopStreamBroadcastEventModel { /// /// Object containing information related to the livestream that stopped /// [JsonPropertyName("livestream")] public required StopStreamBroadcastLiveStreamModel Livestream { get; set; } } public class StreamerIsLiveLiveStreamModel { /// /// ID of the livestream /// [JsonPropertyName("id")] public int Id { get; set; } /// /// ID of the channel /// [JsonPropertyName("channel_id")] public int ChannelId { get; set; } /// /// Title of the stream /// [JsonPropertyName("session_title")] public required string SessionTitle { get; set; } /// /// No idea, just null on my end /// [JsonPropertyName("source")] public string? Source { get; set; } /// /// Time stream started /// [JsonPropertyName("created_at")] public DateTimeOffset CreatedAt { get; set; } } public class StreamerIsLiveEventModel { /// /// Object containing information related to the livestream that has just started /// [JsonPropertyName("livestream")] public required StreamerIsLiveLiveStreamModel Livestream { get; set; } } public class PollUpdatePollOptionModel { /// /// ID of the poll option /// [JsonPropertyName("id")] public int Id { get; set; } /// /// Label of the poll option /// [JsonPropertyName("label")] public required string Label { get; set; } /// /// Number of votes the poll option has gotten /// [JsonPropertyName("votes")] public int Votes { get; set; } } public class PollUpdatePollModel { /// /// Title of the poll /// [JsonPropertyName("title")] public required string Title { get; set; } /// /// Poll options /// [JsonPropertyName("options")] public List Options { get; set; } = []; /// /// Duration of the poll in seconds /// [JsonPropertyName("duration")] public int Duration { get; set; } /// /// Remaining time in seconds /// [JsonPropertyName("remaining")] public int Remaining { get; set; } /// /// Time in seconds to display the results after completion? /// [JsonPropertyName("result_display_duration")] public int ResultDisplayDuration { get; set; } } public class PollUpdateEventModel { /// /// Poll data /// [JsonPropertyName("poll")] public required PollUpdatePollModel Poll { get; set; } } }