Browse Source

Merge branch 'dev' into fix-use-external-emojis

pull/1003/head
Christopher F GitHub 7 years ago
parent
commit
e07d63090c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 370 additions and 345 deletions
  1. +1
    -7
      Discord.Net.targets
  2. +1
    -1
      samples/02_commands_framework/02_commands_framework.csproj
  3. +1
    -1
      src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj
  4. +7
    -3
      src/Discord.Net.Commands/Discord.Net.Commands.csproj
  5. +5
    -5
      src/Discord.Net.Core/Discord.Net.Core.csproj
  6. +1
    -1
      src/Discord.Net.Core/Entities/Channels/ICategoryChannel.cs
  7. +2
    -6
      src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs
  8. +1
    -2
      src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
  9. +16
    -0
      src/Discord.Net.Core/Entities/Channels/INestedChannel.cs
  10. +3
    -3
      src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
  11. +3
    -3
      src/Discord.Net.Core/Entities/Channels/IVoiceChannel.cs
  12. +3
    -3
      src/Discord.Net.Core/Entities/Image.cs
  13. +6
    -6
      src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
  14. +0
    -2
      src/Discord.Net.Core/Extensions/UserExtensions.cs
  15. +10
    -13
      src/Discord.Net.Core/Logging/LogManager.cs
  16. +12
    -13
      src/Discord.Net.Core/Logging/Logger.cs
  17. +2
    -45
      src/Discord.Net.Core/Utils/DateTimeUtils.cs
  18. +2
    -2
      src/Discord.Net.Core/Utils/SnowflakeUtils.cs
  19. +6
    -7
      src/Discord.Net.Rest/Discord.Net.Rest.csproj
  20. +2
    -2
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs
  21. +3
    -17
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleAuditLogData.cs
  22. +16
    -0
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleEditInfo.cs
  23. +3
    -3
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleCreateAuditLogData.cs
  24. +3
    -3
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleDeleteAuditLogData.cs
  25. +21
    -0
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleEditInfo.cs
  26. +0
    -21
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleInfo.cs
  27. +5
    -5
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs
  28. +11
    -2
      src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs
  29. +1
    -2
      src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs
  30. +1
    -5
      src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs
  31. +3
    -1
      src/Discord.Net.Rest/Entities/Channels/RestChannel.cs
  32. +3
    -4
      src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
  33. +3
    -4
      src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
  34. +1
    -10
      src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
  35. +21
    -9
      src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs
  36. +14
    -2
      src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs
  37. +2
    -4
      src/Discord.Net.Rest/Entities/Channels/RpcVirtualMessageChannel.cs
  38. +1
    -2
      src/Discord.Net.Rest/Net/Converters/DiscordContractResolver.cs
  39. +1
    -1
      src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
  40. +2
    -2
      src/Discord.Net.Rest/Net/RateLimitInfo.cs
  41. +4
    -4
      src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj
  42. +1
    -1
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  43. +2
    -2
      src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs
  44. +1
    -2
      src/Discord.Net.WebSocket/Entities/Channels/ISocketMessageChannel.cs
  45. +1
    -1
      src/Discord.Net.WebSocket/Entities/Channels/SocketCategoryChannel.cs
  46. +2
    -4
      src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
  47. +4
    -4
      src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
  48. +3
    -10
      src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
  49. +12
    -5
      src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs
  50. +10
    -3
      src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
  51. +0
    -6
      src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs
  52. +1
    -9
      src/Discord.Net.WebSocket/Net/DefaultUdpSocketProvider.cs
  53. +3
    -10
      src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs
  54. +1
    -9
      src/Discord.Net.WebSocket/Net/DefaultWebSocketClientProvider.cs
  55. +2
    -2
      src/Discord.Net.Webhook/Discord.Net.Webhook.csproj
  56. +1
    -2
      src/Discord.Net.Webhook/DiscordWebhookClient.cs
  57. +1
    -3
      src/Discord.Net.Webhook/WebhookClientHelper.cs
  58. +5
    -5
      test/Discord.Net.Tests/Discord.Net.Tests.csproj
  59. +1
    -1
      test/Discord.Net.Tests/Tests.ChannelPermissions.cs
  60. +100
    -26
      test/Discord.Net.Tests/Tests.Channels.cs
  61. +2
    -1
      test/Discord.Net.Tests/Tests.Colors.cs
  62. +2
    -1
      test/Discord.Net.Tests/Tests.Emotes.cs
  63. +5
    -5
      test/Discord.Net.Tests/Tests.GuildPermissions.cs
  64. +7
    -7
      test/Discord.Net.Tests/Tests.Permissions.cs

+ 1
- 7
Discord.Net.targets View File

@@ -16,13 +16,7 @@
<PropertyGroup Condition=" '$(BuildNumber)' != '' And $(IsTagBuild) != 'true' "> <PropertyGroup Condition=" '$(BuildNumber)' != '' And $(IsTagBuild) != 'true' ">
<VersionSuffix Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)-$(BuildNumber)</VersionSuffix> <VersionSuffix Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
<VersionSuffix Condition=" '$(VersionSuffix)' == '' ">build-$(BuildNumber)</VersionSuffix> <VersionSuffix Condition=" '$(VersionSuffix)' == '' ">build-$(BuildNumber)</VersionSuffix>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' Or '$(TargetFramework)' == 'net45' ">
<DefineConstants>$(DefineConstants);FILESYSTEM;DEFAULTUDPCLIENT;DEFAULTWEBSOCKET</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<DefineConstants>$(DefineConstants);FORMATSTR;UNIXTIME;MSTRYBUFFER;UDPDISPOSE</DefineConstants>
</PropertyGroup>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn> <NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
<WarningsAsErrors>true</WarningsAsErrors> <WarningsAsErrors>true</WarningsAsErrors>


+ 1
- 1
samples/02_commands_framework/02_commands_framework.csproj View File

@@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>


<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.0-preview1-final" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
</ItemGroup> </ItemGroup>


<ItemGroup> <ItemGroup>


+ 1
- 1
src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj View File

@@ -7,7 +7,7 @@
<TargetFramework>netstandard1.3</TargetFramework> <TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.8.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Discord.Net.Commands\Discord.Net.Commands.csproj" /> <ProjectReference Include="..\Discord.Net.Commands\Discord.Net.Commands.csproj" />


+ 7
- 3
src/Discord.Net.Commands/Discord.Net.Commands.csproj View File

@@ -1,15 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" /> <Import Project="../../Discord.Net.targets" />
<PropertyGroup> <PropertyGroup>
<AssemblyName>Discord.Net.Commands</AssemblyName> <AssemblyName>Discord.Net.Commands</AssemblyName>
<RootNamespace>Discord.Commands</RootNamespace> <RootNamespace>Discord.Commands</RootNamespace>
<Description>A Discord.Net extension adding support for bot commands.</Description> <Description>A Discord.Net extension adding support for bot commands.</Description>
<TargetFrameworks>netstandard1.1</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" /> <ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard2.0' ">
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

+ 5
- 5
src/Discord.Net.Core/Discord.Net.Core.csproj View File

@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" /> <Import Project="../../Discord.Net.targets" />
<PropertyGroup> <PropertyGroup>
<AssemblyName>Discord.Net.Core</AssemblyName> <AssemblyName>Discord.Net.Core</AssemblyName>
<RootNamespace>Discord</RootNamespace> <RootNamespace>Discord</RootNamespace>
<Description>The core components for the Discord.Net library.</Description> <Description>The core components for the Discord.Net library.</Description>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net45;netstandard1.1;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.1;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Interactive.Async" Version="3.1.1" /> <PackageReference Include="System.Interactive.Async" Version="3.1.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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

@@ -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;


+ 2
- 6
src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs View File

@@ -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);
} }
}
}

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

@@ -9,10 +9,9 @@ namespace Discord
{ {
/// <summary> Sends a message to this message channel. </summary> /// <summary> Sends a message to this message channel. </summary>
Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#if FILESYSTEM
/// <summary> Sends a file to this text channel, with an optional caption. </summary> /// <summary> Sends a file to this text channel, with an optional caption. </summary>
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#endif
/// <summary> Sends a file to this text channel, with an optional caption. </summary> /// <summary> Sends a file to this text channel, with an optional caption. </summary>
Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);




+ 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);
}
}

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

@@ -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, 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);
} }
}
}

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

@@ -1,9 +1,9 @@
using System;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord namespace Discord
{ {
public interface IVoiceChannel : IGuildChannel, IAudioChannel
public interface IVoiceChannel : INestedChannel, IAudioChannel
{ {
/// <summary> Gets the bitrate, in bits per second, clients in this voice channel are requested to use. </summary> /// <summary> Gets the bitrate, in bits per second, clients in this voice channel are requested to use. </summary>
int Bitrate { get; } int Bitrate { get; }
@@ -13,4 +13,4 @@ namespace Discord
/// <summary> Modifies this voice channel. </summary> /// <summary> Modifies this voice channel. </summary>
Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null); Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null);
} }
}
}

+ 3
- 3
src/Discord.Net.Core/Entities/Image.cs View File

@@ -1,4 +1,4 @@
using System.IO;
using System.IO;
namespace Discord namespace Discord
{ {
/// <summary> /// <summary>
@@ -15,7 +15,7 @@ namespace Discord
{ {
Stream = stream; Stream = stream;
} }
#if FILESYSTEM
/// <summary> /// <summary>
/// Create the image from a file path. /// Create the image from a file path.
/// </summary> /// </summary>
@@ -27,6 +27,6 @@ namespace Discord
{ {
Stream = File.OpenRead(path); Stream = File.OpenRead(path);
} }
#endif
} }
} }

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

@@ -93,7 +93,7 @@ namespace Discord
bool? manageGuild = null, bool? manageGuild = null,
bool? addReactions = null, bool? addReactions = null,
bool? viewAuditLog = null, bool? viewAuditLog = null,
bool? readMessages = null,
bool? viewChannel = null,
bool? sendMessages = null, bool? sendMessages = null,
bool? sendTTSMessages = null, bool? sendTTSMessages = null,
bool? manageMessages = null, bool? manageMessages = null,
@@ -124,7 +124,7 @@ namespace Discord
Permissions.SetValue(ref value, manageGuild, GuildPermission.ManageGuild); Permissions.SetValue(ref value, manageGuild, GuildPermission.ManageGuild);
Permissions.SetValue(ref value, addReactions, GuildPermission.AddReactions); Permissions.SetValue(ref value, addReactions, GuildPermission.AddReactions);
Permissions.SetValue(ref value, viewAuditLog, GuildPermission.ViewAuditLog); Permissions.SetValue(ref value, viewAuditLog, GuildPermission.ViewAuditLog);
Permissions.SetValue(ref value, readMessages, GuildPermission.ReadMessages);
Permissions.SetValue(ref value, viewChannel, GuildPermission.ViewChannel);
Permissions.SetValue(ref value, sendMessages, GuildPermission.SendMessages); Permissions.SetValue(ref value, sendMessages, GuildPermission.SendMessages);
Permissions.SetValue(ref value, sendTTSMessages, GuildPermission.SendTTSMessages); Permissions.SetValue(ref value, sendTTSMessages, GuildPermission.SendTTSMessages);
Permissions.SetValue(ref value, manageMessages, GuildPermission.ManageMessages); Permissions.SetValue(ref value, manageMessages, GuildPermission.ManageMessages);
@@ -158,7 +158,7 @@ namespace Discord
bool manageGuild = false, bool manageGuild = false,
bool addReactions = false, bool addReactions = false,
bool viewAuditLog = false, bool viewAuditLog = false,
bool readMessages = false,
bool viewChannel = false,
bool sendMessages = false, bool sendMessages = false,
bool sendTTSMessages = false, bool sendTTSMessages = false,
bool manageMessages = false, bool manageMessages = false,
@@ -188,7 +188,7 @@ namespace Discord
manageGuild: manageGuild, manageGuild: manageGuild,
addReactions: addReactions, addReactions: addReactions,
viewAuditLog: viewAuditLog, viewAuditLog: viewAuditLog,
readMessages: readMessages,
viewChannel: viewChannel,
sendMessages: sendMessages, sendMessages: sendMessages,
sendTTSMessages: sendTTSMessages, sendTTSMessages: sendTTSMessages,
manageMessages: manageMessages, manageMessages: manageMessages,
@@ -219,7 +219,7 @@ namespace Discord
bool? manageGuild = null, bool? manageGuild = null,
bool? addReactions = null, bool? addReactions = null,
bool? viewAuditLog = null, bool? viewAuditLog = null,
bool? readMessages = null,
bool? viewChannel = null,
bool? sendMessages = null, bool? sendMessages = null,
bool? sendTTSMessages = null, bool? sendTTSMessages = null,
bool? manageMessages = null, bool? manageMessages = null,
@@ -240,7 +240,7 @@ namespace Discord
bool? manageWebhooks = null, bool? manageWebhooks = null,
bool? manageEmojis = 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, readMessages, 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,
useVoiceActivation, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis); useVoiceActivation, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis);




+ 0
- 2
src/Discord.Net.Core/Extensions/UserExtensions.cs View File

@@ -32,7 +32,6 @@ namespace Discord
return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
} }


#if FILESYSTEM
/// <summary> /// <summary>
/// Sends a file to the user via DM. /// Sends a file to the user via DM.
/// </summary> /// </summary>
@@ -45,7 +44,6 @@ namespace Discord
{ {
return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); return await (await user.GetOrCreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
} }
#endif


public static Task BanAsync(this IGuildUser user, int pruneDays = 0, string reason = null, RequestOptions options = null) public static Task BanAsync(this IGuildUser user, int pruneDays = 0, string reason = null, RequestOptions options = null)
=> user.Guild.AddBanAsync(user, pruneDays, reason, options); => user.Guild.AddBanAsync(user, pruneDays, reason, options);


+ 10
- 13
src/Discord.Net.Core/Logging/LogManager.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.Logging namespace Discord.Logging
@@ -35,7 +35,7 @@ namespace Discord.Logging
} }
catch { } catch { }
} }
#if FORMATSTR
public async Task LogAsync(LogSeverity severity, string source, FormattableString message, Exception ex = null) public async Task LogAsync(LogSeverity severity, string source, FormattableString message, Exception ex = null)
{ {
try try
@@ -45,52 +45,49 @@ namespace Discord.Logging
} }
catch { } catch { }
} }
#endif


public Task ErrorAsync(string source, Exception ex) public Task ErrorAsync(string source, Exception ex)
=> LogAsync(LogSeverity.Error, source, ex); => LogAsync(LogSeverity.Error, source, ex);
public Task ErrorAsync(string source, string message, Exception ex = null) public Task ErrorAsync(string source, string message, Exception ex = null)
=> LogAsync(LogSeverity.Error, source, message, ex); => LogAsync(LogSeverity.Error, source, message, ex);
#if FORMATSTR
public Task ErrorAsync(string source, FormattableString message, Exception ex = null) public Task ErrorAsync(string source, FormattableString message, Exception ex = null)
=> LogAsync(LogSeverity.Error, source, message, ex); => LogAsync(LogSeverity.Error, source, message, ex);
#endif


public Task WarningAsync(string source, Exception ex) public Task WarningAsync(string source, Exception ex)
=> LogAsync(LogSeverity.Warning, source, ex); => LogAsync(LogSeverity.Warning, source, ex);
public Task WarningAsync(string source, string message, Exception ex = null) public Task WarningAsync(string source, string message, Exception ex = null)
=> LogAsync(LogSeverity.Warning, source, message, ex); => LogAsync(LogSeverity.Warning, source, message, ex);
#if FORMATSTR
public Task WarningAsync(string source, FormattableString message, Exception ex = null) public Task WarningAsync(string source, FormattableString message, Exception ex = null)
=> LogAsync(LogSeverity.Warning, source, message, ex); => LogAsync(LogSeverity.Warning, source, message, ex);
#endif


public Task InfoAsync(string source, Exception ex) public Task InfoAsync(string source, Exception ex)
=> LogAsync(LogSeverity.Info, source, ex); => LogAsync(LogSeverity.Info, source, ex);
public Task InfoAsync(string source, string message, Exception ex = null) public Task InfoAsync(string source, string message, Exception ex = null)
=> LogAsync(LogSeverity.Info, source, message, ex); => LogAsync(LogSeverity.Info, source, message, ex);
#if FORMATSTR
public Task InfoAsync(string source, FormattableString message, Exception ex = null) public Task InfoAsync(string source, FormattableString message, Exception ex = null)
=> LogAsync(LogSeverity.Info, source, message, ex); => LogAsync(LogSeverity.Info, source, message, ex);
#endif


public Task VerboseAsync(string source, Exception ex) public Task VerboseAsync(string source, Exception ex)
=> LogAsync(LogSeverity.Verbose, source, ex); => LogAsync(LogSeverity.Verbose, source, ex);
public Task VerboseAsync(string source, string message, Exception ex = null) public Task VerboseAsync(string source, string message, Exception ex = null)
=> LogAsync(LogSeverity.Verbose, source, message, ex); => LogAsync(LogSeverity.Verbose, source, message, ex);
#if FORMATSTR
public Task VerboseAsync(string source, FormattableString message, Exception ex = null) public Task VerboseAsync(string source, FormattableString message, Exception ex = null)
=> LogAsync(LogSeverity.Verbose, source, message, ex); => LogAsync(LogSeverity.Verbose, source, message, ex);
#endif


public Task DebugAsync(string source, Exception ex) public Task DebugAsync(string source, Exception ex)
=> LogAsync(LogSeverity.Debug, source, ex); => LogAsync(LogSeverity.Debug, source, ex);
public Task DebugAsync(string source, string message, Exception ex = null) public Task DebugAsync(string source, string message, Exception ex = null)
=> LogAsync(LogSeverity.Debug, source, message, ex); => LogAsync(LogSeverity.Debug, source, message, ex);
#if FORMATSTR
public Task DebugAsync(string source, FormattableString message, Exception ex = null) public Task DebugAsync(string source, FormattableString message, Exception ex = null)
=> LogAsync(LogSeverity.Debug, source, message, ex); => LogAsync(LogSeverity.Debug, source, message, ex);
#endif


public Logger CreateLogger(string name) => new Logger(this, name); public Logger CreateLogger(string name) => new Logger(this, name);




+ 12
- 13
src/Discord.Net.Core/Logging/Logger.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;


namespace Discord.Logging namespace Discord.Logging
@@ -20,54 +20,53 @@ namespace Discord.Logging
=> _manager.LogAsync(severity, Name, exception); => _manager.LogAsync(severity, Name, exception);
public Task LogAsync(LogSeverity severity, string message, Exception exception = null) public Task LogAsync(LogSeverity severity, string message, Exception exception = null)
=> _manager.LogAsync(severity, Name, message, exception); => _manager.LogAsync(severity, Name, message, exception);
#if FORMATSTR
public Task LogAsync(LogSeverity severity, FormattableString message, Exception exception = null) public Task LogAsync(LogSeverity severity, FormattableString message, Exception exception = null)
=> _manager.LogAsync(severity, Name, message, exception); => _manager.LogAsync(severity, Name, message, exception);
#endif


public Task ErrorAsync(Exception exception) public Task ErrorAsync(Exception exception)
=> _manager.ErrorAsync(Name, exception); => _manager.ErrorAsync(Name, exception);
public Task ErrorAsync(string message, Exception exception = null) public Task ErrorAsync(string message, Exception exception = null)
=> _manager.ErrorAsync(Name, message, exception); => _manager.ErrorAsync(Name, message, exception);
#if FORMATSTR
public Task ErrorAsync(FormattableString message, Exception exception = null) public Task ErrorAsync(FormattableString message, Exception exception = null)
=> _manager.ErrorAsync(Name, message, exception); => _manager.ErrorAsync(Name, message, exception);
#endif


public Task WarningAsync(Exception exception) public Task WarningAsync(Exception exception)
=> _manager.WarningAsync(Name, exception); => _manager.WarningAsync(Name, exception);
public Task WarningAsync(string message, Exception exception = null) public Task WarningAsync(string message, Exception exception = null)
=> _manager.WarningAsync(Name, message, exception); => _manager.WarningAsync(Name, message, exception);
#if FORMATSTR
public Task WarningAsync(FormattableString message, Exception exception = null) public Task WarningAsync(FormattableString message, Exception exception = null)
=> _manager.WarningAsync(Name, message, exception); => _manager.WarningAsync(Name, message, exception);
#endif


public Task InfoAsync(Exception exception) public Task InfoAsync(Exception exception)
=> _manager.InfoAsync(Name, exception); => _manager.InfoAsync(Name, exception);
public Task InfoAsync(string message, Exception exception = null) public Task InfoAsync(string message, Exception exception = null)
=> _manager.InfoAsync(Name, message, exception); => _manager.InfoAsync(Name, message, exception);
#if FORMATSTR
public Task InfoAsync(FormattableString message, Exception exception = null) public Task InfoAsync(FormattableString message, Exception exception = null)
=> _manager.InfoAsync(Name, message, exception); => _manager.InfoAsync(Name, message, exception);
#endif


public Task VerboseAsync(Exception exception) public Task VerboseAsync(Exception exception)
=> _manager.VerboseAsync(Name, exception); => _manager.VerboseAsync(Name, exception);
public Task VerboseAsync(string message, Exception exception = null) public Task VerboseAsync(string message, Exception exception = null)
=> _manager.VerboseAsync(Name, message, exception); => _manager.VerboseAsync(Name, message, exception);
#if FORMATSTR
public Task VerboseAsync(FormattableString message, Exception exception = null) public Task VerboseAsync(FormattableString message, Exception exception = null)
=> _manager.VerboseAsync(Name, message, exception); => _manager.VerboseAsync(Name, message, exception);
#endif


public Task DebugAsync(Exception exception) public Task DebugAsync(Exception exception)
=> _manager.DebugAsync(Name, exception); => _manager.DebugAsync(Name, exception);
public Task DebugAsync(string message, Exception exception = null) public Task DebugAsync(string message, Exception exception = null)
=> _manager.DebugAsync(Name, message, exception); => _manager.DebugAsync(Name, message, exception);
#if FORMATSTR
public Task DebugAsync(FormattableString message, Exception exception = null) public Task DebugAsync(FormattableString message, Exception exception = null)
=> _manager.DebugAsync(Name, message, exception); => _manager.DebugAsync(Name, message, exception);
#endif
} }
} }

+ 2
- 45
src/Discord.Net.Core/Utils/DateTimeUtils.cs View File

@@ -1,57 +1,14 @@
using System;
using System;


namespace Discord namespace Discord
{ {
//Source: https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/DateTimeOffset.cs //Source: https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/DateTimeOffset.cs
internal static class DateTimeUtils internal static class DateTimeUtils
{ {
#if !UNIXTIME
private const long UnixEpochTicks = 621_355_968_000_000_000;
private const long UnixEpochSeconds = 62_135_596_800;
private const long UnixEpochMilliseconds = 62_135_596_800_000;
#endif

public static DateTimeOffset FromTicks(long ticks) public static DateTimeOffset FromTicks(long ticks)
=> new DateTimeOffset(ticks, TimeSpan.Zero); => new DateTimeOffset(ticks, TimeSpan.Zero);
public static DateTimeOffset? FromTicks(long? ticks) public static DateTimeOffset? FromTicks(long? ticks)
=> ticks != null ? new DateTimeOffset(ticks.Value, TimeSpan.Zero) : (DateTimeOffset?)null; => ticks != null ? new DateTimeOffset(ticks.Value, TimeSpan.Zero) : (DateTimeOffset?)null;

public static DateTimeOffset FromUnixSeconds(long seconds)
{
#if UNIXTIME
return DateTimeOffset.FromUnixTimeSeconds(seconds);
#else
long ticks = seconds * TimeSpan.TicksPerSecond + UnixEpochTicks;
return new DateTimeOffset(ticks, TimeSpan.Zero);
#endif
}
public static DateTimeOffset FromUnixMilliseconds(long milliseconds)
{
#if UNIXTIME
return DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
#else
long ticks = milliseconds * TimeSpan.TicksPerMillisecond + UnixEpochTicks;
return new DateTimeOffset(ticks, TimeSpan.Zero);
#endif
}

public static long ToUnixSeconds(DateTimeOffset dto)
{
#if UNIXTIME
return dto.ToUnixTimeSeconds();
#else
long seconds = dto.UtcDateTime.Ticks / TimeSpan.TicksPerSecond;
return seconds - UnixEpochSeconds;
#endif
}
public static long ToUnixMilliseconds(DateTimeOffset dto)
{
#if UNIXTIME
return dto.ToUnixTimeMilliseconds();
#else
long milliseconds = dto.UtcDateTime.Ticks / TimeSpan.TicksPerMillisecond;
return milliseconds - UnixEpochMilliseconds;
#endif
}
} }
} }

+ 2
- 2
src/Discord.Net.Core/Utils/SnowflakeUtils.cs View File

@@ -5,8 +5,8 @@ namespace Discord
public static class SnowflakeUtils public static class SnowflakeUtils
{ {
public static DateTimeOffset FromSnowflake(ulong value) public static DateTimeOffset FromSnowflake(ulong value)
=> DateTimeUtils.FromUnixMilliseconds((long)((value >> 22) + 1420070400000UL));
=> DateTimeOffset.FromUnixTimeMilliseconds((long)((value >> 22) + 1420070400000UL));
public static ulong ToSnowflake(DateTimeOffset value) public static ulong ToSnowflake(DateTimeOffset value)
=> ((ulong)DateTimeUtils.ToUnixMilliseconds(value) - 1420070400000UL) << 22;
=> ((ulong)value.ToUnixTimeMilliseconds() - 1420070400000UL) << 22;
} }
} }

+ 6
- 7
src/Discord.Net.Rest/Discord.Net.Rest.csproj View File

@@ -1,20 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" /> <Import Project="../../Discord.Net.targets" />
<PropertyGroup> <PropertyGroup>
<AssemblyName>Discord.Net.Rest</AssemblyName> <AssemblyName>Discord.Net.Rest</AssemblyName>
<RootNamespace>Discord.Rest</RootNamespace> <RootNamespace>Discord.Rest</RootNamespace>
<Description>A core Discord.Net library containing the REST client and models.</Description> <Description>A core Discord.Net library containing the REST client and models.</Description>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net45;netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" /> <ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net45' ">
<PackageReference Include="System.Net.Http" Version="4.3.2" />
<!-- https://github.com/dotnet/corefx/issues/19535 -->
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Net.Http" Version="4.3.3" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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

@@ -39,7 +39,7 @@ namespace Discord.Rest
} }


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

@@ -9,7 +9,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;
@@ -21,7 +21,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);
@@ -30,21 +30,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; }
} }
} }

+ 21
- 0
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleEditInfo.cs View File

@@ -0,0 +1,21 @@
namespace Discord.Rest
{
public struct RoleEditInfo
{
internal RoleEditInfo(Color? color, bool? mentionable, bool? hoist, string name,
GuildPermissions? permissions)
{
Color = color;
Mentionable = mentionable;
Hoist = hoist;
Name = name;
Permissions = permissions;
}

public Color? Color { get; }
public bool? Mentionable { get; }
public bool? Hoist { get; }
public string Name { get; }
public GuildPermissions? Permissions { get; }
}
}

+ 0
- 21
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleInfo.cs View File

@@ -1,21 +0,0 @@
namespace Discord.Rest
{
public struct RoleInfo
{
internal RoleInfo(Color? color, bool? mentionable, bool? hoist, string name,
GuildPermissions? permissions)
{
Color = color;
Mentionable = mentionable;
Hoist = hoist;
Name = name;
Permissions = permissions;
}

public Color? Color { get; }
public bool? Mentionable { get; }
public bool? Hoist { get; }
public string Name { get; }
public GuildPermissions? Permissions { get; }
}
}

+ 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; }
} }
} }

+ 11
- 2
src/Discord.Net.Rest/Entities/Channels/ChannelHelper.cs View File

@@ -168,7 +168,6 @@ namespace Discord.Rest
return RestUserMessage.Create(client, channel, client.CurrentUser, model); return RestUserMessage.Create(client, channel, client.CurrentUser, model);
} }


#if FILESYSTEM
public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client, public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
string filePath, string text, bool isTTS, Embed embed, RequestOptions options) string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
{ {
@@ -176,7 +175,7 @@ namespace Discord.Rest
using (var file = File.OpenRead(filePath)) using (var file = File.OpenRead(filePath))
return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, options).ConfigureAwait(false); return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, options).ConfigureAwait(false);
} }
#endif
public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client, public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
{ {
@@ -317,6 +316,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)


+ 1
- 2
src/Discord.Net.Rest/Entities/Channels/IRestMessageChannel.cs View File

@@ -8,10 +8,9 @@ namespace Discord.Rest
{ {
/// <summary> Sends a message to this message channel. </summary> /// <summary> Sends a message to this message channel. </summary>
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#if FILESYSTEM
/// <summary> Sends a file to this text channel, with an optional caption. </summary> /// <summary> Sends a file to this text channel, with an optional caption. </summary>
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#endif
/// <summary> Sends a file to this text channel, with an optional caption. </summary> /// <summary> Sends a file to this text channel, with an optional caption. </summary>
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);




+ 1
- 5
src/Discord.Net.Rest/Entities/Channels/RestCategoryChannel.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@@ -25,10 +25,6 @@ namespace Discord.Rest
private string DebuggerDisplay => $"{Name} ({Id}, Category)"; private string DebuggerDisplay => $"{Name} ({Id}, Category)";


// IGuildChannel // IGuildChannel
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)


+ 3
- 1
src/Discord.Net.Rest/Entities/Channels/RestChannel.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -24,6 +24,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);
} }


+ 3
- 4
src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs View File

@@ -65,10 +65,10 @@ namespace Discord.Rest


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -126,10 +126,9 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); => await GetPinnedMessagesAsync(options).ConfigureAwait(false);


#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)


+ 3
- 4
src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs View File

@@ -83,10 +83,10 @@ namespace Discord.Rest


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -136,10 +136,9 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); => await GetPinnedMessagesAsync(options).ConfigureAwait(false);


#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)


+ 1
- 10
src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs View File

@@ -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)
@@ -35,7 +34,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);
} }
} }
@@ -64,13 +62,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++)


+ 21
- 9
src/Discord.Net.Rest/Entities/Channels/RestTextChannel.cs View File

@@ -12,6 +12,7 @@ namespace Discord.Rest
public class RestTextChannel : RestGuildChannel, IRestMessageChannel, ITextChannel public class RestTextChannel : RestGuildChannel, IRestMessageChannel, ITextChannel
{ {
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);


@@ -31,7 +32,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();
} }
@@ -46,7 +47,7 @@ namespace Discord.Rest
=> ChannelHelper.GetUserAsync(this, Guild, Discord, id, options); => ChannelHelper.GetUserAsync(this, Guild, Discord, id, options);
public IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(RequestOptions options = null) public IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(RequestOptions options = null)
=> ChannelHelper.GetUsersAsync(this, Guild, Discord, null, null, options); => ChannelHelper.GetUsersAsync(this, Guild, Discord, null, null, options);
public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null) public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null)
=> ChannelHelper.GetMessageAsync(this, Discord, id, options); => ChannelHelper.GetMessageAsync(this, Discord, id, options);
public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null) public IAsyncEnumerable<IReadOnlyCollection<RestMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
@@ -60,10 +61,10 @@ namespace Discord.Rest


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -88,16 +89,19 @@ 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)";


//ITextChannel //ITextChannel
async Task<IWebhook> ITextChannel.CreateWebhookAsync(string name, Stream avatar, RequestOptions options) async Task<IWebhook> ITextChannel.CreateWebhookAsync(string name, Stream avatar, RequestOptions options)
=> await CreateWebhookAsync(name, avatar, options);
=> await CreateWebhookAsync(name, avatar, options).ConfigureAwait(false);
async Task<IWebhook> ITextChannel.GetWebhookAsync(ulong id, RequestOptions options) async Task<IWebhook> ITextChannel.GetWebhookAsync(ulong id, RequestOptions options)
=> await GetWebhookAsync(id, options);
=> await GetWebhookAsync(id, options).ConfigureAwait(false);
async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options) async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options)
=> await GetWebhooksAsync(options);
=> await GetWebhooksAsync(options).ConfigureAwait(false);


//IMessageChannel //IMessageChannel
async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options) async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options)
@@ -114,6 +118,7 @@ namespace Discord.Rest
else else
return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>(); return AsyncEnumerable.Empty<IReadOnlyCollection<IMessage>>();
} }
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)
{ {
if (mode == CacheMode.AllowDownload) if (mode == CacheMode.AllowDownload)
@@ -131,10 +136,9 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); => await GetPinnedMessagesAsync(options).ConfigureAwait(false);


#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)
@@ -173,5 +177,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;
}
} }
} }

+ 14
- 2
src/Discord.Net.Rest/Entities/Channels/RestVoiceChannel.cs View File

@@ -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;
@@ -13,6 +13,7 @@ namespace Discord.Rest
{ {
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)
@@ -27,7 +28,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;
} }
@@ -38,6 +39,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
@@ -48,5 +52,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(CacheMode mode, RequestOptions options)
{
if (CategoryId.HasValue && mode == CacheMode.AllowDownload)
return (await Guild.GetChannelAsync(CategoryId.Value, mode, options).ConfigureAwait(false)) as ICategoryChannel;
return null;
}
} }
} }

+ 2
- 4
src/Discord.Net.Rest/Entities/Channels/RpcVirtualMessageChannel.cs View File

@@ -35,11 +35,10 @@ namespace Discord.Rest


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)

=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null) public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
@@ -86,10 +85,9 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options); => await GetPinnedMessagesAsync(options);


#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options); => await SendFileAsync(filePath, text, isTTS, embed, options);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options); => await SendFileAsync(stream, filename, text, isTTS, embed, options);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)


+ 1
- 2
src/Discord.Net.Rest/Net/Converters/DiscordContractResolver.cs View File

@@ -1,4 +1,4 @@
using Discord.API;
using Discord.API;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using System; using System;
@@ -25,7 +25,6 @@ namespace Discord.Net.Converters
if (converter != null) if (converter != null)
{ {
property.Converter = converter; property.Converter = converter;
property.MemberConverter = converter;
} }
} }
else else


+ 1
- 1
src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs View File

@@ -230,7 +230,7 @@ namespace Discord.Net.Queue
#endif #endif
} }


var now = DateTimeUtils.ToUnixSeconds(DateTimeOffset.UtcNow);
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
DateTimeOffset? resetTick = null; DateTimeOffset? resetTick = null;


//Using X-RateLimit-Remaining causes a race condition //Using X-RateLimit-Remaining causes a race condition


+ 2
- 2
src/Discord.Net.Rest/Net/RateLimitInfo.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;


namespace Discord.Net namespace Discord.Net
@@ -21,7 +21,7 @@ namespace Discord.Net
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) && Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) &&
int.TryParse(temp, out var remaining) ? remaining : (int?)null; int.TryParse(temp, out var remaining) ? remaining : (int?)null;
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) && Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) &&
int.TryParse(temp, out var reset) ? DateTimeUtils.FromUnixSeconds(reset) : (DateTimeOffset?)null;
int.TryParse(temp, out var reset) ? DateTimeOffset.FromUnixTimeSeconds(reset) : (DateTimeOffset?)null;
RetryAfter = headers.TryGetValue("Retry-After", out temp) && RetryAfter = headers.TryGetValue("Retry-After", out temp) &&
int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null; int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null;
Lag = headers.TryGetValue("Date", out temp) && Lag = headers.TryGetValue("Date", out temp) &&


+ 4
- 4
src/Discord.Net.WebSocket/Discord.Net.WebSocket.csproj View File

@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" /> <Import Project="../../Discord.Net.targets" />
<PropertyGroup> <PropertyGroup>
<AssemblyName>Discord.Net.WebSocket</AssemblyName> <AssemblyName>Discord.Net.WebSocket</AssemblyName>
<RootNamespace>Discord.WebSocket</RootNamespace> <RootNamespace>Discord.WebSocket</RootNamespace>
<Description>A core Discord.Net library containing the WebSocket client and models.</Description> <Description>A core Discord.Net library containing the WebSocket client and models.</Description>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net45;netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.1;netstandard1.3</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' ">netstandard1.3;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -13,6 +13,6 @@
<ProjectReference Include="..\Discord.Net.Rest\Discord.Net.Rest.csproj" /> <ProjectReference Include="..\Discord.Net.Rest\Discord.Net.Rest.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.1" />
<PackageReference Include="System.Net.WebSockets.Client" Version="4.3.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

+ 1
- 1
src/Discord.Net.WebSocket/DiscordSocketClient.cs View File

@@ -365,7 +365,7 @@ namespace Discord.WebSocket
await ApiClient.SendStatusUpdateAsync( await ApiClient.SendStatusUpdateAsync(
status, status,
status == UserStatus.AFK, status == UserStatus.AFK,
statusSince != null ? DateTimeUtils.ToUnixMilliseconds(_statusSince.Value) : (long?)null,
statusSince != null ? _statusSince.Value.ToUnixTimeMilliseconds() : (long?)null,
gameModel).ConfigureAwait(false); gameModel).ConfigureAwait(false);
} }




+ 2
- 2
src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs View File

@@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CS1591
using Discord.API; using Discord.API;
using Discord.API.Voice; using Discord.API.Voice;
using Discord.Net.Converters; using Discord.Net.Converters;
@@ -129,7 +129,7 @@ namespace Discord.Audio
//WebSocket //WebSocket
public async Task SendHeartbeatAsync(RequestOptions options = null) public async Task SendHeartbeatAsync(RequestOptions options = null)
{ {
await SendAsync(VoiceOpCode.Heartbeat, DateTimeUtils.ToUnixMilliseconds(DateTimeOffset.UtcNow), options: options).ConfigureAwait(false);
await SendAsync(VoiceOpCode.Heartbeat, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), options: options).ConfigureAwait(false);
} }
public async Task SendIdentityAsync(ulong userId, string sessionId, string token) public async Task SendIdentityAsync(ulong userId, string sessionId, string token)
{ {


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

@@ -12,10 +12,9 @@ namespace Discord.WebSocket


/// <summary> Sends a message to this message channel. </summary> /// <summary> Sends a message to this message channel. </summary>
new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); new Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#if FILESYSTEM
/// <summary> Sends a file to this text channel, with an optional caption. </summary> /// <summary> Sends a file to this text channel, with an optional caption. </summary>
new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); new Task<RestUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#endif
/// <summary> Sends a file to this text channel, with an optional caption. </summary> /// <summary> Sends a file to this text channel, with an optional caption. </summary>
new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null); new Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null);




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

@@ -20,7 +20,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
- 4
src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs View File

@@ -69,10 +69,10 @@ namespace Discord.WebSocket


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -135,10 +135,8 @@ namespace Discord.WebSocket
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options);
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); => await GetPinnedMessagesAsync(options).ConfigureAwait(false);
#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)


+ 4
- 4
src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs View File

@@ -97,10 +97,10 @@ namespace Discord.WebSocket


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -199,10 +199,10 @@ namespace Discord.WebSocket
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options);
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); => await GetPinnedMessagesAsync(options).ConfigureAwait(false);
#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)


+ 3
- 10
src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs View File

@@ -1,4 +1,4 @@
using Discord.Rest;
using Discord.Rest;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -16,10 +16,7 @@ namespace Discord.WebSocket


public SocketGuild Guild { get; } public SocketGuild Guild { get; }
public string Name { get; private set; } public string Name { get; private set; }
public int Position { get; private set; }
public ulong? CategoryId { get; private set; }
public ICategoryChannel Category
=> CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null;
public int Position { get; private set; }


public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites; public IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites;
public new virtual IReadOnlyCollection<SocketGuildUser> Users => ImmutableArray.Create<SocketGuildUser>(); public new virtual IReadOnlyCollection<SocketGuildUser> Users => ImmutableArray.Create<SocketGuildUser>();
@@ -48,8 +45,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++)
@@ -135,9 +131,6 @@ namespace Discord.WebSocket
IGuild IGuildChannel.Guild => Guild; IGuild IGuildChannel.Guild => Guild;
ulong IGuildChannel.GuildId => Guild.Id; ulong IGuildChannel.GuildId => Guild.Id;


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

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);
async Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options) async Task<IInviteMetadata> IGuildChannel.CreateInviteAsync(int? maxAge, int? maxUses, bool isTemporary, bool isUnique, RequestOptions options)


+ 12
- 5
src/Discord.Net.WebSocket/Entities/Channels/SocketTextChannel.cs View File

@@ -16,6 +16,9 @@ namespace Discord.WebSocket
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);
@@ -42,7 +45,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();
} }
@@ -77,10 +80,10 @@ namespace Discord.WebSocket


public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options); => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
#if FILESYSTEM
public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
#endif
public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null) public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options); => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);


@@ -159,15 +162,19 @@ namespace Discord.WebSocket
=> SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options); => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options);
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options) async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false); => await GetPinnedMessagesAsync(options).ConfigureAwait(false);
#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
#endif
async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false); => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options) async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)
=> 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(CacheMode mode, RequestOptions options)
=> Task.FromResult(Category);
} }
} }

+ 10
- 3
src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs View File

@@ -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;
@@ -15,6 +15,9 @@ namespace Discord.WebSocket
{ {
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();
@@ -32,7 +35,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;
} }
@@ -52,7 +55,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;


@@ -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(CacheMode mode, RequestOptions options)
=> Task.FromResult(Category);
} }
} }

+ 0
- 6
src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs View File

@@ -1,4 +1,3 @@
#if DEFAULTUDPCLIENT
using System; using System;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@@ -85,11 +84,7 @@ namespace Discord.Net.Udp


if (_udp != null) if (_udp != null)
{ {
#if UDPDISPOSE
try { _udp.Dispose(); } try { _udp.Dispose(); }
#else
try { _udp.Close(); }
#endif
catch { } catch { }
_udp = null; _udp = null;
} }
@@ -132,4 +127,3 @@ namespace Discord.Net.Udp
} }
} }
} }
#endif

+ 1
- 9
src/Discord.Net.WebSocket/Net/DefaultUdpSocketProvider.cs View File

@@ -4,7 +4,6 @@ namespace Discord.Net.Udp
{ {
public static class DefaultUdpSocketProvider public static class DefaultUdpSocketProvider
{ {
#if DEFAULTUDPCLIENT
public static readonly UdpSocketProvider Instance = () => public static readonly UdpSocketProvider Instance = () =>
{ {
try try
@@ -16,12 +15,5 @@ namespace Discord.Net.Udp
throw new PlatformNotSupportedException("The default UdpSocketProvider is not supported on this platform.", ex); throw new PlatformNotSupportedException("The default UdpSocketProvider is not supported on this platform.", ex);
} }
}; };
#else
public static readonly UdpSocketProvider Instance = () =>
{
throw new PlatformNotSupportedException("The default UdpSocketProvider is not supported on this platform.\n" +
"You must specify a UdpSocketProvider or target a runtime supporting .NET Standard 1.3, such as .NET Framework 4.6+.");
};
#endif
} }
}
}

+ 3
- 10
src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs View File

@@ -1,4 +1,3 @@
#if DEFAULTWEBSOCKET
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -209,14 +208,9 @@ namespace Discord.Net.WebSockets


//Use the internal buffer if we can get it //Use the internal buffer if we can get it
resultCount = (int)stream.Length; resultCount = (int)stream.Length;
#if MSTRYBUFFER
if (stream.TryGetBuffer(out var streamBuffer))
result = streamBuffer.Array;
else
result = stream.ToArray();
#else
result = stream.GetBuffer();
#endif

result = stream.TryGetBuffer(out var streamBuffer) ? streamBuffer.Array : stream.ToArray();

} }
} }
else else
@@ -248,4 +242,3 @@ namespace Discord.Net.WebSockets
} }
} }
} }
#endif

+ 1
- 9
src/Discord.Net.WebSocket/Net/DefaultWebSocketClientProvider.cs View File

@@ -5,7 +5,6 @@ namespace Discord.Net.WebSockets
{ {
public static class DefaultWebSocketProvider public static class DefaultWebSocketProvider
{ {
#if DEFAULTWEBSOCKET
public static readonly WebSocketProvider Instance = Create(); public static readonly WebSocketProvider Instance = Create();


public static WebSocketProvider Create(IWebProxy proxy = null) public static WebSocketProvider Create(IWebProxy proxy = null)
@@ -22,12 +21,5 @@ namespace Discord.Net.WebSockets
} }
}; };
} }
#else
public static readonly WebSocketProvider Instance = () =>
{
throw new PlatformNotSupportedException("The default WebSocketProvider is not supported on this platform.\n" +
"You must specify a WebSocketProvider or target a runtime supporting .NET Standard 1.3, such as .NET Framework 4.6+.");
};
#endif
} }
}
}

+ 2
- 2
src/Discord.Net.Webhook/Discord.Net.Webhook.csproj View File

@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../Discord.Net.targets" /> <Import Project="../../Discord.Net.targets" />
<PropertyGroup> <PropertyGroup>
<AssemblyName>Discord.Net.Webhook</AssemblyName> <AssemblyName>Discord.Net.Webhook</AssemblyName>
<RootNamespace>Discord.Webhook</RootNamespace> <RootNamespace>Discord.Webhook</RootNamespace>
<Description>A core Discord.Net library containing the Webhook client and models.</Description> <Description>A core Discord.Net library containing the Webhook client and models.</Description>
<TargetFrameworks>netstandard1.1</TargetFrameworks>
<TargetFrameworks>netstandard1.3</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" /> <ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />


+ 1
- 2
src/Discord.Net.Webhook/DiscordWebhookClient.cs View File

@@ -67,12 +67,11 @@ namespace Discord.Webhook
string username = null, string avatarUrl = null, RequestOptions options = null) string username = null, string avatarUrl = null, RequestOptions options = null)
=> WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, options); => WebhookClientHelper.SendMessageAsync(this, text, isTTS, embeds, username, avatarUrl, options);


#if FILESYSTEM
/// <summary> Send a message to the channel for this webhook with an attachment. Returns the ID of the created message. </summary> /// <summary> Send a message to the channel for this webhook with an attachment. Returns the ID of the created message. </summary>
public Task<ulong> SendFileAsync(string filePath, string text, bool isTTS = false, public Task<ulong> SendFileAsync(string filePath, string text, bool isTTS = false,
IEnumerable<Embed> embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null) IEnumerable<Embed> embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null)
=> WebhookClientHelper.SendFileAsync(this, filePath, text, isTTS, embeds, username, avatarUrl, options); => WebhookClientHelper.SendFileAsync(this, filePath, text, isTTS, embeds, username, avatarUrl, options);
#endif
/// <summary> Send a message to the channel for this webhook with an attachment. Returns the ID of the created message. </summary> /// <summary> Send a message to the channel for this webhook with an attachment. Returns the ID of the created message. </summary>
public Task<ulong> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, public Task<ulong> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false,
IEnumerable<Embed> embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null) IEnumerable<Embed> embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null)


+ 1
- 3
src/Discord.Net.Webhook/WebhookClientHelper.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -33,7 +33,6 @@ namespace Discord.Webhook
var model = await client.ApiClient.CreateWebhookMessageAsync(client.Webhook.Id, args, options: options).ConfigureAwait(false); var model = await client.ApiClient.CreateWebhookMessageAsync(client.Webhook.Id, args, options: options).ConfigureAwait(false);
return model.Id; return model.Id;
} }
#if FILESYSTEM
public static async Task<ulong> SendFileAsync(DiscordWebhookClient client, string filePath, string text, bool isTTS, public static async Task<ulong> SendFileAsync(DiscordWebhookClient client, string filePath, string text, bool isTTS,
IEnumerable<Embed> embeds, string username, string avatarUrl, RequestOptions options) IEnumerable<Embed> embeds, string username, string avatarUrl, RequestOptions options)
{ {
@@ -41,7 +40,6 @@ namespace Discord.Webhook
using (var file = File.OpenRead(filePath)) using (var file = File.OpenRead(filePath))
return await SendFileAsync(client, file, filename, text, isTTS, embeds, username, avatarUrl, options).ConfigureAwait(false); return await SendFileAsync(client, file, filename, text, isTTS, embeds, username, avatarUrl, options).ConfigureAwait(false);
} }
#endif
public static async Task<ulong> SendFileAsync(DiscordWebhookClient client, Stream stream, string filename, string text, bool isTTS, public static async Task<ulong> SendFileAsync(DiscordWebhookClient client, Stream stream, string filename, string text, bool isTTS,
IEnumerable<Embed> embeds, string username, string avatarUrl, RequestOptions options) IEnumerable<Embed> embeds, string username, string avatarUrl, RequestOptions options)
{ {


+ 5
- 5
test/Discord.Net.Tests/Discord.Net.Tests.csproj View File

@@ -21,10 +21,10 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Akavache" Version="5.0.0" /> <PackageReference Include="Akavache" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="xunit.runner.reporters" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="xunit.runner.reporters" Version="2.3.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

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

@@ -105,7 +105,7 @@ namespace Discord
Assert.Equal(groupChannel, ChannelPermissions.Group.RawValue); Assert.Equal(groupChannel, ChannelPermissions.Group.RawValue);
return Task.CompletedTask; return Task.CompletedTask;
} }
[Fact]
public Task TestChannelPermissionModify() public Task TestChannelPermissionModify()
{ {
// test channel permission modify // test channel permission modify


+ 100
- 26
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 =>
{ {
@@ -49,35 +61,35 @@ namespace Discord
} }
private static void CheckTextChannels(RestGuild guild, params RestTextChannel[] textChannels) private static void CheckTextChannels(RestGuild guild, params RestTextChannel[] textChannels)
{ {
Assert.Equal(textChannels.Length, 5);
Assert.Equal(5, textChannels.Length);
Assert.All(textChannels, x => Assert.All(textChannels, x =>
{ {
Assert.NotNull(x); Assert.NotNull(x);
Assert.NotEqual(x.Id, 0UL);
Assert.NotEqual(0UL, x.Id);
Assert.True(x.Position >= 0); Assert.True(x.Position >= 0);
}); });


var text1 = textChannels.Where(x => x.Name == "text1").FirstOrDefault();
var text2 = textChannels.Where(x => x.Name == "text2").FirstOrDefault();
var text3 = textChannels.Where(x => x.Name == "text3").FirstOrDefault();
var text4 = textChannels.Where(x => x.Name == "text4").FirstOrDefault();
var text5 = textChannels.Where(x => x.Name == "text5").FirstOrDefault();
var text1 = textChannels.FirstOrDefault(x => x.Name == "text1");
var text2 = textChannels.FirstOrDefault(x => x.Name == "text2");
var text3 = textChannels.FirstOrDefault(x => x.Name == "text3");
var text4 = textChannels.FirstOrDefault(x => x.Name == "text4");
var text5 = textChannels.FirstOrDefault(x => x.Name == "text5");


Assert.NotNull(text1); Assert.NotNull(text1);
//Assert.True(text1.Id == guild.DefaultChannelId); //Assert.True(text1.Id == guild.DefaultChannelId);
Assert.Equal(text1.Position, 1);
Assert.Equal(text1.Topic, "Topic1");
Assert.Equal(1, text1.Position);
Assert.Equal("Topic1", text1.Topic);


Assert.NotNull(text2); Assert.NotNull(text2);
Assert.Equal(text2.Position, 2);
Assert.Equal(2, text2.Position);
Assert.Null(text2.Topic); Assert.Null(text2.Topic);


Assert.NotNull(text3); Assert.NotNull(text3);
Assert.Equal(text3.Topic, "Topic2");
Assert.Equal("Topic2", text3.Topic);


Assert.NotNull(text4); Assert.NotNull(text4);
Assert.Equal(text4.Position, 3);
Assert.Equal(text4.Topic, "Topic2");
Assert.Equal(3, text4.Position);
Assert.Equal("Topic2", text4.Topic);


Assert.NotNull(text5); Assert.NotNull(text5);
Assert.Null(text5.Topic); Assert.Null(text5.Topic);
@@ -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);
@@ -114,31 +130,89 @@ namespace Discord
} }
private static void CheckVoiceChannels(params RestVoiceChannel[] voiceChannels) private static void CheckVoiceChannels(params RestVoiceChannel[] voiceChannels)
{ {
Assert.Equal(voiceChannels.Length, 3);
Assert.Equal(3, voiceChannels.Length);
Assert.All(voiceChannels, x => Assert.All(voiceChannels, x =>
{ {
Assert.NotNull(x); Assert.NotNull(x);
Assert.NotEqual(x.Id, 0UL);
Assert.NotEqual(x.UserLimit, 0);
Assert.NotEqual(0UL, x.Id);
Assert.NotEqual(0, x.UserLimit);
Assert.True(x.Bitrate > 0); Assert.True(x.Bitrate > 0);
Assert.True(x.Position >= 0); Assert.True(x.Position >= 0);
}); });


var voice1 = voiceChannels.Where(x => x.Name == "voice1").FirstOrDefault();
var voice2 = voiceChannels.Where(x => x.Name == "voice2").FirstOrDefault();
var voice3 = voiceChannels.Where(x => x.Name == "voice3").FirstOrDefault();
var voice1 = voiceChannels.FirstOrDefault(x => x.Name == "voice1");
var voice2 = voiceChannels.FirstOrDefault(x => x.Name == "voice2");
var voice3 = voiceChannels.FirstOrDefault(x => x.Name == "voice3");


Assert.NotNull(voice1); Assert.NotNull(voice1);
Assert.Equal(voice1.Bitrate, 96000);
Assert.Equal(voice1.Position, 1);
Assert.Equal(96000, voice1.Bitrate);
Assert.Equal(1, voice1.Position);


Assert.NotNull(voice2); Assert.NotNull(voice2);
Assert.Equal(voice2.UserLimit, null);
Assert.Null(voice2.UserLimit);

Assert.NotNull(voice3);
Assert.Equal(8000, voice3.Bitrate);
Assert.Equal(1, voice3.Position);
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.NotNull(voice3);
Assert.Equal(voice3.Bitrate, 8000);
Assert.Equal(voice3.Position, 1);
Assert.Equal(voice3.UserLimit, 16);
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);

} }
} }
}
}

+ 2
- 1
test/Discord.Net.Tests/Tests.Colors.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using Xunit; using Xunit;


namespace Discord namespace Discord
@@ -12,6 +12,7 @@ namespace Discord
Assert.Equal(uint.MinValue, new Color(uint.MinValue).RawValue); Assert.Equal(uint.MinValue, new Color(uint.MinValue).RawValue);
Assert.Equal(uint.MaxValue, new Color(uint.MaxValue).RawValue); Assert.Equal(uint.MaxValue, new Color(uint.MaxValue).RawValue);
} }
[Fact]
public void Color_Default() public void Color_Default()
{ {
Assert.Equal(0u, Color.Default.RawValue); Assert.Equal(0u, Color.Default.RawValue);


+ 2
- 1
test/Discord.Net.Tests/Tests.Emotes.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using Xunit; using Xunit;


namespace Discord namespace Discord
@@ -34,6 +34,7 @@ namespace Discord
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt); Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt);
Assert.EndsWith("gif", emote.Url); Assert.EndsWith("gif", emote.Url);
} }
[Fact]
public void Test_Invalid_Amimated_Emote_Parse() public void Test_Invalid_Amimated_Emote_Parse()
{ {
Assert.False(Emote.TryParse("<x:typingstatus:394207658351263745>", out _)); Assert.False(Emote.TryParse("<x:typingstatus:394207658351263745>", out _));


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

@@ -150,12 +150,12 @@ namespace Discord




// individual permission test // individual permission test
perm = perm.Modify(readMessages: true);
Assert.True(perm.ReadMessages);
Assert.Equal(perm.RawValue, (ulong)GuildPermission.ReadMessages);
perm = perm.Modify(viewChannel: true);
Assert.True(perm.ViewChannel);
Assert.Equal(perm.RawValue, (ulong)GuildPermission.ViewChannel);


perm = perm.Modify(readMessages: false);
Assert.False(perm.ReadMessages);
perm = perm.Modify(viewChannel: false);
Assert.False(perm.ViewChannel);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue); Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);






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

@@ -25,15 +25,15 @@ namespace Discord


// check that toggling the bit works // check that toggling the bit works
Permissions.UnsetFlag(ref rawValue, flagValue); Permissions.UnsetFlag(ref rawValue, flagValue);
Assert.Equal(false, Permissions.GetValue(rawValue, flagValue));
Assert.False(Permissions.GetValue(rawValue, flagValue));
Permissions.SetFlag(ref rawValue, flagValue); Permissions.SetFlag(ref rawValue, flagValue);
Assert.Equal(true, Permissions.GetValue(rawValue, flagValue));
Assert.True(Permissions.GetValue(rawValue, flagValue));


// do the same, but with the SetValue method // do the same, but with the SetValue method
Permissions.SetValue(ref rawValue, true, flagValue); Permissions.SetValue(ref rawValue, true, flagValue);
Assert.Equal(true, Permissions.GetValue(rawValue, flagValue));
Assert.True(Permissions.GetValue(rawValue, flagValue));
Permissions.SetValue(ref rawValue, false, flagValue); Permissions.SetValue(ref rawValue, false, flagValue);
Assert.Equal(false, Permissions.GetValue(rawValue, flagValue));
Assert.False(Permissions.GetValue(rawValue, flagValue));
} }


/// <summary> /// <summary>
@@ -280,7 +280,7 @@ namespace Discord
TestHelper(value, GuildPermission.ManageGuild, false); TestHelper(value, GuildPermission.ManageGuild, false);
TestHelper(value, GuildPermission.AddReactions, false); TestHelper(value, GuildPermission.AddReactions, false);
TestHelper(value, GuildPermission.ViewAuditLog, false); TestHelper(value, GuildPermission.ViewAuditLog, false);
TestHelper(value, GuildPermission.ReadMessages, false);
TestHelper(value, GuildPermission.ViewChannel, false);
TestHelper(value, GuildPermission.SendMessages, false); TestHelper(value, GuildPermission.SendMessages, false);
TestHelper(value, GuildPermission.SendTTSMessages, false); TestHelper(value, GuildPermission.SendTTSMessages, false);
TestHelper(value, GuildPermission.ManageMessages, false); TestHelper(value, GuildPermission.ManageMessages, false);
@@ -323,7 +323,7 @@ namespace Discord
TestHelper(value, GuildPermission.ManageGuild, true); TestHelper(value, GuildPermission.ManageGuild, true);
TestHelper(value, GuildPermission.AddReactions, true); TestHelper(value, GuildPermission.AddReactions, true);
TestHelper(value, GuildPermission.ViewAuditLog, true); TestHelper(value, GuildPermission.ViewAuditLog, true);
TestHelper(value, GuildPermission.ReadMessages, true);
TestHelper(value, GuildPermission.ViewChannel, true);
TestHelper(value, GuildPermission.SendMessages, true); TestHelper(value, GuildPermission.SendMessages, true);
TestHelper(value, GuildPermission.SendTTSMessages, true); TestHelper(value, GuildPermission.SendTTSMessages, true);
TestHelper(value, GuildPermission.ManageMessages, true); TestHelper(value, GuildPermission.ManageMessages, true);
@@ -367,7 +367,7 @@ namespace Discord
TestHelper(value, GuildPermission.ManageGuild, false); TestHelper(value, GuildPermission.ManageGuild, false);
TestHelper(value, GuildPermission.AddReactions, false); TestHelper(value, GuildPermission.AddReactions, false);
TestHelper(value, GuildPermission.ViewAuditLog, false); TestHelper(value, GuildPermission.ViewAuditLog, false);
TestHelper(value, GuildPermission.ReadMessages, false);
TestHelper(value, GuildPermission.ViewChannel, false);
TestHelper(value, GuildPermission.SendMessages, true); TestHelper(value, GuildPermission.SendMessages, true);
TestHelper(value, GuildPermission.SendTTSMessages, true); TestHelper(value, GuildPermission.SendTTSMessages, true);
TestHelper(value, GuildPermission.ManageMessages, false); TestHelper(value, GuildPermission.ManageMessages, false);


Loading…
Cancel
Save