| @@ -8,7 +8,7 @@ namespace Discord | |||||
| { | { | ||||
| internal static class CacheableEntityExtensions | 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() | 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() | return new TModel() | ||||
| { | { | ||||
| @@ -53,11 +53,12 @@ namespace Discord | |||||
| } | } | ||||
| public static IActivityModel ToModel<TModel, TEmoteModel>(this CustomStatusGame custom) | 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 | return new TModel | ||||
| { | { | ||||
| Id = "custom", | |||||
| Type = ActivityType.CustomStatus, | Type = ActivityType.CustomStatus, | ||||
| Name = custom.Name, | Name = custom.Name, | ||||
| State = custom.State, | 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 | 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() | var model = new TModel() | ||||
| { | { | ||||
| Name = emote.Name | Name = emote.Name | ||||
| @@ -8,27 +8,14 @@ namespace Discord | |||||
| { | { | ||||
| public interface IEmojiModel | 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 | 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 | #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 | #endregion | ||||
| #region Party | #region Party | ||||
| string PartyId { get; } | |||||
| long[] PartySize { get; } | |||||
| string PartyId { get; set; } | |||||
| long[] PartySize { get; set; } | |||||
| #endregion | #endregion | ||||
| #region Secrets | #region Secrets | ||||
| string JoinSecret { get; } | |||||
| string SpectateSecret { get; } | |||||
| string MatchSecret { get; } | |||||
| string JoinSecret { get; set; } | |||||
| string SpectateSecret { get; set; } | |||||
| string MatchSecret { get; set; } | |||||
| #endregion | #endregion | ||||
| #region Timestamps | #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 | #endregion | ||||
| } | } | ||||
| } | } | ||||
| @@ -8,10 +8,10 @@ namespace Discord | |||||
| { | { | ||||
| public interface IPresenceModel | 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 | 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 | 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 | 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; } | public Optional<UserProperties> PublicFlags { get; set; } | ||||
| // ICurrentUserModel | // 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 Newtonsoft.Json; | ||||
| using System; | |||||
| namespace Discord.API | namespace Discord.API | ||||
| { | { | ||||
| @@ -21,20 +22,52 @@ namespace Discord.API | |||||
| [JsonProperty("user")] | [JsonProperty("user")] | ||||
| public Optional<User> User { get; set; } | 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")] | [JsonProperty("created_at")] | ||||
| public Optional<long> CreatedAt { get; set; } | 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; } | public Optional<DateTimeOffset?> TimedOutUntil { get; set; } | ||||
| // IMemberModel | // 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")] | [JsonProperty("premium_since")] | ||||
| public Optional<DateTimeOffset?> PremiumSince { get; set; } | 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 Newtonsoft.Json; | ||||
| using System; | |||||
| namespace Discord.API | namespace Discord.API | ||||
| { | { | ||||
| @@ -21,14 +22,31 @@ namespace Discord.API | |||||
| // IUserModel | // 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 | #region Presence | ||||
| ValueTask<IPresenceModel> GetPresenceAsync(ulong userId, CacheRunMode runmode); | 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); | ValueTask RemovePresenseAsync(ulong userId, CacheRunMode runmode); | ||||
| #endregion | #endregion | ||||
| @@ -41,7 +41,10 @@ namespace Discord.WebSocket | |||||
| #region Global users | #region Global users | ||||
| internal void RemoveReferencedGlobalUser(ulong id) | 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) | private void TrackGlobalUser(ulong id, SocketGlobalUser user) | ||||
| { | { | ||||
| @@ -116,6 +116,45 @@ namespace Discord.WebSocket | |||||
| public ulong? GuildId { get; set; } | 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() | internal Model ToModel() | ||||
| { | { | ||||
| return new CacheModel | return new CacheModel | ||||
| @@ -132,18 +171,18 @@ namespace Discord.WebSocket | |||||
| switch (game) | switch (game) | ||||
| { | { | ||||
| case RichGame richGame: | case RichGame richGame: | ||||
| return richGame.ToModel<WritableActivityModel>(); | |||||
| return richGame.ToModel<ActivityCacheModel>(); | |||||
| case SpotifyGame spotify: | case SpotifyGame spotify: | ||||
| return spotify.ToModel<WritableActivityModel>(); | |||||
| return spotify.ToModel<ActivityCacheModel>(); | |||||
| case CustomStatusGame custom: | case CustomStatusGame custom: | ||||
| return custom.ToModel<WritableActivityModel, WritableEmojiModel>(); | |||||
| return custom.ToModel<ActivityCacheModel, EmojiCacheModel>(); | |||||
| case StreamingGame stream: | case StreamingGame stream: | ||||
| return stream.ToModel<WritableActivityModel>(); | |||||
| return stream.ToModel<ActivityCacheModel>(); | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| return new WritableActivityModel | |||||
| return new ActivityCacheModel | |||||
| { | { | ||||
| Name = x.Name, | Name = x.Name, | ||||
| Details = x.Details, | Details = x.Details, | ||||
| @@ -15,7 +15,7 @@ namespace Discord.WebSocket | |||||
| /// Represents a WebSocket-based user. | /// Represents a WebSocket-based user. | ||||
| /// </summary> | /// </summary> | ||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public abstract class SocketUser : SocketEntity<ulong>, IUser, ICached<Model> | |||||
| public abstract class SocketUser : SocketEntity<ulong>, IUser, ICached<Model>, IDisposable | |||||
| { | { | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public abstract bool IsBot { get; internal set; } | public abstract bool IsBot { get; internal set; } | ||||
| @@ -41,9 +41,9 @@ namespace Discord.WebSocket | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public UserStatus Status => Presence.Value.Status; | public UserStatus Status => Presence.Value.Status; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public IReadOnlyCollection<ClientType> ActiveClients => Presence.Value.ActiveClients ?? ImmutableHashSet<ClientType>.Empty; | |||||
| public IReadOnlyCollection<ClientType> ActiveClients => Presence.Value?.ActiveClients ?? ImmutableHashSet<ClientType>.Empty; | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public IReadOnlyCollection<IActivity> Activities => Presence.Value.Activities ?? ImmutableList<IActivity>.Empty; | |||||
| public IReadOnlyCollection<IActivity> Activities => Presence.Value?.Activities ?? ImmutableList<IActivity>.Empty; | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets mutual guilds shared with this user. | /// Gets mutual guilds shared with this user. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -59,7 +59,7 @@ namespace Discord.WebSocket | |||||
| } | } | ||||
| internal virtual bool Update(ClientStateManager state, Model model) | 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; | bool hasChanges = false; | ||||
| if (model.Avatar != AvatarId) | if (model.Avatar != AvatarId) | ||||
| { | { | ||||
| @@ -117,6 +117,8 @@ namespace Discord.WebSocket | |||||
| /// The full name of the user. | /// The full name of the user. | ||||
| /// </returns> | /// </returns> | ||||
| public override string ToString() => Format.UsernameAndDiscriminator(this, Discord.FormatUsersInBidirectionalUnicode); | 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" : "")})"; | private string DebuggerDisplay => $"{Format.UsernameAndDiscriminator(this, Discord.FormatUsersInBidirectionalUnicode)} ({Id}{(IsBot ? ", Bot" : "")})"; | ||||
| internal SocketUser Clone() => MemberwiseClone() as SocketUser; | internal SocketUser Clone() => MemberwiseClone() as SocketUser; | ||||