using Newtonsoft.Json; namespace KickWsClient.Models; public class KickModels { public class ChatMessageSenderIdentityBadgeModel { /// /// Internal type for badge e.g. moderator /// [JsonProperty("type")] public required string Type { get; set; } /// /// Friendly name for badge e.g. Moderator /// [JsonProperty("text")] public required string Text { get; set; } /// /// Count (if applicable) for badge (e.g. sub count for gifted subs) /// [JsonProperty("count")] public int? Count { get; set; } } public class ChatMessageSenderIdentityModel { /// /// User's hex color /// [JsonProperty("color")] public required string Color { get; set; } /// /// Badges a user has /// [JsonProperty("badges")] public List Badges = []; } public class ChatMessageSenderModel { /// /// Kick internal user ID /// [JsonProperty("id")] public int Id { get; set; } /// /// Kick display name /// [JsonProperty("username")] public required string Username { get; set; } /// /// Kick slug (for URLs) /// [JsonProperty("slug")] public required string Slug { get; set; } /// /// Identity info for display color and badges /// [JsonProperty("identity")] public required ChatMessageSenderIdentityModel Identity { get; set; } } public class ChatMessageMetadataOriginalSenderModel { /// /// Original sender's user ID /// [JsonProperty("id")] public int Id { get; set; } /// /// Original sender's username /// [JsonProperty("username")] public required string Username { get; set; } } public class ChatMessageMetadataOriginalMessageModel { /// /// ID (GUID) of the original message /// [JsonProperty("id")] public required string Id { get; set; } /// /// Content of the original message /// [JsonProperty("content")] public required string Content { get; set; } } public class ChatMessageMetadataModel { /// /// Sender of the message that this message is in reply to /// [JsonProperty("original_sender")] public required ChatMessageMetadataOriginalSenderModel OriginalSender { get; set; } /// /// Content of the message that this message is in reply to /// [JsonProperty("original_message")] public required ChatMessageMetadataOriginalMessageModel OriginalMessage { get; set; } } public class FollowersUpdatedEventModel { /// /// Channel follower count /// [JsonProperty("followersCount")] public int FollowersCount { get; set; } /// /// ID to identify what chatroom this event belongs to /// [JsonProperty("chatroom_id")] public int ChatroomId { get; set; } /// /// Maybe returns your username if you're auth'd? No idea. Just returned null for me /// [JsonProperty("username")] public string? Username { get; set; } /// /// Epoch value that signifies ??? /// [JsonProperty("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 /// [JsonProperty("followed")] public bool? Followed { get; set; } } public class ChatMessageEventModel { /// /// Message unique GUID that's referenced for replies and deletions /// [JsonProperty("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 /// [JsonProperty("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 /// [JsonProperty("content")] public required string Content { get; set; } /// /// Regular message is 'message', replies are 'reply' /// [JsonProperty("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 /// [JsonProperty("created_at")] public DateTimeOffset CreatedAt { get; set; } /// /// Sender of the message /// [JsonProperty("sender")] public required ChatMessageSenderModel Sender { get; set; } /// /// Message metadata which is set for replies only /// [JsonProperty("metadata")] public ChatMessageMetadataModel? Metadata { get; set; } } public class ChannelSubscriptionEventModel { /// /// User IDs of subscription recipients /// [JsonProperty("user_ids")] public List UserIds { get; set; } = []; /// /// Username of the person who subbed / gifted /// [JsonProperty("username")] public required string Username { get; set; } /// /// Channel ID where the sub event occurred /// [JsonProperty("channel_id")] public int ChannelId { get; set; } } public class SubscriptionEventModel { /// /// ID of channel where the subscription event occurred /// [JsonProperty("chatroom_id")] public int ChatroomId { get; set; } /// /// Username of the person who bought a sub /// [JsonProperty("username")] public required string Username { get; set; } /// /// Number of months they've subbed now (e.g. 2 if they bought their 2nd month) /// [JsonProperty("months")] public int Months { get; set; } } public class MessageDeletedMessageModel { /// /// ID of the message that was deleted /// [JsonProperty("id")] public required string Id { get; set; } } public class MessageDeletedEventModel { /// /// ID of this event (NOT the message to be removed!) /// [JsonProperty("id")] public required string Id { get; set; } /// /// Message that was deleted /// [JsonProperty("message")] public required MessageDeletedMessageModel Message { get; set; } } public class UserBannedUserModel { /// /// ID of the user. Note it'll be 0 for the janny /// [JsonProperty("id")] public int Id { get; set; } /// /// User's username /// [JsonProperty("username")] public required string Username { get; set; } /// /// Slug suitable for URLs /// [JsonProperty("slug")] public required string Slug { get; set; } } public class UserBannedEventModel { /// /// GUID of the event /// [JsonProperty("id")] public required string Id { get; set; } /// /// User who was banished /// [JsonProperty("user")] public required UserBannedUserModel User { get; set; } /// /// Janny who did the sweeping /// [JsonProperty("banned_by")] public required UserBannedUserModel BannedBy { get; set; } /// /// Datetime that the ban expires. Null for permabans /// [JsonProperty("expires_at")] public DateTimeOffset? ExpiresAt { get; set; } } public class UserUnbannedEventModel { /// /// GUID of the event /// [JsonProperty("id")] public required string Id { get; set; } /// /// User who was unbanned /// [JsonProperty("user")] public required UserBannedUserModel User { get; set; } /// /// Janny who unbanned /// [JsonProperty("unbanned_by")] public required UserBannedUserModel UnbannedBy { get; set; } } public class UpdatedLiveStreamCategoryParentModel { /// /// ID representing the category /// [JsonProperty("id")] public int Id { get; set; } /// /// Slug representing the category /// [JsonProperty("slug")] public required string Slug { get; set; } } public class UpdatedLiveStreamCategoryModel { /// /// ID of the category /// [JsonProperty("id")] public int Id { get; set; } /// /// Friendly name of the category /// [JsonProperty("name")] public required string Name { get; set; } /// /// Category's slug for forming URls etc. /// [JsonProperty("slug")] public required string Slug { get; set; } /// /// Tags for the category /// [JsonProperty("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 /// [JsonProperty("parent_category")] public UpdatedLiveStreamCategoryParentModel? ParentCategory { get; set; } } public class UpdatedLiveStreamEventModel { /// /// ID of the livestream (numeric) /// [JsonProperty("id")] public int Id { get; set; } /// /// Livestream slug /// [JsonProperty("slug")] public required string Slug { get; set; } /// /// Livestream title /// [JsonProperty("session_title")] public required string SessionTitle { get; set; } /// /// Livestream start time /// [JsonProperty("created_at")] public DateTimeOffset CreatedAt { get; set; } /// /// Language of the livestream (e.g. English) /// [JsonProperty("language")] public string? Language { get; set; } /// /// Whether the stream is marked as for a mature audience /// [JsonProperty("is_mature")] public bool IsMature { get; set; } /// /// Number of viewers presently watching /// [JsonProperty("viewers")] public int Viewers { get; set; } /// /// Category of the livestream. I believe this is always required but marked it as nullable just in case /// [JsonProperty("category")] public UpdatedLiveStreamCategoryModel? Category { get; set; } } public class StopStreamBroadcastLiveStreamChannelModel { /// /// ID of the channel /// [JsonProperty("id")] public int Id { get; set; } /// /// Whether the streamer was sent to ban world /// [JsonProperty("is_banned")] public bool IsBanned { get; set; } } public class StopStreamBroadcastLiveStreamModel { /// /// Livestream event ID /// [JsonProperty("id")] public int Id { get; set; } /// /// Channel that stopped streaming /// [JsonProperty("channel")] public required StopStreamBroadcastLiveStreamChannelModel Channel { get; set; } } public class StopStreamBroadcastEventModel { /// /// Object containing information related to the livestream that stopped /// [JsonProperty("livestream")] public required StopStreamBroadcastLiveStreamModel Livestream { get; set; } } public class StreamerIsLiveLiveStreamModel { /// /// ID of the livestream /// [JsonProperty("id")] public int Id { get; set; } /// /// ID of the channel /// [JsonProperty("channel_id")] public int ChannelId { get; set; } /// /// Title of the stream /// [JsonProperty("session_title")] public required string SessionTitle { get; set; } /// /// No idea, just null on my end /// [JsonProperty("source")] public string? Source { get; set; } /// /// Time stream started /// [JsonProperty("created_at")] public DateTimeOffset CreatedAt { get; set; } } public class StreamerIsLiveEventModel { /// /// Object containing information related to the livestream that has just started /// [JsonProperty("livestream")] public required StreamerIsLiveLiveStreamModel Livestream { get; set; } } public class PollUpdatePollOptionModel { /// /// ID of the poll option /// [JsonProperty("id")] public int Id { get; set; } /// /// Label of the poll option /// [JsonProperty("label")] public required string Label { get; set; } /// /// Number of votes the poll option has gotten /// [JsonProperty("votes")] public int Votes { get; set; } } public class PollUpdatePollModel { /// /// Title of the poll /// [JsonProperty("title")] public required string Title { get; set; } /// /// Poll options /// [JsonProperty("options")] public List Options { get; set; } = []; /// /// Duration of the poll in seconds /// [JsonProperty("duration")] public int Duration { get; set; } /// /// Remaining time in seconds /// [JsonProperty("remaining")] public int Remaining { get; set; } /// /// Time in seconds to display the results after completion? /// [JsonProperty("result_display_duration")] public int ResultDisplayDuration { get; set; } } public class PollUpdateEventModel { /// /// Poll data /// [JsonProperty("poll")] public required PollUpdatePollModel Poll { get; set; } } }