| @@ -918,17 +918,28 @@ namespace Discord.API | |||||
| //Was this an empty batch? | //Was this an empty batch? | ||||
| if (models.Length == 0) break; | if (models.Length == 0) break; | ||||
| //We can't assume these messages to be sorted by id (fails in rare cases), lets search for the highest/lowest id ourselves | |||||
| switch (args.RelativeDirection) | switch (args.RelativeDirection) | ||||
| { | { | ||||
| case Direction.Before: | case Direction.Before: | ||||
| case Direction.Around: | case Direction.Around: | ||||
| default: | default: | ||||
| result[i] = models; | result[i] = models; | ||||
| relativeId = models[models.Length - 1].Id; | |||||
| relativeId = ulong.MaxValue; | |||||
| for (int j = 0; j < models.Length; j++) | |||||
| { | |||||
| if (models[j].Id < relativeId.Value) | |||||
| relativeId = models[j].Id; | |||||
| } | |||||
| break; | break; | ||||
| case Direction.After: | case Direction.After: | ||||
| result[runs - i - 1] = models; | result[runs - i - 1] = models; | ||||
| relativeId = models[0].Id; | |||||
| relativeId = ulong.MinValue; | |||||
| for (int j = 0; j < models.Length; j++) | |||||
| { | |||||
| if (models[j].Id > relativeId.Value) | |||||
| relativeId = models[j].Id; | |||||
| } | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -194,11 +194,23 @@ namespace Discord | |||||
| return null; | return null; | ||||
| } | } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual async Task<IReadOnlyCollection<IUserGuild>> GetGuildsAsync() | |||||
| public virtual async Task<IReadOnlyCollection<IUserGuild>> GetGuildSummariesAsync() | |||||
| { | { | ||||
| var models = await ApiClient.GetMyGuildsAsync().ConfigureAwait(false); | var models = await ApiClient.GetMyGuildsAsync().ConfigureAwait(false); | ||||
| return models.Select(x => new UserGuild(this, x)).ToImmutableArray(); | return models.Select(x => new UserGuild(this, x)).ToImmutableArray(); | ||||
| } | |||||
| /// <inheritdoc /> | |||||
| public virtual async Task<IReadOnlyCollection<IGuild>> GetGuildsAsync() | |||||
| { | |||||
| var summaryModels = await ApiClient.GetMyGuildsAsync().ConfigureAwait(false); | |||||
| var guilds = ImmutableArray.CreateBuilder<IGuild>(summaryModels.Count); | |||||
| foreach (var summaryModel in summaryModels) | |||||
| { | |||||
| var guildModel = await ApiClient.GetGuildAsync(summaryModel.Id).ConfigureAwait(false); | |||||
| if (guildModel != null) | |||||
| guilds.Add(new Guild(this, guildModel)); | |||||
| } | |||||
| return guilds.ToImmutable(); | |||||
| } | } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual async Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null) | public virtual async Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null) | ||||
| @@ -190,24 +190,29 @@ namespace Discord | |||||
| ConnectionState = ConnectionState.Disconnecting; | ConnectionState = ConnectionState.Disconnecting; | ||||
| await _gatewayLogger.InfoAsync("Disconnecting").ConfigureAwait(false); | await _gatewayLogger.InfoAsync("Disconnecting").ConfigureAwait(false); | ||||
| await _gatewayLogger.DebugAsync("Disconnecting - CancelToken").ConfigureAwait(false); | |||||
| //Signal tasks to complete | //Signal tasks to complete | ||||
| try { _cancelToken.Cancel(); } catch { } | try { _cancelToken.Cancel(); } catch { } | ||||
| await _gatewayLogger.DebugAsync("Disconnecting - ApiClient").ConfigureAwait(false); | |||||
| //Disconnect from server | //Disconnect from server | ||||
| await ApiClient.DisconnectAsync().ConfigureAwait(false); | await ApiClient.DisconnectAsync().ConfigureAwait(false); | ||||
| //Wait for tasks to complete | //Wait for tasks to complete | ||||
| await _gatewayLogger.DebugAsync("Disconnecting - Heartbeat").ConfigureAwait(false); | |||||
| var heartbeatTask = _heartbeatTask; | var heartbeatTask = _heartbeatTask; | ||||
| if (heartbeatTask != null) | if (heartbeatTask != null) | ||||
| await heartbeatTask.ConfigureAwait(false); | await heartbeatTask.ConfigureAwait(false); | ||||
| _heartbeatTask = null; | _heartbeatTask = null; | ||||
| await _gatewayLogger.DebugAsync("Disconnecting - Guild Downloader").ConfigureAwait(false); | |||||
| var guildDownloadTask = _guildDownloadTask; | var guildDownloadTask = _guildDownloadTask; | ||||
| if (guildDownloadTask != null) | if (guildDownloadTask != null) | ||||
| await guildDownloadTask.ConfigureAwait(false); | await guildDownloadTask.ConfigureAwait(false); | ||||
| _guildDownloadTask = null; | _guildDownloadTask = null; | ||||
| //Clear large guild queue | //Clear large guild queue | ||||
| await _gatewayLogger.DebugAsync("Disconnecting - Clean Large Guilds").ConfigureAwait(false); | |||||
| while (_largeGuilds.TryDequeue(out guildId)) { } | while (_largeGuilds.TryDequeue(out guildId)) { } | ||||
| ConnectionState = ConnectionState.Disconnected; | ConnectionState = ConnectionState.Disconnected; | ||||
| @@ -293,10 +298,14 @@ namespace Discord | |||||
| else | else | ||||
| return Task.FromResult<GuildEmbed?>(null); | return Task.FromResult<GuildEmbed?>(null); | ||||
| } | } | ||||
| public override Task<IReadOnlyCollection<IUserGuild>> GetGuildsAsync() | |||||
| public override Task<IReadOnlyCollection<IUserGuild>> GetGuildSummariesAsync() | |||||
| { | { | ||||
| return Task.FromResult<IReadOnlyCollection<IUserGuild>>(Guilds); | return Task.FromResult<IReadOnlyCollection<IUserGuild>>(Guilds); | ||||
| } | } | ||||
| public override Task<IReadOnlyCollection<IGuild>> GetGuildsAsync() | |||||
| { | |||||
| return Task.FromResult<IReadOnlyCollection<IGuild>>(Guilds); | |||||
| } | |||||
| internal CachedGuild AddGuild(ExtendedGuild model, DataStore dataStore) | internal CachedGuild AddGuild(ExtendedGuild model, DataStore dataStore) | ||||
| { | { | ||||
| var guild = new CachedGuild(this, model, dataStore); | var guild = new CachedGuild(this, model, dataStore); | ||||
| @@ -8,6 +8,7 @@ using System.Threading.Tasks; | |||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| //TODO: Add docstrings | //TODO: Add docstrings | ||||
| //TODO: Docstrings should explain when REST requests are sent and how many | |||||
| public interface IDiscordClient : IDisposable | public interface IDiscordClient : IDisposable | ||||
| { | { | ||||
| LoginState LoginState { get; } | LoginState LoginState { get; } | ||||
| @@ -28,7 +29,8 @@ namespace Discord | |||||
| Task<IReadOnlyCollection<IConnection>> GetConnectionsAsync(); | Task<IReadOnlyCollection<IConnection>> GetConnectionsAsync(); | ||||
| Task<IGuild> GetGuildAsync(ulong id); | Task<IGuild> GetGuildAsync(ulong id); | ||||
| Task<IReadOnlyCollection<IUserGuild>> GetGuildsAsync(); | |||||
| Task<IReadOnlyCollection<IGuild>> GetGuildsAsync(); | |||||
| Task<IReadOnlyCollection<IUserGuild>> GetGuildSummariesAsync(); | |||||
| Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null); | Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null); | ||||
| Task<IInvite> GetInviteAsync(string inviteIdOrXkcd); | Task<IInvite> GetInviteAsync(string inviteIdOrXkcd); | ||||