Browse Source

Users can no longer directly request user downloads.

tags/1.0-rc
RogueException 8 years ago
parent
commit
b00b69234f
3 changed files with 40 additions and 46 deletions
  1. +4
    -10
      src/Discord.Net.WebSocket/DiscordShardedClient.cs
  2. +35
    -35
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  3. +1
    -1
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

+ 4
- 10
src/Discord.Net.WebSocket/DiscordShardedClient.cs View File

@@ -112,12 +112,12 @@ namespace Discord.WebSocket
} }


/// <inheritdoc /> /// <inheritdoc />
public async Task ConnectAsync(bool waitForGuilds = true)
public async Task ConnectAsync()
{ {
await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
{ {
await ConnectInternalAsync(waitForGuilds).ConfigureAwait(false);
await ConnectInternalAsync().ConfigureAwait(false);
} }
catch catch
{ {
@@ -126,10 +126,10 @@ namespace Discord.WebSocket
} }
finally { _connectionLock.Release(); } finally { _connectionLock.Release(); }
} }
private async Task ConnectInternalAsync(bool waitForGuilds)
private async Task ConnectInternalAsync()
{ {
await Task.WhenAll( await Task.WhenAll(
_shards.Select(x => x.ConnectAsync(waitForGuilds))
_shards.Select(x => x.ConnectAsync())
).ConfigureAwait(false); ).ConfigureAwait(false);


CurrentUser = _shards[0].CurrentUser; CurrentUser = _shards[0].CurrentUser;
@@ -253,12 +253,6 @@ namespace Discord.WebSocket
public RestVoiceRegion GetVoiceRegion(string id) public RestVoiceRegion GetVoiceRegion(string id)
=> _shards[0].GetVoiceRegion(id); => _shards[0].GetVoiceRegion(id);


/// <summary> Downloads the users list for all large guilds. </summary>
public async Task DownloadAllUsersAsync()
{
for (int i = 0; i < _shards.Length; i++)
await _shards[i].DownloadAllUsersAsync().ConfigureAwait(false);
}
/// <summary> Downloads the users list for the provided guilds, if they don't have a complete list. </summary> /// <summary> Downloads the users list for the provided guilds, if they don't have a complete list. </summary>
public async Task DownloadUsersAsync(IEnumerable<SocketGuild> guilds) public async Task DownloadUsersAsync(IEnumerable<SocketGuild> guilds)
{ {


+ 35
- 35
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -42,6 +42,7 @@ namespace Discord.WebSocket
private bool _canReconnect; private bool _canReconnect;
private DateTimeOffset? _statusSince; private DateTimeOffset? _statusSince;
private RestApplication _applicationInfo; private RestApplication _applicationInfo;
private ConcurrentHashSet<ulong> _downloadUsersFor;


/// <summary> Gets the shard of of this client. </summary> /// <summary> Gets the shard of of this client. </summary>
public int ShardId { get; } public int ShardId { get; }
@@ -61,7 +62,7 @@ namespace Discord.WebSocket
internal int ConnectionTimeout { get; private set; } internal int ConnectionTimeout { get; private set; }
internal UdpSocketProvider UdpSocketProvider { get; private set; } internal UdpSocketProvider UdpSocketProvider { get; private set; }
internal WebSocketProvider WebSocketProvider { get; private set; } internal WebSocketProvider WebSocketProvider { get; private set; }
internal bool DownloadUsersOnGuildAvailable { get; private set; }
internal bool AlwaysDownloadUsers { get; private set; }


internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient;
public new SocketSelfUser CurrentUser { get { return base.CurrentUser as SocketSelfUser; } private set { base.CurrentUser = value; } } public new SocketSelfUser CurrentUser { get { return base.CurrentUser as SocketSelfUser; } private set { base.CurrentUser = value; } }
@@ -84,9 +85,10 @@ namespace Discord.WebSocket
AudioMode = config.AudioMode; AudioMode = config.AudioMode;
UdpSocketProvider = config.UdpSocketProvider; UdpSocketProvider = config.UdpSocketProvider;
WebSocketProvider = config.WebSocketProvider; WebSocketProvider = config.WebSocketProvider;
DownloadUsersOnGuildAvailable = config.DownloadUsersOnGuildAvailable;
AlwaysDownloadUsers = config.AlwaysDownloadUsers;
ConnectionTimeout = config.ConnectionTimeout; ConnectionTimeout = config.ConnectionTimeout;
State = new ClientState(0, 0); State = new ClientState(0, 0);
_downloadUsersFor = new ConcurrentHashSet<ulong>();
_nextAudioId = 1; _nextAudioId = 1;
_gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : "Shard #" + ShardId); _gatewayLogger = LogManager.CreateLogger(ShardId == 0 && TotalShards == 1 ? "Gateway" : "Shard #" + ShardId);
@@ -119,14 +121,17 @@ namespace Discord.WebSocket
GuildUnavailable += async g => await _gatewayLogger.VerboseAsync($"Disconnected from {g.Name}").ConfigureAwait(false); GuildUnavailable += async g => await _gatewayLogger.VerboseAsync($"Disconnected from {g.Name}").ConfigureAwait(false);
LatencyUpdated += async (old, val) => await _gatewayLogger.VerboseAsync($"Latency = {val} ms").ConfigureAwait(false); LatencyUpdated += async (old, val) => await _gatewayLogger.VerboseAsync($"Latency = {val} ms").ConfigureAwait(false);


if (DownloadUsersOnGuildAvailable)
GuildAvailable += g =>
{ {
GuildAvailable += g =>
if (ConnectionState == ConnectionState.Connected && (AlwaysDownloadUsers || _downloadUsersFor.ContainsKey(g.Id)))
{ {
var _ = g.DownloadUsersAsync();
return Task.Delay(0);
};
}
if (!g.HasAllMembers)
{
var _ = g.DownloadUsersAsync();
}
}
return Task.Delay(0);
};


_voiceRegions = ImmutableDictionary.Create<string, RestVoiceRegion>(); _voiceRegions = ImmutableDictionary.Create<string, RestVoiceRegion>();
_largeGuilds = new ConcurrentQueue<ulong>(); _largeGuilds = new ConcurrentQueue<ulong>();
@@ -151,10 +156,11 @@ namespace Discord.WebSocket


_applicationInfo = null; _applicationInfo = null;
_voiceRegions = ImmutableDictionary.Create<string, RestVoiceRegion>(); _voiceRegions = ImmutableDictionary.Create<string, RestVoiceRegion>();
_downloadUsersFor.Clear();
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task ConnectAsync(bool waitForGuilds = true)
public async Task ConnectAsync()
{ {
await _connectionLock.WaitAsync().ConfigureAwait(false); await _connectionLock.WaitAsync().ConfigureAwait(false);
try try
@@ -162,13 +168,6 @@ namespace Discord.WebSocket
await ConnectInternalAsync(false).ConfigureAwait(false); await ConnectInternalAsync(false).ConfigureAwait(false);
} }
finally { _connectionLock.Release(); } finally { _connectionLock.Release(); }

if (waitForGuilds)
{
var downloadTask = _guildDownloadTask;
if (downloadTask != null)
await _guildDownloadTask.ConfigureAwait(false);
}
} }
private async Task ConnectInternalAsync(bool isReconnecting) private async Task ConnectInternalAsync(bool isReconnecting)
{ {
@@ -227,6 +226,8 @@ namespace Discord.WebSocket
await _gatewayLogger.DebugAsync("Raising Event").ConfigureAwait(false); await _gatewayLogger.DebugAsync("Raising Event").ConfigureAwait(false);
ConnectionState = ConnectionState.Connected; ConnectionState = ConnectionState.Connected;
await _gatewayLogger.InfoAsync("Connected").ConfigureAwait(false); await _gatewayLogger.InfoAsync("Connected").ConfigureAwait(false);

await ProcessUserDownloadsAsync(_downloadUsersFor.Select(x => GetGuild(x)).Where(x => x != null).ToImmutableArray()).ConfigureAwait(false);
} }
catch (Exception) catch (Exception)
{ {
@@ -442,31 +443,23 @@ namespace Discord.WebSocket
return null; return null;
} }


/// <summary> Downloads the users list for all large guilds. </summary>
public Task DownloadAllUsersAsync()
=> DownloadUsersAsync(State.Guilds.Where(x => !x.HasAllMembers));
/// <summary> Downloads the users list for the provided guilds, if they don't have a complete list. </summary> /// <summary> Downloads the users list for the provided guilds, if they don't have a complete list. </summary>
public async Task DownloadUsersAsync(IEnumerable<SocketGuild> guilds)
public async Task DownloadUsersAsync(IEnumerable<IGuild> guilds)
{ {
var cachedGuilds = guilds.ToImmutableArray();
if (cachedGuilds.Length == 0) return;
foreach (var guild in guilds)
_downloadUsersFor.TryAdd(guild.Id);


//Wait for unsynced guilds to sync first.
var unsyncedGuilds = guilds.Select(x => x.SyncPromise).Where(x => !x.IsCompleted).ToImmutableArray();
if (unsyncedGuilds.Length > 0)
await Task.WhenAll(unsyncedGuilds).ConfigureAwait(false);

//Download offline members
const short batchSize = 50;

if (cachedGuilds.Length == 1)
if (ConnectionState == ConnectionState.Connected)
{ {
if (!cachedGuilds[0].HasAllMembers)
await ApiClient.SendRequestMembersAsync(new ulong[] { cachedGuilds[0].Id }).ConfigureAwait(false);
await cachedGuilds[0].DownloaderPromise.ConfigureAwait(false);
return;
//Race condition leads to guilds being requested twice, probably okay
await ProcessUserDownloadsAsync(guilds.Select(x => GetGuild(x.Id)).Where(x => x != null)).ConfigureAwait(false);
} }
}
private async Task ProcessUserDownloadsAsync(IEnumerable<SocketGuild> guilds)
{
var cachedGuilds = guilds.ToImmutableArray();


const short batchSize = 50;
ulong[] batchIds = new ulong[Math.Min(batchSize, cachedGuilds.Length)]; ulong[] batchIds = new ulong[Math.Min(batchSize, cachedGuilds.Length)];
Task[] batchTasks = new Task[batchIds.Length]; Task[] batchTasks = new Task[batchIds.Length];
int batchCount = (cachedGuilds.Length + (batchSize - 1)) / batchSize; int batchCount = (cachedGuilds.Length + (batchSize - 1)) / batchSize;
@@ -795,6 +788,7 @@ namespace Discord.WebSocket
{ {
await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_DELETE)").ConfigureAwait(false); await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_DELETE)").ConfigureAwait(false);


_downloadUsersFor.TryRemove(data.Id);
var guild = RemoveGuild(data.Id); var guild = RemoveGuild(data.Id);
if (guild != null) if (guild != null)
{ {
@@ -1728,6 +1722,12 @@ namespace Discord.WebSocket
await logger.ErrorAsync("Heartbeat Errored", ex).ConfigureAwait(false); await logger.ErrorAsync("Heartbeat Errored", ex).ConfigureAwait(false);
} }
} }
public async Task WaitForGuildsAsync()
{
var downloadTask = _guildDownloadTask;
if (downloadTask != null)
await _guildDownloadTask.ConfigureAwait(false);
}
private async Task WaitForGuildsAsync(CancellationToken cancelToken, Logger logger) private async Task WaitForGuildsAsync(CancellationToken cancelToken, Logger logger)
{ {
//Wait for GUILD_AVAILABLEs //Wait for GUILD_AVAILABLEs


+ 1
- 1
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -55,7 +55,7 @@ namespace Discord.WebSocket
public SocketTextChannel DefaultChannel => GetTextChannel(Id); public SocketTextChannel DefaultChannel => GetTextChannel(Id);
public string IconUrl => CDN.GetGuildIconUrl(Id, IconId); public string IconUrl => CDN.GetGuildIconUrl(Id, IconId);
public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId); public string SplashUrl => CDN.GetGuildSplashUrl(Id, SplashId);
public bool HasAllMembers => _downloaderPromise.Task.IsCompleted;
public bool HasAllMembers => MemberCount == DownloadedMemberCount;// _downloaderPromise.Task.IsCompleted;
public bool IsSynced => _syncPromise.Task.IsCompleted; public bool IsSynced => _syncPromise.Task.IsCompleted;
public Task SyncPromise => _syncPromise.Task; public Task SyncPromise => _syncPromise.Task;
public Task DownloaderPromise => _downloaderPromise.Task; public Task DownloaderPromise => _downloaderPromise.Task;


Loading…
Cancel
Save