| @@ -10,7 +10,7 @@ namespace Discord | |||||
| public Members(DiscordClient client, object writerLock) | public Members(DiscordClient client, object writerLock) | ||||
| : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } | : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } | ||||
| private string GetKey(string userId, string serverId) | private string GetKey(string userId, string serverId) | ||||
| => (serverId ?? "Private") + '_' + userId; | |||||
| => User.GetId(userId, serverId); | |||||
| public User this[string userId, string serverId] | public User this[string userId, string serverId] | ||||
| => this[GetKey(userId, serverId)]; | => this[GetKey(userId, serverId)]; | ||||
| @@ -13,7 +13,10 @@ namespace Discord | |||||
| private bool _isEnabled; | private bool _isEnabled; | ||||
| public Messages(DiscordClient client, object writerLock, bool isEnabled) | public Messages(DiscordClient client, object writerLock, bool isEnabled) | ||||
| : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { } | |||||
| : base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) | |||||
| { | |||||
| _isEnabled = isEnabled; | |||||
| } | |||||
| public Message GetOrAdd(string id, string channelId, string userId) | public Message GetOrAdd(string id, string channelId, string userId) | ||||
| { | { | ||||
| @@ -9,9 +9,8 @@ namespace Discord | |||||
| { | { | ||||
| internal sealed class GlobalUser : CachedObject | internal sealed class GlobalUser : CachedObject | ||||
| { | { | ||||
| private readonly ConcurrentDictionary<string, bool> _servers; | |||||
| private int _refCount; | |||||
| private readonly ConcurrentDictionary<string, User> _users; | |||||
| /// <summary> Returns the email for this user. </summary> | /// <summary> Returns the email for this user. </summary> | ||||
| /// <remarks> This field is only ever populated for the current logged in user. </remarks> | /// <remarks> This field is only ever populated for the current logged in user. </remarks> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| @@ -27,15 +26,12 @@ namespace Discord | |||||
| /// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary> | /// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| public IEnumerable<User> Memberships => _servers.Select(x => _client.Members[Id, x.Key]); | |||||
| /// <summary> Returns a collection of all servers this user is a member of. </summary> | |||||
| [JsonIgnore] | |||||
| public IEnumerable<Server> Servers => _servers.Select(x => _client.Servers[x.Key]); | |||||
| public IEnumerable<User> Memberships => _users.Select(x => _client.Members[Id, x.Key]); | |||||
| internal GlobalUser(DiscordClient client, string id) | internal GlobalUser(DiscordClient client, string id) | ||||
| : base(client, id) | : base(client, id) | ||||
| { | { | ||||
| _servers = new ConcurrentDictionary<string, bool>(); | |||||
| _users = new ConcurrentDictionary<string, User>(); | |||||
| } | } | ||||
| internal override void OnCached() { } | internal override void OnCached() { } | ||||
| internal override void OnUncached() { } | internal override void OnUncached() { } | ||||
| @@ -48,24 +44,14 @@ namespace Discord | |||||
| IsVerified = model.IsVerified; | IsVerified = model.IsVerified; | ||||
| } | } | ||||
| internal void AddServer(string serverId) | |||||
| { | |||||
| _servers.TryAdd(serverId, true); | |||||
| } | |||||
| internal bool RemoveServer(string serverId) | |||||
| { | |||||
| bool ignored; | |||||
| return _servers.TryRemove(serverId, out ignored); | |||||
| } | |||||
| internal void AddRef() | |||||
| { | |||||
| Interlocked.Increment(ref _refCount); | |||||
| } | |||||
| internal void RemoveRef() | |||||
| internal void AddUser(User user) => _users.TryAdd(user.Id, user); | |||||
| internal void RemoveUser(User user) | |||||
| { | { | ||||
| if (Interlocked.Decrement(ref _refCount) == 0) | |||||
| _client.Users.TryRemove(Id); | |||||
| if (_users.TryRemove(user.Id, out user)) | |||||
| { | |||||
| if (_users.Count == 0) | |||||
| _client.Users.TryRemove(Id); | |||||
| } | |||||
| } | } | ||||
| public override string ToString() => Id; | public override string ToString() => Id; | ||||
| @@ -11,12 +11,15 @@ namespace Discord | |||||
| { | { | ||||
| private static readonly string[] _initialRoleIds = new string[0]; | private static readonly string[] _initialRoleIds = new string[0]; | ||||
| internal static string GetId(string userId, string serverId) => (serverId ?? "Private") + '_' + userId; | |||||
| private ConcurrentDictionary<string, Channel> _channels; | private ConcurrentDictionary<string, Channel> _channels; | ||||
| private ConcurrentDictionary<string, ChannelPermissions> _permissions; | private ConcurrentDictionary<string, ChannelPermissions> _permissions; | ||||
| private ServerPermissions _serverPermissions; | private ServerPermissions _serverPermissions; | ||||
| private bool _hasRef; | |||||
| private string[] _roleIds; | private string[] _roleIds; | ||||
| /// <summary> Returns a unique identifier combining this user's id with its server's. </summary> | |||||
| internal string UniqueId => GetId(Id, ServerId); | |||||
| /// <summary> Returns the name of this user on this server. </summary> | /// <summary> Returns the name of this user on this server. </summary> | ||||
| public string Name { get; private set; } | public string Name { get; private set; } | ||||
| /// <summary> Returns a by-name unique identifier separating this user from others with the same name. </summary> | /// <summary> Returns a by-name unique identifier separating this user from others with the same name. </summary> | ||||
| @@ -81,20 +84,13 @@ namespace Discord | |||||
| internal override void OnCached() | internal override void OnCached() | ||||
| { | { | ||||
| var server = Server; | var server = Server; | ||||
| if (server != null) | |||||
| { | |||||
| server.AddMember(this); | |||||
| if (Id == _client.CurrentUserId) | |||||
| server.CurrentMember = this; | |||||
| } | |||||
| server.AddMember(this); | |||||
| if (Id == _client.CurrentUserId) | |||||
| server.CurrentMember = this; | |||||
| var user = GlobalUser; | var user = GlobalUser; | ||||
| if (user != null) | |||||
| { | |||||
| if (server == null || !server.IsVirtual) | |||||
| user.AddServer(ServerId); | |||||
| user.AddRef(); | |||||
| _hasRef = true; | |||||
| } | |||||
| if (server == null || !server.IsVirtual) | |||||
| user.AddUser(this); | |||||
| } | } | ||||
| internal override void OnUncached() | internal override void OnUncached() | ||||
| { | { | ||||
| @@ -105,14 +101,9 @@ namespace Discord | |||||
| if (Id == _client.CurrentUserId) | if (Id == _client.CurrentUserId) | ||||
| server.CurrentMember = null; | server.CurrentMember = null; | ||||
| } | } | ||||
| var user = GlobalUser; | |||||
| if (user != null) | |||||
| { | |||||
| user.RemoveServer(ServerId); | |||||
| if (_hasRef) | |||||
| user.RemoveRef(); | |||||
| } | |||||
| _hasRef = false; | |||||
| var globalUser = GlobalUser; | |||||
| if (globalUser != null) | |||||
| globalUser.RemoveUser(this); | |||||
| } | } | ||||
| public override string ToString() => Id; | public override string ToString() => Id; | ||||