Browse Source

Added UsePermissionsCache config, fixed a few permission bugs

tags/docs-0.9
RogueException 9 years ago
parent
commit
a44e08bba1
5 changed files with 154 additions and 114 deletions
  1. +59
    -59
      src/Discord.Net.Shared/TaskExtensions.cs
  2. +8
    -8
      src/Discord.Net.Shared/TaskHelper.cs
  3. +5
    -2
      src/Discord.Net/DiscordConfig.cs
  4. +77
    -37
      src/Discord.Net/Models/Channel.cs
  5. +5
    -8
      src/Discord.Net/Models/Server.cs

+ 59
- 59
src/Discord.Net.Shared/TaskExtensions.cs View File

@@ -5,64 +5,64 @@ using System.Threading.Tasks;
namespace Discord namespace Discord
{ {
internal static class TaskExtensions internal static class TaskExtensions
{
public static async Task Timeout(this Task task, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
await task.ConfigureAwait(false);
}
public static async Task<T> Timeout<T>(this Task<T> task, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
return await task.ConfigureAwait(false);
}
public static async Task Timeout(this Task task, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
await task.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}
public static async Task<T> Timeout<T>(this Task<T> task, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
return await task.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}
{
public static async Task Timeout(this Task task, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
await task.ConfigureAwait(false);
}
public static async Task<T> Timeout<T>(this Task<T> task, int milliseconds)
{
Task timeoutTask = Task.Delay(milliseconds);
Task finishedTask = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false);
if (finishedTask == timeoutTask)
throw new TimeoutException();
else
return await task.ConfigureAwait(false);
}
public static async Task Timeout(this Task task, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
await task.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}
public static async Task<T> Timeout<T>(this Task<T> task, int milliseconds, CancellationTokenSource timeoutToken)
{
try
{
timeoutToken.CancelAfter(milliseconds);
return await task.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
if (timeoutToken.IsCancellationRequested)
throw new TimeoutException();
throw;
}
}


public static async Task Wait(this CancellationTokenSource tokenSource)
{
var token = tokenSource.Token;
try { await Task.Delay(-1, token).ConfigureAwait(false); }
catch (OperationCanceledException) { } //Expected
}
public static async Task Wait(this CancellationToken token)
{
try { await Task.Delay(-1, token).ConfigureAwait(false); }
catch (OperationCanceledException) { } //Expected
}
}
public static async Task Wait(this CancellationTokenSource tokenSource)
{
var token = tokenSource.Token;
try { await Task.Delay(-1, token).ConfigureAwait(false); }
catch (OperationCanceledException) { } //Expected
}
public static async Task Wait(this CancellationToken token)
{
try { await Task.Delay(-1, token).ConfigureAwait(false); }
catch (OperationCanceledException) { } //Expected
}
}
} }

+ 8
- 8
src/Discord.Net.Shared/TaskHelper.cs View File

@@ -2,12 +2,12 @@


namespace Discord namespace Discord
{ {
internal static class TaskHelper
{
public static Task CompletedTask { get; }
static TaskHelper()
{
CompletedTask = Task.Delay(0);
}
}
internal static class TaskHelper
{
public static Task CompletedTask { get; }
static TaskHelper()
{
CompletedTask = Task.Delay(0);
}
}
} }

+ 5
- 2
src/Discord.Net/DiscordConfig.cs View File

@@ -83,8 +83,11 @@ namespace Discord
/// <summary> Gets or sets the number of messages per channel that should be kept in cache. Setting this to zero disables the message cache entirely. </summary> /// <summary> Gets or sets the number of messages per channel that should be kept in cache. Setting this to zero disables the message cache entirely. </summary>
public int MessageCacheSize { get { return _messageCacheSize; } set { SetValue(ref _messageCacheSize, value); } } public int MessageCacheSize { get { return _messageCacheSize; } set { SetValue(ref _messageCacheSize, value); } }
private int _messageCacheSize = 100; private int _messageCacheSize = 100;
/// <summary> Maintains the LastActivity property for users, showing when they last made an action (sent message, joined server, typed, etc). </summary>
public bool TrackActivity { get { return _trackActivity; } set { SetValue(ref _trackActivity, value); } }
/// <summary> Gets or sets whether the permissions cache should be used. This makes operations such as User.GetPermissions(Channel), User.ServerPermissions and Channel.Members </summary>
public bool UsePermissionsCache { get { return _usePermissionsCache; } set { SetValue(ref _usePermissionsCache, value); } }
private bool _usePermissionsCache = true;
/// <summary> Maintains the LastActivity property for users, showing when they last made an action (sent message, joined server, typed, etc). </summary>
public bool TrackActivity { get { return _trackActivity; } set { SetValue(ref _trackActivity, value); } }
private bool _trackActivity = true; private bool _trackActivity = true;
} }
} }

+ 77
- 37
src/Discord.Net/Models/Channel.cs View File

@@ -68,12 +68,30 @@ namespace Discord
{ {
get get
{ {
if (Type == ChannelType.Text)
return _members.Values.Where(x => x.Permissions.ReadMessages == true).Select(x => x.User);
else if (Type == ChannelType.Voice)
return _members.Values.Select(x => x.User).Where(x => x.VoiceChannel == this);
else
return Enumerable.Empty<User>();
if (IsPrivate)
return _members.Values.Select(x => x.User);
if (_client.Config.UsePermissionsCache)
{
if (Type == ChannelType.Text)
return _members.Values.Where(x => x.Permissions.ReadMessages == true).Select(x => x.User);
else if (Type == ChannelType.Voice)
return _members.Values.Select(x => x.User).Where(x => x.VoiceChannel == this);
}
else
{
if (Type == ChannelType.Text)
{
ChannelPermissions perms = new ChannelPermissions();
return Server.Members.Where(x =>
{
UpdatePermissions(x, perms);
return perms.ReadMessages == true;
});
}
else if (Type == ChannelType.Voice)
return Server.Members.Where(x => x.VoiceChannel == this);
}
return Enumerable.Empty<User>();
} }
} }
[JsonProperty] [JsonProperty]
@@ -115,13 +133,13 @@ namespace Discord
x.Global.PrivateChannel = null; x.Global.PrivateChannel = null;
}); });
_permissionOverwrites = new PermissionOverwrite[0]; _permissionOverwrites = new PermissionOverwrite[0];
_members = new ConcurrentDictionary<long, ChannelMember>();
_members = new ConcurrentDictionary<long, ChannelMember>();


if (recipientId != null)
{
AddMember(client.PrivateUser);
AddMember(Recipient);
}
if (recipientId != null)
{
AddMember(client.PrivateUser);
AddMember(Recipient);
}


//Local Cache //Local Cache
if (client.Config.MessageCacheSize > 0) if (client.Config.MessageCacheSize > 0)
@@ -190,40 +208,61 @@ 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 AddMember(User user) internal void AddMember(User user)
{
var member = new ChannelMember(user);
{
if (!_client.Config.UsePermissionsCache)
return;

var member = new ChannelMember(user);
if (_members.TryAdd(user.Id, member)) if (_members.TryAdd(user.Id, member))
UpdatePermissions(user, member.Permissions); UpdatePermissions(user, member.Permissions);
} }
internal void RemoveMember(User user) internal void RemoveMember(User user)
{
ChannelMember ignored;
{
if (!_client.Config.UsePermissionsCache)
return;

ChannelMember ignored;
_members.TryRemove(user.Id, out ignored); _members.TryRemove(user.Id, out ignored);
} }


internal ChannelPermissions GetPermissions(User user)
{
ChannelMember member;
if (_members.TryGetValue(user.Id, out member))
return member.Permissions;
else
return null;
internal ChannelPermissions GetPermissions(User user)
{
if (_client.Config.UsePermissionsCache)
{
ChannelMember member;
if (_members.TryGetValue(user.Id, out member))
return member.Permissions;
else
return null;
}
else
{
ChannelPermissions perms = new ChannelPermissions();
UpdatePermissions(user, perms);
return perms;
}
} }
internal void UpdatePermissions() internal void UpdatePermissions()
{
foreach (var pair in _members)
{
ChannelMember member = pair.Value;
UpdatePermissions(member.User, member.Permissions);
}
{
if (!_client.Config.UsePermissionsCache)
return;

foreach (var pair in _members)
{
ChannelMember member = pair.Value;
UpdatePermissions(member.User, member.Permissions);
}
} }
internal void UpdatePermissions(User user)
{
ChannelMember member;
if (_members.TryGetValue(user.Id, out member))
UpdatePermissions(member.User, member.Permissions);
internal void UpdatePermissions(User user)
{
if (!_client.Config.UsePermissionsCache)
return;

ChannelMember member;
if (_members.TryGetValue(user.Id, out member))
UpdatePermissions(member.User, member.Permissions);
} }
private void UpdatePermissions(User user, ChannelPermissions permissions)
internal void UpdatePermissions(User user, ChannelPermissions permissions)
{ {
uint newPermissions = 0; uint newPermissions = 0;
var server = Server; var server = Server;
@@ -236,7 +275,7 @@ namespace Discord
//Start with this user's server permissions //Start with this user's server permissions
newPermissions = server.GetPermissions(user).RawValue; newPermissions = server.GetPermissions(user).RawValue;


if (IsPrivate || server.Owner == user)
if (IsPrivate || user.IsOwner)
newPermissions = mask; //Owners always have all permissions newPermissions = mask; //Owners always have all permissions
else else
{ {
@@ -263,7 +302,8 @@ namespace Discord
else else
newPermissions = mask; //Private messages always have all permissions newPermissions = mask; //Private messages always have all permissions


permissions.SetRawValueInternal(newPermissions);
if (newPermissions != permissions.RawValue)
permissions.SetRawValueInternal(newPermissions);
} }


public override bool Equals(object obj) => obj is Channel && (obj as Channel).Id == Id; public override bool Equals(object obj) => obj is Channel && (obj as Channel).Id == Id;


+ 5
- 8
src/Discord.Net/Models/Server.cs View File

@@ -38,14 +38,11 @@ namespace Discord
/// <summary> Returns the URL to this user's current avatar. </summary> /// <summary> Returns the URL to this user's current avatar. </summary>
public string IconUrl => IconId != null ? Endpoints.ServerIcon(Id, IconId) : null; public string IconUrl => IconId != null ? Endpoints.ServerIcon(Id, IconId) : null;


/// <summary> Returns true if the current user created this server. </summary>
public bool IsOwner => _client.CurrentUser.Id == _owner.Id;

/// <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 => _owner.Value; public User Owner => _owner.Value;
[JsonProperty] [JsonProperty]
private long? OwnerId => _owner.Id;
internal long? OwnerId => _owner.Id;
private Reference<User> _owner; private Reference<User> _owner;


/// <summary> Returns the AFK voice channel for this server (see AFKTimeout). </summary> /// <summary> Returns the AFK voice channel for this server (see AFKTimeout). </summary>
@@ -110,6 +107,7 @@ namespace Discord
internal override bool LoadReferences() internal override bool LoadReferences()
{ {
_afkChannel.Load(); _afkChannel.Load();
_owner.Load();
return true; return true;
} }
internal override void UnloadReferences() internal override void UnloadReferences()
@@ -185,7 +183,7 @@ namespace Discord
} }
var usersCache = _client.Users; var usersCache = _client.Users;
foreach (var subModel in model.Members)
foreach (var subModel in model.Members)
{ {
var user = usersCache.GetOrAdd(subModel.User.Id, Id); var user = usersCache.GetOrAdd(subModel.User.Id, Id);
user.Update(subModel); user.Update(subModel);
@@ -279,10 +277,9 @@ namespace Discord
} }
private void UpdatePermissions(User user, ServerPermissions permissions) private void UpdatePermissions(User user, ServerPermissions permissions)
{ {
uint oldPermissions = permissions.RawValue;
uint newPermissions = 0; uint newPermissions = 0;


if (Owner == user)
if (user.IsOwner)
newPermissions = ServerPermissions.All.RawValue; newPermissions = ServerPermissions.All.RawValue;
else else
{ {
@@ -294,7 +291,7 @@ namespace Discord
if (BitHelper.GetBit(newPermissions, (int)PermissionsBits.ManageRolesOrPermissions)) if (BitHelper.GetBit(newPermissions, (int)PermissionsBits.ManageRolesOrPermissions))
newPermissions = ServerPermissions.All.RawValue; newPermissions = ServerPermissions.All.RawValue;


if (newPermissions != oldPermissions)
if (newPermissions != permissions.RawValue)
{ {
permissions.SetRawValueInternal(newPermissions); permissions.SetRawValueInternal(newPermissions);
foreach (var channel in _channels) foreach (var channel in _channels)


Loading…
Cancel
Save