diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs index 51dea5f9f..0418727bf 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.Events.cs @@ -21,7 +21,13 @@ namespace Discord.WebSocket remove { _disconnectedEvent.Remove(value); } } private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>(); - /// Fired when guild data has finished downloading. + /// + /// Fired when guild data has finished downloading. + /// + /// + /// It is possible that some guilds might be unsynced if + /// was not long enough to receive all GUILD_AVAILABLEs before READY. + /// public event Func Ready { add { _readyEvent.Add(value); } diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index d19f3f90c..1bfa467b6 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -169,7 +169,7 @@ namespace Discord.WebSocket GuildAvailable += g => { - if (ConnectionState == ConnectionState.Connected && AlwaysDownloadUsers && !g.HasAllMembers) + if (_guildDownloadTask?.IsCompleted == true && ConnectionState == ConnectionState.Connected && AlwaysDownloadUsers && !g.HasAllMembers) { var _ = g.DownloadUsersAsync(); } @@ -370,7 +370,7 @@ namespace Discord.WebSocket { var cachedGuilds = guilds.ToImmutableArray(); - const short batchSize = 50; + const short batchSize = 100; //TODO: Gateway Intents will limit to a maximum of 1 guild_id ulong[] batchIds = new ulong[Math.Min(batchSize, cachedGuilds.Length)]; Task[] batchTasks = new Task[batchIds.Length]; int batchCount = (cachedGuilds.Length + (batchSize - 1)) / batchSize; @@ -378,7 +378,7 @@ namespace Discord.WebSocket for (int i = 0, k = 0; i < batchCount; i++) { bool isLast = i == batchCount - 1; - int count = isLast ? (batchIds.Length - (batchCount - 1) * batchSize) : batchSize; + int count = isLast ? (cachedGuilds.Length - (batchCount - 1) * batchSize) : batchSize; for (int j = 0; j < count; j++, k++) { @@ -578,6 +578,9 @@ namespace Discord.WebSocket } else if (_connection.CancelToken.IsCancellationRequested) return; + + if (BaseConfig.AlwaysDownloadUsers) + _ = DownloadUsersAsync(Guilds.Where(x => x.IsAvailable && !x.HasAllMembers)); await TimedInvokeAsync(_readyEvent, nameof(Ready)).ConfigureAwait(false); await _gatewayLogger.InfoAsync("Ready").ConfigureAwait(false); @@ -1772,7 +1775,7 @@ namespace Discord.WebSocket try { await logger.DebugAsync("GuildDownloader Started").ConfigureAwait(false); - while ((_unavailableGuildCount != 0) && (Environment.TickCount - _lastGuildAvailableTime < 2000)) + while ((_unavailableGuildCount != 0) && (Environment.TickCount - _lastGuildAvailableTime < BaseConfig.MaxWaitBetweenGuildAvailablesBeforeReady)) await Task.Delay(500, cancelToken).ConfigureAwait(false); await logger.DebugAsync("GuildDownloader Stopped").ConfigureAwait(false); } diff --git a/src/Discord.Net.WebSocket/DiscordSocketConfig.cs b/src/Discord.Net.WebSocket/DiscordSocketConfig.cs index 4b33c770f..877ccd875 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketConfig.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketConfig.cs @@ -126,6 +126,31 @@ namespace Discord.WebSocket public bool GuildSubscriptions { get; set; } = true; /// + /// Gets or sets the maximum wait time in milliseconds between GUILD_AVAILABLE events before firing READY. + /// + /// If zero, READY will fire as soon as it is received and all guilds will be unavailable. + /// + /// + /// This property is measured in milliseconds, negative values will throw an exception. + /// If a guild is not received before READY, it will be unavailable. + /// + /// + /// The maximum wait time in milliseconds between GUILD_AVAILABLE events before firing READY. + /// + /// Value must be at least 0. + public int MaxWaitBetweenGuildAvailablesBeforeReady { + get + { + return _maxWaitForGuildAvailable; + } + set + { + Preconditions.AtLeast(value, 0, nameof(MaxWaitBetweenGuildAvailablesBeforeReady)); + _maxWaitForGuildAvailable = value; + } + } + private int _maxWaitForGuildAvailable = 10000; + /// Gets or sets gateway intents to limit what events are sent from Discord. Allows for more granular control than the property. /// ///