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' ">
<VersionSuffix Condition=" '$(VersionSuffix)' != '' ">$(VersionSuffix)-$(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' ">
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
<WarningsAsErrors>true</WarningsAsErrors>


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

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

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

<ItemGroup>


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

@@ -7,7 +7,7 @@
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.6.0" />
<PackageReference Include="Microsoft.CodeAnalysis" Version="2.8.0" />
</ItemGroup>
<ItemGroup>
<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" />
<PropertyGroup>
<AssemblyName>Discord.Net.Commands</AssemblyName>
<RootNamespace>Discord.Commands</RootNamespace>
<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>
<ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
</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" />
</ItemGroup>
</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" />
<PropertyGroup>
<AssemblyName>Discord.Net.Core</AssemblyName>
<RootNamespace>Discord</RootNamespace>
<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>
<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" />
</ItemGroup>
</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.Linq;
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.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>
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>
IGuild Guild { get; }
/// <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>
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>
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>
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>
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.IO;
using System.Threading.Tasks;

namespace Discord
{
public interface ITextChannel : IMessageChannel, IMentionable, IGuildChannel
public interface ITextChannel : IMessageChannel, IMentionable, INestedChannel
{
/// <summary> Checks if the channel is NSFW. </summary>
bool IsNsfw { get; }
@@ -28,4 +28,4 @@ namespace Discord
/// <summary> Gets the webhooks for this text channel. </summary>
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;

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>
int Bitrate { get; }
@@ -13,4 +13,4 @@ namespace Discord
/// <summary> Modifies this voice channel. </summary>
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
{
/// <summary>
@@ -15,7 +15,7 @@ namespace Discord
{
Stream = stream;
}
#if FILESYSTEM
/// <summary>
/// Create the image from a file path.
/// </summary>
@@ -27,6 +27,6 @@ namespace Discord
{
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? addReactions = null,
bool? viewAuditLog = null,
bool? readMessages = null,
bool? viewChannel = null,
bool? sendMessages = null,
bool? sendTTSMessages = null,
bool? manageMessages = null,
@@ -124,7 +124,7 @@ namespace Discord
Permissions.SetValue(ref value, manageGuild, GuildPermission.ManageGuild);
Permissions.SetValue(ref value, addReactions, GuildPermission.AddReactions);
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, sendTTSMessages, GuildPermission.SendTTSMessages);
Permissions.SetValue(ref value, manageMessages, GuildPermission.ManageMessages);
@@ -158,7 +158,7 @@ namespace Discord
bool manageGuild = false,
bool addReactions = false,
bool viewAuditLog = false,
bool readMessages = false,
bool viewChannel = false,
bool sendMessages = false,
bool sendTTSMessages = false,
bool manageMessages = false,
@@ -188,7 +188,7 @@ namespace Discord
manageGuild: manageGuild,
addReactions: addReactions,
viewAuditLog: viewAuditLog,
readMessages: readMessages,
viewChannel: viewChannel,
sendMessages: sendMessages,
sendTTSMessages: sendTTSMessages,
manageMessages: manageMessages,
@@ -219,7 +219,7 @@ namespace Discord
bool? manageGuild = null,
bool? addReactions = null,
bool? viewAuditLog = null,
bool? readMessages = null,
bool? viewChannel = null,
bool? sendMessages = null,
bool? sendTTSMessages = null,
bool? manageMessages = null,
@@ -240,7 +240,7 @@ namespace Discord
bool? manageWebhooks = null,
bool? manageEmojis = null)
=> 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,
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);
}

#if FILESYSTEM
/// <summary>
/// Sends a file to the user via DM.
/// </summary>
@@ -45,7 +44,6 @@ namespace Discord
{
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)
=> 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;

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

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

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

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

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

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

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;

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

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

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

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

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

public Task DebugAsync(Exception exception)
=> _manager.DebugAsync(Name, exception);
public Task DebugAsync(string message, Exception exception = null)
=> _manager.DebugAsync(Name, message, exception);
#if FORMATSTR
public Task DebugAsync(FormattableString message, Exception exception = null)
=> _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
{
//Source: https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/DateTimeOffset.cs
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)
=> new DateTimeOffset(ticks, TimeSpan.Zero);
public static DateTimeOffset? FromTicks(long? ticks)
=> 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 DateTimeOffset FromSnowflake(ulong value)
=> DateTimeUtils.FromUnixMilliseconds((long)((value >> 22) + 1420070400000UL));
=> DateTimeOffset.FromUnixTimeMilliseconds((long)((value >> 22) + 1420070400000UL));
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" />
<PropertyGroup>
<AssemblyName>Discord.Net.Rest</AssemblyName>
<RootNamespace>Discord.Rest</RootNamespace>
<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>
<ItemGroup>
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" />
</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 Condition=" '$(TargetFramework)' == 'net45' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<Reference Include="System.Net.Http" />
</ItemGroup>
</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 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
{
private MemberRoleAuditLogData(IReadOnlyCollection<RoleInfo> roles, IUser target)
private MemberRoleAuditLogData(IReadOnlyCollection<MemberRoleEditInfo> roles, IUser target)
{
Roles = roles;
Target = target;
@@ -21,7 +21,7 @@ namespace Discord.Rest

var roleInfos = changes.SelectMany(x => x.NewValue.ToObject<API.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();

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

public IReadOnlyCollection<RoleInfo> Roles { get; }
public IReadOnlyCollection<MemberRoleEditInfo> Roles { 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
{
private RoleCreateAuditLogData(ulong id, RoleInfo props)
private RoleCreateAuditLogData(ulong id, RoleEditInfo props)
{
RoleId = id;
Properties = props;
@@ -38,10 +38,10 @@ namespace Discord.Rest
permissions = new GuildPermissions(permissionsRaw.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 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
{
private RoleDeleteAuditLogData(ulong id, RoleInfo props)
private RoleDeleteAuditLogData(ulong id, RoleEditInfo props)
{
RoleId = id;
Properties = props;
@@ -38,10 +38,10 @@ namespace Discord.Rest
permissions = new GuildPermissions(permissionsRaw.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 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
{
private RoleUpdateAuditLogData(ulong id, RoleInfo oldProps, RoleInfo newProps)
private RoleUpdateAuditLogData(ulong id, RoleEditInfo oldProps, RoleEditInfo newProps)
{
RoleId = id;
Before = oldProps;
@@ -49,14 +49,14 @@ namespace Discord.Rest
if (newPermissionsRaw.HasValue)
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);
}

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

#if FILESYSTEM
public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
{
@@ -176,7 +175,7 @@ namespace Discord.Rest
using (var file = File.OpenRead(filePath))
return await SendFileAsync(channel, client, file, filename, text, isTTS, embed, options).ConfigureAwait(false);
}
#endif
public static async Task<RestUserMessage> SendFileAsync(IMessageChannel channel, BaseDiscordClient client,
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))
.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
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>
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>
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>
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.Diagnostics;
using System.IO;
@@ -25,10 +25,6 @@ namespace Discord.Rest
private string DebuggerDisplay => $"{Name} ({Id}, Category)";

// 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)
=> throw new NotSupportedException();
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.Linq;
using System.Threading.Tasks;
@@ -24,6 +24,8 @@ namespace Discord.Rest
case ChannelType.DM:
case ChannelType.Group:
return CreatePrivate(discord, model) as RestChannel;
case ChannelType.Category:
return RestCategoryChannel.Create(discord, new RestGuild(discord, model.GuildId.Value), model);
default:
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)
=> 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)
=> 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)
=> 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)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);

#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
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)
=> 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)
=> 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)
=> 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)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);

#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
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.Immutable;
using System.Linq;
@@ -16,7 +16,6 @@ namespace Discord.Rest
internal IGuild Guild { get; }
public string Name { get; private set; }
public int Position { get; private set; }
public ulong? CategoryId { get; private set; }
public ulong GuildId => Guild.Id;

internal RestGuildChannel(BaseDiscordClient discord, IGuild guild, ulong id)
@@ -35,7 +34,6 @@ namespace Discord.Rest
case ChannelType.Category:
return RestCategoryChannel.Create(discord, guild, model);
default:
// TODO: Channel categories
return new RestGuildChannel(discord, guild, model.Id);
}
}
@@ -64,13 +62,6 @@ namespace Discord.Rest
public Task DeleteAsync(RequestOptions options = null)
=> 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)
{
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 string Topic { get; private set; }
public ulong? CategoryId { get; private set; }

public string Mention => MentionUtils.MentionChannel(Id);

@@ -31,7 +32,7 @@ namespace Discord.Rest
internal override void Update(Model model)
{
base.Update(model);
CategoryId = model.CategoryId;
Topic = model.Topic.Value;
_nsfw = model.Nsfw.GetValueOrDefault();
}
@@ -46,7 +47,7 @@ namespace Discord.Rest
=> ChannelHelper.GetUserAsync(this, Guild, Discord, id, options);
public IAsyncEnumerable<IReadOnlyCollection<RestGuildUser>> GetUsersAsync(RequestOptions options = null)
=> ChannelHelper.GetUsersAsync(this, Guild, Discord, null, null, options);
public Task<RestMessage> GetMessageAsync(ulong id, RequestOptions options = null)
=> ChannelHelper.GetMessageAsync(this, Discord, id, options);
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)
=> 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)
=> 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)
=> ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);

@@ -88,16 +89,19 @@ namespace Discord.Rest
=> ChannelHelper.GetWebhookAsync(this, Discord, id, options);
public Task<IReadOnlyCollection<RestWebhook>> GetWebhooksAsync(RequestOptions options = null)
=> ChannelHelper.GetWebhooksAsync(this, Discord, options);
public Task<ICategoryChannel> GetCategoryAsync(RequestOptions options = null)
=> ChannelHelper.GetCategoryAsync(this, Discord, options);

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

//ITextChannel
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)
=> await GetWebhookAsync(id, options);
=> await GetWebhookAsync(id, options).ConfigureAwait(false);
async Task<IReadOnlyCollection<IWebhook>> ITextChannel.GetWebhooksAsync(RequestOptions options)
=> await GetWebhooksAsync(options);
=> await GetWebhooksAsync(options).ConfigureAwait(false);

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

#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)
@@ -173,5 +177,13 @@ namespace Discord.Rest
else
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.Collections.Generic;
using System.Diagnostics;
@@ -13,6 +13,7 @@ namespace Discord.Rest
{
public int Bitrate { get; private set; }
public int? UserLimit { get; private set; }
public ulong? CategoryId { get; private set; }

internal RestVoiceChannel(BaseDiscordClient discord, IGuild guild, ulong id)
: base(discord, guild, id)
@@ -27,7 +28,7 @@ namespace Discord.Rest
internal override void Update(Model model)
{
base.Update(model);
CategoryId = model.CategoryId;
Bitrate = model.Bitrate.Value;
UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null;
}
@@ -38,6 +39,9 @@ namespace Discord.Rest
Update(model);
}

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

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

//IAudioChannel
@@ -48,5 +52,13 @@ namespace Discord.Rest
=> Task.FromResult<IGuildUser>(null);
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> 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)
=> 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)
=> 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)

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

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

#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, 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.Serialization;
using System;
@@ -25,7 +25,6 @@ namespace Discord.Net.Converters
if (converter != null)
{
property.Converter = converter;
property.MemberConverter = converter;
}
}
else


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

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

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

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

namespace Discord.Net
@@ -21,7 +21,7 @@ namespace Discord.Net
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) &&
int.TryParse(temp, out var remaining) ? remaining : (int?)null;
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) &&
int.TryParse(temp, out var retryAfter) ? retryAfter : (int?)null;
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" />
<PropertyGroup>
<AssemblyName>Discord.Net.WebSocket</AssemblyName>
<RootNamespace>Discord.WebSocket</RootNamespace>
<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>
</PropertyGroup>
<ItemGroup>
@@ -13,6 +13,6 @@
<ProjectReference Include="..\Discord.Net.Rest\Discord.Net.Rest.csproj" />
</ItemGroup>
<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>
</Project>

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

@@ -365,7 +365,7 @@ namespace Discord.WebSocket
await ApiClient.SendStatusUpdateAsync(
status,
status == UserStatus.AFK,
statusSince != null ? DateTimeUtils.ToUnixMilliseconds(_statusSince.Value) : (long?)null,
statusSince != null ? _statusSince.Value.ToUnixTimeMilliseconds() : (long?)null,
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.Voice;
using Discord.Net.Converters;
@@ -129,7 +129,7 @@ namespace Discord.Audio
//WebSocket
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)
{


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

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)
: 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)
=> 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)
=> 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)
=> 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);
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);
#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
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)
=> 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)
=> 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)
=> 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);
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);
#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
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.Collections.Generic;
using System.Collections.Immutable;
@@ -16,10 +16,7 @@ namespace Discord.WebSocket

public SocketGuild Guild { get; }
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 new virtual IReadOnlyCollection<SocketGuildUser> Users => ImmutableArray.Create<SocketGuildUser>();
@@ -48,8 +45,7 @@ namespace Discord.WebSocket
{
Name = model.Name.Value;
Position = model.Position.Value;
CategoryId = model.CategoryId;

var overwrites = model.PermissionOverwrites.Value;
var newOverwrites = ImmutableArray.CreateBuilder<Overwrite>(overwrites.Length);
for (int i = 0; i < overwrites.Length; i++)
@@ -135,9 +131,6 @@ namespace Discord.WebSocket
IGuild IGuildChannel.Guild => Guild;
ulong IGuildChannel.GuildId => Guild.Id;

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

async Task<IReadOnlyCollection<IInviteMetadata>> IGuildChannel.GetInvitesAsync(RequestOptions options)
=> await GetInvitesAsync(options).ConfigureAwait(false);
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;

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;
public bool IsNsfw => _nsfw || ChannelHelper.IsNsfw(this);
@@ -42,7 +45,7 @@ namespace Discord.WebSocket
internal override void Update(ClientState state, Model model)
{
base.Update(state, model);
CategoryId = model.CategoryId;
Topic = model.Topic.Value;
_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)
=> 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)
=> 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)
=> 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);
async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
=> await GetPinnedMessagesAsync(options).ConfigureAwait(false);
#if FILESYSTEM
async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
=> 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)
=> await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)
=> await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false);
IDisposable IMessageChannel.EnterTypingState(RequestOptions 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 System;
using System.Collections.Generic;
@@ -15,6 +15,9 @@ namespace Discord.WebSocket
{
public int Bitrate { 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
=> Guild.Users.Where(x => x.VoiceChannel?.Id == Id).ToImmutableArray();
@@ -32,7 +35,7 @@ namespace Discord.WebSocket
internal override void Update(ClientState state, Model model)
{
base.Update(state, model);
CategoryId = model.CategoryId;
Bitrate = model.Bitrate.Value;
UserLimit = model.UserLimit.Value != 0 ? model.UserLimit.Value : (int?)null;
}
@@ -52,7 +55,7 @@ namespace Discord.WebSocket
return user;
return null;
}
private string DebuggerDisplay => $"{Name} ({Id}, Voice)";
internal new SocketVoiceChannel Clone() => MemberwiseClone() as SocketVoiceChannel;

@@ -61,5 +64,9 @@ namespace Discord.WebSocket
=> Task.FromResult<IGuildUser>(GetUser(id));
IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> IGuildChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
=> 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.Net;
using System.Net.Sockets;
@@ -85,11 +84,7 @@ namespace Discord.Net.Udp

if (_udp != null)
{
#if UDPDISPOSE
try { _udp.Dispose(); }
#else
try { _udp.Close(); }
#endif
catch { }
_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
{
#if DEFAULTUDPCLIENT
public static readonly UdpSocketProvider Instance = () =>
{
try
@@ -16,12 +15,5 @@ namespace Discord.Net.Udp
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.Collections.Generic;
using System.ComponentModel;
@@ -209,14 +208,9 @@ namespace Discord.Net.WebSockets

//Use the internal buffer if we can get it
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
@@ -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
{
#if DEFAULTWEBSOCKET
public static readonly WebSocketProvider Instance = Create();

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" />
<PropertyGroup>
<AssemblyName>Discord.Net.Webhook</AssemblyName>
<RootNamespace>Discord.Webhook</RootNamespace>
<Description>A core Discord.Net library containing the Webhook client and models.</Description>
<TargetFrameworks>netstandard1.1</TargetFrameworks>
<TargetFrameworks>netstandard1.3</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<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)
=> 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>
public Task<ulong> SendFileAsync(string filePath, string text, bool isTTS = false,
IEnumerable<Embed> embeds = null, string username = null, string avatarUrl = null, RequestOptions options = null)
=> 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>
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)


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

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

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

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


+ 100
- 26
test/Discord.Net.Tests/Tests.Channels.cs View File

@@ -1,4 +1,5 @@
using Discord.Rest;
using System;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
@@ -15,17 +16,28 @@ namespace Discord
var text4 = await guild.CreateTextChannelAsync("text4");
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
await text1.ModifyAsync(x =>
{
x.Name = "text1";
x.Position = 1;
x.Topic = "Topic1";
x.CategoryId = cat1.Id;
});

await text2.ModifyAsync(x =>
{
x.Position = 2;
x.CategoryId = cat1.Id;
});
await text3.ModifyAsync(x =>
{
@@ -49,35 +61,35 @@ namespace Discord
}
private static void CheckTextChannels(RestGuild guild, params RestTextChannel[] textChannels)
{
Assert.Equal(textChannels.Length, 5);
Assert.Equal(5, textChannels.Length);
Assert.All(textChannels, x =>
{
Assert.NotNull(x);
Assert.NotEqual(x.Id, 0UL);
Assert.NotEqual(0UL, x.Id);
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.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.Equal(text2.Position, 2);
Assert.Equal(2, text2.Position);
Assert.Null(text2.Topic);

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

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.Null(text5.Topic);
@@ -89,10 +101,13 @@ namespace Discord
var voice2 = await guild.CreateVoiceChannelAsync("voice2");
var voice3 = await guild.CreateVoiceChannelAsync("voice3");

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

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

CheckVoiceChannels(voice1, voice2, voice3);
@@ -114,31 +130,89 @@ namespace Discord
}
private static void CheckVoiceChannels(params RestVoiceChannel[] voiceChannels)
{
Assert.Equal(voiceChannels.Length, 3);
Assert.Equal(3, voiceChannels.Length);
Assert.All(voiceChannels, 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.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.Equal(voice1.Bitrate, 96000);
Assert.Equal(voice1.Position, 1);
Assert.Equal(96000, voice1.Bitrate);
Assert.Equal(1, voice1.Position);

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

namespace Discord
@@ -12,6 +12,7 @@ namespace Discord
Assert.Equal(uint.MinValue, new Color(uint.MinValue).RawValue);
Assert.Equal(uint.MaxValue, new Color(uint.MaxValue).RawValue);
}
[Fact]
public void Color_Default()
{
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;

namespace Discord
@@ -34,6 +34,7 @@ namespace Discord
Assert.Equal(DateTimeOffset.FromUnixTimeMilliseconds(1514056829775), emote.CreatedAt);
Assert.EndsWith("gif", emote.Url);
}
[Fact]
public void Test_Invalid_Amimated_Emote_Parse()
{
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
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);




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

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

// check that toggling the bit works
Permissions.UnsetFlag(ref rawValue, flagValue);
Assert.Equal(false, Permissions.GetValue(rawValue, flagValue));
Assert.False(Permissions.GetValue(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
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);
Assert.Equal(false, Permissions.GetValue(rawValue, flagValue));
Assert.False(Permissions.GetValue(rawValue, flagValue));
}

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


Loading…
Cancel
Save