Browse Source

Merge pull request #1 from RogueException/dev

Update fork
pull/1120/head
FakeZane GitHub 7 years ago
parent
commit
731b7108a8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 493 additions and 288 deletions
  1. +1
    -6
      README.md
  2. +6
    -1
      src/Discord.Net.Commands/Attributes/CommandAttribute.cs
  3. +2
    -2
      src/Discord.Net.Commands/Attributes/OverrideTypeReaderAttribute.cs
  4. +3
    -3
      src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs
  5. +2
    -2
      src/Discord.Net.Commands/CommandService.cs
  6. +2
    -2
      src/Discord.Net.Commands/Info/CommandInfo.cs
  7. +2
    -2
      src/Discord.Net.Commands/Map/CommandMap.cs
  8. +5
    -6
      src/Discord.Net.Commands/Map/CommandMapNode.cs
  9. +4
    -4
      src/Discord.Net.Commands/PrimitiveParsers.cs
  10. +2
    -3
      src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs
  11. +2
    -2
      src/Discord.Net.Commands/Readers/UserTypeReader.cs
  12. +4
    -1
      src/Discord.Net.Commands/Results/ParseResult.cs
  13. +4
    -1
      src/Discord.Net.Commands/Results/PreconditionGroupResult.cs
  14. +4
    -1
      src/Discord.Net.Commands/Results/PreconditionResult.cs
  15. +4
    -1
      src/Discord.Net.Commands/Results/SearchResult.cs
  16. +2
    -0
      src/Discord.Net.Commands/Results/TypeReaderResult.cs
  17. +2
    -2
      src/Discord.Net.Commands/Utilities/ReflectionUtils.cs
  18. +2
    -2
      src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs
  19. +2
    -2
      src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs
  20. +2
    -2
      src/Discord.Net.Core/Entities/Messages/EmbedImage.cs
  21. +2
    -2
      src/Discord.Net.Core/Entities/Messages/EmbedThumbnail.cs
  22. +2
    -2
      src/Discord.Net.Core/Entities/Messages/EmbedVideo.cs
  23. +11
    -0
      src/Discord.Net.Core/Entities/Roles/Color.cs
  24. +2
    -2
      src/Discord.Net.Core/Extensions/DiscordClientExtensions.cs
  25. +2
    -2
      src/Discord.Net.Core/Format.cs
  26. +9
    -9
      src/Discord.Net.Core/Utils/MentionUtils.cs
  27. +3
    -3
      src/Discord.Net.Core/Utils/Paging/PagedEnumerator.cs
  28. +4
    -6
      src/Discord.Net.Core/Utils/Permissions.cs
  29. +2
    -2
      src/Discord.Net.Core/Utils/Preconditions.cs
  30. +46
    -0
      src/Discord.Net.Core/Utils/TokenUtils.cs
  31. +1
    -1
      src/Discord.Net.Rest/API/Common/AuditLogOptions.cs
  32. +18
    -3
      src/Discord.Net.Rest/BaseDiscordClient.cs
  33. +1
    -1
      src/Discord.Net.Rest/ClientHelper.cs
  34. +15
    -13
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  35. +3
    -5
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelCreateAuditLogData.cs
  36. +3
    -3
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelDeleteAuditLogData.cs
  37. +8
    -8
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/ChannelUpdateAuditLogData.cs
  38. +1
    -1
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/EmoteCreateAuditLogData.cs
  39. +1
    -1
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/EmoteDeleteAuditLogData.cs
  40. +2
    -2
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/EmoteUpdateAuditLogData.cs
  41. +20
    -20
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs
  42. +7
    -7
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteCreateAuditLogData.cs
  43. +7
    -7
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteDeleteAuditLogData.cs
  44. +10
    -10
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteUpdateAuditLogData.cs
  45. +1
    -1
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberRoleAuditLogData.cs
  46. +8
    -8
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs
  47. +3
    -5
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteCreateAuditLogData.cs
  48. +5
    -7
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteDeleteAuditLogData.cs
  49. +6
    -6
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs
  50. +5
    -5
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleCreateAuditLogData.cs
  51. +5
    -5
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleDeleteAuditLogData.cs
  52. +10
    -10
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/RoleUpdateAuditLogData.cs
  53. +3
    -3
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookCreateAuditLogData.cs
  54. +4
    -4
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookDeleteAuditLogData.cs
  55. +7
    -7
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookUpdateAuditLogData.cs
  56. +4
    -1
      src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs
  57. +1
    -1
      src/Discord.Net.Rest/Entities/Channels/RestDMChannel.cs
  58. +1
    -1
      src/Discord.Net.Rest/Entities/Channels/RestGroupChannel.cs
  59. +1
    -1
      src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
  60. +3
    -3
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  61. +2
    -2
      src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs
  62. +2
    -2
      src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs
  63. +2
    -2
      src/Discord.Net.Rest/Net/DefaultRestClient.cs
  64. +7
    -7
      src/Discord.Net.Rest/Net/Queue/ClientBucket.cs
  65. +3
    -3
      src/Discord.Net.Rest/Net/Queue/RequestQueue.cs
  66. +1
    -1
      src/Discord.Net.Rest/Net/RateLimitInfo.cs
  67. +9
    -9
      src/Discord.Net.WebSocket/Audio/AudioClient.cs
  68. +5
    -5
      src/Discord.Net.WebSocket/Audio/Streams/BufferedWriteStream.cs
  69. +2
    -2
      src/Discord.Net.WebSocket/ClientState.cs
  70. +4
    -4
      src/Discord.Net.WebSocket/DiscordShardedClient.cs
  71. +1
    -1
      src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
  72. +11
    -11
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  73. +2
    -2
      src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs
  74. +1
    -1
      src/Discord.Net.WebSocket/Entities/Channels/SocketDMChannel.cs
  75. +3
    -3
      src/Discord.Net.WebSocket/Entities/Channels/SocketGroupChannel.cs
  76. +1
    -1
      src/Discord.Net.WebSocket/Entities/Channels/SocketVoiceChannel.cs
  77. +5
    -5
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
  78. +2
    -2
      src/Discord.Net.WebSocket/Entities/Messages/MessageCache.cs
  79. +1
    -1
      src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs
  80. +1
    -1
      src/Discord.Net.WebSocket/Net/DefaultWebSocketClient.cs
  81. +124
    -0
      test/Discord.Net.Tests/Tests.TokenUtils.cs

+ 1
- 6
README.md View File

@@ -16,13 +16,9 @@ Our stable builds available from NuGet through the Discord.Net metapackage:
The individual components may also be installed from NuGet:
- [Discord.Net.Commands](https://www.nuget.org/packages/Discord.Net.Commands/)
- [Discord.Net.Rest](https://www.nuget.org/packages/Discord.Net.Rest/)
- [Discord.Net.Rpc](https://www.nuget.org/packages/Discord.Net.Rpc/)
- [Discord.Net.WebSocket](https://www.nuget.org/packages/Discord.Net.WebSocket/)
- [Discord.Net.Webhook](https://www.nuget.org/packages/Discord.Net.Webhook/)

The following provider is available for platforms not supporting .NET Standard 1.3:
- [Discord.Net.Providers.WS4Net](https://www.nuget.org/packages/Discord.Net.Providers.WS4Net/)

### Unstable (MyGet)
Nightly builds are available through our MyGet feed (`https://www.myget.org/F/discord-net/api/v3/index.json`).

@@ -41,5 +37,4 @@ The .NET Core workload must be selected during Visual Studio installation.
## Known Issues

### WebSockets (Win7 and earlier)
.NET Core 1.1 does not support WebSockets on Win7 and earlier. It's recommended to use the Discord.Net.Providers.WS4Net package until this is resolved.
Track the issue [here](https://github.com/dotnet/corefx/issues/9503).
.NET Core 1.1 does not support WebSockets on Win7 and earlier. This issue has been fixed since the release of .NET Core 2.1. It is recommended to target .NET Core 2.1 or above for your project if you wish to run your bot on legacy platforms; alternatively, you may choose to install the [Discord.Net.Providers.WS4Net](https://www.nuget.org/packages/Discord.Net.Providers.WS4Net/) package.

+ 6
- 1
src/Discord.Net.Commands/Attributes/CommandAttribute.cs View File

@@ -7,7 +7,7 @@ namespace Discord.Commands
{
public string Text { get; }
public RunMode RunMode { get; set; } = RunMode.Default;
public bool? IgnoreExtraArgs { get; set; }
public bool? IgnoreExtraArgs { get; }

public CommandAttribute()
{
@@ -17,5 +17,10 @@ namespace Discord.Commands
{
Text = text;
}
public CommandAttribute(string text, bool ignoreExtraArgs)
{
Text = text;
IgnoreExtraArgs = ignoreExtraArgs;
}
}
}

+ 2
- 2
src/Discord.Net.Commands/Attributes/OverrideTypeReaderAttribute.cs View File

@@ -7,13 +7,13 @@ namespace Discord.Commands
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public class OverrideTypeReaderAttribute : Attribute
{
private static readonly TypeInfo _typeReaderTypeInfo = typeof(TypeReader).GetTypeInfo();
private static readonly TypeInfo TypeReaderTypeInfo = typeof(TypeReader).GetTypeInfo();

public Type TypeReader { get; }

public OverrideTypeReaderAttribute(Type overridenTypeReader)
{
if (!_typeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo()))
if (!TypeReaderTypeInfo.IsAssignableFrom(overridenTypeReader.GetTypeInfo()))
throw new ArgumentException($"{nameof(overridenTypeReader)} must inherit from {nameof(TypeReader)}");
TypeReader = overridenTypeReader;


+ 3
- 3
src/Discord.Net.Commands/Builders/ModuleClassBuilder.cs View File

@@ -10,7 +10,7 @@ namespace Discord.Commands
{
internal static class ModuleClassBuilder
{
private static readonly TypeInfo _moduleTypeInfo = typeof(IModuleBase).GetTypeInfo();
private static readonly TypeInfo ModuleTypeInfo = typeof(IModuleBase).GetTypeInfo();

public static async Task<IReadOnlyList<TypeInfo>> SearchAsync(Assembly assembly, CommandService service)
{
@@ -135,7 +135,7 @@ namespace Discord.Commands
if (builder.Name == null)
builder.Name = typeInfo.Name;

var validCommands = typeInfo.DeclaredMethods.Where(x => IsValidCommandDefinition(x));
var validCommands = typeInfo.DeclaredMethods.Where(IsValidCommandDefinition);

foreach (var method in validCommands)
{
@@ -299,7 +299,7 @@ namespace Discord.Commands

private static bool IsValidModuleDefinition(TypeInfo typeInfo)
{
return _moduleTypeInfo.IsAssignableFrom(typeInfo) &&
return ModuleTypeInfo.IsAssignableFrom(typeInfo) &&
!typeInfo.IsAbstract &&
!typeInfo.ContainsGenericParameters;
}


+ 2
- 2
src/Discord.Net.Commands/CommandService.cs View File

@@ -118,7 +118,7 @@ namespace Discord.Commands
var typeInfo = type.GetTypeInfo();

if (_typedModuleDefs.ContainsKey(type))
throw new ArgumentException($"This module has already been added.");
throw new ArgumentException("This module has already been added.");

var module = (await ModuleClassBuilder.BuildAsync(this, services, typeInfo).ConfigureAwait(false)).FirstOrDefault();

@@ -241,7 +241,7 @@ namespace Discord.Commands
{
if (_defaultTypeReaders.ContainsKey(type))
_ = _cmdLogger.WarningAsync($"The default TypeReader for {type.FullName} was replaced by {reader.GetType().FullName}." +
$"To suppress this message, use AddTypeReader<T>(reader, true).");
"To suppress this message, use AddTypeReader<T>(reader, true).");
AddTypeReader(type, reader, true);
}
/// <summary>


+ 2
- 2
src/Discord.Net.Commands/Info/CommandInfo.cs View File

@@ -1,4 +1,4 @@
using Discord.Commands.Builders;
using Discord.Commands.Builders;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -63,7 +63,7 @@ namespace Discord.Commands
Attributes = builder.Attributes.ToImmutableArray();

Parameters = builder.Parameters.Select(x => x.Build(this)).ToImmutableArray();
HasVarArgs = builder.Parameters.Count > 0 ? builder.Parameters[builder.Parameters.Count - 1].IsMultiple : false;
HasVarArgs = builder.Parameters.Count > 0 && builder.Parameters[builder.Parameters.Count - 1].IsMultiple;
IgnoreExtraArgs = builder.IgnoreExtraArgs;

_action = builder.Callback;


+ 2
- 2
src/Discord.Net.Commands/Map/CommandMap.cs View File

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

namespace Discord.Commands
{
@@ -6,7 +6,7 @@ namespace Discord.Commands
{
private readonly CommandService _service;
private readonly CommandMapNode _root;
private static readonly string[] _blankAliases = new[] { "" };
private static readonly string[] BlankAliases = { "" };

public CommandMap(CommandService service)
{


+ 5
- 6
src/Discord.Net.Commands/Map/CommandMapNode.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -7,7 +7,7 @@ namespace Discord.Commands
{
internal class CommandMapNode
{
private static readonly char[] _whitespaceChars = new[] { ' ', '\r', '\n' };
private static readonly char[] WhitespaceChars = { ' ', '\r', '\n' };

private readonly ConcurrentDictionary<string, CommandMapNode> _nodes;
private readonly string _name;
@@ -52,7 +52,6 @@ namespace Discord.Commands
public void RemoveCommand(CommandService service, string text, int index, CommandInfo command)
{
int nextSegment = NextSegment(text, index, service._separatorChar);
string name;

lock (_lockObj)
{
@@ -60,13 +59,13 @@ namespace Discord.Commands
_commands = _commands.Remove(command);
else
{
string name;
if (nextSegment == -1)
name = text.Substring(index);
else
name = text.Substring(index, nextSegment - index);

CommandMapNode nextNode;
if (_nodes.TryGetValue(name, out nextNode))
if (_nodes.TryGetValue(name, out var nextNode))
{
nextNode.RemoveCommand(service, nextSegment == -1 ? "" : text, nextSegment + 1, command);
if (nextNode.IsEmpty)
@@ -100,7 +99,7 @@ namespace Discord.Commands
}

//Check if this is the last command segment before args
nextSegment = NextSegment(text, index, _whitespaceChars, service._separatorChar);
nextSegment = NextSegment(text, index, WhitespaceChars, service._separatorChar);
if (nextSegment != -1)
{
name = text.Substring(index, nextSegment - index);


+ 4
- 4
src/Discord.Net.Commands/PrimitiveParsers.cs View File

@@ -8,9 +8,9 @@ namespace Discord.Commands

internal static class PrimitiveParsers
{
private static readonly Lazy<IReadOnlyDictionary<Type, Delegate>> _parsers = new Lazy<IReadOnlyDictionary<Type, Delegate>>(CreateParsers);
private static readonly Lazy<IReadOnlyDictionary<Type, Delegate>> Parsers = new Lazy<IReadOnlyDictionary<Type, Delegate>>(CreateParsers);

public static IEnumerable<Type> SupportedTypes = _parsers.Value.Keys;
public static IEnumerable<Type> SupportedTypes = Parsers.Value.Keys;

static IReadOnlyDictionary<Type, Delegate> CreateParsers()
{
@@ -34,7 +34,7 @@ namespace Discord.Commands
return parserBuilder.ToImmutable();
}

public static TryParseDelegate<T> Get<T>() => (TryParseDelegate<T>)_parsers.Value[typeof(T)];
public static Delegate Get(Type type) => _parsers.Value[type];
public static TryParseDelegate<T> Get<T>() => (TryParseDelegate<T>)Parsers.Value[typeof(T)];
public static Delegate Get(Type type) => Parsers.Value[type];
}
}

+ 2
- 3
src/Discord.Net.Commands/Readers/TimeSpanTypeReader.cs View File

@@ -6,8 +6,7 @@ namespace Discord.Commands
{
internal class TimeSpanTypeReader : TypeReader
{
private static readonly string[] _formats = new[]
{
private static readonly string[] Formats = {
"%d'd'%h'h'%m'm'%s's'", //4d3h2m1s
"%d'd'%h'h'%m'm'", //4d3h2m
"%d'd'%h'h'%s's'", //4d3h 1s
@@ -27,7 +26,7 @@ namespace Discord.Commands

public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
{
return (TimeSpan.TryParseExact(input.ToLowerInvariant(), _formats, CultureInfo.InvariantCulture, out var timeSpan))
return (TimeSpan.TryParseExact(input.ToLowerInvariant(), Formats, CultureInfo.InvariantCulture, out var timeSpan))
? Task.FromResult(TypeReaderResult.FromSuccess(timeSpan))
: Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Failed to parse TimeSpan"));
}


+ 2
- 2
src/Discord.Net.Commands/Readers/UserTypeReader.cs View File

@@ -71,8 +71,8 @@ namespace Discord.Commands
.Where(x => string.Equals(input, (x as IGuildUser)?.Nickname, StringComparison.OrdinalIgnoreCase))
.ForEachAsync(channelUser => AddResult(results, channelUser as T, (channelUser as IGuildUser).Nickname == input ? 0.65f : 0.55f));

foreach (var guildUser in guildUsers.Where(x => string.Equals(input, (x as IGuildUser).Nickname, StringComparison.OrdinalIgnoreCase)))
AddResult(results, guildUser as T, (guildUser as IGuildUser).Nickname == input ? 0.60f : 0.50f);
foreach (var guildUser in guildUsers.Where(x => string.Equals(input, x.Nickname, StringComparison.OrdinalIgnoreCase)))
AddResult(results, guildUser as T, guildUser.Nickname == input ? 0.60f : 0.50f);
}

if (results.Count > 0)


+ 4
- 1
src/Discord.Net.Commands/Results/ParseResult.cs View File

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

namespace Discord.Commands
@@ -53,6 +54,8 @@ namespace Discord.Commands

public static ParseResult FromError(CommandError error, string reason)
=> new ParseResult(null, null, error, reason);
public static ParseResult FromError(Exception ex)
=> FromError(CommandError.Exception, ex.Message);
public static ParseResult FromError(IResult result)
=> new ParseResult(null, null, result.Error, result.ErrorReason);



+ 4
- 1
src/Discord.Net.Commands/Results/PreconditionGroupResult.cs View File

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

namespace Discord.Commands
@@ -18,6 +19,8 @@ namespace Discord.Commands
=> new PreconditionGroupResult(null, null, null);
public static PreconditionGroupResult FromError(string reason, ICollection<PreconditionResult> preconditions)
=> new PreconditionGroupResult(CommandError.UnmetPrecondition, reason, preconditions);
public static new PreconditionGroupResult FromError(Exception ex)
=> new PreconditionGroupResult(CommandError.Exception, ex.Message, null);
public static new PreconditionGroupResult FromError(IResult result) //needed?
=> new PreconditionGroupResult(result.Error, result.ErrorReason, null);



+ 4
- 1
src/Discord.Net.Commands/Results/PreconditionResult.cs View File

@@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;

namespace Discord.Commands
{
@@ -20,6 +21,8 @@ namespace Discord.Commands
=> new PreconditionResult(null, null);
public static PreconditionResult FromError(string reason)
=> new PreconditionResult(CommandError.UnmetPrecondition, reason);
public static PreconditionResult FromError(Exception ex)
=> new PreconditionResult(CommandError.Exception, ex.Message);
public static PreconditionResult FromError(IResult result)
=> new PreconditionResult(result.Error, result.ErrorReason);



+ 4
- 1
src/Discord.Net.Commands/Results/SearchResult.cs View File

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

namespace Discord.Commands
@@ -26,6 +27,8 @@ namespace Discord.Commands
=> new SearchResult(text, commands, null, null);
public static SearchResult FromError(CommandError error, string reason)
=> new SearchResult(null, null, error, reason);
public static SearchResult FromError(Exception ex)
=> FromError(CommandError.Exception, ex.Message);
public static SearchResult FromError(IResult result)
=> new SearchResult(null, null, result.Error, result.ErrorReason);



+ 2
- 0
src/Discord.Net.Commands/Results/TypeReaderResult.cs View File

@@ -50,6 +50,8 @@ namespace Discord.Commands
=> new TypeReaderResult(values, null, null);
public static TypeReaderResult FromError(CommandError error, string reason)
=> new TypeReaderResult(null, error, reason);
public static TypeReaderResult FromError(Exception ex)
=> FromError(CommandError.Exception, ex.Message);
public static TypeReaderResult FromError(IResult result)
=> new TypeReaderResult(null, result.Error, result.ErrorReason);



+ 2
- 2
src/Discord.Net.Commands/Utilities/ReflectionUtils.cs View File

@@ -8,7 +8,7 @@ namespace Discord.Commands
{
internal static class ReflectionUtils
{
private static readonly TypeInfo _objectTypeInfo = typeof(object).GetTypeInfo();
private static readonly TypeInfo ObjectTypeInfo = typeof(object).GetTypeInfo();

internal static T CreateObject<T>(TypeInfo typeInfo, CommandService commands, IServiceProvider services = null)
=> CreateBuilder<T>(typeInfo, commands)(services);
@@ -54,7 +54,7 @@ namespace Discord.Commands
private static System.Reflection.PropertyInfo[] GetProperties(TypeInfo ownerType)
{
var result = new List<System.Reflection.PropertyInfo>();
while (ownerType != _objectTypeInfo)
while (ownerType != ObjectTypeInfo)
{
foreach (var prop in ownerType.DeclaredProperties)
{


+ 2
- 2
src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -9,7 +9,7 @@ namespace Discord
/// <summary>
/// Represents an entry in an audit log
/// </summary>
public interface IAuditLogEntry : IEntity<ulong>
public interface IAuditLogEntry : ISnowflakeEntity
{
/// <summary>
/// The action which occured to create this entry


+ 2
- 2
src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs View File

@@ -239,7 +239,7 @@ namespace Discord
get => _name;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException($"Field name must not be null, empty or entirely whitespace.", nameof(Name));
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("Field name must not be null, empty or entirely whitespace.", nameof(Name));
if (value.Length > MaxFieldNameLength) throw new ArgumentException($"Field name length must be less than or equal to {MaxFieldNameLength}.", nameof(Name));
_name = value;
}
@@ -251,7 +251,7 @@ namespace Discord
set
{
var stringValue = value?.ToString();
if (string.IsNullOrEmpty(stringValue)) throw new ArgumentException($"Field value must not be null or empty.", nameof(Value));
if (string.IsNullOrEmpty(stringValue)) throw new ArgumentException("Field value must not be null or empty.", nameof(Value));
if (stringValue.Length > MaxFieldValueLength) throw new ArgumentException($"Field value length must be less than or equal to {MaxFieldValueLength}.", nameof(Value));
_value = stringValue;
}


+ 2
- 2
src/Discord.Net.Core/Entities/Messages/EmbedImage.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;

namespace Discord
@@ -20,6 +20,6 @@ namespace Discord
}

private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url.ToString();
public override string ToString() => Url;
}
}

+ 2
- 2
src/Discord.Net.Core/Entities/Messages/EmbedThumbnail.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;

namespace Discord
@@ -20,6 +20,6 @@ namespace Discord
}

private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url.ToString();
public override string ToString() => Url;
}
}

+ 2
- 2
src/Discord.Net.Core/Entities/Messages/EmbedVideo.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;

namespace Discord
@@ -18,6 +18,6 @@ namespace Discord
}

private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url.ToString();
public override string ToString() => Url;
}
}

+ 11
- 0
src/Discord.Net.Core/Entities/Roles/Color.cs View File

@@ -100,6 +100,17 @@ namespace Discord
(uint)(b * 255.0f);
}

public static bool operator ==(Color lhs, Color rhs)
=> lhs.RawValue == rhs.RawValue;

public static bool operator !=(Color lhs, Color rhs)
=> lhs.RawValue != rhs.RawValue;

public override bool Equals(object obj)
=> (obj is Color c && RawValue == c.RawValue);

public override int GetHashCode() => RawValue.GetHashCode();

#if NETSTANDARD2_0 || NET45
public static implicit operator StandardColor(Color color) =>
StandardColor.FromArgb((int)color.RawValue);


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

@@ -12,12 +12,12 @@ namespace Discord
public static async Task<IDMChannel> GetDMChannelAsync(this IDiscordClient client, ulong id)
=> await client.GetPrivateChannelAsync(id).ConfigureAwait(false) as IDMChannel;
public static async Task<IEnumerable<IDMChannel>> GetDMChannelsAsync(this IDiscordClient client)
=> (await client.GetPrivateChannelsAsync().ConfigureAwait(false)).Select(x => x as IDMChannel).Where(x => x != null);
=> (await client.GetPrivateChannelsAsync().ConfigureAwait(false)).OfType<IDMChannel>();

public static async Task<IGroupChannel> GetGroupChannelAsync(this IDiscordClient client, ulong id)
=> await client.GetPrivateChannelAsync(id).ConfigureAwait(false) as IGroupChannel;
public static async Task<IEnumerable<IGroupChannel>> GetGroupChannelsAsync(this IDiscordClient client)
=> (await client.GetPrivateChannelsAsync().ConfigureAwait(false)).Select(x => x as IGroupChannel).Where(x => x != null);
=> (await client.GetPrivateChannelsAsync().ConfigureAwait(false)).OfType<IGroupChannel>();

public static async Task<IVoiceRegion> GetOptimalVoiceRegionAsync(this IDiscordClient discord)
{


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

@@ -1,9 +1,9 @@
namespace Discord
namespace Discord
{
public static class Format
{
// Characters which need escaping
private static string[] SensitiveCharacters = { "\\", "*", "_", "~", "`" };
private static readonly string[] SensitiveCharacters = { "\\", "*", "_", "~", "`" };

/// <summary> Returns a markdown-formatted string with bold formatting. </summary>
public static string Bold(string text) => $"**{text}**";


+ 9
- 9
src/Discord.Net.Core/Utils/MentionUtils.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Globalization;
using System.Text;

@@ -139,22 +139,22 @@ namespace Discord
if (user != null)
return $"@{guildUser?.Nickname ?? user?.Username}";
else
return $"";
return "";
case TagHandling.NameNoPrefix:
if (user != null)
return $"{guildUser?.Nickname ?? user?.Username}";
else
return $"";
return "";
case TagHandling.FullName:
if (user != null)
return $"@{user.Username}#{user.Discriminator}";
else
return $"";
return "";
case TagHandling.FullNameNoPrefix:
if (user != null)
return $"{user.Username}#{user.Discriminator}";
else
return $"";
return "";
case TagHandling.Sanitize:
if (guildUser != null && guildUser.Nickname == null)
return MentionUser($"{SanitizeChar}{tag.Key}", false);
@@ -176,13 +176,13 @@ namespace Discord
if (channel != null)
return $"#{channel.Name}";
else
return $"";
return "";
case TagHandling.NameNoPrefix:
case TagHandling.FullNameNoPrefix:
if (channel != null)
return $"{channel.Name}";
else
return $"";
return "";
case TagHandling.Sanitize:
return MentionChannel($"{SanitizeChar}{tag.Key}");
}
@@ -201,13 +201,13 @@ namespace Discord
if (role != null)
return $"@{role.Name}";
else
return $"";
return "";
case TagHandling.NameNoPrefix:
case TagHandling.FullNameNoPrefix:
if (role != null)
return $"{role.Name}";
else
return $"";
return "";
case TagHandling.Sanitize:
return MentionRole($"{SanitizeChar}{tag.Key}");
}


+ 3
- 3
src/Discord.Net.Core/Utils/Paging/PagedEnumerator.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -60,7 +60,7 @@ namespace Discord
if (Current.Count == 0)
_info.Remaining = 0;
}
_info.PageSize = _info.Remaining != null ? (int)Math.Min(_info.Remaining.Value, _source.PageSize) : _source.PageSize;
_info.PageSize = _info.Remaining != null ? Math.Min(_info.Remaining.Value, _source.PageSize) : _source.PageSize;

if (_info.Remaining != 0)
{
@@ -74,4 +74,4 @@ namespace Discord
public void Dispose() { Current = null; }
}
}
}
}

+ 4
- 6
src/Discord.Net.Core/Utils/Permissions.cs View File

@@ -1,4 +1,4 @@
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;

namespace Discord
{
@@ -119,13 +119,11 @@ namespace Discord
resolvedPermissions = mask; //Owners and administrators always have all permissions
else
{
OverwritePermissions? perms;

//Start with this user's guild permissions
resolvedPermissions = guildPermissions;

//Give/Take Everyone permissions
perms = channel.GetPermissionOverwrite(guild.EveryoneRole);
var perms = channel.GetPermissionOverwrite(guild.EveryoneRole);
if (perms != null)
resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;

@@ -133,7 +131,7 @@ namespace Discord
ulong deniedPermissions = 0UL, allowedPermissions = 0UL;
foreach (var roleId in user.RoleIds)
{
IRole role = null;
IRole role;
if (roleId != guild.EveryoneRole.Id && (role = guild.GetRole(roleId)) != null)
{
perms = channel.GetPermissionOverwrite(role);
@@ -151,7 +149,7 @@ namespace Discord
if (perms != null)
resolvedPermissions = (resolvedPermissions & ~perms.Value.DenyValue) | perms.Value.AllowValue;

if (channel is ITextChannel textChannel)
if (channel is ITextChannel)
{
if (!GetValue(resolvedPermissions, ChannelPermission.ViewChannel))
{


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

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

namespace Discord
{
@@ -198,7 +198,7 @@ namespace Discord
for (var i = 0; i < roles.Length; i++)
{
if (roles[i] == guildId)
throw new ArgumentException($"The everyone role cannot be assigned to a user", name);
throw new ArgumentException("The everyone role cannot be assigned to a user", name);
}
}
}


+ 46
- 0
src/Discord.Net.Core/Utils/TokenUtils.cs View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
public static class TokenUtils
{
/// <summary>
/// Checks the validity of the supplied token of a specific type.
/// </summary>
/// <param name="tokenType"> The type of token to validate. </param>
/// <param name="token"> The token value to validate. </param>
/// <exception cref="ArgumentNullException"> Thrown when the supplied token string is null, empty, or contains only whitespace.</exception>
/// <exception cref="ArgumentException"> Thrown when the supplied TokenType or token value is invalid. </exception>
public static void ValidateToken(TokenType tokenType, string token)
{
// A Null or WhiteSpace token of any type is invalid.
if (string.IsNullOrWhiteSpace(token))
throw new ArgumentNullException("A token cannot be null, empty, or contain only whitespace.", nameof(token));

switch (tokenType)
{
case TokenType.Webhook:
// no validation is performed on Webhook tokens
break;
case TokenType.Bearer:
// no validation is performed on Bearer tokens
break;
case TokenType.Bot:
// bot tokens are assumed to be at least 59 characters in length
// this value was determined by referencing examples in the discord documentation, and by comparing with
// pre-existing tokens
if (token.Length < 59)
throw new ArgumentException("A Bot token must be at least 59 characters in length.", nameof(token));
break;
default:
// All unrecognized TokenTypes (including User tokens) are considered to be invalid.
throw new ArgumentException("Unrecognized TokenType.", nameof(token));
}
}

}
}

+ 1
- 1
src/Discord.Net.Rest/API/Common/AuditLogOptions.cs View File

@@ -20,7 +20,7 @@ namespace Discord.API
[JsonProperty("role_name")]
public string OverwriteRoleName { get; set; }
[JsonProperty("type")]
public string OverwriteType { get; set; }
public PermissionTarget OverwriteType { get; set; }
[JsonProperty("id")]
public ulong? OverwriteTargetId { get; set; }
}


+ 18
- 3
src/Discord.Net.Rest/BaseDiscordClient.cs View File

@@ -55,11 +55,11 @@ namespace Discord.Rest
await _stateLock.WaitAsync().ConfigureAwait(false);
try
{
await LoginInternalAsync(tokenType, token).ConfigureAwait(false);
await LoginInternalAsync(tokenType, token, validateToken).ConfigureAwait(false);
}
finally { _stateLock.Release(); }
}
private async Task LoginInternalAsync(TokenType tokenType, string token)
private async Task LoginInternalAsync(TokenType tokenType, string token, bool validateToken)
{
if (_isFirstLogin)
{
@@ -73,11 +73,26 @@ namespace Discord.Rest

try
{
// If token validation is enabled, validate the token and let it throw any ArgumentExceptions
// that result from invalid parameters
if (validateToken)
{
try
{
TokenUtils.ValidateToken(tokenType, token);
}
catch (ArgumentException ex)
{
// log these ArgumentExceptions and allow for the client to attempt to log in anyways
await LogManager.WarningAsync("Discord", "A supplied token was invalid", ex).ConfigureAwait(false);
}
}

await ApiClient.LoginAsync(tokenType, token).ConfigureAwait(false);
await OnLoginAsync(tokenType, token).ConfigureAwait(false);
LoginState = LoginState.LoggedIn;
}
catch (Exception)
catch
{
await LogoutInternalAsync().ConfigureAwait(false);
throw;


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

@@ -47,7 +47,7 @@ namespace Discord.Rest
public static async Task<IReadOnlyCollection<RestConnection>> GetConnectionsAsync(BaseDiscordClient client, RequestOptions options)
{
var models = await client.ApiClient.GetMyConnectionsAsync(options).ConfigureAwait(false);
return models.Select(x => RestConnection.Create(x)).ToImmutableArray();
return models.Select(RestConnection.Create).ToImmutableArray();
}
public static async Task<RestInviteMetadata> GetInviteAsync(BaseDiscordClient client,


+ 15
- 13
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -43,9 +43,11 @@ namespace Discord.API
public TokenType AuthTokenType { get; private set; }
internal string AuthToken { get; private set; }
internal IRestClient RestClient { get; private set; }
internal ulong? CurrentUserId { get; set;}
internal ulong? CurrentUserId { get; set; }

public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, RetryMode defaultRetryMode = RetryMode.AlwaysRetry,
internal JsonSerializer Serializer => _serializer;

public DiscordRestApiClient(RestClientProvider restClientProvider, string userAgent, RetryMode defaultRetryMode = RetryMode.AlwaysRetry,
JsonSerializer serializer = null)
{
_restClientProvider = restClientProvider;
@@ -123,7 +125,7 @@ namespace Discord.API

LoginState = LoginState.LoggedIn;
}
catch (Exception)
catch
{
await LogoutInternalAsync().ConfigureAwait(false);
throw;
@@ -235,7 +237,7 @@ namespace Discord.API
internal Task<TResponse> SendMultipartAsync<TResponse>(string method, Expression<Func<string>> endpointExpr, IReadOnlyDictionary<string, object> multipartArgs, BucketIds ids,
ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null, [CallerMemberName] string funcName = null)
=> SendMultipartAsync<TResponse>(method, GetEndpoint(endpointExpr), multipartArgs, GetBucketId(ids, endpointExpr, AuthTokenType, funcName), clientBucket, options);
public async Task<TResponse> SendMultipartAsync<TResponse>(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs,
public async Task<TResponse> SendMultipartAsync<TResponse>(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs,
string bucketId = null, ClientBucketType clientBucket = ClientBucketType.Unbucketed, RequestOptions options = null)
{
options = options ?? new RequestOptions();
@@ -414,7 +416,7 @@ namespace Discord.API
var ids = new BucketIds(guildId: guildId);
await SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}/roles/{roleId}", ids, options: options);
}
//Channel Messages
public async Task<Message> GetChannelMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null)
{
@@ -490,7 +492,7 @@ namespace Discord.API
if (args.Content?.Length > DiscordConfig.MaxMessageSize)
throw new ArgumentException($"Message content is too long, length must be less or equal to {DiscordConfig.MaxMessageSize}.", nameof(args.Content));
options = RequestOptions.CreateOrClone(options);
return await SendJsonAsync<Message>("POST", () => $"webhooks/{webhookId}/{AuthToken}?wait=true", args, new BucketIds(), clientBucket: ClientBucketType.SendEdit, options: options).ConfigureAwait(false);
}
public async Task<Message> UploadFileAsync(ulong channelId, UploadFileParams args, RequestOptions options = null)
@@ -737,7 +739,7 @@ namespace Discord.API
Preconditions.NotNullOrWhitespace(args.Name, nameof(args.Name));
Preconditions.NotNullOrWhitespace(args.RegionId, nameof(args.RegionId));
options = RequestOptions.CreateOrClone(options);
return await SendJsonAsync<Guild>("POST", () => "guilds", args, new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task<Guild> DeleteGuildAsync(ulong guildId, RequestOptions options = null)
@@ -964,7 +966,7 @@ namespace Discord.API
{
Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId));
options = RequestOptions.CreateOrClone(options);
return await SendAsync<Invite>("DELETE", () => $"invites/{inviteId}", new BucketIds(), options: options).ConfigureAwait(false);
}

@@ -1163,7 +1165,7 @@ namespace Discord.API

int limit = args.Limit.GetValueOrDefault(int.MaxValue);
ulong afterGuildId = args.AfterGuildId.GetValueOrDefault(0);
return await SendAsync<IReadOnlyCollection<UserGuild>>("GET", () => $"users/@me/guilds?limit={limit}&after={afterGuildId}", new BucketIds(), options: options).ConfigureAwait(false);
}
public async Task<Application> GetMyApplicationAsync(RequestOptions options = null)
@@ -1263,7 +1265,7 @@ namespace Discord.API
Preconditions.NotNull(args, nameof(args));
Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name));
options = RequestOptions.CreateOrClone(options);
if (AuthTokenType == TokenType.Webhook)
return await SendJsonAsync<Webhook>("PATCH", () => $"webhooks/{webhookId}/{AuthToken}", args, new BucketIds(), options: options).ConfigureAwait(false);
else
@@ -1392,9 +1394,9 @@ namespace Discord.API

int argId = int.Parse(format.Substring(leftIndex + 1, rightIndex - leftIndex - 1));
string fieldName = GetFieldName(methodArgs[argId + 1]);
int? mappedId;
mappedId = BucketIds.GetIndex(fieldName);
var mappedId = BucketIds.GetIndex(fieldName);
if(!mappedId.HasValue && rightIndex != endIndex && format.Length > rightIndex + 1 && format[rightIndex + 1] == '/') //Ignore the next slash
rightIndex++;



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

@@ -26,18 +26,16 @@ namespace Discord.Rest
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");

var type = typeModel.NewValue.ToObject<ChannelType>();
var name = nameModel.NewValue.ToObject<string>();
var type = typeModel.NewValue.ToObject<ChannelType>(discord.ApiClient.Serializer);
var name = nameModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);

foreach (var overwrite in overwritesModel.NewValue)
{
var deny = overwrite.Value<ulong>("deny");
var _type = overwrite.Value<string>("type");
var permType = overwrite.Value<PermissionTarget>("type");
var id = overwrite.Value<ulong>("id");
var allow = overwrite.Value<ulong>("allow");

PermissionTarget permType = _type == "member" ? PermissionTarget.User : PermissionTarget.Role;

overwrites.Add(new Overwrite(id, permType, new OverwritePermissions(allow, deny)));
}



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

@@ -27,11 +27,11 @@ namespace Discord.Rest
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");

var overwrites = overwritesModel.OldValue.ToObject<API.Overwrite[]>()
var overwrites = overwritesModel.OldValue.ToObject<API.Overwrite[]>(discord.ApiClient.Serializer)
.Select(x => new Overwrite(x.TargetId, x.TargetType, new OverwritePermissions(x.Allow, x.Deny)))
.ToList();
var type = typeModel.OldValue.ToObject<ChannelType>();
var name = nameModel.OldValue.ToObject<string>();
var type = typeModel.OldValue.ToObject<ChannelType>(discord.ApiClient.Serializer);
var name = nameModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var id = entry.TargetId.Value;

return new ChannelDeleteAuditLogData(id, name, type, overwrites.ToReadOnlyCollection());


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

@@ -23,14 +23,14 @@ namespace Discord.Rest
var bitrateModel = changes.FirstOrDefault(x => x.ChangedProperty == "bitrate");
var userLimitModel = changes.FirstOrDefault(x => x.ChangedProperty == "user_limit");

string oldName = nameModel?.OldValue?.ToObject<string>(),
newName = nameModel?.NewValue?.ToObject<string>();
string oldTopic = topicModel?.OldValue?.ToObject<string>(),
newTopic = topicModel?.NewValue?.ToObject<string>();
int? oldBitrate = bitrateModel?.OldValue?.ToObject<int>(),
newBitrate = bitrateModel?.NewValue?.ToObject<int>();
int? oldLimit = userLimitModel?.OldValue?.ToObject<int>(),
newLimit = userLimitModel?.NewValue?.ToObject<int>();
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
string oldTopic = topicModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newTopic = topicModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
int? oldBitrate = bitrateModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newBitrate = bitrateModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
int? oldLimit = userLimitModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newLimit = userLimitModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);

var before = new ChannelInfo(oldName, oldTopic, oldBitrate, oldLimit);
var after = new ChannelInfo(newName, newTopic, newBitrate, newLimit);


+ 1
- 1
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/EmoteCreateAuditLogData.cs View File

@@ -21,7 +21,7 @@ namespace Discord.Rest
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");

var emoteName = change.NewValue?.ToObject<string>();
var emoteName = change.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
return new EmoteCreateAuditLogData(entry.TargetId.Value, emoteName);
}



+ 1
- 1
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/EmoteDeleteAuditLogData.cs View File

@@ -17,7 +17,7 @@ namespace Discord.Rest
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");

var emoteName = change.OldValue?.ToObject<string>();
var emoteName = change.OldValue?.ToObject<string>(discord.ApiClient.Serializer);

return new EmoteDeleteAuditLogData(entry.TargetId.Value, emoteName);
}


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

@@ -18,8 +18,8 @@ namespace Discord.Rest
{
var change = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "name");

var newName = change.NewValue?.ToObject<string>();
var oldName = change.OldValue?.ToObject<string>();
var newName = change.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var oldName = change.OldValue?.ToObject<string>(discord.ApiClient.Serializer);

return new EmoteUpdateAuditLogData(entry.TargetId.Value, oldName, newName);
}


+ 20
- 20
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/GuildUpdateAuditLogData.cs View File

@@ -28,26 +28,26 @@ namespace Discord.Rest
var mfaLevelModel = changes.FirstOrDefault(x => x.ChangedProperty == "afk_timeout");
var contentFilterModel = changes.FirstOrDefault(x => x.ChangedProperty == "afk_timeout");

int? oldAfkTimeout = afkTimeoutModel?.OldValue?.ToObject<int>(),
newAfkTimeout = afkTimeoutModel?.NewValue?.ToObject<int>();
DefaultMessageNotifications? oldDefaultMessageNotifications = defaultMessageNotificationsModel?.OldValue?.ToObject<DefaultMessageNotifications>(),
newDefaultMessageNotifications = defaultMessageNotificationsModel?.NewValue?.ToObject<DefaultMessageNotifications>();
ulong? oldAfkChannelId = afkChannelModel?.OldValue?.ToObject<ulong>(),
newAfkChannelId = afkChannelModel?.NewValue?.ToObject<ulong>();
string oldName = nameModel?.OldValue?.ToObject<string>(),
newName = nameModel?.NewValue?.ToObject<string>();
string oldRegionId = regionIdModel?.OldValue?.ToObject<string>(),
newRegionId = regionIdModel?.NewValue?.ToObject<string>();
string oldIconHash = iconHashModel?.OldValue?.ToObject<string>(),
newIconHash = iconHashModel?.NewValue?.ToObject<string>();
VerificationLevel? oldVerificationLevel = verificationLevelModel?.OldValue?.ToObject<VerificationLevel>(),
newVerificationLevel = verificationLevelModel?.NewValue?.ToObject<VerificationLevel>();
ulong? oldOwnerId = ownerIdModel?.OldValue?.ToObject<ulong>(),
newOwnerId = ownerIdModel?.NewValue?.ToObject<ulong>();
MfaLevel? oldMfaLevel = mfaLevelModel?.OldValue?.ToObject<MfaLevel>(),
newMfaLevel = mfaLevelModel?.NewValue?.ToObject<MfaLevel>();
int? oldContentFilter = contentFilterModel?.OldValue?.ToObject<int>(),
newContentFilter = contentFilterModel?.NewValue?.ToObject<int>();
int? oldAfkTimeout = afkTimeoutModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newAfkTimeout = afkTimeoutModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
DefaultMessageNotifications? oldDefaultMessageNotifications = defaultMessageNotificationsModel?.OldValue?.ToObject<DefaultMessageNotifications>(discord.ApiClient.Serializer),
newDefaultMessageNotifications = defaultMessageNotificationsModel?.NewValue?.ToObject<DefaultMessageNotifications>(discord.ApiClient.Serializer);
ulong? oldAfkChannelId = afkChannelModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newAfkChannelId = afkChannelModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
string oldRegionId = regionIdModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newRegionId = regionIdModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
string oldIconHash = iconHashModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newIconHash = iconHashModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
VerificationLevel? oldVerificationLevel = verificationLevelModel?.OldValue?.ToObject<VerificationLevel>(discord.ApiClient.Serializer),
newVerificationLevel = verificationLevelModel?.NewValue?.ToObject<VerificationLevel>(discord.ApiClient.Serializer);
ulong? oldOwnerId = ownerIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newOwnerId = ownerIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
MfaLevel? oldMfaLevel = mfaLevelModel?.OldValue?.ToObject<MfaLevel>(discord.ApiClient.Serializer),
newMfaLevel = mfaLevelModel?.NewValue?.ToObject<MfaLevel>(discord.ApiClient.Serializer);
int? oldContentFilter = contentFilterModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newContentFilter = contentFilterModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);

IUser oldOwner = null;
if (oldOwnerId != null)


+ 7
- 7
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteCreateAuditLogData.cs View File

@@ -30,13 +30,13 @@ namespace Discord.Rest
var usesModel = changes.FirstOrDefault(x => x.ChangedProperty == "uses");
var maxUsesModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_uses");

var maxAge = maxAgeModel.NewValue.ToObject<int>();
var code = codeModel.NewValue.ToObject<string>();
var temporary = temporaryModel.NewValue.ToObject<bool>();
var inviterId = inviterIdModel.NewValue.ToObject<ulong>();
var channelId = channelIdModel.NewValue.ToObject<ulong>();
var uses = usesModel.NewValue.ToObject<int>();
var maxUses = maxUsesModel.NewValue.ToObject<int>();
var maxAge = maxAgeModel.NewValue.ToObject<int>(discord.ApiClient.Serializer);
var code = codeModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);
var temporary = temporaryModel.NewValue.ToObject<bool>(discord.ApiClient.Serializer);
var inviterId = inviterIdModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var channelId = channelIdModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var uses = usesModel.NewValue.ToObject<int>(discord.ApiClient.Serializer);
var maxUses = maxUsesModel.NewValue.ToObject<int>(discord.ApiClient.Serializer);

var inviterInfo = log.Users.FirstOrDefault(x => x.Id == inviterId);
var inviter = RestUser.Create(discord, inviterInfo);


+ 7
- 7
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteDeleteAuditLogData.cs View File

@@ -30,13 +30,13 @@ namespace Discord.Rest
var usesModel = changes.FirstOrDefault(x => x.ChangedProperty == "uses");
var maxUsesModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_uses");

var maxAge = maxAgeModel.OldValue.ToObject<int>();
var code = codeModel.OldValue.ToObject<string>();
var temporary = temporaryModel.OldValue.ToObject<bool>();
var inviterId = inviterIdModel.OldValue.ToObject<ulong>();
var channelId = channelIdModel.OldValue.ToObject<ulong>();
var uses = usesModel.OldValue.ToObject<int>();
var maxUses = maxUsesModel.OldValue.ToObject<int>();
var maxAge = maxAgeModel.OldValue.ToObject<int>(discord.ApiClient.Serializer);
var code = codeModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var temporary = temporaryModel.OldValue.ToObject<bool>(discord.ApiClient.Serializer);
var inviterId = inviterIdModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var channelId = channelIdModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var uses = usesModel.OldValue.ToObject<int>(discord.ApiClient.Serializer);
var maxUses = maxUsesModel.OldValue.ToObject<int>(discord.ApiClient.Serializer);

var inviterInfo = log.Users.FirstOrDefault(x => x.Id == inviterId);
var inviter = RestUser.Create(discord, inviterInfo);


+ 10
- 10
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/InviteUpdateAuditLogData.cs View File

@@ -23,16 +23,16 @@ namespace Discord.Rest
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var maxUsesModel = changes.FirstOrDefault(x => x.ChangedProperty == "max_uses");

int? oldMaxAge = maxAgeModel?.OldValue?.ToObject<int>(),
newMaxAge = maxAgeModel?.NewValue?.ToObject<int>();
string oldCode = codeModel?.OldValue?.ToObject<string>(),
newCode = codeModel?.NewValue?.ToObject<string>();
bool? oldTemporary = temporaryModel?.OldValue?.ToObject<bool>(),
newTemporary = temporaryModel?.NewValue?.ToObject<bool>();
ulong? oldChannelId = channelIdModel?.OldValue?.ToObject<ulong>(),
newChannelId = channelIdModel?.NewValue?.ToObject<ulong>();
int? oldMaxUses = maxUsesModel?.OldValue?.ToObject<int>(),
newMaxUses = maxUsesModel?.NewValue?.ToObject<int>();
int? oldMaxAge = maxAgeModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newMaxAge = maxAgeModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);
string oldCode = codeModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newCode = codeModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
bool? oldTemporary = temporaryModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newTemporary = temporaryModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
ulong? oldChannelId = channelIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newChannelId = channelIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
int? oldMaxUses = maxUsesModel?.OldValue?.ToObject<int>(discord.ApiClient.Serializer),
newMaxUses = maxUsesModel?.NewValue?.ToObject<int>(discord.ApiClient.Serializer);

var before = new InviteInfo(oldMaxAge, oldCode, oldTemporary, oldChannelId, oldMaxUses);
var after = new InviteInfo(newMaxAge, newCode, newTemporary, newChannelId, newMaxUses);


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

@@ -19,7 +19,7 @@ namespace Discord.Rest
{
var changes = entry.Changes;

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


+ 8
- 8
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs View File

@@ -24,14 +24,14 @@ namespace Discord.Rest
var muteModel = changes.FirstOrDefault(x => x.ChangedProperty == "mute");
var avatarModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash");

string oldNick = nickModel?.OldValue?.ToObject<string>(),
newNick = nickModel?.NewValue?.ToObject<string>();
bool? oldDeaf = deafModel?.OldValue?.ToObject<bool>(),
newDeaf = deafModel?.NewValue?.ToObject<bool>();
bool? oldMute = muteModel?.OldValue?.ToObject<bool>(),
newMute = muteModel?.NewValue?.ToObject<bool>();
string oldAvatar = avatarModel?.OldValue?.ToObject<string>(),
newAvatar = avatarModel?.NewValue?.ToObject<string>();
string oldNick = nickModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newNick = nickModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
bool? oldDeaf = deafModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newDeaf = deafModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? oldMute = muteModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newMute = muteModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
string oldAvatar = avatarModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newAvatar = avatarModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);

var targetInfo = log.Users.FirstOrDefault(x => x.Id == entry.TargetId);
var user = RestUser.Create(discord, targetInfo);


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

@@ -19,17 +19,15 @@ namespace Discord.Rest
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");

var deny = denyModel.NewValue.ToObject<ulong>();
var allow = allowModel.NewValue.ToObject<ulong>();
var deny = denyModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var allow = allowModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);

var permissions = new OverwritePermissions(allow, deny);

var id = entry.Options.OverwriteTargetId.Value;
var type = entry.Options.OverwriteType;

PermissionTarget target = type == "member" ? PermissionTarget.User : PermissionTarget.Role;

return new OverwriteCreateAuditLogData(new Overwrite(id, target, permissions));
return new OverwriteCreateAuditLogData(new Overwrite(id, type, permissions));
}

public Overwrite Overwrite { get; }


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

@@ -27,14 +27,12 @@ namespace Discord.Rest
var idModel = changes.FirstOrDefault(x => x.ChangedProperty == "id");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");

var deny = denyModel.OldValue.ToObject<ulong>();
var type = typeModel.OldValue.ToObject<string>();
var id = idModel.OldValue.ToObject<ulong>();
var allow = allowModel.OldValue.ToObject<ulong>();
var deny = denyModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var type = typeModel.OldValue.ToObject<PermissionTarget>(discord.ApiClient.Serializer);
var id = idModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var allow = allowModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);

PermissionTarget target = type == "member" ? PermissionTarget.User : PermissionTarget.Role;

return new OverwriteDeleteAuditLogData(new Overwrite(id, target, new OverwritePermissions(allow, deny)));
return new OverwriteDeleteAuditLogData(new Overwrite(id, type, new OverwritePermissions(allow, deny)));
}

public Overwrite Overwrite { get; }


+ 6
- 6
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/OverwriteUpdateAuditLogData.cs View File

@@ -22,17 +22,17 @@ namespace Discord.Rest
var denyModel = changes.FirstOrDefault(x => x.ChangedProperty == "deny");
var allowModel = changes.FirstOrDefault(x => x.ChangedProperty == "allow");

var beforeAllow = allowModel?.OldValue?.ToObject<ulong>();
var afterAllow = allowModel?.NewValue?.ToObject<ulong>();
var beforeDeny = denyModel?.OldValue?.ToObject<ulong>();
var afterDeny = denyModel?.OldValue?.ToObject<ulong>();
var beforeAllow = allowModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var afterAllow = allowModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var beforeDeny = denyModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var afterDeny = denyModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);

var beforePermissions = new OverwritePermissions(beforeAllow ?? 0, beforeDeny ?? 0);
var afterPermissions = new OverwritePermissions(afterAllow ?? 0, afterDeny ?? 0);

PermissionTarget target = entry.Options.OverwriteType == "member" ? PermissionTarget.User : PermissionTarget.Role;
var type = entry.Options.OverwriteType;

return new OverwriteUpdateAuditLogData(beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, target);
return new OverwriteUpdateAuditLogData(beforePermissions, afterPermissions, entry.Options.OverwriteTargetId.Value, type);
}

public OverwritePermissions OldPermissions { get; }


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

@@ -23,11 +23,11 @@ namespace Discord.Rest
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var permissionsModel = changes.FirstOrDefault(x => x.ChangedProperty == "permissions");

uint? colorRaw = colorModel?.NewValue?.ToObject<uint>();
bool? mentionable = mentionableModel?.NewValue?.ToObject<bool>();
bool? hoist = hoistModel?.NewValue?.ToObject<bool>();
string name = nameModel?.NewValue?.ToObject<string>();
ulong? permissionsRaw = permissionsModel?.NewValue?.ToObject<ulong>();
uint? colorRaw = colorModel?.NewValue?.ToObject<uint>(discord.ApiClient.Serializer);
bool? mentionable = mentionableModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? hoist = hoistModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
string name = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
ulong? permissionsRaw = permissionsModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);

Color? color = null;
GuildPermissions? permissions = null;


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

@@ -23,11 +23,11 @@ namespace Discord.Rest
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var permissionsModel = changes.FirstOrDefault(x => x.ChangedProperty == "permissions");

uint? colorRaw = colorModel?.OldValue?.ToObject<uint>();
bool? mentionable = mentionableModel?.OldValue?.ToObject<bool>();
bool? hoist = hoistModel?.OldValue?.ToObject<bool>();
string name = nameModel?.OldValue?.ToObject<string>();
ulong? permissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>();
uint? colorRaw = colorModel?.OldValue?.ToObject<uint>(discord.ApiClient.Serializer);
bool? mentionable = mentionableModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? hoist = hoistModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer);
string name = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
ulong? permissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);

Color? color = null;
GuildPermissions? permissions = null;


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

@@ -24,16 +24,16 @@ namespace Discord.Rest
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var permissionsModel = changes.FirstOrDefault(x => x.ChangedProperty == "permissions");

uint? oldColorRaw = colorModel?.OldValue?.ToObject<uint>(),
newColorRaw = colorModel?.NewValue?.ToObject<uint>();
bool? oldMentionable = mentionableModel?.OldValue?.ToObject<bool>(),
newMentionable = mentionableModel?.NewValue?.ToObject<bool>();
bool? oldHoist = hoistModel?.OldValue?.ToObject<bool>(),
newHoist = hoistModel?.NewValue?.ToObject<bool>();
string oldName = nameModel?.OldValue?.ToObject<string>(),
newName = nameModel?.NewValue?.ToObject<string>();
ulong? oldPermissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>(),
newPermissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>();
uint? oldColorRaw = colorModel?.OldValue?.ToObject<uint>(discord.ApiClient.Serializer),
newColorRaw = colorModel?.NewValue?.ToObject<uint>(discord.ApiClient.Serializer);
bool? oldMentionable = mentionableModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newMentionable = mentionableModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
bool? oldHoist = hoistModel?.OldValue?.ToObject<bool>(discord.ApiClient.Serializer),
newHoist = hoistModel?.NewValue?.ToObject<bool>(discord.ApiClient.Serializer);
string oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer),
newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
ulong? oldPermissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer),
newPermissionsRaw = permissionsModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);

Color? oldColor = null,
newColor = null;


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

@@ -23,9 +23,9 @@ namespace Discord.Rest
var typeModel = changes.FirstOrDefault(x => x.ChangedProperty == "type");
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");

var channelId = channelIdModel.NewValue.ToObject<ulong>();
var type = typeModel.NewValue.ToObject<WebhookType>();
var name = nameModel.NewValue.ToObject<string>();
var channelId = channelIdModel.NewValue.ToObject<ulong>(discord.ApiClient.Serializer);
var type = typeModel.NewValue.ToObject<WebhookType>(discord.ApiClient.Serializer);
var name = nameModel.NewValue.ToObject<string>(discord.ApiClient.Serializer);

var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId);
var webhook = RestWebhook.Create(discord, (IGuild)null, webhookInfo);


+ 4
- 4
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookDeleteAuditLogData.cs View File

@@ -29,10 +29,10 @@ namespace Discord.Rest
var nameModel = changes.FirstOrDefault(x => x.ChangedProperty == "name");
var avatarHashModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash");

var channelId = channelIdModel.OldValue.ToObject<ulong>();
var type = typeModel.OldValue.ToObject<WebhookType>();
var name = nameModel.OldValue.ToObject<string>();
var avatarHash = avatarHashModel?.OldValue?.ToObject<string>();
var channelId = channelIdModel.OldValue.ToObject<ulong>(discord.ApiClient.Serializer);
var type = typeModel.OldValue.ToObject<WebhookType>(discord.ApiClient.Serializer);
var name = nameModel.OldValue.ToObject<string>(discord.ApiClient.Serializer);
var avatarHash = avatarHashModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);

return new WebhookDeleteAuditLogData(entry.TargetId.Value, channelId, type, name, avatarHash);
}


+ 7
- 7
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/WebhookUpdateAuditLogData.cs View File

@@ -26,18 +26,18 @@ namespace Discord.Rest
var channelIdModel = changes.FirstOrDefault(x => x.ChangedProperty == "channel_id");
var avatarHashModel = changes.FirstOrDefault(x => x.ChangedProperty == "avatar_hash");

var oldName = nameModel?.OldValue?.ToObject<string>();
var oldChannelId = channelIdModel?.OldValue?.ToObject<ulong>();
var oldAvatar = avatarHashModel?.OldValue?.ToObject<string>();
var oldName = nameModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
var oldChannelId = channelIdModel?.OldValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var oldAvatar = avatarHashModel?.OldValue?.ToObject<string>(discord.ApiClient.Serializer);
var before = new WebhookInfo(oldName, oldChannelId, oldAvatar);

var newName = nameModel?.NewValue?.ToObject<string>();
var newChannelId = channelIdModel?.NewValue?.ToObject<ulong>();
var newAvatar = avatarHashModel?.NewValue?.ToObject<string>();
var newName = nameModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var newChannelId = channelIdModel?.NewValue?.ToObject<ulong>(discord.ApiClient.Serializer);
var newAvatar = avatarHashModel?.NewValue?.ToObject<string>(discord.ApiClient.Serializer);
var after = new WebhookInfo(newName, newChannelId, newAvatar);

var webhookInfo = log.Webhooks?.FirstOrDefault(x => x.Id == entry.TargetId);
var webhook = RestWebhook.Create(discord, (IGuild)null, webhookInfo);
var webhook = webhookInfo != null ? RestWebhook.Create(discord, (IGuild)null, webhookInfo) : null;

return new WebhookUpdateAuditLogData(webhook, before, after);
}


+ 4
- 1
src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs View File

@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;

using Model = Discord.API.AuditLog;
using EntryModel = Discord.API.AuditLogEntry;
@@ -26,6 +27,8 @@ namespace Discord.Rest
return new RestAuditLogEntry(discord, fullLog, model, user);
}

/// <inheritdoc/>
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
/// <inheritdoc/>
public ActionType Action { get; }
/// <inheritdoc/>


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

@@ -10,7 +10,7 @@ using Model = Discord.API.Channel;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestDMChannel : RestChannel, IDMChannel, IRestPrivateChannel, IRestMessageChannel, IUpdateable
public class RestDMChannel : RestChannel, IDMChannel, IRestPrivateChannel, IRestMessageChannel
{
public RestUser CurrentUser { get; private set; }
public RestUser Recipient { get; private set; }


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

@@ -11,7 +11,7 @@ using Model = Discord.API.Channel;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGroupChannel : RestChannel, IGroupChannel, IRestPrivateChannel, IRestMessageChannel, IRestAudioChannel, IUpdateable
public class RestGroupChannel : RestChannel, IGroupChannel, IRestPrivateChannel, IRestMessageChannel, IRestAudioChannel
{
private string _iconId;
private ImmutableDictionary<ulong, RestGroupUser> _users;


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

@@ -7,7 +7,7 @@ using Model = Discord.API.Channel;

namespace Discord.Rest
{
public class RestGuildChannel : RestChannel, IGuildChannel, IUpdateable
public class RestGuildChannel : RestChannel, IGuildChannel
{
private ImmutableArray<Overwrite> _overwrites;



+ 3
- 3
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs View File

@@ -168,7 +168,7 @@ namespace Discord.Rest
public async Task<IReadOnlyCollection<RestTextChannel>> GetTextChannelsAsync(RequestOptions options = null)
{
var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false);
return channels.Select(x => x as RestTextChannel).Where(x => x != null).ToImmutableArray();
return channels.OfType<RestTextChannel>().ToImmutableArray();
}
public async Task<RestVoiceChannel> GetVoiceChannelAsync(ulong id, RequestOptions options = null)
{
@@ -178,12 +178,12 @@ namespace Discord.Rest
public async Task<IReadOnlyCollection<RestVoiceChannel>> GetVoiceChannelsAsync(RequestOptions options = null)
{
var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false);
return channels.Select(x => x as RestVoiceChannel).Where(x => x != null).ToImmutableArray();
return channels.OfType<RestVoiceChannel>().ToImmutableArray();
}
public async Task<IReadOnlyCollection<RestCategoryChannel>> GetCategoryChannelsAsync(RequestOptions options = null)
{
var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false);
return channels.Select(x => x as RestCategoryChannel).Where(x => x != null).ToImmutableArray();
return channels.OfType<RestCategoryChannel>().ToImmutableArray();
}

public async Task<RestVoiceChannel> GetAFKChannelAsync(RequestOptions options = null)


+ 2
- 2
src/Discord.Net.Rest/Entities/Guilds/RestUserGuild.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Model = Discord.API.UserGuild;
@@ -6,7 +6,7 @@ using Model = Discord.API.UserGuild;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestUserGuild : RestEntity<ulong>, ISnowflakeEntity, IUserGuild
public class RestUserGuild : RestEntity<ulong>, IUserGuild
{
private string _iconId;


+ 2
- 2
src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
@@ -9,7 +9,7 @@ using Model = Discord.API.GuildMember;
namespace Discord.Rest
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestGuildUser : RestUser, IGuildUser, IUpdateable
public class RestGuildUser : RestUser, IGuildUser
{
private long? _joinedAtTicks;
private ImmutableArray<ulong> _roleIds;


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

@@ -131,14 +131,14 @@ namespace Discord.Net.Rest
return new RestResponse(response.StatusCode, headers, stream);
}

private static readonly HttpMethod _patch = new HttpMethod("PATCH");
private static readonly HttpMethod Patch = new HttpMethod("PATCH");
private HttpMethod GetMethod(string method)
{
switch (method)
{
case "DELETE": return HttpMethod.Delete;
case "GET": return HttpMethod.Get;
case "PATCH": return _patch;
case "PATCH": return Patch;
case "POST": return HttpMethod.Post;
case "PUT": return HttpMethod.Put;
default: throw new ArgumentOutOfRangeException(nameof(method), $"Unknown HttpMethod: {method}");


+ 7
- 7
src/Discord.Net.Rest/Net/Queue/ClientBucket.cs View File

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

namespace Discord.Net.Queue
{
@@ -9,8 +9,8 @@ namespace Discord.Net.Queue
}
internal struct ClientBucket
{
private static readonly ImmutableDictionary<ClientBucketType, ClientBucket> _defsByType;
private static readonly ImmutableDictionary<string, ClientBucket> _defsById;
private static readonly ImmutableDictionary<ClientBucketType, ClientBucket> DefsByType;
private static readonly ImmutableDictionary<string, ClientBucket> DefsById;

static ClientBucket()
{
@@ -23,16 +23,16 @@ namespace Discord.Net.Queue
var builder = ImmutableDictionary.CreateBuilder<ClientBucketType, ClientBucket>();
foreach (var bucket in buckets)
builder.Add(bucket.Type, bucket);
_defsByType = builder.ToImmutable();
DefsByType = builder.ToImmutable();

var builder2 = ImmutableDictionary.CreateBuilder<string, ClientBucket>();
foreach (var bucket in buckets)
builder2.Add(bucket.Id, bucket);
_defsById = builder2.ToImmutable();
DefsById = builder2.ToImmutable();
}

public static ClientBucket Get(ClientBucketType type) => _defsByType[type];
public static ClientBucket Get(string id) => _defsById[id];
public static ClientBucket Get(ClientBucketType type) => DefsByType[type];
public static ClientBucket Get(string id) => DefsById[id];
public ClientBucketType Type { get; }
public string Id { get; }


+ 3
- 3
src/Discord.Net.Rest/Net/Queue/RequestQueue.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
#if DEBUG_LIMITS
using System.Diagnostics;
@@ -16,10 +16,10 @@ namespace Discord.Net.Queue

private readonly ConcurrentDictionary<string, RequestBucket> _buckets;
private readonly SemaphoreSlim _tokenLock;
private readonly CancellationTokenSource _cancelToken; //Dispose token
private CancellationTokenSource _clearToken;
private CancellationToken _parentToken;
private CancellationToken _requestCancelToken; //Parent token + Clear token
private CancellationTokenSource _cancelToken; //Dispose token
private DateTimeOffset _waitUntil;

private Task _cleanupTask;
@@ -115,7 +115,7 @@ namespace Discord.Net.Queue
foreach (var bucket in _buckets.Select(x => x.Value))
{
if ((now - bucket.LastAttemptAt).TotalMinutes > 1.0)
_buckets.TryRemove(bucket.Id, out RequestBucket ignored);
_buckets.TryRemove(bucket.Id, out _);
}
await Task.Delay(60000, _cancelToken.Token); //Runs each minute
}


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

@@ -15,7 +15,7 @@ namespace Discord.Net
internal RateLimitInfo(Dictionary<string, string> headers)
{
IsGlobal = headers.TryGetValue("X-RateLimit-Global", out string temp) &&
bool.TryParse(temp, out var isGlobal) ? isGlobal : false;
bool.TryParse(temp, out var isGlobal) && isGlobal;
Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) &&
int.TryParse(temp, out var limit) ? limit : (int?)null;
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) &&


+ 9
- 9
src/Discord.Net.WebSocket/Audio/AudioClient.cs View File

@@ -16,7 +16,7 @@ using System.Collections.Generic;
namespace Discord.Audio
{
//TODO: Add audio reconnecting
internal partial class AudioClient : IAudioClient, IDisposable
internal partial class AudioClient : IAudioClient
{
internal struct StreamPair
{
@@ -65,7 +65,7 @@ namespace Discord.Audio

ApiClient = new DiscordVoiceAPIClient(guild.Id, Discord.WebSocketProvider, Discord.UdpSocketProvider);
ApiClient.SentGatewayMessage += async opCode => await _audioLogger.DebugAsync($"Sent {opCode}").ConfigureAwait(false);
ApiClient.SentDiscovery += async () => await _audioLogger.DebugAsync($"Sent Discovery").ConfigureAwait(false);
ApiClient.SentDiscovery += async () => await _audioLogger.DebugAsync("Sent Discovery").ConfigureAwait(false);
//ApiClient.SentData += async bytes => await _audioLogger.DebugAsync($"Sent {bytes} Bytes").ConfigureAwait(false);
ApiClient.ReceivedEvent += ProcessMessageAsync;
ApiClient.ReceivedPacket += ProcessPacketAsync;
@@ -131,7 +131,7 @@ namespace Discord.Audio
await keepaliveTask.ConfigureAwait(false);
_keepaliveTask = null;

while (_heartbeatTimes.TryDequeue(out long time)) { }
while (_heartbeatTimes.TryDequeue(out _)) { }
_lastMessageTime = 0;

await ClearInputStreamsAsync().ConfigureAwait(false);
@@ -292,7 +292,7 @@ namespace Discord.Audio
{
if (packet.Length != 70)
{
await _audioLogger.DebugAsync($"Malformed Packet").ConfigureAwait(false);
await _audioLogger.DebugAsync("Malformed Packet").ConfigureAwait(false);
return;
}
string ip;
@@ -304,7 +304,7 @@ namespace Discord.Audio
}
catch (Exception ex)
{
await _audioLogger.DebugAsync($"Malformed Packet", ex).ConfigureAwait(false);
await _audioLogger.DebugAsync("Malformed Packet", ex).ConfigureAwait(false);
return;
}
@@ -331,7 +331,7 @@ namespace Discord.Audio
{
if (pair.Key == value)
{
int latency = (int)(Environment.TickCount - pair.Value);
int latency = Environment.TickCount - pair.Value;
int before = UdpLatency;
UdpLatency = latency;

@@ -344,7 +344,7 @@ namespace Discord.Audio
{
if (!RTPReadStream.TryReadSsrc(packet, 0, out var ssrc))
{
await _audioLogger.DebugAsync($"Malformed Frame").ConfigureAwait(false);
await _audioLogger.DebugAsync("Malformed Frame").ConfigureAwait(false);
return;
}
if (!_ssrcMap.TryGetValue(ssrc, out var userId))
@@ -363,7 +363,7 @@ namespace Discord.Audio
}
catch (Exception ex)
{
await _audioLogger.DebugAsync($"Malformed Frame", ex).ConfigureAwait(false);
await _audioLogger.DebugAsync("Malformed Frame", ex).ConfigureAwait(false);
return;
}
//await _audioLogger.DebugAsync($"Received {packet.Length} bytes from user {userId}").ConfigureAwait(false);
@@ -372,7 +372,7 @@ namespace Discord.Audio
}
catch (Exception ex)
{
await _audioLogger.WarningAsync($"Failed to process UDP packet", ex).ConfigureAwait(false);
await _audioLogger.WarningAsync("Failed to process UDP packet", ex).ConfigureAwait(false);
return;
}
}


+ 5
- 5
src/Discord.Net.WebSocket/Audio/Streams/BufferedWriteStream.cs View File

@@ -116,7 +116,7 @@ namespace Discord.Audio.Streams
timestamp += OpusEncoder.FrameSamplesPerChannel;
}
#if DEBUG
var _ = _logger?.DebugAsync($"Buffer underrun");
var _ = _logger?.DebugAsync("Buffer underrun");
#endif
}
}
@@ -140,7 +140,7 @@ namespace Discord.Audio.Streams
if (!_bufferPool.TryDequeue(out byte[] buffer))
{
#if DEBUG
var _ = _logger?.DebugAsync($"Buffer overflow"); //Should never happen because of the queueLock
var _ = _logger?.DebugAsync("Buffer overflow"); //Should never happen because of the queueLock
#endif
return;
}
@@ -149,7 +149,7 @@ namespace Discord.Audio.Streams
if (!_isPreloaded && _queuedFrames.Count == _queueLength)
{
#if DEBUG
var _ = _logger?.DebugAsync($"Preloaded");
var _ = _logger?.DebugAsync("Preloaded");
#endif
_isPreloaded = true;
}
@@ -169,8 +169,8 @@ namespace Discord.Audio.Streams
{
do
cancelToken.ThrowIfCancellationRequested();
while (_queuedFrames.TryDequeue(out Frame ignored));
while (_queuedFrames.TryDequeue(out _));
return Task.Delay(0);
}
}
}
}

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

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@@ -72,7 +72,7 @@ namespace Discord.WebSocket
switch (channel)
{
case SocketDMChannel dmChannel:
_dmChannels.TryRemove(dmChannel.Recipient.Id, out var ignored);
_dmChannels.TryRemove(dmChannel.Recipient.Id, out _);
break;
case SocketGroupChannel groupChannel:
_groupChannels.TryRemove(id);


+ 4
- 4
src/Discord.Net.WebSocket/DiscordShardedClient.cs View File

@@ -13,11 +13,11 @@ namespace Discord.WebSocket
{
private readonly DiscordSocketConfig _baseConfig;
private readonly SemaphoreSlim _connectionGroupLock;
private readonly Dictionary<int, int> _shardIdsToIndex;
private readonly bool _automaticShards;
private int[] _shardIds;
private Dictionary<int, int> _shardIdsToIndex;
private DiscordSocketClient[] _shards;
private int _totalShards;
private bool _automaticShards;
/// <summary> Gets the estimated round-trip latency, in milliseconds, to the gateway server. </summary>
public override int Latency { get => GetLatency(); protected set { } }
@@ -25,8 +25,8 @@ namespace Discord.WebSocket
public override IActivity Activity { get => _shards[0].Activity; protected set { } }

internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient;
public override IReadOnlyCollection<SocketGuild> Guilds => GetGuilds().ToReadOnlyCollection(() => GetGuildCount());
public override IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels => GetPrivateChannels().ToReadOnlyCollection(() => GetPrivateChannelCount());
public override IReadOnlyCollection<SocketGuild> Guilds => GetGuilds().ToReadOnlyCollection(GetGuildCount);
public override IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels => GetPrivateChannels().ToReadOnlyCollection(GetPrivateChannelCount);
public IReadOnlyCollection<DiscordSocketClient> Shards => _shards;
public override IReadOnlyCollection<RestVoiceRegion> VoiceRegions => _shards[0].VoiceRegions;



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

@@ -26,9 +26,9 @@ namespace Discord.API
public event Func<Exception, Task> Disconnected { add { _disconnectedEvent.Add(value); } remove { _disconnectedEvent.Remove(value); } }
private readonly AsyncEvent<Func<Exception, Task>> _disconnectedEvent = new AsyncEvent<Func<Exception, Task>>();

private readonly bool _isExplicitUrl;
private CancellationTokenSource _connectCancelToken;
private string _gatewayUrl;
private bool _isExplicitUrl;

//Store our decompression streams for zlib shared state
private MemoryStream _compressed;


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

@@ -63,9 +63,9 @@ namespace Discord.WebSocket
public override IReadOnlyCollection<SocketGuild> Guilds => State.Guilds;
public override IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels => State.PrivateChannels;
public IReadOnlyCollection<SocketDMChannel> DMChannels
=> State.PrivateChannels.Select(x => x as SocketDMChannel).Where(x => x != null).ToImmutableArray();
=> State.PrivateChannels.OfType<SocketDMChannel>().ToImmutableArray();
public IReadOnlyCollection<SocketGroupChannel> GroupChannels
=> State.PrivateChannels.Select(x => x as SocketGroupChannel).Where(x => x != null).ToImmutableArray();
=> State.PrivateChannels.OfType<SocketGroupChannel>().ToImmutableArray();
public override IReadOnlyCollection<RestVoiceRegion> VoiceRegions => _voiceRegions.ToReadOnlyCollection();

/// <summary> Creates a new REST/WebSocket discord client. </summary>
@@ -207,7 +207,7 @@ namespace Discord.WebSocket
await heartbeatTask.ConfigureAwait(false);
_heartbeatTask = null;

while (_heartbeatTimes.TryDequeue(out long time)) { }
while (_heartbeatTimes.TryDequeue(out _)) { }
_lastMessageTime = 0;

await _gatewayLogger.DebugAsync("Waiting for guild downloader").ConfigureAwait(false);
@@ -218,7 +218,7 @@ namespace Discord.WebSocket

//Clear large guild queue
await _gatewayLogger.DebugAsync("Clearing large guild queue").ConfigureAwait(false);
while (_largeGuilds.TryDequeue(out ulong guildId)) { }
while (_largeGuilds.TryDequeue(out _)) { }

//Raise virtual GUILD_UNAVAILABLEs
await _gatewayLogger.DebugAsync("Raising virtual GuildUnavailables").ConfigureAwait(false);
@@ -351,7 +351,7 @@ namespace Discord.WebSocket

var gameModel = new GameModel();
// Discord only accepts rich presence over RPC, don't even bother building a payload
if (Activity is RichGame game)
if (Activity is RichGame)
throw new NotSupportedException("Outgoing Rich Presences are not supported");

if (Activity != null)
@@ -508,7 +508,7 @@ namespace Discord.WebSocket
{
type = "GUILD_AVAILABLE";
_lastGuildAvailableTime = Environment.TickCount;
await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_AVAILABLE)").ConfigureAwait(false);
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_AVAILABLE)").ConfigureAwait(false);

var guild = State.GetGuild(data.Id);
if (guild != null)
@@ -533,7 +533,7 @@ namespace Discord.WebSocket
}
else
{
await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_CREATE)").ConfigureAwait(false);
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_CREATE)").ConfigureAwait(false);

var guild = AddGuild(data, State);
if (guild != null)
@@ -614,7 +614,7 @@ namespace Discord.WebSocket
if (data.Unavailable == true)
{
type = "GUILD_UNAVAILABLE";
await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_UNAVAILABLE)").ConfigureAwait(false);
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_UNAVAILABLE)").ConfigureAwait(false);

var guild = State.GetGuild(data.Id);
if (guild != null)
@@ -630,7 +630,7 @@ namespace Discord.WebSocket
}
else
{
await _gatewayLogger.DebugAsync($"Received Dispatch (GUILD_DELETE)").ConfigureAwait(false);
await _gatewayLogger.DebugAsync("Received Dispatch (GUILD_DELETE)").ConfigureAwait(false);

var guild = RemoveGuild(data.Id);
if (guild != null)
@@ -1630,7 +1630,7 @@ namespace Discord.WebSocket
var guild = State.RemoveGuild(id);
if (guild != null)
{
foreach (var channel in guild.Channels)
foreach (var _ in guild.Channels)
State.RemoveChannel(id);
foreach (var user in guild.Users)
user.GlobalUser.RemoveRef(this);
@@ -1683,7 +1683,7 @@ namespace Discord.WebSocket
if (eventHandler.HasSubscribers)
{
if (HandlerTimeout.HasValue)
await TimeoutWrap(name, () => eventHandler.InvokeAsync()).ConfigureAwait(false);
await TimeoutWrap(name, eventHandler.InvokeAsync).ConfigureAwait(false);
else
await eventHandler.InvokeAsync().ConfigureAwait(false);
}


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

@@ -39,8 +39,8 @@ namespace Discord.Audio
private readonly JsonSerializer _serializer;
private readonly SemaphoreSlim _connectionLock;
private readonly IUdpSocket _udp;
private CancellationTokenSource _connectCancelToken;
private IUdpSocket _udp;
private bool _isDisposed;
private ulong _nextKeepalive;

@@ -188,7 +188,7 @@ namespace Discord.Audio

ConnectionState = ConnectionState.Connected;
}
catch (Exception)
catch
{
await DisconnectInternalAsync().ConfigureAwait(false);
throw;


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

@@ -97,7 +97,7 @@ namespace Discord.WebSocket
if (id == Recipient.Id)
return Recipient;
else if (id == Discord.CurrentUser.Id)
return Discord.CurrentUser as SocketSelfUser;
return Discord.CurrentUser;
else
return null;
}


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

@@ -18,10 +18,10 @@ namespace Discord.WebSocket
public class SocketGroupChannel : SocketChannel, IGroupChannel, ISocketPrivateChannel, ISocketMessageChannel, ISocketAudioChannel
{
private readonly MessageCache _messages;
private readonly ConcurrentDictionary<ulong, SocketVoiceState> _voiceStates;

private string _iconId;
private ConcurrentDictionary<ulong, SocketGroupUser> _users;
private ConcurrentDictionary<ulong, SocketVoiceState> _voiceStates;

public string Name { get; private set; }

@@ -129,7 +129,7 @@ namespace Discord.WebSocket
internal SocketGroupUser GetOrAddUser(UserModel model)
{
if (_users.TryGetValue(model.Id, out SocketGroupUser user))
return user as SocketGroupUser;
return user;
else
{
var privateUser = SocketGroupUser.Create(this, Discord.State, model);
@@ -143,7 +143,7 @@ namespace Discord.WebSocket
if (_users.TryRemove(id, out SocketGroupUser user))
{
user.GlobalUser.RemoveRef(Discord);
return user as SocketGroupUser;
return user;
}
return null;
}


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

@@ -43,7 +43,7 @@ namespace Discord.WebSocket
public Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null)
=> ChannelHelper.ModifyAsync(this, Discord, func, options);

public async Task<IAudioClient> ConnectAsync(bool selfDeaf, bool selfMute, bool external)
public async Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false)
{
return await Guild.ConnectAudioAsync(Id, selfDeaf, selfMute, external).ConfigureAwait(false);
}


+ 5
- 5
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -91,11 +91,11 @@ namespace Discord.WebSocket
}
}
public IReadOnlyCollection<SocketTextChannel> TextChannels
=> Channels.Select(x => x as SocketTextChannel).Where(x => x != null).ToImmutableArray();
=> Channels.OfType<SocketTextChannel>().ToImmutableArray();
public IReadOnlyCollection<SocketVoiceChannel> VoiceChannels
=> Channels.Select(x => x as SocketVoiceChannel).Where(x => x != null).ToImmutableArray();
=> Channels.OfType<SocketVoiceChannel>().ToImmutableArray();
public IReadOnlyCollection<SocketCategoryChannel> CategoryChannels
=> Channels.Select(x => x as SocketCategoryChannel).Where(x => x != null).ToImmutableArray();
=> Channels.OfType<SocketCategoryChannel>().ToImmutableArray();
public SocketGuildUser CurrentUser => _members.TryGetValue(Discord.CurrentUser.Id, out SocketGuildUser member) ? member : null;
public SocketRole EveryoneRole => GetRole(Id);
public IReadOnlyCollection<SocketGuildChannel> Channels
@@ -563,7 +563,7 @@ namespace Discord.WebSocket

await Discord.ApiClient.SendVoiceStateUpdateAsync(Id, channelId, selfDeaf, selfMute).ConfigureAwait(false);
}
catch (Exception)
catch
{
await DisconnectAudioInternalAsync().ConfigureAwait(false);
throw;
@@ -580,7 +580,7 @@ namespace Discord.WebSocket
throw new TimeoutException();
return await promise.Task.ConfigureAwait(false);
}
catch (Exception)
catch
{
await DisconnectAudioAsync().ConfigureAwait(false);
throw;


+ 2
- 2
src/Discord.Net.WebSocket/Entities/Messages/MessageCache.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -28,7 +28,7 @@ namespace Discord.WebSocket
_orderedMessages.Enqueue(message.Id);

while (_orderedMessages.Count > _size && _orderedMessages.TryDequeue(out ulong msgId))
_messages.TryRemove(msgId, out SocketMessage msg);
_messages.TryRemove(msgId, out _);
}
}



+ 1
- 1
src/Discord.Net.WebSocket/Entities/Messages/SocketUserMessage.cs View File

@@ -12,12 +12,12 @@ namespace Discord.WebSocket
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class SocketUserMessage : SocketMessage, IUserMessage
{
private readonly List<SocketReaction> _reactions = new List<SocketReaction>();
private bool _isMentioningEveryone, _isTTS, _isPinned;
private long? _editedTimestampTicks;
private ImmutableArray<Attachment> _attachments;
private ImmutableArray<Embed> _embeds;
private ImmutableArray<ITag> _tags;
private List<SocketReaction> _reactions = new List<SocketReaction>();
public override bool IsTTS => _isTTS;
public override bool IsPinned => _isPinned;


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

@@ -22,8 +22,8 @@ namespace Discord.Net.WebSockets

private readonly SemaphoreSlim _lock;
private readonly Dictionary<string, string> _headers;
private readonly IWebProxy _proxy;
private ClientWebSocket _client;
private IWebProxy _proxy;
private Task _task;
private CancellationTokenSource _cancelTokenSource;
private CancellationToken _cancelToken, _parentToken;


+ 124
- 0
test/Discord.Net.Tests/Tests.TokenUtils.cs View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
public class TokenUtilsTests
{
/// <summary>
/// Tests the usage of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
/// to see that when a null, empty or whitespace-only string is passed as the token,
/// it will throw an ArgumentNullException.
/// </summary>
[Theory]
[InlineData(null)]
[InlineData("")] // string.Empty isn't a constant type
[InlineData(" ")]
[InlineData(" ")]
[InlineData("\t")]
public void TestNullOrWhitespaceToken(string token)
{
// an ArgumentNullException should be thrown, regardless of the TokenType
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Bearer, token));
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Bot, token));
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Webhook, token));
}
/// <summary>
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
/// to see that valid Webhook tokens do not throw Exceptions.
/// </summary>
/// <param name="token"></param>
[Theory]
[InlineData("123123123")]
// bot token
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
// bearer token taken from discord docs
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
// client secret
[InlineData("937it3ow87i4ery69876wqire")]
public void TestWebhookTokenDoesNotThrowExceptions(string token)
{
TokenUtils.ValidateToken(TokenType.Webhook, token);
}

// No tests for invalid webhook token behavior, because there is nothing there yet.

/// <summary>
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
/// to see that valid Webhook tokens do not throw Exceptions.
/// </summary>
/// <param name="token"></param>
[Theory]
[InlineData("123123123")]
// bot token
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
// bearer token taken from discord docs
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
// client secret
[InlineData("937it3ow87i4ery69876wqire")]
public void TestBearerTokenDoesNotThrowExceptions(string token)
{
TokenUtils.ValidateToken(TokenType.Bearer, token);
}

// No tests for invalid bearer token behavior, because there is nothing there yet.

/// <summary>
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
/// to see that valid Bot tokens do not throw Exceptions.
/// Valid Bot tokens can be strings of length 59 or above.
/// </summary>
[Theory]
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
[InlineData("This appears to be completely invalid, however the current validation rules are not very strict.")]
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWss")]
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWsMTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
public void TestBotTokenDoesNotThrowExceptions(string token)
{
// This example token is pulled from the Discord Docs
// https://discordapp.com/developers/docs/reference#authentication-example-bot-token-authorization-header
// should not throw any exception
TokenUtils.ValidateToken(TokenType.Bot, token);
}

/// <summary>
/// Tests the usage of <see cref="TokenUtils.ValidateToken(TokenType, string)"/> with
/// a Bot token that is invalid.
/// </summary>
[Theory]
[InlineData("This is invalid")]
// missing a single character from the end
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKW")]
// bearer token
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
// client secret
[InlineData("937it3ow87i4ery69876wqire")]
public void TestBotTokenInvalidThrowsArgumentException(string token)
{
Assert.Throws<ArgumentException>(() => TokenUtils.ValidateToken(TokenType.Bot, token));
}

/// <summary>
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
/// to see that an <see cref="ArgumentException"/> is thrown when an invalid
/// <see cref="TokenType"/> is supplied as a parameter.
/// </summary>
/// <remarks>
/// The <see cref="TokenType.User"/> type is treated as an invalid <see cref="TokenType"/>.
/// </remarks>
[Theory]
// TokenType.User
[InlineData(0)]
// out of range TokenType
[InlineData(4)]
[InlineData(7)]
public void TestUnrecognizedTokenType(int type)
{
Assert.Throws<ArgumentException>(() =>
TokenUtils.ValidateToken((TokenType)type, "MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs"));
}
}
}

Loading…
Cancel
Save