diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj index 68ed60e20..960a597f9 100644 --- a/src/Discord.Net.Net45/Discord.Net.csproj +++ b/src/Discord.Net.Net45/Discord.Net.csproj @@ -148,27 +148,6 @@ Audio\VoiceBuffer.cs - - Collections\AsyncCollection.cs - - - Collections\Channels.cs - - - Collections\Members.cs - - - Collections\Messages.cs - - - Collections\Roles.cs - - - Collections\Servers.cs - - - Collections\Users.cs - DiscordAPIClient.cs @@ -250,6 +229,9 @@ HttpException.cs + + Models\AsyncCollection.cs + Models\Channel.cs diff --git a/src/Discord.Net/Collections/Channels.cs b/src/Discord.Net/Collections/Channels.cs deleted file mode 100644 index ec9d28c1c..000000000 --- a/src/Discord.Net/Collections/Channels.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; - -namespace Discord.Collections -{ - internal sealed class Channels : AsyncCollection - { - public Channels(DiscordClient client, object writerLock) - : base(client, writerLock) { } - - public Channel GetOrAdd(string id, string serverId, string recipientId = null) - => GetOrAdd(id, () => new Channel(_client, id, serverId, recipientId)); - - protected override void OnCreated(Channel item) - { - if (!item.IsPrivate) - item.Server.AddChannel(item.Id); - if (item.RecipientId != null) - { - var user = item.Recipient; - if (user.PrivateChannelId != null) - throw new Exception("User already has a private channel."); - user.PrivateChannelId = item.Id; - user.AddRef(); - } - } - protected override void OnRemoved(Channel item) - { - if (!item.IsPrivate) - { - var server = item.Server; - if (server != null) - item.Server.RemoveChannel(item.Id); - } - if (item.RecipientId != null) - { - var user = item.Recipient; - if (user != null) - { - if (user.PrivateChannelId != item.Id) - throw new Exception("User has a different private channel."); - user.PrivateChannelId = null; - user.RemoveRef(); - } - } - } - } -} diff --git a/src/Discord.Net/Collections/Members.cs b/src/Discord.Net/Collections/Members.cs deleted file mode 100644 index 7801b8aa3..000000000 --- a/src/Discord.Net/Collections/Members.cs +++ /dev/null @@ -1,42 +0,0 @@ -namespace Discord.Collections -{ - internal sealed class Members : AsyncCollection - { - public Members(DiscordClient client, object writerLock) - : base(client, writerLock) { } - private string GetKey(string userId, string serverId) - => serverId + '_' + userId; - - public Member this[string userId, string serverId] - => this[GetKey(userId, serverId)]; - public Member GetOrAdd(string userId, string serverId) - => GetOrAdd(GetKey(userId, serverId), () => new Member(_client, userId, serverId)); - public Member TryRemove(string userId, string serverId) - => TryRemove(GetKey(userId, serverId)); - - protected override void OnCreated(Member item) - { - item.Server.AddMember(item); - item.User.AddServer(item.ServerId); - item.User.AddRef(); - if (item.UserId == _client.CurrentUserId) - item.Server.CurrentMember = item; - } - protected override void OnRemoved(Member item) - { - var server = item.Server; - if (server != null) - { - server.RemoveMember(item); - if (item.UserId == _client.CurrentUserId) - server.CurrentMember = null; - } - var user = item.User; - if (user != null) - { - user.RemoveServer(item.ServerId); - user.RemoveRef(); - } - } - } -} diff --git a/src/Discord.Net/Collections/Messages.cs b/src/Discord.Net/Collections/Messages.cs deleted file mode 100644 index 5e2b38ce3..000000000 --- a/src/Discord.Net/Collections/Messages.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Discord.Collections -{ - internal sealed class Messages : AsyncCollection - { - public Messages(DiscordClient client, object writerLock) - : base(client, writerLock) { } - - public Message GetOrAdd(string id, string channelId, string userId) - => GetOrAdd(id, () => new Message(_client, id, channelId, userId)); - - protected override void OnCreated(Message item) - { - item.Channel.AddMessage(item.Id); - item.User.AddRef(); - } - protected override void OnRemoved(Message item) - { - var channel = item.Channel; - if (channel != null) - channel.RemoveMessage(item.Id); - var user = item.User; - if (user != null) - user.RemoveRef(); - } - } -} diff --git a/src/Discord.Net/Collections/Roles.cs b/src/Discord.Net/Collections/Roles.cs deleted file mode 100644 index 4bc4bd1d8..000000000 --- a/src/Discord.Net/Collections/Roles.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Discord.Collections -{ - internal sealed class Roles : AsyncCollection - { - public Roles(DiscordClient client, object writerLock) - : base(client, writerLock) { } - - public Role GetOrAdd(string id, string serverId) - => GetOrAdd(id, () => new Role(_client, id, serverId)); - - protected override void OnCreated(Role item) - { - item.Server.AddRole(item.Id); - } - protected override void OnRemoved(Role item) - { - var server = item.Server; - if (server != null) - item.Server.RemoveRole(item.Id); - } - } -} diff --git a/src/Discord.Net/Collections/Servers.cs b/src/Discord.Net/Collections/Servers.cs deleted file mode 100644 index 977c3b99f..000000000 --- a/src/Discord.Net/Collections/Servers.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Discord.Collections -{ - internal sealed class Servers : AsyncCollection - { - public Servers(DiscordClient client, object writerLock) - : base(client, writerLock) { } - - public Server GetOrAdd(string id) - => base.GetOrAdd(id, () => new Server(_client, id)); - - protected override void OnRemoved(Server item) - { - var channels = _client.Channels; - foreach (var channelId in item.ChannelIds) - channels.TryRemove(channelId); - - var members = _client.Members; - foreach (var userId in item.UserIds) - members.TryRemove(userId, item.Id); - - var roles = _client.Roles; - foreach (var roleId in item.RoleIds) - roles.TryRemove(roleId); - } - } -} diff --git a/src/Discord.Net/Collections/Users.cs b/src/Discord.Net/Collections/Users.cs deleted file mode 100644 index 31d12c1e2..000000000 --- a/src/Discord.Net/Collections/Users.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Discord.Collections -{ - internal sealed class Users : AsyncCollection - { - public Users(DiscordClient client, object writerLock) - : base(client, writerLock) { } - - public User GetOrAdd(string id) => GetOrAdd(id, () => new User(_client, id)); - } -} diff --git a/src/Discord.Net/DiscordClient.Bans.cs b/src/Discord.Net/DiscordClient.Bans.cs index 2c0d98ad0..4c7563447 100644 --- a/src/Discord.Net/DiscordClient.Bans.cs +++ b/src/Discord.Net/DiscordClient.Bans.cs @@ -5,6 +5,21 @@ using System.Threading.Tasks; namespace Discord { + public class BanEventArgs : EventArgs + { + public User User { get; } + public string UserId { get; } + public Server Server { get; } + public string ServerId => Server.Id; + + internal BanEventArgs(User user, string userId, Server server) + { + User = user; + UserId = userId; + Server = server; + } + } + public partial class DiscordClient { public event EventHandler BanAdded; diff --git a/src/Discord.Net/DiscordClient.Channels.cs b/src/Discord.Net/DiscordClient.Channels.cs index 8b98cc395..5ab562943 100644 --- a/src/Discord.Net/DiscordClient.Channels.cs +++ b/src/Discord.Net/DiscordClient.Channels.cs @@ -1,4 +1,3 @@ -using Discord.Collections; using Discord.Net; using System; using System.Collections.Generic; @@ -8,7 +7,16 @@ using System.Threading.Tasks; namespace Discord { - public sealed class ChannelEventArgs : EventArgs + internal sealed class Channels : AsyncCollection + { + public Channels(DiscordClient client, object writerLock) + : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } + + public Channel GetOrAdd(string id, string serverId, string recipientId = null) + => GetOrAdd(id, () => new Channel(_client, id, serverId, recipientId)); + } + + public class ChannelEventArgs : EventArgs { public Channel Channel { get; } public string ChannelId => Channel.Id; diff --git a/src/Discord.Net/DiscordClient.Members.cs b/src/Discord.Net/DiscordClient.Members.cs index 235eb704f..980841bb3 100644 --- a/src/Discord.Net/DiscordClient.Members.cs +++ b/src/Discord.Net/DiscordClient.Members.cs @@ -1,4 +1,3 @@ -using Discord.Collections; using System; using System.Collections.Generic; using System.Linq; @@ -6,54 +5,66 @@ using System.Threading.Tasks; namespace Discord { - public sealed class MemberTypingEventArgs : EventArgs + internal sealed class Members : AsyncCollection + { + public Members(DiscordClient client, object writerLock) + : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } + private string GetKey(string userId, string serverId) + => serverId + '_' + userId; + + public Member this[string userId, string serverId] + => this[GetKey(userId, serverId)]; + public Member GetOrAdd(string userId, string serverId) + => GetOrAdd(GetKey(userId, serverId), () => new Member(_client, userId, serverId)); + public Member TryRemove(string userId, string serverId) + => TryRemove(GetKey(userId, serverId)); + } + + public class MemberEventArgs : EventArgs { - public Channel Channel { get; } - public string ChannelId => Channel.Id; - public Server Server => Channel.Server; - public string ServerId => Channel.ServerId; public Member Member { get; } - public string UserId => User.Id; public User User => Member.User; + public string UserId => Member.UserId; + public Server Server => Member.Server; + public string ServerId => Member.ServerId; + + internal MemberEventArgs(Member member) { Member = member; } + } + public class MemberChannelEventArgs : MemberEventArgs + { + public Channel Channel { get; } + public string ChannelId => Channel.Id; - internal MemberTypingEventArgs(Member member, Channel channel) + internal MemberChannelEventArgs(Member member, Channel channel) + : base(member) { - Member = member; Channel = channel; } } - - public sealed class MemberIsSpeakingEventArgs : EventArgs + public class MemberIsSpeakingEventArgs : MemberChannelEventArgs { - public Channel Channel => Member.VoiceChannel; - public string ChannelId => Member.VoiceChannelId; - public Server Server => Member.Server; - public string ServerId => Member.ServerId; - public User User => Member.User; - public string UserId => Member.UserId; - public Member Member { get; } public bool IsSpeaking { get; } - internal MemberIsSpeakingEventArgs(Member member, bool isSpeaking) + internal MemberIsSpeakingEventArgs(Member member, Channel channel, bool isSpeaking) + : base(member, channel) { - Member = member; IsSpeaking = isSpeaking; } } public partial class DiscordClient { - public event EventHandler UserIsTyping; + public event EventHandler UserIsTyping; private void RaiseUserIsTyping(Member member, Channel channel) { if (UserIsTyping != null) - RaiseEvent(nameof(UserIsTyping), () => UserIsTyping(this, new MemberTypingEventArgs(member, channel))); + RaiseEvent(nameof(UserIsTyping), () => UserIsTyping(this, new MemberChannelEventArgs(member, channel))); } public event EventHandler UserIsSpeaking; - private void RaiseUserIsSpeaking(Member member, bool isSpeaking) + private void RaiseUserIsSpeaking(Member member, Channel channel, bool isSpeaking) { if (UserIsSpeaking != null) - RaiseEvent(nameof(UserIsSpeaking), () => UserIsSpeaking(this, new MemberIsSpeakingEventArgs(member, isSpeaking))); + RaiseEvent(nameof(UserIsSpeaking), () => UserIsSpeaking(this, new MemberIsSpeakingEventArgs(member, channel, isSpeaking))); } internal Members Members => _members; diff --git a/src/Discord.Net/DiscordClient.Messages.cs b/src/Discord.Net/DiscordClient.Messages.cs index fe71dc233..59e4301e4 100644 --- a/src/Discord.Net/DiscordClient.Messages.cs +++ b/src/Discord.Net/DiscordClient.Messages.cs @@ -1,5 +1,4 @@ using Discord.API; -using Discord.Collections; using Discord.Net; using System; using System.Collections.Generic; @@ -9,6 +8,30 @@ using System.Threading.Tasks; namespace Discord { + internal sealed class Messages : AsyncCollection + { + public Messages(DiscordClient client, object writerLock) + : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } + + public Message GetOrAdd(string id, string channelId, string userId) + => GetOrAdd(id, () => new Message(_client, id, channelId, userId)); + } + + public class MessageEventArgs : EventArgs + { + public Message Message { get; } + public string MessageId => Message.Id; + public Member Member => Message.Member; + public Channel Channel => Message.Channel; + public string ChannelId => Message.ChannelId; + public Server Server => Message.Server; + public string ServerId => Message.ServerId; + public User User => Member.User; + public string UserId => Message.UserId; + + internal MessageEventArgs(Message msg) { Message = msg; } + } + public partial class DiscordClient { public const int MaxMessageSize = 2000; diff --git a/src/Discord.Net/DiscordClient.Roles.cs b/src/Discord.Net/DiscordClient.Roles.cs index 35802fb6d..24e316401 100644 --- a/src/Discord.Net/DiscordClient.Roles.cs +++ b/src/Discord.Net/DiscordClient.Roles.cs @@ -1,4 +1,3 @@ -using Discord.Collections; using System; using System.Collections.Generic; using System.Linq; @@ -6,6 +5,25 @@ using System.Threading.Tasks; namespace Discord { + internal sealed class Roles : AsyncCollection + { + public Roles(DiscordClient client, object writerLock) + : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } + + public Role GetOrAdd(string id, string serverId) + => GetOrAdd(id, () => new Role(_client, id, serverId)); + } + + public class RoleEventArgs : EventArgs + { + public Role Role { get; } + public string RoleId => Role.Id; + public Server Server => Role.Server; + public string ServerId => Role.ServerId; + + internal RoleEventArgs(Role role) { Role = role; } + } + public partial class DiscordClient { public event EventHandler RoleCreated; diff --git a/src/Discord.Net/DiscordClient.Servers.cs b/src/Discord.Net/DiscordClient.Servers.cs index c52be5c42..dbdcc9338 100644 --- a/src/Discord.Net/DiscordClient.Servers.cs +++ b/src/Discord.Net/DiscordClient.Servers.cs @@ -1,4 +1,3 @@ -using Discord.Collections; using Discord.Net; using System; using System.Collections.Generic; @@ -8,7 +7,16 @@ using System.Threading.Tasks; namespace Discord { - public sealed class ServerEventArgs : EventArgs + internal sealed class Servers : AsyncCollection + { + public Servers(DiscordClient client, object writerLock) + : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } + + public Server GetOrAdd(string id) + => base.GetOrAdd(id, () => new Server(_client, id)); + } + + public class ServerEventArgs : EventArgs { public Server Server { get; } public string ServerId => Server.Id; diff --git a/src/Discord.Net/DiscordClient.Users.cs b/src/Discord.Net/DiscordClient.Users.cs index 29b9a3bb5..21b432beb 100644 --- a/src/Discord.Net/DiscordClient.Users.cs +++ b/src/Discord.Net/DiscordClient.Users.cs @@ -1,5 +1,4 @@ using Discord.API; -using Discord.Collections; using System; using System.Collections.Generic; using System.Linq; @@ -7,6 +6,14 @@ using System.Threading.Tasks; namespace Discord { + internal sealed class Users : AsyncCollection + { + public Users(DiscordClient client, object writerLock) + : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } + + public User GetOrAdd(string id) => GetOrAdd(id, () => new User(_client, id)); + } + public sealed class UserEventArgs : EventArgs { public User User { get; } diff --git a/src/Discord.Net/DiscordClient.Voice.cs b/src/Discord.Net/DiscordClient.Voice.cs index 247977e59..56f4e2635 100644 --- a/src/Discord.Net/DiscordClient.Voice.cs +++ b/src/Discord.Net/DiscordClient.Voice.cs @@ -1,5 +1,6 @@ using Discord.Audio; using System; +using System.Threading.Tasks; namespace Discord { diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index c8c5b7e60..6cc5fc0e9 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -1,5 +1,4 @@ using Discord.API; -using Discord.Collections; using Discord.Net.WebSockets; using Newtonsoft.Json; using System; @@ -10,54 +9,6 @@ using System.Threading.Tasks; namespace Discord { - public sealed class MessageEventArgs : EventArgs - { - public Message Message { get; } - public string MessageId => Message.Id; - public Member Member => Message.Member; - public Channel Channel => Message.Channel; - public string ChannelId => Message.ChannelId; - public Server Server => Message.Server; - public string ServerId => Message.ServerId; - public User User => Member.User; - public string UserId => Message.UserId; - - internal MessageEventArgs(Message msg) { Message = msg; } - } - public sealed class RoleEventArgs : EventArgs - { - public Role Role { get; } - public string RoleId => Role.Id; - public Server Server => Role.Server; - public string ServerId => Role.ServerId; - - internal RoleEventArgs(Role role) { Role = role; } - } - public sealed class BanEventArgs : EventArgs - { - public User User { get; } - public string UserId { get; } - public Server Server { get; } - public string ServerId => Server.Id; - - internal BanEventArgs(User user, string userId, Server server) - { - User = user; - UserId = userId; - Server = server; - } - } - public sealed class MemberEventArgs : EventArgs - { - public Member Member { get; } - public User User => Member.User; - public string UserId => Member.UserId; - public Server Server => Member.Server; - public string ServerId => Member.ServerId; - - internal MemberEventArgs(Member member) { Member = member; } - } - /// Provides a connection to the DiscordApp service. public partial class DiscordClient : DiscordWSClient { @@ -106,7 +57,7 @@ namespace Discord if (member.ServerId == e.ServerId && member.IsSpeaking) { member.IsSpeaking = false; - RaiseUserIsSpeaking(member, false); + RaiseUserIsSpeaking(member, _channels[_voiceSocket.CurrentChannelId], false); } } }; @@ -157,10 +108,10 @@ namespace Discord $"Deleted Role: {e.Server?.Name ?? "[Private]"}/{e.Role.Name}" + (showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.RoleId})." : "")); BanAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"Added Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? "Unknown"}" + + $"Added Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? e.UserId}" + (showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : "")); BanRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, - $"Removed Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? "Unknown"}" + + $"Removed Ban: {e.Server?.Name ?? "[Private]"}/{e.User?.Name ?? e.UserId}" + (showIDs ? $" ({e.ServerId ?? "[Private]"}/{e.UserId})." : "")); UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client, $"Added Member: {e.Server?.Name ?? "[Private]"}/{e.User.Name}" + @@ -246,7 +197,8 @@ namespace Discord if (member.IsSpeaking != value) { member.IsSpeaking = value; - RaiseUserIsSpeaking(member, value); + var channel = _channels[_voiceSocket.CurrentChannelId]; + RaiseUserIsSpeaking(member, channel, value); if (Config.TrackActivity) member.UpdateActivity(); } @@ -665,7 +617,7 @@ namespace Discord if (data.ChannelId != member.VoiceChannelId && member.IsSpeaking) { member.IsSpeaking = false; - RaiseUserIsSpeaking(member, false); + RaiseUserIsSpeaking(member, _channels[member.VoiceChannelId], false); } member.Update(data); RaiseUserVoiceStateUpdated(member); diff --git a/src/Discord.Net/Collections/AsyncCollection.cs b/src/Discord.Net/Models/AsyncCollection.cs similarity index 85% rename from src/Discord.Net/Collections/AsyncCollection.cs rename to src/Discord.Net/Models/AsyncCollection.cs index f206011e0..d7533e58b 100644 --- a/src/Discord.Net/Collections/AsyncCollection.cs +++ b/src/Discord.Net/Models/AsyncCollection.cs @@ -4,7 +4,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -namespace Discord.Collections +namespace Discord { internal abstract class AsyncCollection : IEnumerable where TValue : class @@ -52,13 +52,16 @@ namespace Discord.Collections protected readonly DiscordClient _client; protected readonly ConcurrentDictionary _dictionary; + private readonly Action _onCache, _onUncache; - protected AsyncCollection(DiscordClient client, object writerLock) + protected AsyncCollection(DiscordClient client, object writerLock, Action onCache, Action onUncache) { _client = client; _writerLock = writerLock; _dictionary = new ConcurrentDictionary(); - } + _onCache = onCache; + _onUncache = onUncache; + } public TValue this[string key] { @@ -85,7 +88,7 @@ namespace Discord.Collections result = _dictionary.GetOrAdd(key, newItem); if (result == newItem) { - OnCreated(newItem); + _onCache(result); RaiseItemCreated(result); } } @@ -100,7 +103,7 @@ namespace Discord.Collections TValue result; if (_dictionary.TryRemove(key, out result)) { - OnRemoved(result); //TODO: If this object is accessed before OnRemoved finished firing, properties such as Server.Channels will have null elements + _onUncache(result); //TODO: If this object is accessed before OnRemoved finished firing, properties such as Server.Channels will have null elements return result; } } @@ -130,16 +133,7 @@ namespace Discord.Collections } } - protected virtual void OnCreated(TValue item) { } - protected virtual void OnRemoved(TValue item) { } - - public IEnumerator GetEnumerator() - { - return _dictionary.Select(x => x.Value).GetEnumerator(); - } - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } + public IEnumerator GetEnumerator() => _dictionary.Select(x => x.Value).GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } diff --git a/src/Discord.Net/Models/Channel.cs b/src/Discord.Net/Models/Channel.cs index 1a4c8bf77..0b6a2bf07 100644 --- a/src/Discord.Net/Models/Channel.cs +++ b/src/Discord.Net/Models/Channel.cs @@ -1,5 +1,6 @@ using Discord.API; using Newtonsoft.Json; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -29,6 +30,7 @@ namespace Discord private readonly DiscordClient _client; private readonly ConcurrentDictionary _messages; private bool _areMembersStale; + private bool _hasRef; /// Returns the unique identifier for this channel. public string Id { get; } @@ -101,6 +103,39 @@ namespace Discord _permissionOverwrites = _initialPermissionsOverwrites; _areMembersStale = true; } + internal void OnCached() + { + var server = Server; + if (server != null) + server.AddChannel(Id); + if (RecipientId != null) + { + var user = Recipient; + if (user != null) + { + user.PrivateChannelId = Id; + user.AddRef(); + _hasRef = true; + } + } + } + internal void OnUncached() + { + var server = Server; + if (server != null) + server.RemoveChannel(Id); + if (RecipientId != null) + { + var user = Recipient; + if (user != null) + { + user.PrivateChannelId = null; + if (_hasRef) + user.RemoveRef(); + } + } + _hasRef = false; + } internal void Update(ChannelReference model) { diff --git a/src/Discord.Net/Models/Member.cs b/src/Discord.Net/Models/Member.cs index ec48c2375..3012de7d9 100644 --- a/src/Discord.Net/Models/Member.cs +++ b/src/Discord.Net/Models/Member.cs @@ -11,6 +11,7 @@ namespace Discord { private readonly DiscordClient _client; private ConcurrentDictionary _permissions; + private bool _hasRef; /// Returns the name of this user on this server. public string Name { get; private set; } @@ -77,6 +78,41 @@ namespace Discord RoleIds = _initialRoleIds; _permissions = new ConcurrentDictionary(); } + internal void OnCached() + { + var server = Server; + if (server != null) + { + server.AddMember(this); + if (UserId == _client.CurrentUserId) + server.CurrentMember = this; + } + var user = User; + if (user != null) + { + user.AddServer(ServerId); + user.AddRef(); + _hasRef = true; + } + } + internal void OnUncached() + { + var server = Server; + if (server != null) + { + server.RemoveMember(this); + if (UserId == _client.CurrentUserId) + server.CurrentMember = null; + } + var user = User; + if (user != null) + { + user.RemoveServer(ServerId); + if (_hasRef) + user.RemoveRef(); + } + _hasRef = false; + } public override string ToString() => UserId; diff --git a/src/Discord.Net/Models/Message.cs b/src/Discord.Net/Models/Message.cs index a23644448..a7370ac16 100644 --- a/src/Discord.Net/Models/Message.cs +++ b/src/Discord.Net/Models/Message.cs @@ -93,6 +93,7 @@ namespace Discord private readonly DiscordClient _client; private string _cleanText; + private bool _gotRef; /// Returns the global unique identifier for this message. public string Id { get; internal set; } @@ -154,16 +155,7 @@ namespace Discord public User User => _client.Users[UserId]; /// Returns the author of this message. [JsonIgnore] - public Member Member - { - get - { - if (!Channel.IsPrivate) - return _client.Members[UserId, ServerId]; - else - throw new InvalidOperationException("Unable to access Member in a private channel. Use User instead or check for Channel.IsPrivate."); - } - } + public Member Member => _client.Members[UserId, ServerId]; internal Message(DiscordClient client, string id, string channelId, string userId) { @@ -174,6 +166,28 @@ namespace Discord Attachments = _initialAttachments; Embeds = _initialEmbeds; MentionIds = _initialMentions; + } + internal void OnCached() + { + var channel = Channel; + if (channel != null) + channel.AddMessage(Id); + var user = User; + if (user != null) + { + user.AddRef(); + _gotRef = true; + } + } + internal void OnUncached() + { + var channel = Channel; + if (channel != null) + channel.RemoveMessage(Id); + var user = User; + if (user != null && _gotRef) + user.RemoveRef(); + _gotRef = false; } internal void Update(MessageInfo model) diff --git a/src/Discord.Net/Models/Role.cs b/src/Discord.Net/Models/Role.cs index 43215b8f8..399fa5d4b 100644 --- a/src/Discord.Net/Models/Role.cs +++ b/src/Discord.Net/Models/Role.cs @@ -52,7 +52,19 @@ namespace Discord if (IsEveryone) Position = int.MinValue; - } + } + internal void OnCached() + { + var server = Server; + if (server != null) + server.AddRole(Id); + } + internal void OnUncached() + { + var server = Server; + if (server != null) + server.RemoveRole(Id); + } internal void Update(RoleInfo model) { diff --git a/src/Discord.Net/Models/Server.cs b/src/Discord.Net/Models/Server.cs index aada16b20..b99cc8d48 100644 --- a/src/Discord.Net/Models/Server.cs +++ b/src/Discord.Net/Models/Server.cs @@ -104,6 +104,23 @@ namespace Discord _members = new ConcurrentDictionary(); _roles = new ConcurrentDictionary(); } + internal void OnCached() + { + } + internal void OnUncached() + { + var channels = _client.Channels; + foreach (var channelId in ChannelIds) + channels.TryRemove(channelId); + + var members = _client.Members; + foreach (var userId in UserIds) + members.TryRemove(userId, Id); + + var roles = _client.Roles; + foreach (var roleId in RoleIds) + roles.TryRemove(roleId); + } internal void Update(GuildInfo model) { diff --git a/src/Discord.Net/Models/User.cs b/src/Discord.Net/Models/User.cs index baa80c69b..0598ff33d 100644 --- a/src/Discord.Net/Models/User.cs +++ b/src/Discord.Net/Models/User.cs @@ -80,7 +80,13 @@ namespace Discord _client = client; Id = id; _servers = new ConcurrentDictionary(); - } + } + internal void OnCached() + { + } + internal void OnUncached() + { + } internal void Update(UserReference model) {