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