Lots of bug fixes
This commit is contained in:
@@ -36,18 +36,20 @@ namespace Discord
|
|||||||
public Task Ban(User member)
|
public Task Ban(User member)
|
||||||
{
|
{
|
||||||
if (member == null) throw new ArgumentNullException(nameof(member));
|
if (member == null) throw new ArgumentNullException(nameof(member));
|
||||||
|
if (member.Server == null) throw new ArgumentException("Unable to ban a user in a private chat.");
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _api.Ban(member.ServerId, member.Id);
|
return _api.Ban(member.Server.Id, member.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Unbans a user from the provided server. </summary>
|
/// <summary> Unbans a user from the provided server. </summary>
|
||||||
public async Task Unban(User member)
|
public async Task Unban(Server server, string userId)
|
||||||
{
|
{
|
||||||
if (member == null) throw new ArgumentNullException(nameof(member));
|
if (server == null) throw new ArgumentNullException(nameof(server));
|
||||||
|
if (userId == null) throw new ArgumentNullException(nameof(userId));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
try { await _api.Unban(member.ServerId, member.Id).ConfigureAwait(false); }
|
try { await _api.Unban(server.Id, userId).ConfigureAwait(false); }
|
||||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { }
|
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace Discord
|
|||||||
/// <remarks> Supported formats: inviteCode, xkcdCode, https://discord.gg/inviteCode, https://discord.gg/xkcdCode </remarks>
|
/// <remarks> Supported formats: inviteCode, xkcdCode, https://discord.gg/inviteCode, https://discord.gg/xkcdCode </remarks>
|
||||||
public async Task<Invite> GetInvite(string inviteIdOrXkcd)
|
public async Task<Invite> GetInvite(string inviteIdOrXkcd)
|
||||||
{
|
{
|
||||||
|
//This doesn't work well if it's an invite to a different server!
|
||||||
|
|
||||||
if (inviteIdOrXkcd == null) throw new ArgumentNullException(nameof(inviteIdOrXkcd));
|
if (inviteIdOrXkcd == null) throw new ArgumentNullException(nameof(inviteIdOrXkcd));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
@@ -22,8 +24,8 @@ namespace Discord
|
|||||||
inviteIdOrXkcd = inviteIdOrXkcd.Substring(index + 1);
|
inviteIdOrXkcd = inviteIdOrXkcd.Substring(index + 1);
|
||||||
|
|
||||||
var response = await _api.GetInvite(inviteIdOrXkcd).ConfigureAwait(false);
|
var response = await _api.GetInvite(inviteIdOrXkcd).ConfigureAwait(false);
|
||||||
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id);
|
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id, response.Inviter?.Id, response.Channel?.Id);
|
||||||
invite.Update(response);
|
invite.Cache(); //Builds references
|
||||||
return invite;
|
return invite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +55,8 @@ namespace Discord
|
|||||||
|
|
||||||
var response = await _api.CreateInvite(channel.Id, maxAge: maxAge, maxUses: maxUses,
|
var response = await _api.CreateInvite(channel.Id, maxAge: maxAge, maxUses: maxUses,
|
||||||
tempMembership: tempMembership, hasXkcd: hasXkcd).ConfigureAwait(false);
|
tempMembership: tempMembership, hasXkcd: hasXkcd).ConfigureAwait(false);
|
||||||
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id);
|
var invite = new Invite(this, response.Code, response.XkcdPass, response.Guild.Id, response.Inviter?.Id, response.Channel?.Id);
|
||||||
invite.Update(response);
|
invite.Cache(); //Builds references
|
||||||
return invite;
|
return invite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ namespace Discord
|
|||||||
if (member == null) throw new ArgumentNullException(nameof(member));
|
if (member == null) throw new ArgumentNullException(nameof(member));
|
||||||
CheckReady();
|
CheckReady();
|
||||||
|
|
||||||
return _api.EditMember(member.ServerId, member.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id));
|
return _api.EditMember(member.Server?.Id, member.Id, mute: mute, deaf: deaf, roles: roles.Select(x => x.Id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ namespace Discord
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var msg = new Message(_client, id, channelId, userId);
|
var msg = new Message(_client, id, channelId, userId);
|
||||||
msg.Cache(); //Creates references to channel/server
|
msg.Cache(); //Builds references
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,17 @@ namespace Discord
|
|||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
if (targetType == PermissionTarget.Role)
|
if (targetType == PermissionTarget.Role)
|
||||||
channel.InvalidatePermissionsCache();
|
{
|
||||||
|
var role = _roles[targetId];
|
||||||
|
if (role != null)
|
||||||
|
channel.InvalidatePermissionsCache(role);
|
||||||
|
}
|
||||||
else if (targetType == PermissionTarget.User)
|
else if (targetType == PermissionTarget.User)
|
||||||
channel.InvalidatePermissionsCache(targetId);
|
{
|
||||||
|
var user = _users[targetId, channel.Server?.Id];
|
||||||
|
if (user != null)
|
||||||
|
channel.InvalidatePermissionsCache(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +122,16 @@ namespace Discord
|
|||||||
channel.PermissionOverwrites.Where(x => x.TargetType != targetType || x.TargetId != userOrRoleId).ToArray();
|
channel.PermissionOverwrites.Where(x => x.TargetType != targetType || x.TargetId != userOrRoleId).ToArray();
|
||||||
|
|
||||||
if (targetType == PermissionTarget.Role)
|
if (targetType == PermissionTarget.Role)
|
||||||
channel.InvalidatePermissionsCache();
|
{
|
||||||
|
var role = _roles[userOrRoleId];
|
||||||
|
channel.InvalidatePermissionsCache(role);
|
||||||
|
}
|
||||||
else if (targetType == PermissionTarget.User)
|
else if (targetType == PermissionTarget.User)
|
||||||
channel.InvalidatePermissionsCache(userOrRoleId);
|
{
|
||||||
|
var user = _users[userOrRoleId, channel.Server?.Id];
|
||||||
|
if (user != null)
|
||||||
|
channel.InvalidatePermissionsCache(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { }
|
catch (HttpException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { }
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
internal sealed class Roles : AsyncCollection<Role>
|
internal sealed class Roles : AsyncCollection<Role>
|
||||||
{
|
{
|
||||||
private const string VirtualEveryoneId = "[Virtual]";
|
|
||||||
public Role VirtualEveryone { get; private set; }
|
public Role VirtualEveryone { get; private set; }
|
||||||
|
|
||||||
public Roles(DiscordClient client, object writerLock)
|
public Roles(DiscordClient client, object writerLock)
|
||||||
: base(client, writerLock, x => x.OnCached(), x => x.OnUncached()) { }
|
: base(client, writerLock, x => x.OnCached(), x => x.OnUncached())
|
||||||
|
{
|
||||||
|
VirtualEveryone = new Role(client, "Private", null);
|
||||||
|
}
|
||||||
|
|
||||||
public Role GetOrAdd(string id, string serverId)
|
public Role GetOrAdd(string id, string serverId)
|
||||||
=> GetOrAdd(id, () => new Role(_client, id, serverId));
|
=> GetOrAdd(id, () => new Role(_client, id, serverId));
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Returns a collection of all servers this client is a member of. </summary>
|
/// <summary> Returns a collection of all servers this client is a member of. </summary>
|
||||||
public IEnumerable<Server> AllServers => _servers.Where(x => !x.IsVirtual);
|
public IEnumerable<Server> AllServers => _servers;
|
||||||
internal Servers Servers => _servers;
|
internal Servers Servers => _servers;
|
||||||
private readonly Servers _servers;
|
private readonly Servers _servers;
|
||||||
|
|
||||||
|
|||||||
@@ -59,12 +59,16 @@ namespace Discord
|
|||||||
|
|
||||||
VoiceDisconnected += (s, e) =>
|
VoiceDisconnected += (s, e) =>
|
||||||
{
|
{
|
||||||
foreach (var member in _users)
|
var server = _servers[e.ServerId];
|
||||||
|
if (server != null)
|
||||||
{
|
{
|
||||||
if (member.ServerId == e.ServerId && member.IsSpeaking)
|
foreach (var member in server.Members)
|
||||||
{
|
{
|
||||||
member.IsSpeaking = false;
|
if (member.IsSpeaking)
|
||||||
RaiseUserIsSpeaking(member, _channels[_voiceSocket.CurrentChannelId], false);
|
{
|
||||||
|
member.IsSpeaking = false;
|
||||||
|
RaiseUserIsSpeaking(member, _channels[_voiceSocket.CurrentChannelId], false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -104,13 +108,13 @@ namespace Discord
|
|||||||
BanRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
BanRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
||||||
$"Removed Ban: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
|
$"Removed Ban: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
|
||||||
UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
UserAdded += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
||||||
$"Added Member: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
|
$"Added Member: {e.Server?.Name ?? "[Private]"}/{e.User.Id}");
|
||||||
UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
UserRemoved += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
||||||
$"Removed Member: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
|
$"Removed Member: {e.Server?.Name ?? "[Private]"}/{e.User.Id}");
|
||||||
MemberUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
MemberUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
||||||
$"Updated Member: {e.Server?.Name ?? "[Private]"}/{e.UserId}");
|
$"Updated Member: {e.Server?.Name ?? "[Private]"}/{e.User.Id}");
|
||||||
UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
UserVoiceStateUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
||||||
$"Updated Member (Voice State): {e.Server?.Name ?? "[Private]"}/{e.UserId}");
|
$"Updated Member (Voice State): {e.Server?.Name ?? "[Private]"}/{e.User.Id}");
|
||||||
ProfileUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
ProfileUpdated += (s, e) => RaiseOnLog(LogMessageSeverity.Info, LogMessageSource.Client,
|
||||||
"Updated Profile");
|
"Updated Profile");
|
||||||
}
|
}
|
||||||
@@ -281,13 +285,12 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await base.OnReceivedEvent(e);
|
|
||||||
|
|
||||||
switch (e.Type)
|
switch (e.Type)
|
||||||
{
|
{
|
||||||
//Global
|
//Global
|
||||||
case "READY": //Resync
|
case "READY": //Resync
|
||||||
{
|
{
|
||||||
|
base.OnReceivedEvent(e).Wait(); //This cannot be an await, or we'll get later messages before we're ready
|
||||||
var data = e.Payload.ToObject<ReadyEvent>(_serializer);
|
var data = e.Payload.ToObject<ReadyEvent>(_serializer);
|
||||||
_currentUser = _users.GetOrAdd(data.User.Id, null);
|
_currentUser = _users.GetOrAdd(data.User.Id, null);
|
||||||
_currentUser.Update(data.User);
|
_currentUser.Update(data.User);
|
||||||
@@ -576,10 +579,11 @@ namespace Discord
|
|||||||
var member = _users[data.UserId, data.GuildId];
|
var member = _users[data.UserId, data.GuildId];
|
||||||
if (member != null)
|
if (member != null)
|
||||||
{
|
{
|
||||||
if (data.ChannelId != member.VoiceChannelId && member.IsSpeaking)
|
var voiceChannel = member.VoiceChannel;
|
||||||
|
if (voiceChannel != null && data.ChannelId != voiceChannel.Id && member.IsSpeaking)
|
||||||
{
|
{
|
||||||
member.IsSpeaking = false;
|
member.IsSpeaking = false;
|
||||||
RaiseUserIsSpeaking(member, _channels[member.VoiceChannelId], false);
|
RaiseUserIsSpeaking(member, _channels[voiceChannel.Id], false);
|
||||||
}
|
}
|
||||||
member.Update(data);
|
member.Update(data);
|
||||||
RaiseUserVoiceStateUpdated(member);
|
RaiseUserVoiceStateUpdated(member);
|
||||||
@@ -611,6 +615,7 @@ namespace Discord
|
|||||||
|
|
||||||
//Internal (handled in DiscordSimpleClient)
|
//Internal (handled in DiscordSimpleClient)
|
||||||
case "VOICE_SERVER_UPDATE":
|
case "VOICE_SERVER_UPDATE":
|
||||||
|
await base.OnReceivedEvent(e);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Others
|
//Others
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.ReceivedEvent += (s, e) => OnReceivedEvent(e);
|
socket.ReceivedEvent += async (s, e) => await OnReceivedEvent(e);
|
||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
internal virtual VoiceWebSocket CreateVoiceSocket()
|
internal virtual VoiceWebSocket CreateVoiceSocket()
|
||||||
@@ -292,7 +292,7 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual Task OnReceivedEvent(WebSocketEventEventArgs e)
|
internal virtual async Task OnReceivedEvent(WebSocketEventEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -309,7 +309,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
string token = e.Payload.Value<string>("token");
|
string token = e.Payload.Value<string>("token");
|
||||||
_voiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
|
_voiceSocket.Host = "wss://" + e.Payload.Value<string>("endpoint").Split(':')[0];
|
||||||
return _voiceSocket.Login(_userId, _dataSocket.SessionId, token, CancelToken);
|
await _voiceSocket.Login(_userId, _dataSocket.SessionId, token, CancelToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -319,7 +319,6 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
RaiseOnLog(LogMessageSeverity.Error, LogMessageSource.Client, $"Error handling {e.Type} event: {ex.GetBaseException().Message}");
|
RaiseOnLog(LogMessageSeverity.Error, LogMessageSource.Client, $"Error handling {e.Type} event: {ex.GetBaseException().Message}");
|
||||||
}
|
}
|
||||||
return TaskHelper.CompletedTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,11 +53,8 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!_areMembersStale)
|
if (_areMembersStale)
|
||||||
return _members.Select(x => x.Value);
|
UpdateMembersCache();
|
||||||
|
|
||||||
_members = Server.Members.Where(x => x.GetPermissions(this)?.ReadMessages ?? false).ToDictionary(x => x.Id, x => x);
|
|
||||||
_areMembersStale = false;
|
|
||||||
return _members.Select(x => x.Value);
|
return _members.Select(x => x.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,22 +154,32 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
internal void RemoveMessage(Message message) => _messages.TryRemove(message.Id, out message);
|
internal void RemoveMessage(Message message) => _messages.TryRemove(message.Id, out message);
|
||||||
|
|
||||||
internal void InvalidMembersCache()
|
internal void InvalidateMembersCache()
|
||||||
{
|
{
|
||||||
_areMembersStale = true;
|
_areMembersStale = true;
|
||||||
}
|
}
|
||||||
internal void InvalidatePermissionsCache()
|
private void UpdateMembersCache()
|
||||||
|
{
|
||||||
|
_members = Server.Members.Where(x => x.GetPermissions(this)?.ReadMessages ?? false).ToDictionary(x => x.Id, x => x);
|
||||||
|
_areMembersStale = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void InvalidatePermissionsCache()
|
||||||
|
{
|
||||||
|
UpdateMembersCache();
|
||||||
|
foreach (var member in _members)
|
||||||
|
member.Value.UpdateChannelPermissions(this);
|
||||||
|
}
|
||||||
|
internal void InvalidatePermissionsCache(Role role)
|
||||||
{
|
{
|
||||||
_areMembersStale = true;
|
_areMembersStale = true;
|
||||||
foreach (var member in Members)
|
foreach (var member in role.Members)
|
||||||
member.UpdateChannelPermissions(this);
|
member.UpdateChannelPermissions(this);
|
||||||
}
|
}
|
||||||
internal void InvalidatePermissionsCache(string userId)
|
internal void InvalidatePermissionsCache(User user)
|
||||||
{
|
{
|
||||||
_areMembersStale = true;
|
_areMembersStale = true;
|
||||||
var user = _members[userId]
|
user.UpdateChannelPermissions(this);
|
||||||
if (user != null)
|
|
||||||
user.UpdateChannelPermissions(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,10 @@ namespace Discord
|
|||||||
_users = new ConcurrentDictionary<string, User>();
|
_users = new ConcurrentDictionary<string, User>();
|
||||||
}
|
}
|
||||||
internal override void OnCached() { }
|
internal override void OnCached() { }
|
||||||
internal override void OnUncached() { }
|
internal override void OnUncached()
|
||||||
|
{
|
||||||
|
//Don't need to clean _users - they're considered owned by server
|
||||||
|
}
|
||||||
|
|
||||||
internal void Update(UserInfo model)
|
internal void Update(UserInfo model)
|
||||||
{
|
{
|
||||||
@@ -44,10 +47,10 @@ namespace Discord
|
|||||||
IsVerified = model.IsVerified;
|
IsVerified = model.IsVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddUser(User user) => _users.TryAdd(user.Id, user);
|
internal void AddUser(User user) => _users.TryAdd(user.UniqueId, user);
|
||||||
internal void RemoveUser(User user)
|
internal void RemoveUser(User user)
|
||||||
{
|
{
|
||||||
if (_users.TryRemove(user.Id, out user))
|
if (_users.TryRemove(user.UniqueId, out user))
|
||||||
{
|
{
|
||||||
if (_users.Count == 0)
|
if (_users.Count == 0)
|
||||||
_client.GlobalUsers.TryRemove(Id);
|
_client.GlobalUsers.TryRemove(Id);
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
public sealed class Invite : CachedObject
|
public sealed class Invite : CachedObject
|
||||||
{
|
{
|
||||||
private readonly string _serverId;
|
/// <summary> Returns the unique code for this invite. </summary>
|
||||||
private string _inviterId, _channelId;
|
public string Code { get; private set; }
|
||||||
|
/// <summary> Returns, if enabled, an alternative human-readable code for URLs. </summary>
|
||||||
|
public string XkcdCode { get; }
|
||||||
/// <summary> Time (in seconds) until the invite expires. Set to 0 to never expire. </summary>
|
/// <summary> Time (in seconds) until the invite expires. Set to 0 to never expire. </summary>
|
||||||
public int MaxAge { get; private set; }
|
public int MaxAge { get; private set; }
|
||||||
/// <summary> The amount of times this invite has been used. </summary>
|
/// <summary> The amount of times this invite has been used. </summary>
|
||||||
@@ -19,47 +20,72 @@ namespace Discord
|
|||||||
public bool IsRevoked { get; private set; }
|
public bool IsRevoked { get; private set; }
|
||||||
/// <summary> If true, a user accepting this invite will be kicked from the server after closing their client. </summary>
|
/// <summary> If true, a user accepting this invite will be kicked from the server after closing their client. </summary>
|
||||||
public bool IsTemporary { get; private set; }
|
public bool IsTemporary { get; private set; }
|
||||||
/// <summary> Returns, if enabled, an alternative human-readable code for URLs. </summary>
|
|
||||||
public string XkcdPass { get; }
|
|
||||||
|
|
||||||
/// <summary> Returns a URL for this invite using XkcdPass if available or Id if not. </summary>
|
/// <summary> Returns a URL for this invite using XkcdCode if available or Id if not. </summary>
|
||||||
public string Url => API.Endpoints.InviteUrl(XkcdPass ?? Id);
|
public string Url => API.Endpoints.InviteUrl(XkcdCode ?? Code);
|
||||||
|
|
||||||
/// <summary> Returns the user that created this invite. </summary>
|
/// <summary> Returns the user that created this invite. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public User Inviter => _client.Users[_inviterId, _serverId];
|
public User Inviter { get; private set; }
|
||||||
|
[JsonProperty("InviterId")]
|
||||||
|
private readonly string _inviterId;
|
||||||
|
|
||||||
/// <summary> Returns the server this invite is to. </summary>
|
/// <summary> Returns the server this invite is to. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Server Server => _client.Servers[_serverId];
|
public Server Server { get; private set; }
|
||||||
|
[JsonProperty("ServerId")]
|
||||||
|
private readonly string _serverId;
|
||||||
|
|
||||||
/// <summary> Returns the channel this invite is to. </summary>
|
/// <summary> Returns the channel this invite is to. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Channel Channel => _client.Channels[_channelId];
|
public Channel Channel { get; private set; }
|
||||||
|
[JsonProperty("ChannelId")]
|
||||||
|
private readonly string _channelId;
|
||||||
|
|
||||||
internal Invite(DiscordClient client, string code, string xkcdPass, string serverId)
|
internal Invite(DiscordClient client, string code, string xkcdPass, string serverId, string inviterId, string channelId)
|
||||||
: base(client, code)
|
: base(client, code)
|
||||||
{
|
{
|
||||||
XkcdPass = xkcdPass;
|
XkcdCode = xkcdPass;
|
||||||
_serverId = serverId;
|
_serverId = serverId;
|
||||||
|
_inviterId = inviterId;
|
||||||
|
_channelId = channelId;
|
||||||
}
|
}
|
||||||
internal override void OnCached() { }
|
|
||||||
internal override void OnUncached() { }
|
|
||||||
|
|
||||||
public override string ToString() => XkcdPass ?? Id;
|
internal override void OnCached()
|
||||||
|
|
||||||
|
|
||||||
internal void Update(InviteReference model)
|
|
||||||
{
|
{
|
||||||
if (model.Channel != null)
|
var server = _client.Servers[_serverId];
|
||||||
_channelId = model.Channel.Id;
|
if (server == null)
|
||||||
if (model.Inviter != null)
|
server = new Server(_client, _serverId);
|
||||||
_inviterId = model.Inviter.Id;
|
Server = server;
|
||||||
|
|
||||||
|
if (_inviterId != null)
|
||||||
|
{
|
||||||
|
var inviter = _client.Users[_inviterId, _serverId];
|
||||||
|
if (inviter == null)
|
||||||
|
inviter = new User(_client, _inviterId, _serverId);
|
||||||
|
Inviter = inviter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_channelId != null)
|
||||||
|
{
|
||||||
|
var channel = _client.Channels[_channelId];
|
||||||
|
if (channel == null)
|
||||||
|
channel = new Channel(_client, _channelId, _serverId, null);
|
||||||
|
Channel = channel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
internal override void OnUncached()
|
||||||
|
{
|
||||||
|
Server = null;
|
||||||
|
Inviter = null;
|
||||||
|
Channel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => XkcdCode ?? Id;
|
||||||
|
|
||||||
|
|
||||||
internal void Update(InviteInfo model)
|
internal void Update(InviteInfo model)
|
||||||
{
|
{
|
||||||
Update(model as InviteReference);
|
|
||||||
if (model.IsRevoked != null)
|
if (model.IsRevoked != null)
|
||||||
IsRevoked = model.IsRevoked.Value;
|
IsRevoked = model.IsRevoked.Value;
|
||||||
if (model.IsTemporary != null)
|
if (model.IsTemporary != null)
|
||||||
|
|||||||
@@ -157,15 +157,18 @@ namespace Discord
|
|||||||
}
|
}
|
||||||
internal override void OnCached()
|
internal override void OnCached()
|
||||||
{
|
{
|
||||||
|
//References
|
||||||
var channel = _client.Channels[_channelId];
|
var channel = _client.Channels[_channelId];
|
||||||
channel.AddMessage(this);
|
channel.AddMessage(this);
|
||||||
Channel = channel;
|
Channel = channel;
|
||||||
}
|
}
|
||||||
internal override void OnUncached()
|
internal override void OnUncached()
|
||||||
{
|
{
|
||||||
|
//References
|
||||||
var channel = Channel;
|
var channel = Channel;
|
||||||
if (channel != null)
|
if (channel != null)
|
||||||
channel.RemoveMessage(this);
|
channel.RemoveMessage(this);
|
||||||
|
Channel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Update(MessageInfo model)
|
internal void Update(MessageInfo model)
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ namespace Discord
|
|||||||
public Server Server { get; private set; }
|
public Server Server { get; private set; }
|
||||||
|
|
||||||
/// <summary> Returns true if this is the role representing all users in a server. </summary>
|
/// <summary> Returns true if this is the role representing all users in a server. </summary>
|
||||||
public bool IsEveryone => Id == _serverId;
|
public bool IsEveryone => _serverId == null || Id == _serverId;
|
||||||
/// <summary> Returns a list of all members in this role. </summary>
|
/// <summary> Returns a list of all members in this role. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<User> Members => IsEveryone ? Server.Members : Server.Members.Where(x => x.HasRole(this));
|
public IEnumerable<User> Members => IsEveryone ? Server.Members : Server.Members.Where(x => x.HasRole(this));
|
||||||
|
//TODO: Add local members cache
|
||||||
|
|
||||||
internal Role(DiscordClient client, string id, string serverId)
|
internal Role(DiscordClient client, string id, string serverId)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
@@ -41,18 +42,17 @@ namespace Discord
|
|||||||
Permissions.Lock();
|
Permissions.Lock();
|
||||||
Color = new Color(0);
|
Color = new Color(0);
|
||||||
Color.Lock();
|
Color.Lock();
|
||||||
|
|
||||||
if (IsEveryone)
|
|
||||||
Position = int.MinValue;
|
|
||||||
}
|
}
|
||||||
internal override void OnCached()
|
internal override void OnCached()
|
||||||
{
|
{
|
||||||
|
//References
|
||||||
var server = _client.Servers[_serverId];
|
var server = _client.Servers[_serverId];
|
||||||
server.AddRole(this);
|
server.AddRole(this);
|
||||||
Server = server;
|
Server = server;
|
||||||
}
|
}
|
||||||
internal override void OnUncached()
|
internal override void OnUncached()
|
||||||
{
|
{
|
||||||
|
//References
|
||||||
var server = Server;
|
var server = Server;
|
||||||
if (server != null)
|
if (server != null)
|
||||||
server.RemoveRole(this);
|
server.RemoveRole(this);
|
||||||
|
|||||||
@@ -9,20 +9,10 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
public sealed class Server : CachedObject
|
public sealed class Server : CachedObject
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, bool> _bans;
|
|
||||||
private readonly ConcurrentDictionary<string, Channel> _channels;
|
|
||||||
private readonly ConcurrentDictionary<string, User> _members;
|
|
||||||
private readonly ConcurrentDictionary<string, Role> _roles;
|
|
||||||
private readonly ConcurrentDictionary<string, Invite> _invites;
|
|
||||||
|
|
||||||
private string _ownerId;
|
|
||||||
|
|
||||||
/// <summary> Returns the name of this channel. </summary>
|
/// <summary> Returns the name of this channel. </summary>
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
/// <summary> Returns the current logged-in user's data for this server. </summary>
|
/// <summary> Returns the current logged-in user's data for this server. </summary>
|
||||||
public User CurrentMember { get; internal set; }
|
public User CurrentMember { get; internal set; }
|
||||||
/// <summary> Returns true if this is a virtual server used by Discord.Net and not a real Discord server. </summary>
|
|
||||||
public bool IsVirtual { get; internal set; }
|
|
||||||
|
|
||||||
/// <summary> Returns the amount of time (in seconds) a user must be inactive for until they are automatically moved to the AFK channel (see AFKChannel). </summary>
|
/// <summary> Returns the amount of time (in seconds) a user must be inactive for until they are automatically moved to the AFK channel (see AFKChannel). </summary>
|
||||||
public int AFKTimeout { get; private set; }
|
public int AFKTimeout { get; private set; }
|
||||||
@@ -38,49 +28,49 @@ namespace Discord
|
|||||||
/// <summary> Returns the user that first created this server. </summary>
|
/// <summary> Returns the user that first created this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public User Owner { get; private set; }
|
public User Owner { get; private set; }
|
||||||
|
private string _ownerId;
|
||||||
|
|
||||||
/// <summary> Returns the id of the AFK voice channel for this server (see AFKTimeout). </summary>
|
|
||||||
public string AFKChannelId { get; private set; }
|
|
||||||
/// <summary> Returns the AFK voice channel for this server (see AFKTimeout). </summary>
|
/// <summary> Returns the AFK voice channel for this server (see AFKTimeout). </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Channel AFKChannel => _client.Channels[AFKChannelId];
|
public Channel AFKChannel { get; private set; }
|
||||||
|
|
||||||
/// <summary> Returns the id of the default channel for this server. </summary>
|
|
||||||
public string DefaultChannelId => Id;
|
|
||||||
/// <summary> Returns the default channel for this server. </summary>
|
/// <summary> Returns the default channel for this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Channel DefaultChannel => _client.Channels[DefaultChannelId];
|
public Channel DefaultChannel { get; private set; }
|
||||||
|
|
||||||
/// <summary> Returns a collection of the ids of all users banned on this server. </summary>
|
/// <summary> Returns a collection of the ids of all users banned on this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<string> Bans => _bans.Select(x => x.Key);
|
public IEnumerable<string> Bans => _bans.Select(x => x.Key);
|
||||||
|
private ConcurrentDictionary<string, bool> _bans;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all channels within this server. </summary>
|
/// <summary> Returns a collection of all channels within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Channel> Channels => _channels.Select(x => _client.Channels[x.Key]);
|
public IEnumerable<Channel> Channels => _channels.Select(x => x.Value);
|
||||||
/// <summary> Returns a collection of all channels within this server. </summary>
|
/// <summary> Returns a collection of all channels within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Channel> TextChannels => _channels.Select(x => _client.Channels[x.Key]).Where(x => x.Type == ChannelType.Text);
|
public IEnumerable<Channel> TextChannels => _channels.Select(x => x.Value).Where(x => x.Type == ChannelType.Text);
|
||||||
/// <summary> Returns a collection of all channels within this server. </summary>
|
/// <summary> Returns a collection of all channels within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Channel> VoiceChannels => _channels.Select(x => _client.Channels[x.Key]).Where(x => x.Type == ChannelType.Voice);
|
public IEnumerable<Channel> VoiceChannels => _channels.Select(x => x.Value).Where(x => x.Type == ChannelType.Voice);
|
||||||
|
private ConcurrentDictionary<string, Channel> _channels;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all invites to this server. </summary>
|
/// <summary> Returns a collection of all invites to this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Invite> Invites => _invites.Values;
|
public IEnumerable<Invite> Invites => _invites.Values;
|
||||||
|
private ConcurrentDictionary<string, Invite> _invites;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all users within this server with their server-specific data. </summary>
|
/// <summary> Returns a collection of all users within this server with their server-specific data. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<User> Members => _members.Select(x => _client.Users[x.Key, Id]);
|
public IEnumerable<User> Members => _members.Select(x => x.Value);
|
||||||
|
private ConcurrentDictionary<string, User> _members;
|
||||||
|
|
||||||
/// <summary> Return the id of the role representing all users in a server. </summary>
|
|
||||||
public string EveryoneRoleId => Id;
|
|
||||||
/// <summary> Return the the role representing all users in a server. </summary>
|
/// <summary> Return the the role representing all users in a server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Role EveryoneRole => _client.Roles[EveryoneRoleId];
|
public Role EveryoneRole { get; private set; }
|
||||||
/// <summary> Returns a collection of all roles within this server. </summary>
|
/// <summary> Returns a collection of all roles within this server. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Role> Roles => _roles.Select(x => _client.Roles[x.Key]);
|
public IEnumerable<Role> Roles => _roles.Select(x => x.Value);
|
||||||
|
private ConcurrentDictionary<string, Role> _roles;
|
||||||
|
|
||||||
internal Server(DiscordClient client, string id)
|
internal Server(DiscordClient client, string id)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
@@ -98,30 +88,37 @@ namespace Discord
|
|||||||
internal override void OnUncached()
|
internal override void OnUncached()
|
||||||
{
|
{
|
||||||
//Global Cache
|
//Global Cache
|
||||||
var channels = _client.Channels;
|
var globalChannels = _client.Channels;
|
||||||
foreach (var channel in _channels)
|
var channels = _channels;
|
||||||
channels.TryRemove(channel.Key);
|
foreach (var channel in channels)
|
||||||
|
globalChannels.TryRemove(channel.Key);
|
||||||
|
channels.Clear();
|
||||||
|
|
||||||
var members = _client.Users;
|
var globalMembers = _client.Users;
|
||||||
foreach (var user in _members)
|
var members = _members;
|
||||||
members.TryRemove(user.Key, Id);
|
foreach (var user in members)
|
||||||
|
globalMembers.TryRemove(user.Key, Id);
|
||||||
|
members.Clear();
|
||||||
|
|
||||||
var roles = _client.Roles;
|
var globalRoles = _client.Roles;
|
||||||
foreach (var role in _roles)
|
var roles = _roles;
|
||||||
roles.TryRemove(role.Key);
|
foreach (var role in roles)
|
||||||
|
globalRoles.TryRemove(role.Key);
|
||||||
|
roles.Clear();
|
||||||
|
|
||||||
//Local Cache
|
//Local Cache
|
||||||
foreach (var invite in _invites)
|
var invites = _invites;
|
||||||
|
foreach (var invite in invites)
|
||||||
invite.Value.Uncache();
|
invite.Value.Uncache();
|
||||||
_invites.Clear();
|
invites.Clear();
|
||||||
|
|
||||||
_bans.Clear();
|
_bans.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Update(GuildInfo model)
|
internal void Update(GuildInfo model)
|
||||||
{
|
{
|
||||||
//Can be null
|
//Can be null
|
||||||
AFKChannelId = model.AFKChannelId;
|
AFKChannel = _client.Channels[model.AFKChannelId];
|
||||||
|
|
||||||
if (model.AFKTimeout != null)
|
if (model.AFKTimeout != null)
|
||||||
AFKTimeout = model.AFKTimeout.Value;
|
AFKTimeout = model.AFKTimeout.Value;
|
||||||
@@ -139,13 +136,13 @@ namespace Discord
|
|||||||
|
|
||||||
if (model.Roles != null)
|
if (model.Roles != null)
|
||||||
{
|
{
|
||||||
var roles = _client.Roles;
|
var roleCache = _client.Roles;
|
||||||
foreach (var subModel in model.Roles)
|
foreach (var x in model.Roles)
|
||||||
{
|
{
|
||||||
var role = roles.GetOrAdd(subModel.Id, Id);
|
var role = roleCache.GetOrAdd(x.Id, Id);
|
||||||
role.Update(subModel);
|
role.Update(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal void Update(ExtendedGuildInfo model)
|
internal void Update(ExtendedGuildInfo model)
|
||||||
{
|
{
|
||||||
@@ -158,22 +155,22 @@ namespace Discord
|
|||||||
channel.Update(subModel);
|
channel.Update(subModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
var users = _client.GlobalUsers;
|
var usersCache = _client.GlobalUsers;
|
||||||
var members = _client.Users;
|
var membersCache = _client.Users;
|
||||||
foreach (var subModel in model.Members)
|
foreach (var subModel in model.Members)
|
||||||
{
|
{
|
||||||
var member = members.GetOrAdd(subModel.User.Id, Id);
|
var member = membersCache.GetOrAdd(subModel.User.Id, Id);
|
||||||
member.Update(subModel);
|
member.Update(subModel);
|
||||||
}
|
}
|
||||||
foreach (var subModel in model.VoiceStates)
|
foreach (var subModel in model.VoiceStates)
|
||||||
{
|
{
|
||||||
var member = members[subModel.UserId, Id];
|
var member = membersCache[subModel.UserId, Id];
|
||||||
if (member != null)
|
if (member != null)
|
||||||
member.Update(subModel);
|
member.Update(subModel);
|
||||||
}
|
}
|
||||||
foreach (var subModel in model.Presences)
|
foreach (var subModel in model.Presences)
|
||||||
{
|
{
|
||||||
var member = members[subModel.User.Id, Id];
|
var member = membersCache[subModel.User.Id, Id];
|
||||||
if (member != null)
|
if (member != null)
|
||||||
member.Update(subModel);
|
member.Update(subModel);
|
||||||
}
|
}
|
||||||
@@ -193,9 +190,13 @@ namespace Discord
|
|||||||
|
|
||||||
internal void AddChannel(Channel channel)
|
internal void AddChannel(Channel channel)
|
||||||
{
|
{
|
||||||
_channels.TryAdd(channel.Id, channel);
|
if (_channels.TryAdd(channel.Id, channel))
|
||||||
foreach (var member in Members)
|
{
|
||||||
member.AddChannel(channel);
|
if (channel.Id == Id)
|
||||||
|
DefaultChannel = channel;
|
||||||
|
foreach (var member in Members)
|
||||||
|
member.AddChannel(channel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
internal void RemoveChannel(Channel channel)
|
internal void RemoveChannel(Channel channel)
|
||||||
{
|
{
|
||||||
@@ -213,7 +214,7 @@ namespace Discord
|
|||||||
foreach (var channel in Channels)
|
foreach (var channel in Channels)
|
||||||
{
|
{
|
||||||
member.AddChannel(channel);
|
member.AddChannel(channel);
|
||||||
channel.InvalidatePermissionsCache(member.Id);
|
channel.InvalidatePermissionsCache(member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal void RemoveMember(User member)
|
internal void RemoveMember(User member)
|
||||||
@@ -221,13 +222,27 @@ namespace Discord
|
|||||||
foreach (var channel in Channels)
|
foreach (var channel in Channels)
|
||||||
{
|
{
|
||||||
member.RemoveChannel(channel);
|
member.RemoveChannel(channel);
|
||||||
channel.InvalidatePermissionsCache(member.Id);
|
channel.InvalidatePermissionsCache(member);
|
||||||
}
|
}
|
||||||
_members.TryRemove(member.Id, out member);
|
_members.TryRemove(member.Id, out member);
|
||||||
}
|
}
|
||||||
internal void HasMember(User user) => _members.ContainsKey(user.Id);
|
internal void HasMember(User user) => _members.ContainsKey(user.Id);
|
||||||
|
|
||||||
internal void AddRole(Role role) => _roles.TryAdd(role.Id, role);
|
internal void AddRole(Role role)
|
||||||
internal void RemoveRole(Role role) => _roles.TryRemove(role.Id, out role);
|
{
|
||||||
|
if (_roles.TryAdd(role.Id, role))
|
||||||
|
{
|
||||||
|
if (role.Id == Id)
|
||||||
|
EveryoneRole = role;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal void RemoveRole(Role role)
|
||||||
|
{
|
||||||
|
if (_roles.TryRemove(role.Id, out role))
|
||||||
|
{
|
||||||
|
if (role.Id == Id)
|
||||||
|
EveryoneRole = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,17 +9,14 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
public class User : CachedObject
|
public class User : CachedObject
|
||||||
{
|
{
|
||||||
private static readonly string[] _initialRoleIds = new string[0];
|
|
||||||
|
|
||||||
internal static string GetId(string userId, string serverId) => (serverId ?? "Private") + '_' + userId;
|
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 string[] _roleIds;
|
|
||||||
|
|
||||||
/// <summary> Returns a unique identifier combining this user's id with its server's. </summary>
|
/// <summary> Returns a unique identifier combining this user's id with its server's. </summary>
|
||||||
internal string UniqueId => GetId(Id, ServerId);
|
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>
|
||||||
@@ -52,48 +49,55 @@ namespace Discord
|
|||||||
private DateTime _lastOnline;
|
private DateTime _lastOnline;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
internal GlobalUser GlobalUser => _client.GlobalUsers[Id];
|
internal GlobalUser GlobalUser { get; private set; }
|
||||||
|
|
||||||
public string ServerId { get; }
|
|
||||||
[JsonIgnore]
|
|
||||||
public Server Server => _client.Servers[ServerId];
|
|
||||||
|
|
||||||
public string VoiceChannelId { get; private set; }
|
|
||||||
[JsonIgnore]
|
|
||||||
public Channel VoiceChannel => _client.Channels[VoiceChannelId];
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Role> Roles => _roleIds.Select(x => _client.Roles[x]);
|
public Server Server { get; private set; }
|
||||||
|
private string _serverId;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public Channel VoiceChannel { get; private set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public IEnumerable<Role> Roles => _roles.Select(x => x.Value);
|
||||||
|
private Dictionary<string, Role> _roles;
|
||||||
|
|
||||||
/// <summary> Returns a collection of all messages this user has sent on this server that are still in cache. </summary>
|
/// <summary> Returns a collection of all messages this user has sent on this server that are still in cache. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Message> Messages => _client.Messages.Where(x => x.UserId == Id && x.Server.Id == ServerId);
|
public IEnumerable<Message> Messages => _client.Messages.Where(x => x.UserId == Id && x.Server.Id == _serverId);
|
||||||
|
|
||||||
/// <summary> Returns a collection of all channels this user is a member of. </summary>
|
/// <summary> Returns a collection of all channels this user is a member of. </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IEnumerable<Channel> Channels => _client.Channels.Where(x => x.Server.Id == ServerId && x.Members == this);
|
public IEnumerable<Channel> Channels => _channels.Select(x => x.Value);
|
||||||
|
|
||||||
internal User(DiscordClient client, string id, string serverId)
|
internal User(DiscordClient client, string id, string serverId)
|
||||||
: base(client, id)
|
: base(client, id)
|
||||||
{
|
{
|
||||||
ServerId = serverId;
|
_serverId = serverId;
|
||||||
Status = UserStatus.Offline;
|
Status = UserStatus.Offline;
|
||||||
_roleIds = _initialRoleIds;
|
//_roles = new Dictionary<string, Role>();
|
||||||
_channels = new ConcurrentDictionary<string, Channel>();
|
_channels = new ConcurrentDictionary<string, Channel>();
|
||||||
_permissions = new ConcurrentDictionary<string, ChannelPermissions>();
|
_permissions = new ConcurrentDictionary<string, ChannelPermissions>();
|
||||||
_serverPermissions = new ServerPermissions();
|
_serverPermissions = new ServerPermissions();
|
||||||
}
|
}
|
||||||
internal override void OnCached()
|
internal override void OnCached()
|
||||||
{
|
{
|
||||||
var server = Server;
|
var server = _client.Servers[_serverId];
|
||||||
server.AddMember(this);
|
if (server != null)
|
||||||
if (Id == _client.CurrentUserId)
|
{
|
||||||
server.CurrentMember = this;
|
server.AddMember(this);
|
||||||
|
if (Id == _client.CurrentUserId)
|
||||||
|
server.CurrentMember = this;
|
||||||
|
Server = server;
|
||||||
|
}
|
||||||
|
|
||||||
var user = GlobalUser;
|
var user = _client.GlobalUsers.GetOrAdd(Id);
|
||||||
if (server == null || !server.IsVirtual)
|
user.AddUser(this);
|
||||||
user.AddUser(this);
|
GlobalUser = user;
|
||||||
}
|
}
|
||||||
internal override void OnUncached()
|
internal override void OnUncached()
|
||||||
{
|
{
|
||||||
|
//References
|
||||||
var server = Server;
|
var server = Server;
|
||||||
if (server != null)
|
if (server != null)
|
||||||
{
|
{
|
||||||
@@ -101,9 +105,12 @@ namespace Discord
|
|||||||
if (Id == _client.CurrentUserId)
|
if (Id == _client.CurrentUserId)
|
||||||
server.CurrentMember = null;
|
server.CurrentMember = null;
|
||||||
}
|
}
|
||||||
|
Server = null;
|
||||||
|
|
||||||
var globalUser = GlobalUser;
|
var globalUser = GlobalUser;
|
||||||
if (globalUser != null)
|
if (globalUser != null)
|
||||||
globalUser.RemoveUser(this);
|
globalUser.RemoveUser(this);
|
||||||
|
GlobalUser = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => Id;
|
public override string ToString() => Id;
|
||||||
@@ -124,7 +131,7 @@ namespace Discord
|
|||||||
if (model.JoinedAt.HasValue)
|
if (model.JoinedAt.HasValue)
|
||||||
JoinedAt = model.JoinedAt.Value;
|
JoinedAt = model.JoinedAt.Value;
|
||||||
if (model.Roles != null)
|
if (model.Roles != null)
|
||||||
UpdateRoles(model.Roles);
|
UpdateRoles(model.Roles.Select(x => _client.Roles[x]));
|
||||||
|
|
||||||
UpdateServerPermissions();
|
UpdateServerPermissions();
|
||||||
}
|
}
|
||||||
@@ -142,7 +149,7 @@ namespace Discord
|
|||||||
Update(model.User as UserReference);
|
Update(model.User as UserReference);
|
||||||
|
|
||||||
if (model.Roles != null)
|
if (model.Roles != null)
|
||||||
UpdateRoles(model.Roles);
|
UpdateRoles(model.Roles.Select(x => _client.Roles[x]));
|
||||||
if (model.Status != null && Status != model.Status)
|
if (model.Status != null && Status != model.Status)
|
||||||
{
|
{
|
||||||
Status = UserStatus.FromString(model.Status);
|
Status = UserStatus.FromString(model.Status);
|
||||||
@@ -165,7 +172,7 @@ namespace Discord
|
|||||||
Token = model.Token;
|
Token = model.Token;
|
||||||
|
|
||||||
if (model.ChannelId != null)
|
if (model.ChannelId != null)
|
||||||
VoiceChannelId = model.ChannelId;
|
VoiceChannel = _client.Channels[model.ChannelId];
|
||||||
if (model.IsSelfDeafened != null)
|
if (model.IsSelfDeafened != null)
|
||||||
IsSelfDeafened = model.IsSelfDeafened.Value;
|
IsSelfDeafened = model.IsSelfDeafened.Value;
|
||||||
if (model.IsSelfMuted != null)
|
if (model.IsSelfMuted != null)
|
||||||
@@ -173,14 +180,16 @@ namespace Discord
|
|||||||
if (model.IsServerSuppressed != null)
|
if (model.IsServerSuppressed != null)
|
||||||
IsServerSuppressed = model.IsServerSuppressed.Value;
|
IsServerSuppressed = model.IsServerSuppressed.Value;
|
||||||
}
|
}
|
||||||
private void UpdateRoles(string[] roleIds)
|
private void UpdateRoles(IEnumerable<Role> roles)
|
||||||
{
|
{
|
||||||
//Set roles, with the everyone role added too
|
var newRoles = roles.ToDictionary(x => x.Id, x => x);
|
||||||
string[] newRoles = new string[roleIds.Length + 1];
|
Role everyone;
|
||||||
newRoles[0] = ServerId; //Everyone
|
if (_serverId != null)
|
||||||
for (int i = 0; i < roleIds.Length; i++)
|
everyone = Server.EveryoneRole;
|
||||||
newRoles[i + 1] = roleIds[i];
|
else
|
||||||
_roleIds = newRoles;
|
everyone = _client.Roles.VirtualEveryone;
|
||||||
|
newRoles.Add(everyone.Id, everyone);
|
||||||
|
_roles = newRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void UpdateActivity(DateTime? activity = null)
|
internal void UpdateActivity(DateTime? activity = null)
|
||||||
@@ -191,7 +200,7 @@ namespace Discord
|
|||||||
|
|
||||||
internal void UpdateChannelPermissions(Channel channel)
|
internal void UpdateChannelPermissions(Channel channel)
|
||||||
{
|
{
|
||||||
if (_roleIds == null) return; // We don't have all our data processed yet, this will be called again soon
|
if (_roles == null) return; // We don't have all our data processed yet, this will be called again soon
|
||||||
|
|
||||||
var server = Server;
|
var server = Server;
|
||||||
if (server == null || channel.Server != server) return;
|
if (server == null || channel.Server != server) return;
|
||||||
@@ -225,14 +234,14 @@ namespace Discord
|
|||||||
if (newPermissions != oldPermissions)
|
if (newPermissions != oldPermissions)
|
||||||
{
|
{
|
||||||
permissions.SetRawValueInternal(newPermissions);
|
permissions.SetRawValueInternal(newPermissions);
|
||||||
channel.InvalidMembersCache();
|
channel.InvalidateMembersCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
permissions.SetRawValueInternal(newPermissions);
|
permissions.SetRawValueInternal(newPermissions);
|
||||||
}
|
}
|
||||||
internal void UpdateServerPermissions()
|
internal void UpdateServerPermissions()
|
||||||
{
|
{
|
||||||
if (_roleIds == null) return; // We don't have all our data processed yet, this will be called again soon
|
if (_roles == null) return; // We don't have all our data processed yet, this will be called again soon
|
||||||
|
|
||||||
var server = Server;
|
var server = Server;
|
||||||
if (server == null) return;
|
if (server == null) return;
|
||||||
@@ -290,7 +299,7 @@ namespace Discord
|
|||||||
{
|
{
|
||||||
if (role == null) throw new ArgumentNullException(nameof(role));
|
if (role == null) throw new ArgumentNullException(nameof(role));
|
||||||
|
|
||||||
return _roleIds.Contains(role.Id);
|
return _roles.ContainsKey(role.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,21 +53,21 @@ namespace Discord.Net.WebSockets
|
|||||||
_connectedEvent = new ManualResetEventSlim(false);
|
_connectedEvent = new ManualResetEventSlim(false);
|
||||||
|
|
||||||
_engine = new WebSocketSharpEngine(this, client.Config);
|
_engine = new WebSocketSharpEngine(this, client.Config);
|
||||||
_engine.BinaryMessage += async (s, e) =>
|
_engine.BinaryMessage += (s, e) =>
|
||||||
{
|
{
|
||||||
using (var compressed = new MemoryStream(e.Data, 2, e.Data.Length - 2))
|
using (var compressed = new MemoryStream(e.Data, 2, e.Data.Length - 2))
|
||||||
using (var decompressed = new MemoryStream())
|
using (var decompressed = new MemoryStream())
|
||||||
{
|
{
|
||||||
using (var zlib = new DeflateStream(compressed, CompressionMode.Decompress))
|
using (var zlib = new DeflateStream(compressed, CompressionMode.Decompress))
|
||||||
await zlib.CopyToAsync(decompressed);
|
zlib.CopyTo(decompressed);
|
||||||
decompressed.Position = 0;
|
decompressed.Position = 0;
|
||||||
using (var reader = new StreamReader(decompressed))
|
using (var reader = new StreamReader(decompressed))
|
||||||
await ProcessMessage(await reader.ReadToEndAsync());
|
ProcessMessage(reader.ReadToEnd()).Wait();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_engine.TextMessage += async (s, e) =>
|
_engine.TextMessage += (s, e) =>
|
||||||
{
|
{
|
||||||
await ProcessMessage(e.Message);
|
/*await*/ ProcessMessage(e.Message).Wait();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user