| @@ -8,7 +8,7 @@ namespace Discord | |||
| { | |||
| internal static class CacheableEntityExtensions | |||
| { | |||
| public static IActivityModel ToModel<TModel>(this RichGame richGame) where TModel : WritableActivityModel, new() | |||
| public static IActivityModel ToModel<TModel>(this RichGame richGame) where TModel : IActivityModel, new() | |||
| { | |||
| return new TModel() | |||
| { | |||
| @@ -34,7 +34,7 @@ namespace Discord | |||
| }; | |||
| } | |||
| public static IActivityModel ToModel<TModel>(this SpotifyGame spotify) where TModel : WritableActivityModel, new() | |||
| public static IActivityModel ToModel<TModel>(this SpotifyGame spotify) where TModel : IActivityModel, new() | |||
| { | |||
| return new TModel() | |||
| { | |||
| @@ -53,11 +53,12 @@ namespace Discord | |||
| } | |||
| public static IActivityModel ToModel<TModel, TEmoteModel>(this CustomStatusGame custom) | |||
| where TModel : WritableActivityModel, new() | |||
| where TEmoteModel : WritableEmojiModel, new() | |||
| where TModel : IActivityModel, new() | |||
| where TEmoteModel : IEmojiModel, new() | |||
| { | |||
| return new TModel | |||
| { | |||
| Id = "custom", | |||
| Type = ActivityType.CustomStatus, | |||
| Name = custom.Name, | |||
| State = custom.State, | |||
| @@ -66,7 +67,7 @@ namespace Discord | |||
| }; | |||
| } | |||
| public static IActivityModel ToModel<TModel>(this StreamingGame stream) where TModel : WritableActivityModel, new() | |||
| public static IActivityModel ToModel<TModel>(this StreamingGame stream) where TModel : IActivityModel, new() | |||
| { | |||
| return new TModel | |||
| { | |||
| @@ -77,8 +78,11 @@ namespace Discord | |||
| }; | |||
| } | |||
| public static IEmojiModel ToModel<TModel>(this IEmote emote) where TModel : WritableEmojiModel, new() | |||
| public static IEmojiModel ToModel<TModel>(this IEmote emote) where TModel : IEmojiModel, new() | |||
| { | |||
| if (emote == null) | |||
| return null; | |||
| var model = new TModel() | |||
| { | |||
| Name = emote.Name | |||
| @@ -8,27 +8,14 @@ namespace Discord | |||
| { | |||
| public interface IEmojiModel | |||
| { | |||
| ulong? Id { get; } | |||
| string Name { get; } | |||
| ulong[] Roles { get; } | |||
| bool RequireColons { get; } | |||
| bool IsManaged { get; } | |||
| bool IsAnimated { get; } | |||
| bool IsAvailable { get; } | |||
| ulong? Id { get; set; } | |||
| string Name { get; set; } | |||
| ulong[] Roles { get; set; } | |||
| bool RequireColons { get; set; } | |||
| bool IsManaged { get; set; } | |||
| bool IsAnimated { get; set; } | |||
| bool IsAvailable { get; set; } | |||
| ulong? CreatorId { get; } | |||
| } | |||
| internal class WritableEmojiModel : IEmojiModel | |||
| { | |||
| public ulong? Id { get; set; } | |||
| public string Name { get; set; } | |||
| public ulong[] Roles { get; set; } | |||
| public bool RequireColons { get; set; } | |||
| public bool IsManaged { get; set; } | |||
| public bool IsAnimated { get; set; } | |||
| public bool IsAvailable { get; set; } | |||
| public ulong? CreatorId { get; set; } | |||
| ulong? CreatorId { get; set; } | |||
| } | |||
| } | |||
| @@ -8,81 +8,41 @@ namespace Discord | |||
| { | |||
| public interface IActivityModel | |||
| { | |||
| string Id { get; } | |||
| string Url { get; } | |||
| string Name { get; } | |||
| ActivityType Type { get; } | |||
| string Details { get; } | |||
| string State { get; } | |||
| ActivityProperties Flags { get; } | |||
| DateTimeOffset CreatedAt { get; } | |||
| IEmojiModel Emoji { get; } | |||
| ulong? ApplicationId { get; } | |||
| string SyncId { get; } | |||
| string SessionId { get; } | |||
| string Id { get; set; } | |||
| string Url { get; set; } | |||
| string Name { get; set; } | |||
| ActivityType Type { get; set; } | |||
| string Details { get; set; } | |||
| string State { get; set; } | |||
| ActivityProperties Flags { get; set; } | |||
| DateTimeOffset CreatedAt { get; set; } | |||
| IEmojiModel Emoji { get; set; } | |||
| ulong? ApplicationId { get; set; } | |||
| string SyncId { get; set; } | |||
| string SessionId { get; set; } | |||
| #region Assets | |||
| string LargeImage { get; } | |||
| string LargeText { get; } | |||
| string SmallImage { get; } | |||
| string SmallText { get; } | |||
| string LargeImage { get; set; } | |||
| string LargeText { get; set; } | |||
| string SmallImage { get; set; } | |||
| string SmallText { get; set; } | |||
| #endregion | |||
| #region Party | |||
| string PartyId { get; } | |||
| long[] PartySize { get; } | |||
| string PartyId { get; set; } | |||
| long[] PartySize { get; set; } | |||
| #endregion | |||
| #region Secrets | |||
| string JoinSecret { get; } | |||
| string SpectateSecret { get; } | |||
| string MatchSecret { get; } | |||
| string JoinSecret { get; set; } | |||
| string SpectateSecret { get; set; } | |||
| string MatchSecret { get; set; } | |||
| #endregion | |||
| #region Timestamps | |||
| DateTimeOffset? TimestampStart { get; } | |||
| DateTimeOffset? TimestampEnd { get; } | |||
| #endregion | |||
| } | |||
| internal class WritableActivityModel : IActivityModel | |||
| { | |||
| public string Id { get; set; } | |||
| public string Url { get; set; } | |||
| public string Name { get; set; } | |||
| public ActivityType Type { get; set; } | |||
| public string Details { get; set; } | |||
| public string State { get; set; } | |||
| public ActivityProperties Flags { get; set; } | |||
| public DateTimeOffset CreatedAt { get; set; } | |||
| public IEmojiModel Emoji { get; set; } | |||
| public ulong? ApplicationId { get; set; } | |||
| public string SyncId { get; set; } | |||
| public string SessionId { get; set; } | |||
| #region Assets | |||
| public string LargeImage { get; set; } | |||
| public string LargeText { get; set; } | |||
| public string SmallImage { get; set; } | |||
| public string SmallText { get; set; } | |||
| #endregion | |||
| #region Party | |||
| public string PartyId { get; set; } | |||
| public long[] PartySize { get; set; } | |||
| #endregion | |||
| #region Secrets | |||
| public string JoinSecret { get; set; } | |||
| public string SpectateSecret { get; set; } | |||
| public string MatchSecret { get; set; } | |||
| #endregion | |||
| #region Timestamps | |||
| public DateTimeOffset? TimestampStart { get; set; } | |||
| public DateTimeOffset? TimestampEnd { get; set; } | |||
| DateTimeOffset? TimestampStart { get; set; } | |||
| DateTimeOffset? TimestampEnd { get; set; } | |||
| #endregion | |||
| } | |||
| } | |||
| @@ -8,10 +8,10 @@ namespace Discord | |||
| { | |||
| public interface IPresenceModel | |||
| { | |||
| ulong UserId { get; } | |||
| ulong? GuildId { get; } | |||
| UserStatus Status { get; } | |||
| ClientType[] ActiveClients { get; } | |||
| IActivityModel[] Activities { get; } | |||
| ulong UserId { get; set; } | |||
| ulong? GuildId { get; set; } | |||
| UserStatus Status { get; set; } | |||
| ClientType[] ActiveClients { get; set; } | |||
| IActivityModel[] Activities { get; set; } | |||
| } | |||
| } | |||
| @@ -8,12 +8,12 @@ namespace Discord | |||
| { | |||
| public interface ICurrentUserModel : IUserModel | |||
| { | |||
| bool? IsVerified { get; } | |||
| string Email { get; } | |||
| bool? IsMfaEnabled { get; } | |||
| UserProperties Flags { get; } | |||
| PremiumType PremiumType { get; } | |||
| string Locale { get; } | |||
| UserProperties PublicFlags { get; } | |||
| bool? IsVerified { get; set; } | |||
| string Email { get; set; } | |||
| bool? IsMfaEnabled { get; set; } | |||
| UserProperties Flags { get; set; } | |||
| PremiumType PremiumType { get; set; } | |||
| string Locale { get; set; } | |||
| UserProperties PublicFlags { get; set; } | |||
| } | |||
| } | |||
| @@ -8,16 +8,16 @@ namespace Discord | |||
| { | |||
| public interface IMemberModel | |||
| { | |||
| IUserModel User { get; } | |||
| IUserModel User { get; set; } | |||
| string Nickname { get; } | |||
| string GuildAvatar { get; } | |||
| ulong[] Roles { get; } | |||
| DateTimeOffset JoinedAt { get; } | |||
| DateTimeOffset? PremiumSince { get; } | |||
| bool IsDeaf { get; } | |||
| bool IsMute { get; } | |||
| bool? IsPending { get; } | |||
| DateTimeOffset? CommunicationsDisabledUntil { get; } | |||
| string Nickname { get; set; } | |||
| string GuildAvatar { get; set; } | |||
| ulong[] Roles { get; set; } | |||
| DateTimeOffset JoinedAt { get; set; } | |||
| DateTimeOffset? PremiumSince { get; set; } | |||
| bool IsDeaf { get; set; } | |||
| bool IsMute { get; set; } | |||
| bool? IsPending { get; set; } | |||
| DateTimeOffset? CommunicationsDisabledUntil { get; set; } | |||
| } | |||
| } | |||
| @@ -6,11 +6,12 @@ using System.Threading.Tasks; | |||
| namespace Discord | |||
| { | |||
| public interface IUserModel : IEntity<ulong> | |||
| public interface IUserModel | |||
| { | |||
| string Username { get; } | |||
| string Discriminator { get; } | |||
| bool? IsBot { get; } | |||
| string Avatar { get; } | |||
| ulong Id { get; set; } | |||
| string Username { get; set; } | |||
| string Discriminator { get; set; } | |||
| bool? IsBot { get; set; } | |||
| string Avatar { get; set; } | |||
| } | |||
| } | |||
| @@ -25,18 +25,46 @@ namespace Discord.API | |||
| public Optional<UserProperties> PublicFlags { get; set; } | |||
| // ICurrentUserModel | |||
| bool? ICurrentUserModel.IsVerified => Verified.ToNullable(); | |||
| bool? ICurrentUserModel.IsVerified | |||
| { | |||
| get => Verified.ToNullable(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| string ICurrentUserModel.Email => Email.GetValueOrDefault(); | |||
| string ICurrentUserModel.Email | |||
| { | |||
| get => Email.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| bool? ICurrentUserModel.IsMfaEnabled => MfaEnabled.ToNullable(); | |||
| bool? ICurrentUserModel.IsMfaEnabled | |||
| { | |||
| get => MfaEnabled.ToNullable(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| UserProperties ICurrentUserModel.Flags => Flags.GetValueOrDefault(); | |||
| UserProperties ICurrentUserModel.Flags | |||
| { | |||
| get => Flags.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| PremiumType ICurrentUserModel.PremiumType => PremiumType.GetValueOrDefault(); | |||
| PremiumType ICurrentUserModel.PremiumType | |||
| { | |||
| get => PremiumType.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| string ICurrentUserModel.Locale => Locale.GetValueOrDefault(); | |||
| string ICurrentUserModel.Locale | |||
| { | |||
| get => Locale.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| UserProperties ICurrentUserModel.PublicFlags => PublicFlags.GetValueOrDefault(); | |||
| UserProperties ICurrentUserModel.PublicFlags | |||
| { | |||
| get => PublicFlags.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| namespace Discord.API | |||
| { | |||
| @@ -21,20 +22,52 @@ namespace Discord.API | |||
| [JsonProperty("user")] | |||
| public Optional<User> User { get; set; } | |||
| ulong? IEmojiModel.Id => Id; | |||
| ulong? IEmojiModel.Id | |||
| { | |||
| get => Id; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| string IEmojiModel.Name => Name; | |||
| string IEmojiModel.Name | |||
| { | |||
| get => Name; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| ulong[] IEmojiModel.Roles => Roles; | |||
| ulong[] IEmojiModel.Roles | |||
| { | |||
| get => Roles; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| bool IEmojiModel.RequireColons => RequireColons; | |||
| bool IEmojiModel.RequireColons | |||
| { | |||
| get => RequireColons; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| bool IEmojiModel.IsManaged => Managed; | |||
| bool IEmojiModel.IsManaged | |||
| { | |||
| get => Managed; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| bool IEmojiModel.IsAnimated => Animated.GetValueOrDefault(); | |||
| bool IEmojiModel.IsAnimated | |||
| { | |||
| get => Animated.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| bool IEmojiModel.IsAvailable => Available.GetValueOrDefault(); | |||
| bool IEmojiModel.IsAvailable | |||
| { | |||
| get => Available.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| ulong? IEmojiModel.CreatorId => User.GetValueOrDefault()?.Id; | |||
| ulong? IEmojiModel.CreatorId | |||
| { | |||
| get => User.GetValueOrDefault()?.Id; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -42,50 +42,96 @@ namespace Discord.API | |||
| [JsonProperty("created_at")] | |||
| public Optional<long> CreatedAt { get; set; } | |||
| string IActivityModel.Id => Id.GetValueOrDefault(); | |||
| string IActivityModel.Id { | |||
| get => Id.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.Url => StreamUrl.GetValueOrDefault(); | |||
| string IActivityModel.Url { | |||
| get => StreamUrl.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.State => State.GetValueOrDefault(); | |||
| string IActivityModel.State { | |||
| get => State.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| IEmojiModel IActivityModel.Emoji => Emoji.GetValueOrDefault(); | |||
| IEmojiModel IActivityModel.Emoji { | |||
| get => Emoji.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.Name => Name; | |||
| string IActivityModel.Name { | |||
| get => Name; set => throw new NotSupportedException(); | |||
| } | |||
| ActivityType IActivityModel.Type => Type.GetValueOrDefault().GetValueOrDefault(); | |||
| ActivityType IActivityModel.Type { | |||
| get => Type.GetValueOrDefault().GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| ActivityProperties IActivityModel.Flags => Flags.GetValueOrDefault(); | |||
| ActivityProperties IActivityModel.Flags { | |||
| get => Flags.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.Details => Details.GetValueOrDefault(); | |||
| DateTimeOffset IActivityModel.CreatedAt => DateTimeOffset.FromUnixTimeMilliseconds(CreatedAt.GetValueOrDefault()); | |||
| string IActivityModel.Details { | |||
| get => Details.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| DateTimeOffset IActivityModel.CreatedAt { | |||
| get => DateTimeOffset.FromUnixTimeMilliseconds(CreatedAt.GetValueOrDefault()); set => throw new NotSupportedException(); | |||
| } | |||
| ulong? IActivityModel.ApplicationId => ApplicationId.ToNullable(); | |||
| ulong? IActivityModel.ApplicationId { | |||
| get => ApplicationId.ToNullable(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.SyncId => SyncId.GetValueOrDefault(); | |||
| string IActivityModel.SyncId { | |||
| get => SyncId.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.SessionId => SessionId.GetValueOrDefault(); | |||
| string IActivityModel.SessionId { | |||
| get => SessionId.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.LargeImage => Assets.GetValueOrDefault()?.LargeImage.GetValueOrDefault(); | |||
| string IActivityModel.LargeImage { | |||
| get => Assets.GetValueOrDefault()?.LargeImage.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.LargeText => Assets.GetValueOrDefault()?.LargeText.GetValueOrDefault(); | |||
| string IActivityModel.LargeText { | |||
| get => Assets.GetValueOrDefault()?.LargeText.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.SmallImage => Assets.GetValueOrDefault()?.SmallImage.GetValueOrDefault(); | |||
| string IActivityModel.SmallImage { | |||
| get => Assets.GetValueOrDefault()?.SmallImage.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.SmallText => Assets.GetValueOrDefault()?.SmallText.GetValueOrDefault(); | |||
| string IActivityModel.SmallText { | |||
| get => Assets.GetValueOrDefault()?.SmallText.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.PartyId => Party.GetValueOrDefault()?.Id; | |||
| string IActivityModel.PartyId { | |||
| get => Party.GetValueOrDefault()?.Id; set => throw new NotSupportedException(); | |||
| } | |||
| long[] IActivityModel.PartySize => Party.GetValueOrDefault()?.Size; | |||
| long[] IActivityModel.PartySize { | |||
| get => Party.GetValueOrDefault()?.Size; set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.JoinSecret => Secrets.GetValueOrDefault()?.Join; | |||
| string IActivityModel.JoinSecret { | |||
| get => Secrets.GetValueOrDefault()?.Join; set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.SpectateSecret => Secrets.GetValueOrDefault()?.Spectate; | |||
| string IActivityModel.SpectateSecret { | |||
| get => Secrets.GetValueOrDefault()?.Spectate; set => throw new NotSupportedException(); | |||
| } | |||
| string IActivityModel.MatchSecret => Secrets.GetValueOrDefault()?.Match; | |||
| string IActivityModel.MatchSecret { | |||
| get => Secrets.GetValueOrDefault()?.Match; set => throw new NotSupportedException(); | |||
| } | |||
| DateTimeOffset? IActivityModel.TimestampStart => Timestamps.GetValueOrDefault()?.Start.ToNullable(); | |||
| DateTimeOffset? IActivityModel.TimestampStart { | |||
| get => Timestamps.GetValueOrDefault()?.Start.ToNullable(); set => throw new NotSupportedException(); | |||
| } | |||
| DateTimeOffset? IActivityModel.TimestampEnd => Timestamps.GetValueOrDefault()?.End.ToNullable(); | |||
| DateTimeOffset? IActivityModel.TimestampEnd { | |||
| get => Timestamps.GetValueOrDefault()?.End.ToNullable(); set => throw new NotSupportedException(); | |||
| } | |||
| @@ -27,24 +27,44 @@ namespace Discord.API | |||
| public Optional<DateTimeOffset?> TimedOutUntil { get; set; } | |||
| // IMemberModel | |||
| string IMemberModel.Nickname => Nick.GetValueOrDefault(); | |||
| string IMemberModel.Nickname { | |||
| get => Nick.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| string IMemberModel.GuildAvatar => Avatar.GetValueOrDefault(); | |||
| string IMemberModel.GuildAvatar { | |||
| get => Avatar.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| ulong[] IMemberModel.Roles => Roles.GetValueOrDefault(Array.Empty<ulong>()); | |||
| ulong[] IMemberModel.Roles { | |||
| get => Roles.GetValueOrDefault(Array.Empty<ulong>()); set => throw new NotSupportedException(); | |||
| } | |||
| DateTimeOffset IMemberModel.JoinedAt => JoinedAt.GetValueOrDefault(); | |||
| DateTimeOffset IMemberModel.JoinedAt { | |||
| get => JoinedAt.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| DateTimeOffset? IMemberModel.PremiumSince => PremiumSince.GetValueOrDefault(); | |||
| DateTimeOffset? IMemberModel.PremiumSince { | |||
| get => PremiumSince.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| bool IMemberModel.IsDeaf => Deaf.GetValueOrDefault(false); | |||
| bool IMemberModel.IsDeaf { | |||
| get => Deaf.GetValueOrDefault(false); set => throw new NotSupportedException(); | |||
| } | |||
| bool IMemberModel.IsMute => Mute.GetValueOrDefault(false); | |||
| bool IMemberModel.IsMute { | |||
| get => Mute.GetValueOrDefault(false); set => throw new NotSupportedException(); | |||
| } | |||
| bool? IMemberModel.IsPending => Pending.ToNullable(); | |||
| bool? IMemberModel.IsPending { | |||
| get => Pending.ToNullable(); set => throw new NotSupportedException(); | |||
| } | |||
| DateTimeOffset? IMemberModel.CommunicationsDisabledUntil => TimedOutUntil.GetValueOrDefault(); | |||
| DateTimeOffset? IMemberModel.CommunicationsDisabledUntil { | |||
| get => TimedOutUntil.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| IUserModel IMemberModel.User => User; | |||
| IUserModel IMemberModel.User { | |||
| get => User; set => throw new NotSupportedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -30,16 +30,24 @@ namespace Discord.API | |||
| [JsonProperty("premium_since")] | |||
| public Optional<DateTimeOffset?> PremiumSince { get; set; } | |||
| ulong IPresenceModel.UserId => User.Id; | |||
| ulong IPresenceModel.UserId { | |||
| get => User.Id; set => throw new NotSupportedException(); | |||
| } | |||
| ulong? IPresenceModel.GuildId => GuildId.ToNullable(); | |||
| ulong? IPresenceModel.GuildId { | |||
| get => GuildId.ToNullable(); set => throw new NotSupportedException(); | |||
| } | |||
| UserStatus IPresenceModel.Status => Status; | |||
| UserStatus IPresenceModel.Status { | |||
| get => Status; set => throw new NotSupportedException(); | |||
| } | |||
| ClientType[] IPresenceModel.ActiveClients => ClientStatus.IsSpecified | |||
| ? ClientStatus.Value.Select(x => (ClientType)Enum.Parse(typeof(ClientType), x.Key, true)).ToArray() | |||
| : Array.Empty<ClientType>(); | |||
| ClientType[] IPresenceModel.ActiveClients { | |||
| get => ClientStatus.IsSpecified ? ClientStatus.Value.Select(x => (ClientType)Enum.Parse(typeof(ClientType), x.Key, true)).ToArray() : Array.Empty<ClientType>(); set => throw new NotSupportedException(); | |||
| } | |||
| IActivityModel[] IPresenceModel.Activities => Activities.ToArray(); | |||
| IActivityModel[] IPresenceModel.Activities { | |||
| get => Activities.ToArray(); set => throw new NotSupportedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using Newtonsoft.Json; | |||
| using System; | |||
| namespace Discord.API | |||
| { | |||
| @@ -21,14 +22,31 @@ namespace Discord.API | |||
| // IUserModel | |||
| string IUserModel.Username => Username.GetValueOrDefault(); | |||
| string IUserModel.Username | |||
| { | |||
| get => Username.GetValueOrDefault(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| string IUserModel.Discriminator => Discriminator.GetValueOrDefault(); | |||
| string IUserModel.Discriminator { | |||
| get => Discriminator.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| bool? IUserModel.IsBot => Bot.ToNullable(); | |||
| bool? IUserModel.IsBot | |||
| { | |||
| get => Bot.ToNullable(); | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| string IUserModel.Avatar => Avatar.GetValueOrDefault(); | |||
| string IUserModel.Avatar | |||
| { | |||
| get => Avatar.GetValueOrDefault(); set => throw new NotSupportedException(); | |||
| } | |||
| ulong IEntity<ulong>.Id => Id; | |||
| ulong IUserModel.Id | |||
| { | |||
| get => Id; | |||
| set => throw new NotSupportedException(); | |||
| } | |||
| } | |||
| } | |||
| @@ -29,7 +29,7 @@ namespace Discord.WebSocket | |||
| #region Presence | |||
| ValueTask<IPresenceModel> GetPresenceAsync(ulong userId, CacheRunMode runmode); | |||
| ValueTask AddOrUpdatePresenseAsync(ulong userId, IPresenceModel presense, CacheRunMode runmode); | |||
| ValueTask AddOrUpdatePresenseAsync(ulong userId, IPresenceModel model, CacheRunMode runmode); | |||
| ValueTask RemovePresenseAsync(ulong userId, CacheRunMode runmode); | |||
| #endregion | |||
| @@ -41,7 +41,10 @@ namespace Discord.WebSocket | |||
| #region Global users | |||
| internal void RemoveReferencedGlobalUser(ulong id) | |||
| => _userReferences.TryRemove(id, out _); | |||
| { | |||
| Console.WriteLine("Global user untracked"); | |||
| _userReferences.TryRemove(id, out _); | |||
| } | |||
| private void TrackGlobalUser(ulong id, SocketGlobalUser user) | |||
| { | |||
| @@ -116,6 +116,45 @@ namespace Discord.WebSocket | |||
| public ulong? GuildId { get; set; } | |||
| } | |||
| private struct ActivityCacheModel : IActivityModel | |||
| { | |||
| public string Id { get; set; } | |||
| public string Url { get; set; } | |||
| public string Name { get; set; } | |||
| public ActivityType Type { get; set; } | |||
| public string Details { get; set; } | |||
| public string State { get; set; } | |||
| public ActivityProperties Flags { get; set; } | |||
| public DateTimeOffset CreatedAt { get; set; } | |||
| public IEmojiModel Emoji { get; set; } | |||
| public ulong? ApplicationId { get; set; } | |||
| public string SyncId { get; set; } | |||
| public string SessionId { get; set; } | |||
| public string LargeImage { get; set; } | |||
| public string LargeText { get; set; } | |||
| public string SmallImage { get; set; } | |||
| public string SmallText { get; set; } | |||
| public string PartyId { get; set; } | |||
| public long[] PartySize { get; set; } | |||
| public string JoinSecret { get; set; } | |||
| public string SpectateSecret { get; set; } | |||
| public string MatchSecret { get; set; } | |||
| public DateTimeOffset? TimestampStart { get; set; } | |||
| public DateTimeOffset? TimestampEnd { get; set; } | |||
| } | |||
| private struct EmojiCacheModel : IEmojiModel | |||
| { | |||
| public ulong? Id { get; set; } | |||
| public string Name { get; set; } | |||
| public ulong[] Roles { get; set; } | |||
| public bool RequireColons { get; set; } | |||
| public bool IsManaged { get; set; } | |||
| public bool IsAnimated { get; set; } | |||
| public bool IsAvailable { get; set; } | |||
| public ulong? CreatorId { get; set; } | |||
| } | |||
| internal Model ToModel() | |||
| { | |||
| return new CacheModel | |||
| @@ -132,18 +171,18 @@ namespace Discord.WebSocket | |||
| switch (game) | |||
| { | |||
| case RichGame richGame: | |||
| return richGame.ToModel<WritableActivityModel>(); | |||
| return richGame.ToModel<ActivityCacheModel>(); | |||
| case SpotifyGame spotify: | |||
| return spotify.ToModel<WritableActivityModel>(); | |||
| return spotify.ToModel<ActivityCacheModel>(); | |||
| case CustomStatusGame custom: | |||
| return custom.ToModel<WritableActivityModel, WritableEmojiModel>(); | |||
| return custom.ToModel<ActivityCacheModel, EmojiCacheModel>(); | |||
| case StreamingGame stream: | |||
| return stream.ToModel<WritableActivityModel>(); | |||
| return stream.ToModel<ActivityCacheModel>(); | |||
| } | |||
| break; | |||
| } | |||
| return new WritableActivityModel | |||
| return new ActivityCacheModel | |||
| { | |||
| Name = x.Name, | |||
| Details = x.Details, | |||
| @@ -15,7 +15,7 @@ namespace Discord.WebSocket | |||
| /// Represents a WebSocket-based user. | |||
| /// </summary> | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public abstract class SocketUser : SocketEntity<ulong>, IUser, ICached<Model> | |||
| public abstract class SocketUser : SocketEntity<ulong>, IUser, ICached<Model>, IDisposable | |||
| { | |||
| /// <inheritdoc /> | |||
| public abstract bool IsBot { get; internal set; } | |||
| @@ -41,9 +41,9 @@ namespace Discord.WebSocket | |||
| /// <inheritdoc /> | |||
| public UserStatus Status => Presence.Value.Status; | |||
| /// <inheritdoc /> | |||
| public IReadOnlyCollection<ClientType> ActiveClients => Presence.Value.ActiveClients ?? ImmutableHashSet<ClientType>.Empty; | |||
| public IReadOnlyCollection<ClientType> ActiveClients => Presence.Value?.ActiveClients ?? ImmutableHashSet<ClientType>.Empty; | |||
| /// <inheritdoc /> | |||
| public IReadOnlyCollection<IActivity> Activities => Presence.Value.Activities ?? ImmutableList<IActivity>.Empty; | |||
| public IReadOnlyCollection<IActivity> Activities => Presence.Value?.Activities ?? ImmutableList<IActivity>.Empty; | |||
| /// <summary> | |||
| /// Gets mutual guilds shared with this user. | |||
| /// </summary> | |||
| @@ -59,7 +59,7 @@ namespace Discord.WebSocket | |||
| } | |||
| internal virtual bool Update(ClientStateManager state, Model model) | |||
| { | |||
| Presence ??= new Lazy<SocketPresence>(() => state.GetPresence(Id), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication); | |||
| Presence ??= new Lazy<SocketPresence>(() => state.GetPresence(Id), System.Threading.LazyThreadSafetyMode.PublicationOnly); | |||
| bool hasChanges = false; | |||
| if (model.Avatar != AvatarId) | |||
| { | |||
| @@ -117,6 +117,8 @@ namespace Discord.WebSocket | |||
| /// The full name of the user. | |||
| /// </returns> | |||
| public override string ToString() => Format.UsernameAndDiscriminator(this, Discord.FormatUsersInBidirectionalUnicode); | |||
| ~SocketUser() => GlobalUser?.Dispose(); | |||
| public void Dispose() => GlobalUser?.Dispose(); | |||
| private string DebuggerDisplay => $"{Format.UsernameAndDiscriminator(this, Discord.FormatUsersInBidirectionalUnicode)} ({Id}{(IsBot ? ", Bot" : "")})"; | |||
| internal SocketUser Clone() => MemberwiseClone() as SocketUser; | |||