| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Text; | using System.Text; | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| @@ -9,10 +9,6 @@ namespace Discord | |||||
| /// <summary> Gets the position of this channel in the guild's channel list, relative to others of the same type. </summary> | /// <summary> Gets the position of this channel in the guild's channel list, relative to others of the same type. </summary> | ||||
| int Position { get; } | int Position { get; } | ||||
| /// <summary> Gets the parentid (category) of this channel in the guild's channel list. </summary> | |||||
| ulong? CategoryId { get; } | |||||
| /// <summary> Gets the parent channel (category) of this channel. </summary> | |||||
| Task<ICategoryChannel> GetCategoryAsync(); | |||||
| /// <summary> Gets the guild this channel is a member of. </summary> | /// <summary> Gets the guild this channel is a member of. </summary> | ||||
| IGuild Guild { get; } | IGuild Guild { get; } | ||||
| /// <summary> Gets the id of the guild this channel is a member of. </summary> | /// <summary> Gets the id of the guild this channel is a member of. </summary> | ||||
| @@ -49,4 +45,4 @@ namespace Discord | |||||
| /// <summary> Gets a user in this channel with the provided id.</summary> | /// <summary> Gets a user in this channel with the provided id.</summary> | ||||
| new Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | new Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> | |||||
| /// A type of guild channel that can be nested within a category. | |||||
| /// Contains a CategoryId that is set to the parent category, if it is set. | |||||
| /// </summary> | |||||
| public interface INestedChannel : IGuildChannel | |||||
| { | |||||
| /// <summary> Gets the parentid (category) of this channel in the guild's channel list. </summary> | |||||
| ulong? CategoryId { get; } | |||||
| /// <summary> Gets the parent channel (category) of this channel, if it is set. If unset, returns null.</summary> | |||||
| Task<ICategoryChannel> GetCategoryAsync(); | |||||
| } | |||||
| } | |||||
| @@ -1,11 +1,11 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.IO; | using System.IO; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| namespace Discord | namespace Discord | ||||
| { | { | ||||
| public interface ITextChannel : IMessageChannel, IMentionable, IGuildChannel | |||||
| public interface ITextChannel : IMessageChannel, IMentionable, IGuildChannel, INestedChannel | |||||
| { | { | ||||
| /// <summary> Checks if the channel is NSFW. </summary> | /// <summary> Checks if the channel is NSFW. </summary> | ||||
| bool IsNsfw { get; } | bool IsNsfw { get; } | ||||
| @@ -28,4 +28,4 @@ namespace Discord | |||||
| /// <summary> Gets the webhooks for this text channel. </summary> | /// <summary> Gets the webhooks for this text channel. </summary> | ||||
| Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); | Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null); | ||||
| } | } | ||||
| } | |||||
| } | |||||
| @@ -25,23 +25,6 @@ namespace Discord.Rest | |||||
| private string DebuggerDisplay => $"{Name} ({Id}, Category)"; | private string DebuggerDisplay => $"{Name} ({Id}, Category)"; | ||||
| // IGuildChannel | // IGuildChannel | ||||
| /// <summary> | |||||
| /// Throws a NotSupportedException because Channel Categories cannot be the child of another Channel Category. | |||||
| /// </summary> | |||||
| /// <exception cref="NotSupportedException">A NotSupportedException is always thrown because Channel Categories do not support being nested.</exception> | |||||
| ulong? IGuildChannel.CategoryId | |||||
| => throw new NotSupportedException(); | |||||
| /// <summary> | |||||
| /// Throws a NotSupportedException because Channel Categories cannot be the child of another Channel Category. | |||||
| /// </summary> | |||||
| /// <exception cref="NotSupportedException">A NotSupportedException is always thrown because Channel Categories do not support being nested.</exception> | |||||
| Task<ICategoryChannel> IGuildChannel.GetCategoryAsync() | |||||
| => throw new NotSupportedException(); | |||||
| IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | |||||
| => throw new NotSupportedException(); | |||||
| Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) | |||||
| => throw new NotSupportedException(); | |||||
| Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) | ||||
| => throw new NotSupportedException(); | => throw new NotSupportedException(); | ||||
| Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options) | Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options) | ||||
| @@ -1,4 +1,4 @@ | |||||
| using System; | |||||
| using System; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | using System.Collections.Immutable; | ||||
| using System.Linq; | using System.Linq; | ||||
| @@ -16,7 +16,6 @@ namespace Discord.Rest | |||||
| internal IGuild Guild { get; } | internal IGuild Guild { get; } | ||||
| public string Name { get; private set; } | public string Name { get; private set; } | ||||
| public int Position { get; private set; } | public int Position { get; private set; } | ||||
| public ulong? CategoryId { get; private set; } | |||||
| public ulong GuildId => Guild.Id; | public ulong GuildId => Guild.Id; | ||||
| internal RestGuildChannel(BaseDiscordClient discord, IGuild guild, ulong id) | internal RestGuildChannel(BaseDiscordClient discord, IGuild guild, ulong id) | ||||
| @@ -64,13 +63,6 @@ namespace Discord.Rest | |||||
| public Task DeleteAsync(RequestOptions options = null) | public Task DeleteAsync(RequestOptions options = null) | ||||
| => ChannelHelper.DeleteAsync(this, Discord, options); | => ChannelHelper.DeleteAsync(this, Discord, options); | ||||
| public async Task<ICategoryChannel> GetCategoryAsync() | |||||
| { | |||||
| if (CategoryId.HasValue) | |||||
| return (await Guild.GetChannelAsync(CategoryId.Value).ConfigureAwait(false)) as ICategoryChannel; | |||||
| return null; | |||||
| } | |||||
| public OverwritePermissions? GetPermissionOverwrite(IUser user) | public OverwritePermissions? GetPermissionOverwrite(IUser user) | ||||
| { | { | ||||
| for (int i = 0; i < _overwrites.Length; i++) | for (int i = 0; i < _overwrites.Length; i++) | ||||
| @@ -9,9 +9,10 @@ using Model = Discord.API.Channel; | |||||
| namespace Discord.Rest | namespace Discord.Rest | ||||
| { | { | ||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class RestTextChannel : RestGuildChannel, IRestMessageChannel, ITextChannel | |||||
| public class RestTextChannel : RestGuildChannel, IRestMessageChannel, ITextChannel, INestedChannel | |||||
| { | { | ||||
| public string Topic { get; private set; } | public string Topic { get; private set; } | ||||
| public ulong? CategoryId { get; private set; } | |||||
| public string Mention => MentionUtils.MentionChannel(Id); | public string Mention => MentionUtils.MentionChannel(Id); | ||||
| @@ -168,5 +169,13 @@ namespace Discord.Rest | |||||
| else | else | ||||
| return AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); | return AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); | ||||
| } | } | ||||
| // INestedChannel | |||||
| async Task<ICategoryChannel> INestedChannel.GetCategoryAsync() | |||||
| { | |||||
| if (CategoryId.HasValue) | |||||
| return (await Guild.GetChannelAsync(CategoryId.Value).ConfigureAwait(false)) as ICategoryChannel; | |||||
| return null; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| using Discord.Audio; | |||||
| using Discord.Audio; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Diagnostics; | using System.Diagnostics; | ||||
| @@ -9,10 +9,11 @@ using Model = Discord.API.Channel; | |||||
| namespace Discord.Rest | namespace Discord.Rest | ||||
| { | { | ||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class RestVoiceChannel : RestGuildChannel, IVoiceChannel, IRestAudioChannel | |||||
| public class RestVoiceChannel : RestGuildChannel, IVoiceChannel, IRestAudioChannel, INestedChannel | |||||
| { | { | ||||
| public int Bitrate { get; private set; } | public int Bitrate { get; private set; } | ||||
| public int? UserLimit { get; private set; } | public int? UserLimit { get; private set; } | ||||
| public ulong? CategoryId { get; private set; } | |||||
| internal RestVoiceChannel(BaseDiscordClient discord, IGuild guild, ulong id) | internal RestVoiceChannel(BaseDiscordClient discord, IGuild guild, ulong id) | ||||
| : base(discord, guild, id) | : base(discord, guild, id) | ||||
| @@ -48,5 +49,13 @@ namespace Discord.Rest | |||||
| => Task.FromResult<IGuildUser>(null); | => Task.FromResult<IGuildUser>(null); | ||||
| IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | ||||
| => AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); | => AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); | ||||
| // INestedChannel | |||||
| async Task<ICategoryChannel> INestedChannel.GetCategoryAsync() | |||||
| { | |||||
| if (CategoryId.HasValue) | |||||
| return (await Guild.GetChannelAsync(CategoryId.Value).ConfigureAwait(false)) as ICategoryChannel; | |||||
| return null; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -11,11 +11,14 @@ using Model = Discord.API.Channel; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class SocketTextChannel : SocketGuildChannel, ITextChannel, ISocketMessageChannel | |||||
| public class SocketTextChannel : SocketGuildChannel, ITextChannel, ISocketMessageChannel, INestedChannel | |||||
| { | { | ||||
| private readonly MessageCache _messages; | private readonly MessageCache _messages; | ||||
| public string Topic { get; private set; } | public string Topic { get; private set; } | ||||
| public ulong? CategoryId { get; private set; } | |||||
| public ICategoryChannel Category | |||||
| => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; | |||||
| private bool _nsfw; | private bool _nsfw; | ||||
| public bool IsNsfw => _nsfw || ChannelHelper.IsNsfw(this); | public bool IsNsfw => _nsfw || ChannelHelper.IsNsfw(this); | ||||
| @@ -164,5 +167,9 @@ namespace Discord.WebSocket | |||||
| => await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false); | => await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false); | ||||
| IDisposable IMessageChannel.EnterTypingState(RequestOptions options) | IDisposable IMessageChannel.EnterTypingState(RequestOptions options) | ||||
| => EnterTypingState(options); | => EnterTypingState(options); | ||||
| // INestedChannel | |||||
| Task<ICategoryChannel> INestedChannel.GetCategoryAsync() | |||||
| => Task.FromResult(Category); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| using Discord.Audio; | |||||
| using Discord.Audio; | |||||
| using Discord.Rest; | using Discord.Rest; | ||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| @@ -11,10 +11,13 @@ using Model = Discord.API.Channel; | |||||
| namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
| { | { | ||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public class SocketVoiceChannel : SocketGuildChannel, IVoiceChannel, ISocketAudioChannel | |||||
| public class SocketVoiceChannel : SocketGuildChannel, IVoiceChannel, ISocketAudioChannel, INestedChannel | |||||
| { | { | ||||
| public int Bitrate { get; private set; } | public int Bitrate { get; private set; } | ||||
| public int? UserLimit { get; private set; } | public int? UserLimit { get; private set; } | ||||
| public ulong? CategoryId { get; private set; } | |||||
| public ICategoryChannel Category | |||||
| => CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null; | |||||
| public override IReadOnlyCollection<SocketGuildUser> Users | public override IReadOnlyCollection<SocketGuildUser> Users | ||||
| => Guild.Users.Where(x => x.VoiceChannel?.Id == Id).ToImmutableArray(); | => Guild.Users.Where(x => x.VoiceChannel?.Id == Id).ToImmutableArray(); | ||||
| @@ -61,5 +64,9 @@ namespace Discord.WebSocket | |||||
| => Task.FromResult<IGuildUser>(GetUser(id)); | => Task.FromResult<IGuildUser>(GetUser(id)); | ||||
| IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options) | ||||
| => ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | => ImmutableArray.Create<IReadOnlyCollection<IGuildUser>>(Users).ToAsyncEnumerable(); | ||||
| // INestedChannel | |||||
| Task<ICategoryChannel> INestedChannel.GetCategoryAsync() | |||||
| => Task.FromResult(Category); | |||||
| } | } | ||||
| } | } | ||||