Simplified caches, moved some eventargs, and made caching/uncaching objects more reliable.

This commit is contained in:
RogueException
2015-10-22 03:35:51 -03:00
parent e79e32ca8c
commit 76e4317400
23 changed files with 273 additions and 311 deletions

View File

@@ -148,27 +148,6 @@
<Compile Include="..\Discord.Net\Audio\VoiceBuffer.cs">
<Link>Audio\VoiceBuffer.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\AsyncCollection.cs">
<Link>Collections\AsyncCollection.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\Channels.cs">
<Link>Collections\Channels.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\Members.cs">
<Link>Collections\Members.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\Messages.cs">
<Link>Collections\Messages.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\Roles.cs">
<Link>Collections\Roles.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\Servers.cs">
<Link>Collections\Servers.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Collections\Users.cs">
<Link>Collections\Users.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\DiscordAPIClient.cs">
<Link>DiscordAPIClient.cs</Link>
</Compile>
@@ -250,6 +229,9 @@
<Compile Include="..\Discord.Net\HttpException.cs">
<Link>HttpException.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Models\AsyncCollection.cs">
<Link>Models\AsyncCollection.cs</Link>
</Compile>
<Compile Include="..\Discord.Net\Models\Channel.cs">
<Link>Models\Channel.cs</Link>
</Compile>

View File

@@ -1,47 +0,0 @@
using System;
namespace Discord.Collections
{
internal sealed class Channels : AsyncCollection<Channel>
{
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();
}
}
}
}
}

View File

@@ -1,42 +0,0 @@
namespace Discord.Collections
{
internal sealed class Members : AsyncCollection<Member>
{
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();
}
}
}
}

View File

@@ -1,26 +0,0 @@
namespace Discord.Collections
{
internal sealed class Messages : AsyncCollection<Message>
{
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();
}
}
}

View File

@@ -1,22 +0,0 @@
namespace Discord.Collections
{
internal sealed class Roles : AsyncCollection<Role>
{
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);
}
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Discord.Collections
{
internal sealed class Servers : AsyncCollection<Server>
{
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);
}
}
}

View File

@@ -1,10 +0,0 @@
namespace Discord.Collections
{
internal sealed class Users : AsyncCollection<User>
{
public Users(DiscordClient client, object writerLock)
: base(client, writerLock) { }
public User GetOrAdd(string id) => GetOrAdd(id, () => new User(_client, id));
}
}

View File

@@ -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<BanEventArgs> BanAdded;

View File

@@ -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<Channel>
{
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;

View File

@@ -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<Member>
{
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 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; }
}
public class MemberChannelEventArgs : MemberEventArgs
{
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;
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<MemberTypingEventArgs> UserIsTyping;
public event EventHandler<MemberChannelEventArgs> 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<MemberIsSpeakingEventArgs> 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;

View File

@@ -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<Message>
{
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;

View File

@@ -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<Role>
{
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<RoleEventArgs> RoleCreated;

View File

@@ -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<Server>
{
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;

View File

@@ -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<User>
{
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; }

View File

@@ -1,5 +1,6 @@
using Discord.Audio;
using System;
using System.Threading.Tasks;
namespace Discord
{

View File

@@ -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; }
}
/// <summary> Provides a connection to the DiscordApp service. </summary>
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);

View File

@@ -4,7 +4,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace Discord.Collections
namespace Discord
{
internal abstract class AsyncCollection<TValue> : IEnumerable<TValue>
where TValue : class
@@ -52,13 +52,16 @@ namespace Discord.Collections
protected readonly DiscordClient _client;
protected readonly ConcurrentDictionary<string, TValue> _dictionary;
private readonly Action<TValue> _onCache, _onUncache;
protected AsyncCollection(DiscordClient client, object writerLock)
protected AsyncCollection(DiscordClient client, object writerLock, Action<TValue> onCache, Action<TValue> onUncache)
{
_client = client;
_writerLock = writerLock;
_dictionary = new ConcurrentDictionary<string, TValue>();
}
_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<TValue> GetEnumerator()
{
return _dictionary.Select(x => x.Value).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<TValue> GetEnumerator() => _dictionary.Select(x => x.Value).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

View File

@@ -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<string, bool> _messages;
private bool _areMembersStale;
private bool _hasRef;
/// <summary> Returns the unique identifier for this channel. </summary>
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)
{

View File

@@ -11,6 +11,7 @@ namespace Discord
{
private readonly DiscordClient _client;
private ConcurrentDictionary<string, PackedChannelPermissions> _permissions;
private bool _hasRef;
/// <summary> Returns the name of this user on this server. </summary>
public string Name { get; private set; }
@@ -77,6 +78,41 @@ namespace Discord
RoleIds = _initialRoleIds;
_permissions = new ConcurrentDictionary<string, PackedChannelPermissions>();
}
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;

View File

@@ -93,6 +93,7 @@ namespace Discord
private readonly DiscordClient _client;
private string _cleanText;
private bool _gotRef;
/// <summary> Returns the global unique identifier for this message. </summary>
public string Id { get; internal set; }
@@ -154,16 +155,7 @@ namespace Discord
public User User => _client.Users[UserId];
/// <summary> Returns the author of this message. </summary>
[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)

View File

@@ -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)
{

View File

@@ -104,6 +104,23 @@ namespace Discord
_members = new ConcurrentDictionary<string, bool>();
_roles = new ConcurrentDictionary<string, bool>();
}
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)
{

View File

@@ -80,7 +80,13 @@ namespace Discord
_client = client;
Id = id;
_servers = new ConcurrentDictionary<string, bool>();
}
}
internal void OnCached()
{
}
internal void OnUncached()
{
}
internal void Update(UserReference model)
{