Browse Source

Merge branch 'dev' into docs/faq-n-patches-offline

pull/1161/head
Still Hsu 7 years ago
parent
commit
1a146afbe1
No known key found for this signature in database GPG Key ID: 8601A145FDA95209
28 changed files with 540 additions and 151 deletions
  1. +0
    -11
      src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs
  2. +16
    -0
      src/Discord.Net.Core/Entities/Channels/INestedChannel.cs
  3. +1
    -1
      src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
  4. +1
    -1
      src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
  5. +81
    -18
      src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs
  6. +116
    -31
      src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
  7. +59
    -15
      src/Discord.Net.Core/Entities/Permissions/OverwritePermissions.cs
  8. +2
    -2
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs
  9. +3
    -17
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleAuditLogData.cs
  10. +16
    -0
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleEditInfo.cs
  11. +3
    -3
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleCreateAuditLogData.cs
  12. +3
    -3
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleDeleteAuditLogData.cs
  13. +2
    -2
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleEditInfo.cs
  14. +5
    -5
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs
  15. +10
    -0
      src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
  16. +0
    -8
      src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs
  17. +2
    -0
      src/Discord.Net.Rest/Entities/Channels/RestChannel.cs
  18. +0
    -11
      src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
  19. +14
    -1
      src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
  20. +13
    -1
      src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
  21. +1
    -1
      src/Discord.Net.WebSocket/Entities/Channels/SocketCategoryChannel.cs
  22. +2
    -17
      src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
  23. +8
    -1
      src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
  24. +9
    -2
      src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
  25. +21
    -0
      test/Discord.Net.Tests/Tests.ChannelPermissions.cs
  26. +74
    -0
      test/Discord.Net.Tests/Tests.Channels.cs
  27. +12
    -0
      test/Discord.Net.Tests/Tests.GuildPermissions.cs
  28. +66
    -0
      test/Discord.Net.Tests/Tests.Permissions.cs

+ 0
- 11
src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs View File

@@ -20,17 +20,6 @@ namespace Discord
/// </returns> /// </returns>
int Position { get; } int Position { get; }


/// <summary>
/// Gets the parent ID (category) of this channel in the guild's channel list.
/// </summary>
/// <returns>
/// The parent category ID associated with this channel, or <c>null</c> if none is set.
/// </returns>
ulong? CategoryId { get; }
/// <summary>
/// Gets the parent channel (category) of this channel.
/// </summary>
Task<ICategoryChannel> GetCategoryAsync();
/// <summary> /// <summary>
/// Gets the guild associated with this channel. /// Gets the guild associated with this channel.
/// </summary> /// </summary>


+ 16
- 0
src/Discord.Net.Core/Entities/Channels/INestedChannel.cs View File

@@ -0,0 +1,16 @@
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(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
}
}

+ 1
- 1
src/Discord.Net.Core/Entities/Channels/ITextChannel.cs View File

@@ -8,7 +8,7 @@ namespace Discord
/// <summary> /// <summary>
/// Represents a generic channel in a guild that can send and receive messages. /// Represents a generic channel in a guild that can send and receive messages.
/// </summary> /// </summary>
public interface ITextChannel : IMessageChannel, IMentionable, IGuildChannel
public interface ITextChannel : IMessageChannel, IMentionable, INestedChannel
{ {
/// <summary> /// <summary>
/// Determines whether the channel is NSFW. /// Determines whether the channel is NSFW.


+ 1
- 1
src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs View File

@@ -6,7 +6,7 @@ namespace Discord
/// <summary> /// <summary>
/// Represents a generic voice channel in a guild. /// Represents a generic voice channel in a guild.
/// </summary> /// </summary>
public interface IVoiceChannel : IGuildChannel, IAudioChannel
public interface IVoiceChannel : INestedChannel, IAudioChannel
{ {
/// <summary> /// <summary>
/// Gets the bitrate, in bits per second, clients in this voice channel are requested to use. /// Gets the bitrate, in bits per second, clients in this voice channel are requested to use.


+ 81
- 18
src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs View File

@@ -88,12 +88,27 @@ namespace Discord
/// <summary> Creates a new <see cref="ChannelPermissions"/> with the provided packed value. </summary> /// <summary> Creates a new <see cref="ChannelPermissions"/> with the provided packed value. </summary>
public ChannelPermissions(ulong rawValue) { RawValue = rawValue; } public ChannelPermissions(ulong rawValue) { RawValue = rawValue; }


private ChannelPermissions(ulong initialValue, bool? createInstantInvite = null, bool? manageChannel = null,
private ChannelPermissions(ulong initialValue,
bool? createInstantInvite = null,
bool? manageChannel = null,
bool? addReactions = null, bool? addReactions = null,
bool? viewChannel = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? manageRoles = null, bool? manageWebhooks = null)
bool? viewChannel = null,
bool? sendMessages = null,
bool? sendTTSMessages = null,
bool? manageMessages = null,
bool? embedLinks = null,
bool? attachFiles = null,
bool? readMessageHistory = null,
bool? mentionEveryone = null,
bool? useExternalEmojis = null,
bool? connect = null,
bool? speak = null,
bool? muteMembers = null,
bool? deafenMembers = null,
bool? moveMembers = null,
bool? useVoiceActivation = null,
bool? manageRoles = null,
bool? manageWebhooks = null)
{ {
ulong value = initialValue; ulong value = initialValue;


@@ -122,27 +137,75 @@ namespace Discord
} }


/// <summary> Creates a new <see cref="ChannelPermissions"/> with the provided permissions. </summary> /// <summary> Creates a new <see cref="ChannelPermissions"/> with the provided permissions. </summary>
public ChannelPermissions(bool createInstantInvite = false, bool manageChannel = false,
public ChannelPermissions(
bool createInstantInvite = false,
bool manageChannel = false,
bool addReactions = false, bool addReactions = false,
bool viewChannel = false, bool sendMessages = false, bool sendTTSMessages = false, bool manageMessages = false,
bool embedLinks = false, bool attachFiles = false, bool readMessageHistory = false, bool mentionEveryone = false,
bool useExternalEmojis = false, bool connect = false, bool speak = false, bool muteMembers = false, bool deafenMembers = false,
bool moveMembers = false, bool useVoiceActivation = false, bool manageRoles = false, bool manageWebhooks = false)
bool viewChannel = false,
bool sendMessages = false,
bool sendTTSMessages = false,
bool manageMessages = false,
bool embedLinks = false,
bool attachFiles = false,
bool readMessageHistory = false,
bool mentionEveryone = false,
bool useExternalEmojis = false,
bool connect = false,
bool speak = false,
bool muteMembers = false,
bool deafenMembers = false,
bool moveMembers = false,
bool useVoiceActivation = false,
bool manageRoles = false,
bool manageWebhooks = false)
: this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, : this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect,
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks) speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks)
{ } { }


/// <summary> Creates a new <see cref="ChannelPermissions"/> from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new <see cref="ChannelPermissions"/> from this one, changing the provided non-null permissions. </summary>
public ChannelPermissions Modify(bool? createInstantInvite = null, bool? manageChannel = null,
public ChannelPermissions Modify(
bool? createInstantInvite = null,
bool? manageChannel = null,
bool? addReactions = null, bool? addReactions = null,
bool? viewChannel = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool useExternalEmojis = false, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? manageRoles = null, bool? manageWebhooks = null)
=> new ChannelPermissions(RawValue, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect,
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks);
bool? viewChannel = null,
bool? sendMessages = null,
bool? sendTTSMessages = null,
bool? manageMessages = null,
bool? embedLinks = null,
bool? attachFiles = null,
bool? readMessageHistory = null,
bool? mentionEveryone = null,
bool? useExternalEmojis = null,
bool? connect = null,
bool? speak = null,
bool? muteMembers = null,
bool? deafenMembers = null,
bool? moveMembers = null,
bool? useVoiceActivation = null,
bool? manageRoles = null,
bool? manageWebhooks = null)
=> new ChannelPermissions(RawValue,
createInstantInvite,
manageChannel,
addReactions,
viewChannel,
sendMessages,
sendTTSMessages,
manageMessages,
embedLinks,
attachFiles,
readMessageHistory,
mentionEveryone,
useExternalEmojis,
connect,
speak,
muteMembers,
deafenMembers,
moveMembers,
useVoiceActivation,
manageRoles,
manageWebhooks);


public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission); public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission);




+ 116
- 31
src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs View File

@@ -84,14 +84,35 @@ namespace Discord
/// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary> /// <summary> Creates a new <see cref="GuildPermissions"/> with the provided packed value. </summary>
public GuildPermissions(ulong rawValue) { RawValue = rawValue; } public GuildPermissions(ulong rawValue) { RawValue = rawValue; }


private GuildPermissions(ulong initialValue, bool? createInstantInvite = null, bool? kickMembers = null,
bool? banMembers = null, bool? administrator = null, bool? manageChannels = null, bool? manageGuild = null,
bool? addReactions = null, bool? viewAuditLog = null,
bool? viewChannel = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? changeNickname = null, bool? manageNicknames = null,
bool? manageRoles = null, bool? manageWebhooks = null, bool? manageEmojis = null)
private GuildPermissions(ulong initialValue,
bool? createInstantInvite = null,
bool? kickMembers = null,
bool? banMembers = null,
bool? administrator = null,
bool? manageChannels = null,
bool? manageGuild = null,
bool? addReactions = null,
bool? viewAuditLog = null,
bool? viewChannel = null,
bool? sendMessages = null,
bool? sendTTSMessages = null,
bool? manageMessages = null,
bool? embedLinks = null,
bool? attachFiles = null,
bool? readMessageHistory = null,
bool? mentionEveryone = null,
bool? useExternalEmojis = null,
bool? connect = null,
bool? speak = null,
bool? muteMembers = null,
bool? deafenMembers = null,
bool? moveMembers = null,
bool? useVoiceActivation = null,
bool? changeNickname = null,
bool? manageNicknames = null,
bool? manageRoles = null,
bool? manageWebhooks = null,
bool? manageEmojis = null)
{ {
ulong value = initialValue; ulong value = initialValue;


@@ -128,32 +149,96 @@ namespace Discord
} }


/// <summary> Creates a new <see cref="GuildPermissions"/> with the provided permissions. </summary> /// <summary> Creates a new <see cref="GuildPermissions"/> with the provided permissions. </summary>
public GuildPermissions(bool createInstantInvite = false, bool kickMembers = false,
bool banMembers = false, bool administrator = false, bool manageChannels = false, bool manageGuild = false,
bool addReactions = false, bool viewAuditLog = false,
bool viewChannel = false, bool sendMessages = false, bool sendTTSMessages = false, bool manageMessages = false,
bool embedLinks = false, bool attachFiles = false, bool readMessageHistory = false, bool mentionEveryone = false,
bool useExternalEmojis = false, bool connect = false, bool speak = false, bool muteMembers = false, bool deafenMembers = false,
bool moveMembers = false, bool useVoiceActivation = false, bool? changeNickname = false, bool? manageNicknames = false,
bool manageRoles = false, bool manageWebhooks = false, bool manageEmojis = false)
: this(0, createInstantInvite: createInstantInvite, manageRoles: manageRoles, kickMembers: kickMembers, banMembers: banMembers,
administrator: administrator, manageChannels: manageChannels, manageGuild: manageGuild, addReactions: addReactions,
viewAuditLog: viewAuditLog, viewChannel: viewChannel, sendMessages: sendMessages, sendTTSMessages: sendTTSMessages,
manageMessages: manageMessages, embedLinks: embedLinks, attachFiles: attachFiles, readMessageHistory: readMessageHistory,
mentionEveryone: mentionEveryone, useExternalEmojis: useExternalEmojis, connect: connect, speak: speak, muteMembers: muteMembers,
deafenMembers: deafenMembers, moveMembers: moveMembers, useVoiceActivation: useVoiceActivation, changeNickname: changeNickname,
manageNicknames: manageNicknames, manageWebhooks: manageWebhooks, manageEmojis: manageEmojis)
public GuildPermissions(
bool createInstantInvite = false,
bool kickMembers = false,
bool banMembers = false,
bool administrator = false,
bool manageChannels = false,
bool manageGuild = false,
bool addReactions = false,
bool viewAuditLog = false,
bool viewChannel = false,
bool sendMessages = false,
bool sendTTSMessages = false,
bool manageMessages = false,
bool embedLinks = false,
bool attachFiles = false,
bool readMessageHistory = false,
bool mentionEveryone = false,
bool useExternalEmojis = false,
bool connect = false,
bool speak = false,
bool muteMembers = false,
bool deafenMembers = false,
bool moveMembers = false,
bool useVoiceActivation = false,
bool changeNickname = false,
bool manageNicknames = false,
bool manageRoles = false,
bool manageWebhooks = false,
bool manageEmojis = false)
: this(0,
createInstantInvite: createInstantInvite,
manageRoles: manageRoles,
kickMembers: kickMembers,
banMembers: banMembers,
administrator: administrator,
manageChannels: manageChannels,
manageGuild: manageGuild,
addReactions: addReactions,
viewAuditLog: viewAuditLog,
viewChannel: viewChannel,
sendMessages: sendMessages,
sendTTSMessages: sendTTSMessages,
manageMessages: manageMessages,
embedLinks: embedLinks,
attachFiles: attachFiles,
readMessageHistory: readMessageHistory,
mentionEveryone: mentionEveryone,
useExternalEmojis: useExternalEmojis,
connect: connect,
speak: speak,
muteMembers: muteMembers,
deafenMembers: deafenMembers,
moveMembers: moveMembers,
useVoiceActivation: useVoiceActivation,
changeNickname: changeNickname,
manageNicknames: manageNicknames,
manageWebhooks: manageWebhooks,
manageEmojis: manageEmojis)
{ } { }


/// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new <see cref="GuildPermissions"/> from this one, changing the provided non-null permissions. </summary>
public GuildPermissions Modify(bool? createInstantInvite = null, bool? kickMembers = null,
bool? banMembers = null, bool? administrator = null, bool? manageChannels = null, bool? manageGuild = null,
bool? addReactions = null, bool? viewAuditLog = null,
bool? viewChannel = null, bool? sendMessages = null, bool? sendTTSMessages = null, bool? manageMessages = null,
bool? embedLinks = null, bool? attachFiles = null, bool? readMessageHistory = null, bool? mentionEveryone = null,
bool? useExternalEmojis = null, bool? connect = null, bool? speak = null, bool? muteMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? useVoiceActivation = null, bool? changeNickname = null, bool? manageNicknames = null,
bool? manageRoles = null, bool? manageWebhooks = null, bool? manageEmojis = null)
public GuildPermissions Modify(
bool? createInstantInvite = null,
bool? kickMembers = null,
bool? banMembers = null,
bool? administrator = null,
bool? manageChannels = null,
bool? manageGuild = null,
bool? addReactions = null,
bool? viewAuditLog = null,
bool? viewChannel = null,
bool? sendMessages = null,
bool? sendTTSMessages = null,
bool? manageMessages = null,
bool? embedLinks = null,
bool? attachFiles = null,
bool? readMessageHistory = null,
bool? mentionEveryone = null,
bool? useExternalEmojis = null,
bool? connect = null,
bool? speak = null,
bool? muteMembers = null,
bool? deafenMembers = null,
bool? moveMembers = null,
bool? useVoiceActivation = null,
bool? changeNickname = null,
bool? manageNicknames = null,
bool? manageRoles = null,
bool? manageWebhooks = null,
bool? manageEmojis = null)
=> new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions,
viewAuditLog, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, viewAuditLog, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles,
readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers,


+ 59
- 15
src/Discord.Net.Core/Entities/Permissions/OverwritePermissions.cs View File

@@ -84,12 +84,26 @@ namespace Discord
DenyValue = denyValue; DenyValue = denyValue;
} }


private OverwritePermissions(ulong allowValue, ulong denyValue, PermValue? createInstantInvite = null, PermValue? manageChannel = null,
private OverwritePermissions(ulong allowValue, ulong denyValue,
PermValue? createInstantInvite = null,
PermValue? manageChannel = null,
PermValue? addReactions = null, PermValue? addReactions = null,
PermValue? viewChannel = null, PermValue? sendMessages = null, PermValue? sendTTSMessages = null, PermValue? manageMessages = null,
PermValue? embedLinks = null, PermValue? attachFiles = null, PermValue? readMessageHistory = null, PermValue? mentionEveryone = null,
PermValue? useExternalEmojis = null, PermValue? connect = null, PermValue? speak = null, PermValue? muteMembers = null,
PermValue? deafenMembers = null, PermValue? moveMembers = null, PermValue? useVoiceActivation = null, PermValue? manageRoles = null,
PermValue? viewChannel = null,
PermValue? sendMessages = null,
PermValue? sendTTSMessages = null,
PermValue? manageMessages = null,
PermValue? embedLinks = null,
PermValue? attachFiles = null,
PermValue? readMessageHistory = null,
PermValue? mentionEveryone = null,
PermValue? useExternalEmojis = null,
PermValue? connect = null,
PermValue? speak = null,
PermValue? muteMembers = null,
PermValue? deafenMembers = null,
PermValue? moveMembers = null,
PermValue? useVoiceActivation = null,
PermValue? manageRoles = null,
PermValue? manageWebhooks = null) PermValue? manageWebhooks = null)
{ {
Permissions.SetValue(ref allowValue, ref denyValue, createInstantInvite, ChannelPermission.CreateInstantInvite); Permissions.SetValue(ref allowValue, ref denyValue, createInstantInvite, ChannelPermission.CreateInstantInvite);
@@ -120,12 +134,27 @@ namespace Discord
/// <summary> /// <summary>
/// Creates a new <see cref="ChannelPermissions" /> with the provided permissions. /// Creates a new <see cref="ChannelPermissions" /> with the provided permissions.
/// </summary> /// </summary>
public OverwritePermissions(PermValue createInstantInvite = PermValue.Inherit, PermValue manageChannel = PermValue.Inherit,
public OverwritePermissions(
PermValue createInstantInvite = PermValue.Inherit,
PermValue manageChannel = PermValue.Inherit,
PermValue addReactions = PermValue.Inherit, PermValue addReactions = PermValue.Inherit,
PermValue readMessages = PermValue.Inherit, PermValue sendMessages = PermValue.Inherit, PermValue sendTTSMessages = PermValue.Inherit, PermValue manageMessages = PermValue.Inherit,
PermValue embedLinks = PermValue.Inherit, PermValue attachFiles = PermValue.Inherit, PermValue readMessageHistory = PermValue.Inherit, PermValue mentionEveryone = PermValue.Inherit,
PermValue useExternalEmojis = PermValue.Inherit, PermValue connect = PermValue.Inherit, PermValue speak = PermValue.Inherit, PermValue muteMembers = PermValue.Inherit, PermValue deafenMembers = PermValue.Inherit,
PermValue moveMembers = PermValue.Inherit, PermValue useVoiceActivation = PermValue.Inherit, PermValue manageRoles = PermValue.Inherit, PermValue manageWebhooks = PermValue.Inherit)
PermValue readMessages = PermValue.Inherit,
PermValue sendMessages = PermValue.Inherit,
PermValue sendTTSMessages = PermValue.Inherit,
PermValue manageMessages = PermValue.Inherit,
PermValue embedLinks = PermValue.Inherit,
PermValue attachFiles = PermValue.Inherit,
PermValue readMessageHistory = PermValue.Inherit,
PermValue mentionEveryone = PermValue.Inherit,
PermValue useExternalEmojis = PermValue.Inherit,
PermValue connect = PermValue.Inherit,
PermValue speak = PermValue.Inherit,
PermValue muteMembers = PermValue.Inherit,
PermValue deafenMembers = PermValue.Inherit,
PermValue moveMembers = PermValue.Inherit,
PermValue useVoiceActivation = PermValue.Inherit,
PermValue manageRoles = PermValue.Inherit,
PermValue manageWebhooks = PermValue.Inherit)
: this(0, 0, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages, : this(0, 0, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers,
moveMembers, useVoiceActivation, manageRoles, manageWebhooks) { } moveMembers, useVoiceActivation, manageRoles, manageWebhooks) { }
@@ -134,12 +163,27 @@ namespace Discord
/// Creates a new <see cref="OverwritePermissions" /> from this one, changing the provided non-null /// Creates a new <see cref="OverwritePermissions" /> from this one, changing the provided non-null
/// permissions. /// permissions.
/// </summary> /// </summary>
public OverwritePermissions Modify(PermValue? createInstantInvite = null, PermValue? manageChannel = null,
public OverwritePermissions Modify(
PermValue? createInstantInvite = null,
PermValue? manageChannel = null,
PermValue? addReactions = null, PermValue? addReactions = null,
PermValue? readMessages = null, PermValue? sendMessages = null, PermValue? sendTTSMessages = null, PermValue? manageMessages = null,
PermValue? embedLinks = null, PermValue? attachFiles = null, PermValue? readMessageHistory = null, PermValue? mentionEveryone = null,
PermValue? useExternalEmojis = null, PermValue? connect = null, PermValue? speak = null, PermValue? muteMembers = null, PermValue? deafenMembers = null,
PermValue? moveMembers = null, PermValue? useVoiceActivation = null, PermValue? manageRoles = null, PermValue? manageWebhooks = null)
PermValue? readMessages = null,
PermValue? sendMessages = null,
PermValue? sendTTSMessages = null,
PermValue? manageMessages = null,
PermValue? embedLinks = null,
PermValue? attachFiles = null,
PermValue? readMessageHistory = null,
PermValue? mentionEveryone = null,
PermValue? useExternalEmojis = null,
PermValue? connect = null,
PermValue? speak = null,
PermValue? muteMembers = null,
PermValue? deafenMembers = null,
PermValue? moveMembers = null,
PermValue? useVoiceActivation = null,
PermValue? manageRoles = null,
PermValue? manageWebhooks = null)
=> new OverwritePermissions(AllowValue, DenyValue, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages, => new OverwritePermissions(AllowValue, DenyValue, createInstantInvite, manageChannel, addReactions, readMessages, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers,
moveMembers, useVoiceActivation, manageRoles, manageWebhooks); moveMembers, useVoiceActivation, manageRoles, manageWebhooks);


+ 2
- 2
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs View File

@@ -48,7 +48,7 @@ namespace Discord.Rest
/// An <see cref="ulong"/> representing the snowflake identifier for the updated channel. /// An <see cref="ulong"/> representing the snowflake identifier for the updated channel.
/// </returns> /// </returns>
public ulong ChannelId { get; } public ulong ChannelId { get; }
public ChannelInfo Before { get; set; }
public ChannelInfo After { get; set; }
public ChannelInfo Before { get; }
public ChannelInfo After { get; }
} }
} }

+ 3
- 17
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleAuditLogData.cs View File

@@ -8,7 +8,7 @@ namespace Discord.Rest
{ {
public class MemberRoleAuditLogData : IAuditLogData public class MemberRoleAuditLogData : IAuditLogData
{ {
private MemberRoleAuditLogData(IReadOnlyCollection<RoleInfo> roles, IUser target)
private MemberRoleAuditLogData(IReadOnlyCollection<MemberRoleEditInfo> roles, IUser target)
{ {
Roles = roles; Roles = roles;
Target = target; Target = target;
@@ -20,7 +20,7 @@ namespace Discord.Rest


var roleInfos = changes.SelectMany(x => x.NewValue.ToObject<API.Role[]>(), var roleInfos = changes.SelectMany(x => x.NewValue.ToObject<API.Role[]>(),
(model, role) => new { model.ChangedProperty, Role = role }) (model, role) => new { model.ChangedProperty, Role = role })
.Select(x => new RoleInfo(x.Role.Name, x.Role.Id, x.ChangedProperty == "$add"))
.Select(x => new MemberRoleEditInfo(x.Role.Name, x.Role.Id, x.ChangedProperty == "$add"))
.ToList(); .ToList();


var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId); var userInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
@@ -29,21 +29,7 @@ namespace Discord.Rest
return new MemberRoleAuditLogData(roleInfos.ToReadOnlyCollection(), user); return new MemberRoleAuditLogData(roleInfos.ToReadOnlyCollection(), user);
} }


public IReadOnlyCollection<RoleInfo> Roles { get; }
public IReadOnlyCollection<MemberRoleEditInfo> Roles { get; }
public IUser Target { get; } public IUser Target { get; }

public struct RoleInfo
{
internal RoleInfo(string name, ulong roleId, bool added)
{
Name = name;
RoleId = roleId;
Added = added;
}

public string Name { get; }
public ulong RoleId { get; }
public bool Added { get; }
}
} }
} }

+ 16
- 0
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleEditInfo.cs View File

@@ -0,0 +1,16 @@
namespace Discord.Rest
{
public struct MemberRoleEditInfo
{
internal MemberRoleEditInfo(string name, ulong roleId, bool added)
{
Name = name;
RoleId = roleId;
Added = added;
}

public string Name { get; }
public ulong RoleId { get; }
public bool Added { get; }
}
}

+ 3
- 3
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleCreateAuditLogData.cs View File

@@ -7,7 +7,7 @@ namespace Discord.Rest
{ {
public class RoleCreateAuditLogData : IAuditLogData public class RoleCreateAuditLogData : IAuditLogData
{ {
private RoleCreateAuditLogData(ulong id, RoleInfo props)
private RoleCreateAuditLogData(ulong id, RoleEditInfo props)
{ {
RoleId = id; RoleId = id;
Properties = props; Properties = props;
@@ -38,10 +38,10 @@ namespace Discord.Rest
permissions = new GuildPermissions(permissionsRaw.Value); permissions = new GuildPermissions(permissionsRaw.Value);


return new RoleCreateAuditLogData(entry.TargetId.Value, return new RoleCreateAuditLogData(entry.TargetId.Value,
new RoleInfo(color, mentionable, hoist, name, permissions));
new RoleEditInfo(color, mentionable, hoist, name, permissions));
} }


public ulong RoleId { get; } public ulong RoleId { get; }
public RoleInfo Properties { get; }
public RoleEditInfo Properties { get; }
} }
} }

+ 3
- 3
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleDeleteAuditLogData.cs View File

@@ -7,7 +7,7 @@ namespace Discord.Rest
{ {
public class RoleDeleteAuditLogData : IAuditLogData public class RoleDeleteAuditLogData : IAuditLogData
{ {
private RoleDeleteAuditLogData(ulong id, RoleInfo props)
private RoleDeleteAuditLogData(ulong id, RoleEditInfo props)
{ {
RoleId = id; RoleId = id;
Properties = props; Properties = props;
@@ -38,10 +38,10 @@ namespace Discord.Rest
permissions = new GuildPermissions(permissionsRaw.Value); permissions = new GuildPermissions(permissionsRaw.Value);


return new RoleDeleteAuditLogData(entry.TargetId.Value, return new RoleDeleteAuditLogData(entry.TargetId.Value,
new RoleInfo(color, mentionable, hoist, name, permissions));
new RoleEditInfo(color, mentionable, hoist, name, permissions));
} }


public ulong RoleId { get; } public ulong RoleId { get; }
public RoleInfo Properties { get; }
public RoleEditInfo Properties { get; }
} }
} }

src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleInfo.cs → src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleEditInfo.cs View File

@@ -1,8 +1,8 @@
namespace Discord.Rest namespace Discord.Rest
{ {
public struct RoleInfo
public struct RoleEditInfo
{ {
internal RoleInfo(Color? color, bool? mentionable, bool? hoist, string name,
internal RoleEditInfo(Color? color, bool? mentionable, bool? hoist, string name,
GuildPermissions? permissions) GuildPermissions? permissions)
{ {
Color = color; Color = color;

+ 5
- 5
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs View File

@@ -7,7 +7,7 @@ namespace Discord.Rest
{ {
public class RoleUpdateAuditLogData : IAuditLogData public class RoleUpdateAuditLogData : IAuditLogData
{ {
private RoleUpdateAuditLogData(ulong id, RoleInfo oldProps, RoleInfo newProps)
private RoleUpdateAuditLogData(ulong id, RoleEditInfo oldProps, RoleEditInfo newProps)
{ {
RoleId = id; RoleId = id;
Before = oldProps; Before = oldProps;
@@ -49,14 +49,14 @@ namespace Discord.Rest
if (newPermissionsRaw.HasValue) if (newPermissionsRaw.HasValue)
newPermissions = new GuildPermissions(newPermissionsRaw.Value); newPermissions = new GuildPermissions(newPermissionsRaw.Value);


var oldProps = new RoleInfo(oldColor, oldMentionable, oldHoist, oldName, oldPermissions);
var newProps = new RoleInfo(newColor, newMentionable, newHoist, newName, newPermissions);
var oldProps = new RoleEditInfo(oldColor, oldMentionable, oldHoist, oldName, oldPermissions);
var newProps = new RoleEditInfo(newColor, newMentionable, newHoist, newName, newPermissions);


return new RoleUpdateAuditLogData(entry.TargetId.Value, oldProps, newProps); return new RoleUpdateAuditLogData(entry.TargetId.Value, oldProps, newProps);
} }


public ulong RoleId { get; } public ulong RoleId { get; }
public RoleInfo Before { get; }
public RoleInfo After { get; }
public RoleEditInfo Before { get; }
public RoleEditInfo After { get; }
} }
} }

+ 10
- 0
src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs View File

@@ -337,6 +337,16 @@ namespace Discord.Rest
return models.Select(x => RestWebhook.Create(client, channel, x)) return models.Select(x => RestWebhook.Create(client, channel, x))
.ToImmutableArray(); .ToImmutableArray();
} }
// Categories
public static async Task<ICategoryChannel> GetCategoryAsync(INestedChannel channel, BaseDiscordClient client, RequestOptions options)
{
// if no category id specified, return null
if (!channel.CategoryId.HasValue)
return null;
// CategoryId will contain a value here
var model = await client.ApiClient.GetChannelAsync(channel.CategoryId.Value, options).ConfigureAwait(false);
return RestCategoryChannel.Create(client, model) as ICategoryChannel;
}


//Helpers //Helpers
private static IUser GetAuthor(BaseDiscordClient client, IGuild guild, UserModel model, ulong? webhookId) private static IUser GetAuthor(BaseDiscordClient client, IGuild guild, UserModel model, ulong? webhookId)


+ 0
- 8
src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs View File

@@ -28,14 +28,6 @@ namespace Discord.Rest
// IGuildChannel // IGuildChannel
/// <inheritdoc /> /// <inheritdoc />
/// <exception cref="NotSupportedException">This method is not supported with category channels.</exception> /// <exception cref="NotSupportedException">This method is not supported with category channels.</exception>
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> throw new NotSupportedException();
/// <inheritdoc />
/// <exception cref="NotSupportedException">This method is not supported with category channels.</exception>
Task<IGuildUser> IGuildChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
=> throw new NotSupportedException();
/// <inheritdoc />
/// <exception cref="NotSupportedException">This method is not supported with category channels.</exception>
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();
/// <inheritdoc /> /// <inheritdoc />


+ 2
- 0
src/Discord.Net.Rest/Entities/Channels/RestChannel.cs View File

@@ -29,6 +29,8 @@ namespace Discord.Rest
case ChannelType.DM: case ChannelType.DM:
case ChannelType.Group: case ChannelType.Group:
return CreatePrivate(discord, model) as RestChannel; return CreatePrivate(discord, model) as RestChannel;
case ChannelType.Category:
return RestCategoryChannel.Create(discord, new RestGuild(discord, model.GuildId.Value), model);
default: default:
return new RestChannel(discord, model.Id); return new RestChannel(discord, model.Id);
} }


+ 0
- 11
src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs View File

@@ -23,8 +23,6 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
public int Position { get; private set; } public int Position { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public ulong? CategoryId { get; private set; }
/// <inheritdoc />
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)
@@ -43,7 +41,6 @@ namespace Discord.Rest
case ChannelType.Category: case ChannelType.Category:
return RestCategoryChannel.Create(discord, guild, model); return RestCategoryChannel.Create(discord, guild, model);
default: default:
// TODO: Channel categories
return new RestGuildChannel(discord, guild, model.Id); return new RestGuildChannel(discord, guild, model.Id);
} }
} }
@@ -75,14 +72,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);


/// <inheritdoc />
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++)


+ 14
- 1
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs View File

@@ -16,6 +16,7 @@ namespace Discord.Rest
{ {
/// <inheritdoc /> /// <inheritdoc />
public string Topic { get; private set; } public string Topic { get; private set; }
public ulong? CategoryId { get; private set; }


/// <inheritdoc /> /// <inheritdoc />
public string Mention => MentionUtils.MentionChannel(Id); public string Mention => MentionUtils.MentionChannel(Id);
@@ -37,7 +38,7 @@ namespace Discord.Rest
internal override void Update(Model model) internal override void Update(Model model)
{ {
base.Update(model); base.Update(model);
CategoryId = model.CategoryId;
Topic = model.Topic.Value; Topic = model.Topic.Value;
_nsfw = model.Nsfw.GetValueOrDefault(); _nsfw = model.Nsfw.GetValueOrDefault();
} }
@@ -134,6 +135,9 @@ namespace Discord.Rest
=> ChannelHelper.GetWebhookAsync(this, Discord, id, options); => ChannelHelper.GetWebhookAsync(this, Discord, id, options);
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null)
=> ChannelHelper.GetWebhooksAsync(this, Discord, options); => ChannelHelper.GetWebhooksAsync(this, Discord, options);
public Task<ICategoryChannel> GetCategoryAsync(RequestOptions options = null)
=> ChannelHelper.GetCategoryAsync(this, Discord, options);


private string DebuggerDisplay => $"{Name} ({Id}, Text)"; private string DebuggerDisplay => $"{Name} ({Id}, Text)";


@@ -165,6 +169,7 @@ namespace Discord.Rest
else else
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>();
} }
/// <inheritdoc /> /// <inheritdoc />
IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options) IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options)
{ {
@@ -234,5 +239,13 @@ namespace Discord.Rest
else else
return AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>(); return AsyncEnumerable.Empty<IReadOnlyCollection<IGuildUser>>();
} }

// INestedChannel
async Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options)
{
if (CategoryId.HasValue && mode == CacheMode.AllowDownload)
return (await Guild.GetChannelAsync(CategoryId.Value, mode, options).ConfigureAwait(false)) as ICategoryChannel;
return null;
}
} }
} }

+ 13
- 1
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs View File

@@ -18,6 +18,7 @@ namespace Discord.Rest
public int Bitrate { get; private set; } public int Bitrate { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
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)
@@ -33,7 +34,7 @@ namespace Discord.Rest
internal override void Update(Model model) internal override void Update(Model model)
{ {
base.Update(model); base.Update(model);
CategoryId = model.CategoryId;
Bitrate = model.Bitrate.Value; Bitrate = model.Bitrate.Value;
UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null; UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null;
} }
@@ -45,6 +46,9 @@ namespace Discord.Rest
Update(model); Update(model);
} }


public Task<ICategoryChannel> GetCategoryAsync(RequestOptions options = null)
=> ChannelHelper.GetCategoryAsync(this, Discord, options);

private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; private string DebuggerDisplay => $"{Name} ({Id}, Voice)";


//IAudioChannel //IAudioChannel
@@ -59,5 +63,13 @@ namespace Discord.Rest
/// <inheritdoc /> /// <inheritdoc />
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(CacheMode mode, RequestOptions options)
{
if (CategoryId.HasValue && mode == CacheMode.AllowDownload)
return (await Guild.GetChannelAsync(CategoryId.Value, mode, options).ConfigureAwait(false)) as ICategoryChannel;
return null;
}
} }
} }

+ 1
- 1
src/Discord.Net.WebSocket/Entities/Channels/SocketCategoryChannel.cs View File

@@ -21,7 +21,7 @@ namespace Discord.WebSocket
ChannelPermission.ViewChannel)).ToImmutableArray(); ChannelPermission.ViewChannel)).ToImmutableArray();


public IReadOnlyCollection<SocketGuildChannel> Channels public IReadOnlyCollection<SocketGuildChannel> Channels
=> Guild.Channels.Where(x => x.CategoryId == Id).ToImmutableArray();
=> Guild.Channels.Where(x => x is INestedChannel nestedChannel && nestedChannel.CategoryId == Id).ToImmutableArray();


internal SocketCategoryChannel(DiscordSocketClient discord, ulong id, SocketGuild guild) internal SocketCategoryChannel(DiscordSocketClient discord, ulong id, SocketGuild guild)
: base(discord, id, guild) : base(discord, id, guild)


+ 2
- 17
src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs View File

@@ -27,17 +27,7 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
public string Name { get; private set; } public string Name { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public int Position { get; private set; }
/// <inheritdoc />
public ulong? CategoryId { get; private set; }
/// <summary>
/// Gets the parent category of this channel.
/// </summary>
/// <returns>
/// A parent category ID associated with this channel, or <c>null</c> if none is set.
/// </returns>
public ICategoryChannel Category
=> CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null;
public int Position { get; private set; }


/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites; public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites;
@@ -73,8 +63,7 @@ namespace Discord.WebSocket
{ {
Name = model.Name.Value; Name = model.Name.Value;
Position = model.Position.Value; Position = model.Position.Value;
CategoryId = model.CategoryId;

var overwrites = model.PermissionOverwrites.Value; var overwrites = model.PermissionOverwrites.Value;
var newOverwrites = ImmutableArray.CreateBuilder<Overwrite>(overwrites.Length); var newOverwrites = ImmutableArray.CreateBuilder<Overwrite>(overwrites.Length);
for (int i = 0; i < overwrites.Length; i++) for (int i = 0; i < overwrites.Length; i++)
@@ -168,10 +157,6 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
ulong IGuildChannel.GuildId => Guild.Id; ulong IGuildChannel.GuildId => Guild.Id;


/// <inheritdoc />
Task<ICategoryChannel> IGuildChannel.GetCategoryAsync()
=> Task.FromResult(Category);

/// <inheritdoc /> /// <inheritdoc />
async Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options) async Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options)
=> await GetInvitesAsync(options).ConfigureAwait(false); => await GetInvitesAsync(options).ConfigureAwait(false);


+ 8
- 1
src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs View File

@@ -20,6 +20,9 @@ namespace Discord.WebSocket


/// <inheritdoc /> /// <inheritdoc />
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;
/// <inheritdoc /> /// <inheritdoc />
@@ -50,7 +53,7 @@ namespace Discord.WebSocket
internal override void Update(ClientState state, Model model) internal override void Update(ClientState state, Model model)
{ {
base.Update(state, model); base.Update(state, model);
CategoryId = model.CategoryId;
Topic = model.Topic.Value; Topic = model.Topic.Value;
_nsfw = model.Nsfw.GetValueOrDefault(); _nsfw = model.Nsfw.GetValueOrDefault();
} }
@@ -226,5 +229,9 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
IDisposable IMessageChannel.EnterTypingState(RequestOptions options) IDisposable IMessageChannel.EnterTypingState(RequestOptions options)
=> EnterTypingState(options); => EnterTypingState(options);

// INestedChannel
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options)
=> Task.FromResult(Category);
} }
} }

+ 9
- 2
src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs View File

@@ -20,6 +20,9 @@ namespace Discord.WebSocket
public int Bitrate { get; private set; } public int Bitrate { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
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;


/// <inheritdoc /> /// <inheritdoc />
public override IReadOnlyCollection<SocketGuildUser> Users public override IReadOnlyCollection<SocketGuildUser> Users
@@ -38,7 +41,7 @@ namespace Discord.WebSocket
internal override void Update(ClientState state, Model model) internal override void Update(ClientState state, Model model)
{ {
base.Update(state, model); base.Update(state, model);
CategoryId = model.CategoryId;
Bitrate = model.Bitrate.Value; Bitrate = model.Bitrate.Value;
UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null; UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null;
} }
@@ -61,7 +64,7 @@ namespace Discord.WebSocket
return user; return user;
return null; return null;
} }
private string DebuggerDisplay => $"{Name} ({Id}, Voice)"; private string DebuggerDisplay => $"{Name} ({Id}, Voice)";
internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel; internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel;


@@ -72,5 +75,9 @@ namespace Discord.WebSocket
/// <inheritdoc /> /// <inheritdoc />
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(CacheMode mode, RequestOptions options)
=> Task.FromResult(Category);
} }
} }

+ 21
- 0
test/Discord.Net.Tests/Tests.ChannelPermissions.cs View File

@@ -22,6 +22,27 @@ namespace Discord
var copy = perm.Modify(); var copy = perm.Modify();
Assert.Equal((ulong)0, copy.RawValue); Assert.Equal((ulong)0, copy.RawValue);


// test modify with no parameters after using all
copy = ChannelPermissions.Text;
var modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.Text.RawValue, modified.RawValue);

copy = ChannelPermissions.Voice;
modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.Voice.RawValue, modified.RawValue);

copy = ChannelPermissions.Group;
modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.Group.RawValue, modified.RawValue);

copy = ChannelPermissions.DM;
modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.DM.RawValue, modified.RawValue);

copy = new ChannelPermissions(useExternalEmojis: true);
modified = copy.Modify();
Assert.Equal(copy.RawValue, modified.RawValue);

// test the values that are returned by ChannelPermission.All // test the values that are returned by ChannelPermission.All
Assert.Equal((ulong)0, ChannelPermissions.None.RawValue); Assert.Equal((ulong)0, ChannelPermissions.None.RawValue);




+ 74
- 0
test/Discord.Net.Tests/Tests.Channels.cs View File

@@ -1,4 +1,5 @@
using Discord.Rest; using Discord.Rest;
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;
@@ -15,17 +16,28 @@ namespace Discord
var text4 = await guild.CreateTextChannelAsync("text4"); var text4 = await guild.CreateTextChannelAsync("text4");
var text5 = await guild.CreateTextChannelAsync("text5"); var text5 = await guild.CreateTextChannelAsync("text5");


// create a channel category
var cat1 = await guild.CreateCategoryChannelAsync("cat1");

if (text1 == null)
{
// the guild did not have a default channel, so make a new one
text1 = await guild.CreateTextChannelAsync("default");
}

//Modify #general //Modify #general
await text1.ModifyAsync(x => await text1.ModifyAsync(x =>
{ {
x.Name = "text1"; x.Name = "text1";
x.Position = 1; x.Position = 1;
x.Topic = "Topic1"; x.Topic = "Topic1";
x.CategoryId = cat1.Id;
}); });


await text2.ModifyAsync(x => await text2.ModifyAsync(x =>
{ {
x.Position = 2; x.Position = 2;
x.CategoryId = cat1.Id;
}); });
await text3.ModifyAsync(x => await text3.ModifyAsync(x =>
{ {
@@ -89,10 +101,13 @@ namespace Discord
var voice2 = await guild.CreateVoiceChannelAsync("voice2"); var voice2 = await guild.CreateVoiceChannelAsync("voice2");
var voice3 = await guild.CreateVoiceChannelAsync("voice3"); var voice3 = await guild.CreateVoiceChannelAsync("voice3");


var cat2 = await guild.CreateCategoryChannelAsync("cat2");

await voice1.ModifyAsync(x => await voice1.ModifyAsync(x =>
{ {
x.Bitrate = 96000; x.Bitrate = 96000;
x.Position = 1; x.Position = 1;
x.CategoryId = cat2.Id;
}); });
await voice2.ModifyAsync(x => await voice2.ModifyAsync(x =>
{ {
@@ -103,6 +118,7 @@ namespace Discord
x.Bitrate = 8000; x.Bitrate = 8000;
x.Position = 1; x.Position = 1;
x.UserLimit = 16; x.UserLimit = 16;
x.CategoryId = cat2.Id;
}); });


CheckVoiceChannels(voice1, voice2, voice3); CheckVoiceChannels(voice1, voice2, voice3);
@@ -140,5 +156,63 @@ namespace Discord
Assert.Equal(1, voice3.Position); Assert.Equal(1, voice3.Position);
Assert.Equal(16, voice3.UserLimit); Assert.Equal(16, voice3.UserLimit);
} }

[Fact]
public async Task TestChannelCategories()
{
// (await _guild.GetVoiceChannelsAsync()).ToArray()
var channels = await _guild.GetCategoryChannelsAsync();

await CheckChannelCategories(channels.ToArray(), (await _guild.GetChannelsAsync()).ToArray());
}

private async Task CheckChannelCategories(RestCategoryChannel[] categories, RestGuildChannel[] allChannels)
{
// 2 categories
Assert.Equal(categories.Length, 2);

var cat1 = categories.Where(x => x.Name == "cat1").FirstOrDefault();
var cat2 = categories.Where(x => x.Name == "cat2").FirstOrDefault();

Assert.NotNull(cat1);
Assert.NotNull(cat2);

// get text1, text2, ensure they have category id == cat1
var text1 = allChannels.Where(x => x.Name == "text1").FirstOrDefault() as RestTextChannel;
var text2 = allChannels.Where(x => x.Name == "text2").FirstOrDefault() as RestTextChannel;

Assert.NotNull(text1);
Assert.NotNull(text2);

// check that CategoryID and .GetCategoryAsync work correctly
// for both of the text channels
Assert.Equal(text1.CategoryId, cat1.Id);
var text1Cat = await text1.GetCategoryAsync();
Assert.Equal(text1Cat.Id, cat1.Id);
Assert.Equal(text1Cat.Name, cat1.Name);

Assert.Equal(text2.CategoryId, cat1.Id);
var text2Cat = await text2.GetCategoryAsync();
Assert.Equal(text2Cat.Id, cat1.Id);
Assert.Equal(text2Cat.Name, cat1.Name);

// do the same for the voice channels
var voice1 = allChannels.Where(x => x.Name == "voice1").FirstOrDefault() as RestVoiceChannel;
var voice3 = allChannels.Where(x => x.Name == "voice3").FirstOrDefault() as RestVoiceChannel;

Assert.NotNull(voice1);
Assert.NotNull(voice3);
Assert.Equal(voice1.CategoryId, cat2.Id);
var voice1Cat = await voice1.GetCategoryAsync();
Assert.Equal(voice1Cat.Id, cat2.Id);
Assert.Equal(voice1Cat.Name, cat2.Name);

Assert.Equal(voice3.CategoryId, cat2.Id);
var voice3Cat = await voice3.GetCategoryAsync();
Assert.Equal(voice3Cat.Id, cat2.Id);
Assert.Equal(voice3Cat.Name, cat2.Name);

}
} }
} }

+ 12
- 0
test/Discord.Net.Tests/Tests.GuildPermissions.cs View File

@@ -26,6 +26,18 @@ namespace Discord
// ensure that the raw values match // ensure that the raw values match
Assert.Equal((ulong)0, copy.RawValue); Assert.Equal((ulong)0, copy.RawValue);


// test modify with no parameters
copy = GuildPermissions.None.Modify();
Assert.Equal(GuildPermissions.None.RawValue, copy.RawValue);

// test modify with no paramters on all permissions
copy = GuildPermissions.All.Modify();
Assert.Equal(GuildPermissions.All.RawValue, copy.RawValue);

// test modify with no paramters on webhook permissions
copy = GuildPermissions.Webhook.Modify();
Assert.Equal(GuildPermissions.Webhook.RawValue, copy.RawValue);

// test GuildPermissions.All // test GuildPermissions.All
ulong sumOfAllGuildPermissions = 0; ulong sumOfAllGuildPermissions = 0;
foreach(var v in Enum.GetValues(typeof(GuildPermission))) foreach(var v in Enum.GetValues(typeof(GuildPermission)))


+ 66
- 0
test/Discord.Net.Tests/Tests.Permissions.cs View File

@@ -702,5 +702,71 @@ namespace Discord


return Task.CompletedTask; return Task.CompletedTask;
} }

/// <summary>
/// Tests for the <see cref="OverwritePermissions.Modify(PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?)"/>
/// method to ensure that the default no-param call does not modify the resulting value
/// of the OverwritePermissions.
/// </summary>
/// <returns></returns>
public Task TestOverwritePermissionModifyNoParam()
{
// test for all Text allowed, none denied
var original = new OverwritePermissions(ChannelPermissions.Text.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, text denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Text.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// category allowed, none denied
original = new OverwritePermissions(ChannelPermissions.Category.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, category denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Category.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// DM allowed, none denied
original = new OverwritePermissions(ChannelPermissions.DM.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, DM denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.DM.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// voice allowed, none denied
original = new OverwritePermissions(ChannelPermissions.Voice.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, voice denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Voice.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// group allowed, none denied
original = new OverwritePermissions(ChannelPermissions.Group.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, group denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Group.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, none denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

return Task.CompletedTask;
}
} }
} }

Loading…
Cancel
Save