diff --git a/src/Discord.Net/Common/Entities/Channels/IMessageChannel.cs b/src/Discord.Net/Common/Entities/Channels/IMessageChannel.cs index c2a10f30b..e0613da48 100644 --- a/src/Discord.Net/Common/Entities/Channels/IMessageChannel.cs +++ b/src/Discord.Net/Common/Entities/Channels/IMessageChannel.cs @@ -6,8 +6,12 @@ namespace Discord { public interface IMessageChannel : IChannel { - /// Gets the message in this message channel with the given id, or null if none was found. - Task GetMessage(ulong id); + /// Gets all messages in this channel's cache. + IEnumerable CachedMessages { get; } + + /// Gets the message from this channel's cache with the given id, or null if none was found. + Task GetCachedMessage(ulong id); + /// Gets the last N messages from this message channel. Task> GetMessages(int limit = DiscordConfig.MaxMessagesPerBatch); /// Gets a collection of messages in this channel. diff --git a/src/Discord.Net/Common/Entities/Users/IGuildUser.cs b/src/Discord.Net/Common/Entities/Users/IGuildUser.cs index 222530ecd..5e038909e 100644 --- a/src/Discord.Net/Common/Entities/Users/IGuildUser.cs +++ b/src/Discord.Net/Common/Entities/Users/IGuildUser.cs @@ -21,8 +21,8 @@ namespace Discord IGuild Guild { get; } /// Returns a collection of the roles this user is a member of in this guild, including the guild's @everyone role. IReadOnlyList Roles { get; } - /// Gets the id of the voice channel this user is currently in, if any. - ulong? VoiceChannelId { get; } + /// Gets the voice channel this user is currently in, if any. + IVoiceChannel VoiceChannel { get; } /// Gets the guild-level permissions granted to this user by their roles. GuildPermissions GetGuildPermissions(); diff --git a/src/Discord.Net/Rest/Entities/Channels/DMChannel.cs b/src/Discord.Net/Rest/Entities/Channels/DMChannel.cs index 3a76aa702..57e684493 100644 --- a/src/Discord.Net/Rest/Entities/Channels/DMChannel.cs +++ b/src/Discord.Net/Rest/Entities/Channels/DMChannel.cs @@ -124,13 +124,14 @@ namespace Discord.Rest public override string ToString() => $"@{Recipient} [DM]"; IDMUser IDMChannel.Recipient => Recipient; + IEnumerable IMessageChannel.CachedMessages => Array.Empty(); async Task> IChannel.GetUsers() => await GetUsers().ConfigureAwait(false); async Task IChannel.GetUser(ulong id) => await GetUser(id).ConfigureAwait(false); - Task IMessageChannel.GetMessage(ulong id) - => throw new NotSupportedException(); + Task IMessageChannel.GetCachedMessage(ulong id) + => Task.FromResult(null); async Task> IMessageChannel.GetMessages(int limit) => await GetMessages(limit).ConfigureAwait(false); async Task> IMessageChannel.GetMessages(ulong fromMessageId, Direction dir, int limit) diff --git a/src/Discord.Net/Rest/Entities/Channels/GuildChannel.cs b/src/Discord.Net/Rest/Entities/Channels/GuildChannel.cs index c14e918fe..c06cb8e70 100644 --- a/src/Discord.Net/Rest/Entities/Channels/GuildChannel.cs +++ b/src/Discord.Net/Rest/Entities/Channels/GuildChannel.cs @@ -60,16 +60,11 @@ namespace Discord.Rest } /// Gets a user in this channel with the given id. - public async Task GetUser(ulong id) - { - var model = await Discord.BaseClient.GetGuildMember(Guild.Id, id).ConfigureAwait(false); - if (model != null) - return new GuildUser(Guild, model); - return null; - } - protected abstract Task> GetUsers(); + public abstract Task GetUser(ulong id); + /// Gets all users in this channel. + public abstract Task> GetUsers(); - /// Gets the permission overwrite for a specific user, or null if one does not exist. + /// public OverwritePermissions? GetPermissionOverwrite(IUser user) { Overwrite value; @@ -77,7 +72,7 @@ namespace Discord.Rest return value.Permissions; return null; } - /// Gets the permission overwrite for a specific role, or null if one does not exist. + /// public OverwritePermissions? GetPermissionOverwrite(IRole role) { Overwrite value; @@ -92,21 +87,21 @@ namespace Discord.Rest return models.Select(x => new GuildInvite(Guild, x)); } - /// Adds or updates the permission overwrite for the given user. + /// public async Task AddPermissionOverwrite(IUser user, OverwritePermissions perms) { var args = new ModifyChannelPermissionsParams { Allow = perms.AllowValue, Deny = perms.DenyValue }; await Discord.BaseClient.ModifyChannelPermissions(Id, user.Id, args).ConfigureAwait(false); _overwrites[user.Id] = new Overwrite(new API.Overwrite { Allow = perms.AllowValue, Deny = perms.DenyValue, TargetId = user.Id, TargetType = PermissionTarget.User }); } - /// Adds or updates the permission overwrite for the given role. + /// public async Task AddPermissionOverwrite(IRole role, OverwritePermissions perms) { var args = new ModifyChannelPermissionsParams { Allow = perms.AllowValue, Deny = perms.DenyValue }; await Discord.BaseClient.ModifyChannelPermissions(Id, role.Id, args).ConfigureAwait(false); _overwrites[role.Id] = new Overwrite(new API.Overwrite { Allow = perms.AllowValue, Deny = perms.DenyValue, TargetId = role.Id, TargetType = PermissionTarget.Role }); } - /// Removes the permission overwrite for the given user, if one exists. + /// public async Task RemovePermissionOverwrite(IUser user) { await Discord.BaseClient.DeleteChannelPermission(Id, user.Id).ConfigureAwait(false); @@ -114,7 +109,7 @@ namespace Discord.Rest Overwrite value; _overwrites.TryRemove(user.Id, out value); } - /// Removes the permission overwrite for the given role, if one exists. + /// public async Task RemovePermissionOverwrite(IRole role) { await Discord.BaseClient.DeleteChannelPermission(Id, role.Id).ConfigureAwait(false); diff --git a/src/Discord.Net/Rest/Entities/Channels/TextChannel.cs b/src/Discord.Net/Rest/Entities/Channels/TextChannel.cs index e15d7578a..877483645 100644 --- a/src/Discord.Net/Rest/Entities/Channels/TextChannel.cs +++ b/src/Discord.Net/Rest/Entities/Channels/TextChannel.cs @@ -37,14 +37,19 @@ namespace Discord.Rest Update(model); } - protected override async Task> GetUsers() + public override async Task GetUser(ulong id) + { + var user = await Guild.GetUser(id).ConfigureAwait(false); + if (user != null && PermissionUtilities.GetValue(PermissionHelper.Resolve(user, this), ChannelPermission.ReadMessages)) + return user; + return null; + } + public override async Task> GetUsers() { var users = await Guild.GetUsers().ConfigureAwait(false); return users.Where(x => PermissionUtilities.GetValue(PermissionHelper.Resolve(x, this), ChannelPermission.ReadMessages)); } - - /// - public Task GetMessage(ulong id) { throw new NotSupportedException(); } //Not implemented + /// public async Task> GetMessages(int limit = DiscordConfig.MaxMessagesPerBatch) { @@ -101,8 +106,10 @@ namespace Discord.Rest /// public override string ToString() => $"{base.ToString()} [Text]"; - async Task IMessageChannel.GetMessage(ulong id) - => await GetMessage(id).ConfigureAwait(false); + IEnumerable IMessageChannel.CachedMessages => Array.Empty(); + + Task IMessageChannel.GetCachedMessage(ulong id) + => Task.FromResult(null); async Task> IMessageChannel.GetMessages(int limit) => await GetMessages(limit).ConfigureAwait(false); async Task> IMessageChannel.GetMessages(ulong fromMessageId, Direction dir, int limit) diff --git a/src/Discord.Net/Rest/Entities/Channels/VoiceChannel.cs b/src/Discord.Net/Rest/Entities/Channels/VoiceChannel.cs index 703b58c01..8c76f3290 100644 --- a/src/Discord.Net/Rest/Entities/Channels/VoiceChannel.cs +++ b/src/Discord.Net/Rest/Entities/Channels/VoiceChannel.cs @@ -1,7 +1,6 @@ using Discord.API.Rest; using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Model = Discord.API.Channel; @@ -33,11 +32,8 @@ namespace Discord.Rest Update(model); } - protected override async Task> GetUsers() - { - var users = await Guild.GetUsers().ConfigureAwait(false); - return users.Where(x => PermissionUtilities.GetValue(PermissionHelper.Resolve(x, this), ChannelPermission.Connect)); - } + public override Task GetUser(ulong id) { throw new NotSupportedException(); } + public override Task> GetUsers() { throw new NotSupportedException(); } /// public override string ToString() => $"{base.ToString()} [Voice]"; diff --git a/src/Discord.Net/Rest/Entities/Guilds/Guild.cs b/src/Discord.Net/Rest/Entities/Guilds/Guild.cs index d68ff73c6..055c91bd4 100644 --- a/src/Discord.Net/Rest/Entities/Guilds/Guild.cs +++ b/src/Discord.Net/Rest/Entities/Guilds/Guild.cs @@ -134,7 +134,6 @@ namespace Discord.Rest var args = new ModifyGuildEmbedParams(); func(args); var model = await Discord.BaseClient.ModifyGuildEmbed(Id, args).ConfigureAwait(false); - Update(model); } /// diff --git a/src/Discord.Net/Rest/Entities/Users/GuildUser.cs b/src/Discord.Net/Rest/Entities/Users/GuildUser.cs index c27c06892..d36d094fb 100644 --- a/src/Discord.Net/Rest/Entities/Users/GuildUser.cs +++ b/src/Discord.Net/Rest/Entities/Users/GuildUser.cs @@ -109,7 +109,7 @@ namespace Discord.Rest IGuild IGuildUser.Guild => Guild; IReadOnlyList IGuildUser.Roles => Roles; - ulong? IGuildUser.VoiceChannelId => null; + IVoiceChannel IGuildUser.VoiceChannel => null; ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => GetPermissions(channel); diff --git a/src/Discord.Net/WebSocket/Entities/Channels/DMChannel.cs b/src/Discord.Net/WebSocket/Entities/Channels/DMChannel.cs index cb5294da6..84eb36916 100644 --- a/src/Discord.Net/WebSocket/Entities/Channels/DMChannel.cs +++ b/src/Discord.Net/WebSocket/Entities/Channels/DMChannel.cs @@ -24,6 +24,7 @@ namespace Discord.WebSocket public DateTime CreatedAt => DateTimeHelper.FromSnowflake(Id); /// public IEnumerable Users => ImmutableArray.Create(Discord.CurrentUser, Recipient); + public IEnumerable CachedMessages => _messages.Messages; internal DMChannel(DiscordClient discord, Model model) { @@ -52,15 +53,20 @@ namespace Discord.WebSocket return null; } - /// + /// Gets the message from this channel's cache with the given id, or null if none was found. + public Message GetCachedMessage(ulong id) + { + return _messages.Get(id); + } + /// Gets the last N messages from this message channel. public async Task> GetMessages(int limit = DiscordConfig.MaxMessagesPerBatch) { - return await _messages.GetMany(null, Direction.Before, limit).ConfigureAwait(false); + return await _messages.Download(null, Direction.Before, limit).ConfigureAwait(false); } - /// + /// Gets a collection of messages in this channel. public async Task> GetMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) { - return await _messages.GetMany(fromMessageId, dir, limit).ConfigureAwait(false); + return await _messages.Download(fromMessageId, dir, limit).ConfigureAwait(false); } /// @@ -111,13 +117,14 @@ namespace Discord.WebSocket public override string ToString() => $"@{Recipient} [DM]"; IDMUser IDMChannel.Recipient => Recipient; + IEnumerable IMessageChannel.CachedMessages => CachedMessages; Task> IChannel.GetUsers() => Task.FromResult(Users); Task IChannel.GetUser(ulong id) => Task.FromResult(GetUser(id)); - Task IMessageChannel.GetMessage(ulong id) - => throw new NotSupportedException(); + Task IMessageChannel.GetCachedMessage(ulong id) + => Task.FromResult(GetCachedMessage(id)); async Task> IMessageChannel.GetMessages(int limit) => await GetMessages(limit).ConfigureAwait(false); async Task> IMessageChannel.GetMessages(ulong fromMessageId, Direction dir, int limit) diff --git a/src/Discord.Net/WebSocket/Entities/Channels/GuildChannel.cs b/src/Discord.Net/WebSocket/Entities/Channels/GuildChannel.cs index 645eec5f3..c3a895b28 100644 --- a/src/Discord.Net/WebSocket/Entities/Channels/GuildChannel.cs +++ b/src/Discord.Net/WebSocket/Entities/Channels/GuildChannel.cs @@ -11,7 +11,7 @@ namespace Discord.WebSocket public abstract class GuildChannel : IGuildChannel { private ConcurrentDictionary _overwrites; - private ChannelPermissionsCache _permissions; + internal ChannelPermissionsCache _permissions; /// public ulong Id { get; } @@ -22,6 +22,7 @@ namespace Discord.WebSocket public string Name { get; private set; } /// public int Position { get; private set; } + public abstract IEnumerable Users { get; } /// public DateTime CreatedAt => DateTimeHelper.FromSnowflake(Id); @@ -56,20 +57,13 @@ namespace Discord.WebSocket var args = new ModifyGuildChannelParams(); func(args); - var model = await Discord.BaseClient.ModifyGuildChannel(Id, args).ConfigureAwait(false); + await Discord.BaseClient.ModifyGuildChannel(Id, args).ConfigureAwait(false); } /// Gets a user in this channel with the given id. - public async Task GetUser(ulong id) - { - var model = await Discord.BaseClient.GetGuildMember(Guild.Id, id).ConfigureAwait(false); - if (model != null) - return new GuildUser(Guild, model); - return null; - } - protected abstract Task> GetUsers(); + public abstract GuildUser GetUser(ulong id); - /// Gets the permission overwrite for a specific user, or null if one does not exist. + /// public OverwritePermissions? GetPermissionOverwrite(IUser user) { Overwrite value; @@ -77,7 +71,7 @@ namespace Discord.WebSocket return value.Permissions; return null; } - /// Gets the permission overwrite for a specific role, or null if one does not exist. + /// public OverwritePermissions? GetPermissionOverwrite(IRole role) { Overwrite value; @@ -92,35 +86,27 @@ namespace Discord.WebSocket return models.Select(x => new GuildInvite(Guild, x)); } - /// Adds or updates the permission overwrite for the given user. + /// public async Task AddPermissionOverwrite(IUser user, OverwritePermissions perms) { var args = new ModifyChannelPermissionsParams { Allow = perms.AllowValue, Deny = perms.DenyValue }; await Discord.BaseClient.ModifyChannelPermissions(Id, user.Id, args).ConfigureAwait(false); - _overwrites[user.Id] = new Overwrite(new API.Overwrite { Allow = perms.AllowValue, Deny = perms.DenyValue, TargetId = user.Id, TargetType = PermissionTarget.User }); } - /// Adds or updates the permission overwrite for the given role. + /// public async Task AddPermissionOverwrite(IRole role, OverwritePermissions perms) { var args = new ModifyChannelPermissionsParams { Allow = perms.AllowValue, Deny = perms.DenyValue }; await Discord.BaseClient.ModifyChannelPermissions(Id, role.Id, args).ConfigureAwait(false); - _overwrites[role.Id] = new Overwrite(new API.Overwrite { Allow = perms.AllowValue, Deny = perms.DenyValue, TargetId = role.Id, TargetType = PermissionTarget.Role }); } - /// Removes the permission overwrite for the given user, if one exists. + /// public async Task RemovePermissionOverwrite(IUser user) { await Discord.BaseClient.DeleteChannelPermission(Id, user.Id).ConfigureAwait(false); - - Overwrite value; - _overwrites.TryRemove(user.Id, out value); } - /// Removes the permission overwrite for the given role, if one exists. + /// public async Task RemovePermissionOverwrite(IRole role) { await Discord.BaseClient.DeleteChannelPermission(Id, role.Id).ConfigureAwait(false); - - Overwrite value; - _overwrites.TryRemove(role.Id, out value); } /// Creates a new invite to this channel. @@ -152,14 +138,14 @@ namespace Discord.WebSocket => await CreateInvite(maxAge, maxUses, isTemporary, withXkcd).ConfigureAwait(false); async Task> IGuildChannel.GetInvites() => await GetInvites().ConfigureAwait(false); - async Task> IGuildChannel.GetUsers() - => await GetUsers().ConfigureAwait(false); - async Task IGuildChannel.GetUser(ulong id) - => await GetUser(id).ConfigureAwait(false); - async Task> IChannel.GetUsers() - => await GetUsers().ConfigureAwait(false); - async Task IChannel.GetUser(ulong id) - => await GetUser(id).ConfigureAwait(false); + Task> IGuildChannel.GetUsers() + => Task.FromResult>(Users); + Task IGuildChannel.GetUser(ulong id) + => Task.FromResult(GetUser(id)); + Task> IChannel.GetUsers() + => Task.FromResult>(Users); + Task IChannel.GetUser(ulong id) + => Task.FromResult(GetUser(id)); Task IUpdateable.Update() => Task.CompletedTask; } diff --git a/src/Discord.Net/WebSocket/Entities/Channels/TextChannel.cs b/src/Discord.Net/WebSocket/Entities/Channels/TextChannel.cs index 23b3c2f70..0d8199bb7 100644 --- a/src/Discord.Net/WebSocket/Entities/Channels/TextChannel.cs +++ b/src/Discord.Net/WebSocket/Entities/Channels/TextChannel.cs @@ -1,6 +1,7 @@ using Discord.API.Rest; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -17,6 +18,9 @@ namespace Discord.WebSocket /// public string Mention => MentionHelper.Mention(this); + public override IEnumerable Users + => _permissions.Members.Where(x => x.Permissions.ReadMessages).Select(x => x.User).ToImmutableArray(); + public IEnumerable CachedMessages => _messages.Messages; internal TextChannel(Guild guild, Model model) : base(guild, model) @@ -39,27 +43,28 @@ namespace Discord.WebSocket await Discord.BaseClient.ModifyGuildChannel(Id, args).ConfigureAwait(false); } - protected override async Task> GetUsers() + /// Gets the message from this channel's cache with the given id, or null if none was found. + public Message GetCachedMessage(ulong id) { - var users = await Guild.GetUsers().ConfigureAwait(false); - return users.Where(x => PermissionUtilities.GetValue(PermissionHelper.Resolve(x, this), ChannelPermission.ReadMessages)); + return _messages.Get(id); } - - /// - public Task GetMessage(ulong id) { throw new NotSupportedException(); } //Not implemented - /// + /// Gets the last N messages from this message channel. public async Task> GetMessages(int limit = DiscordConfig.MaxMessagesPerBatch) { - var args = new GetChannelMessagesParams { Limit = limit }; - var models = await Discord.BaseClient.GetChannelMessages(Id, args).ConfigureAwait(false); - return models.Select(x => new Message(this, x)); + return await _messages.Download(null, Direction.Before, limit).ConfigureAwait(false); } - /// + /// Gets a collection of messages in this channel. public async Task> GetMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) { - var args = new GetChannelMessagesParams { Limit = limit }; - var models = await Discord.BaseClient.GetChannelMessages(Id, args).ConfigureAwait(false); - return models.Select(x => new Message(this, x)); + return await _messages.Download(fromMessageId, dir, limit).ConfigureAwait(false); + } + + public override GuildUser GetUser(ulong id) + { + var member = _permissions.Get(id); + if (member != null && member.Value.Permissions.ReadMessages) + return member.Value.User; + return null; } /// @@ -103,8 +108,10 @@ namespace Discord.WebSocket /// public override string ToString() => $"{base.ToString()} [Text]"; - async Task IMessageChannel.GetMessage(ulong id) - => await GetMessage(id).ConfigureAwait(false); + IEnumerable IMessageChannel.CachedMessages => CachedMessages; + + Task IMessageChannel.GetCachedMessage(ulong id) + => Task.FromResult(GetCachedMessage(id)); async Task> IMessageChannel.GetMessages(int limit) => await GetMessages(limit).ConfigureAwait(false); async Task> IMessageChannel.GetMessages(ulong fromMessageId, Direction dir, int limit) diff --git a/src/Discord.Net/WebSocket/Entities/Channels/VoiceChannel.cs b/src/Discord.Net/WebSocket/Entities/Channels/VoiceChannel.cs index 286a67520..40c7ee586 100644 --- a/src/Discord.Net/WebSocket/Entities/Channels/VoiceChannel.cs +++ b/src/Discord.Net/WebSocket/Entities/Channels/VoiceChannel.cs @@ -12,6 +12,9 @@ namespace Discord.WebSocket /// public int Bitrate { get; private set; } + public override IEnumerable Users + => Guild.Users.Where(x => x.VoiceChannel == this); + internal VoiceChannel(Guild guild, Model model) : base(guild, model) { @@ -32,10 +35,12 @@ namespace Discord.WebSocket await Discord.BaseClient.ModifyGuildChannel(Id, args).ConfigureAwait(false); } - protected override async Task> GetUsers() + public override GuildUser GetUser(ulong id) { - var users = await Guild.GetUsers().ConfigureAwait(false); - return users.Where(x => PermissionUtilities.GetValue(PermissionHelper.Resolve(x, this), ChannelPermission.Connect)); + var member = _permissions.Get(id); + if (member != null && member.Value.Permissions.ReadMessages) + return member.Value.User; + return null; } /// diff --git a/src/Discord.Net/WebSocket/Entities/Guilds/Guild.cs b/src/Discord.Net/WebSocket/Entities/Guilds/Guild.cs index 95c4a1413..3f68395d6 100644 --- a/src/Discord.Net/WebSocket/Entities/Guilds/Guild.cs +++ b/src/Discord.Net/WebSocket/Entities/Guilds/Guild.cs @@ -56,6 +56,7 @@ namespace Discord.WebSocket public Role EveryoneRole => GetRole(Id); /// Gets a collection of all roles in this guild. public IEnumerable Roles => _roles?.Select(x => x.Value) ?? Enumerable.Empty(); + public IEnumerable Users => Array.Empty(); internal Guild(DiscordClient discord, Model model) { diff --git a/src/Discord.Net/WebSocket/Entities/Users/GuildUser.cs b/src/Discord.Net/WebSocket/Entities/Users/GuildUser.cs index 614476b5b..919d27fe1 100644 --- a/src/Discord.Net/WebSocket/Entities/Users/GuildUser.cs +++ b/src/Discord.Net/WebSocket/Entities/Users/GuildUser.cs @@ -22,6 +22,8 @@ namespace Discord.WebSocket public DateTime JoinedAt { get; private set; } /// public string Nickname { get; private set; } + /// + public VoiceChannel VoiceChannel { get; private set; } /// public IReadOnlyList Roles => _roles; @@ -103,7 +105,7 @@ namespace Discord.WebSocket IGuild IGuildUser.Guild => Guild; IReadOnlyList IGuildUser.Roles => Roles; - ulong? IGuildUser.VoiceChannelId => null; + IVoiceChannel IGuildUser.VoiceChannel => VoiceChannel; ChannelPermissions IGuildUser.GetPermissions(IGuildChannel channel) => GetPermissions(channel); diff --git a/src/Discord.Net/WebSocket/MessageCache.cs b/src/Discord.Net/WebSocket/MessageCache.cs index f3ef2b58b..1552dd2b1 100644 --- a/src/Discord.Net/WebSocket/MessageCache.cs +++ b/src/Discord.Net/WebSocket/MessageCache.cs @@ -16,6 +16,8 @@ namespace Discord.WebSocket private readonly ConcurrentQueue _orderedMessages; private readonly int _size; + public IEnumerable Messages => _messages.Select(x => x.Value); + public MessageCache(DiscordClient discord, IMessageChannel channel) { _discord = discord; @@ -51,13 +53,11 @@ namespace Discord.WebSocket return result; return null; } - public async Task> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) + public IImmutableList GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) { - //TODO: Test heavily - if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit)); if (limit == 0) return ImmutableArray.Empty; - + IEnumerable cachedMessageIds; if (fromMessageId == null) cachedMessageIds = _orderedMessages; @@ -66,7 +66,7 @@ namespace Discord.WebSocket else cachedMessageIds = _orderedMessages.Where(x => x > fromMessageId.Value); - var cachedMessages = cachedMessageIds + return cachedMessageIds .Take(limit) .Select(x => { @@ -76,19 +76,28 @@ namespace Discord.WebSocket return null; }) .Where(x => x != null) - .ToArray(); + .ToImmutableArray(); + } + + public async Task> Download(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch) + { + //TODO: Test heavily + + if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit)); + if (limit == 0) return ImmutableArray.Empty; - if (cachedMessages.Length == limit) + var cachedMessages = GetMany(fromMessageId, dir, limit); + if (cachedMessages.Count == limit) return cachedMessages; - else if (cachedMessages.Length > limit) - return cachedMessages.Skip(cachedMessages.Length - limit); + else if (cachedMessages.Count > limit) + return cachedMessages.Skip(cachedMessages.Count - limit); else { var args = new GetChannelMessagesParams { - Limit = limit - cachedMessages.Length, + Limit = limit - cachedMessages.Count, RelativeDirection = dir, - RelativeMessageId = dir == Direction.Before ? cachedMessages[0].Id : cachedMessages[cachedMessages.Length - 1].Id + RelativeMessageId = dir == Direction.Before ? cachedMessages[0].Id : cachedMessages[cachedMessages.Count - 1].Id }; var downloadedMessages = await _discord.BaseClient.GetChannelMessages(_channel.Id, args).ConfigureAwait(false); return cachedMessages.AsEnumerable().Concat(downloadedMessages.Select(x => new Message(_channel, x))).ToImmutableArray();