Browse Source

Merge pull request #1 from RogueException/dev

Pulled from origin
pull/1095/head
ComputerMaster1st GitHub 7 years ago
parent
commit
75c5f4fd91
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 228 additions and 110 deletions
  1. +1
    -6
      README.md
  2. +1
    -1
      src/Discord.Net.Commands/Builders/ModuleBuilder.cs
  3. +13
    -11
      src/Discord.Net.Commands/Builders/ParameterBuilder.cs
  4. +12
    -2
      src/Discord.Net.Commands/CommandService.cs
  5. +2
    -2
      src/Discord.Net.Commands/Extensions/MessageExtensions.cs
  6. +4
    -1
      src/Discord.Net.Commands/Results/ParseResult.cs
  7. +4
    -1
      src/Discord.Net.Commands/Results/PreconditionGroupResult.cs
  8. +4
    -1
      src/Discord.Net.Commands/Results/PreconditionResult.cs
  9. +4
    -1
      src/Discord.Net.Commands/Results/SearchResult.cs
  10. +2
    -0
      src/Discord.Net.Commands/Results/TypeReaderResult.cs
  11. +2
    -2
      src/Discord.Net.Core/Entities/AuditLogs/IAuditLogEntry.cs
  12. +0
    -0
      src/Discord.Net.Core/Entities/Channels/ChannelType.cs
  13. +10
    -1
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  14. +3
    -3
      src/Discord.Net.Core/Entities/Invites/IInvite.cs
  15. +4
    -4
      src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs
  16. +2
    -1
      src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs
  17. +9
    -2
      src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs
  18. +1
    -0
      src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs
  19. +9
    -2
      src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
  20. +11
    -0
      src/Discord.Net.Core/Extensions/MessageExtensions.cs
  21. +1
    -1
      src/Discord.Net.Core/IDiscordClient.cs
  22. +1
    -1
      src/Discord.Net.Rest/API/Common/Invite.cs
  23. +2
    -2
      src/Discord.Net.Rest/API/Common/InviteChannel.cs
  24. +5
    -5
      src/Discord.Net.Rest/API/Common/InviteMetadata.cs
  25. +0
    -7
      src/Discord.Net.Rest/API/Rest/GetInviteParams.cs
  26. +1
    -1
      src/Discord.Net.Rest/BaseDiscordClient.cs
  27. +2
    -6
      src/Discord.Net.Rest/ClientHelper.cs
  28. +10
    -4
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  29. +4
    -4
      src/Discord.Net.Rest/DiscordRestClient.cs
  30. +18
    -0
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs
  31. +23
    -9
      src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberUpdateAuditLogData.cs
  32. +4
    -1
      src/Discord.Net.Rest/Entities/AuditLogs/RestAuditLogEntry.cs
  33. +6
    -0
      src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
  34. +13
    -1
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  35. +8
    -10
      src/Discord.Net.Rest/Entities/Invites/RestInvite.cs
  36. +8
    -8
      src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs
  37. +4
    -4
      src/Discord.Net.WebSocket/BaseSocketClient.cs
  38. +2
    -2
      src/Discord.Net.WebSocket/DiscordShardedClient.cs
  39. +5
    -2
      src/Discord.Net.WebSocket/DiscordSocketClient.cs
  40. +13
    -1
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.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: The individual components may also be installed from NuGet:
- [Discord.Net.Commands](https://www.nuget.org/packages/Discord.Net.Commands/) - [Discord.Net.Commands](https://www.nuget.org/packages/Discord.Net.Commands/)
- [Discord.Net.Rest](https://www.nuget.org/packages/Discord.Net.Rest/) - [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.WebSocket](https://www.nuget.org/packages/Discord.Net.WebSocket/)
- [Discord.Net.Webhook](https://www.nuget.org/packages/Discord.Net.Webhook/) - [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) ### Unstable (MyGet)
Nightly builds are available through our MyGet feed (`https://www.myget.org/F/discord-net/api/v3/index.json`). 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 ## Known Issues


### WebSockets (Win7 and earlier) ### 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.

+ 1
- 1
src/Discord.Net.Commands/Builders/ModuleBuilder.cs View File

@@ -120,7 +120,7 @@ namespace Discord.Commands.Builders
if (Name == null) if (Name == null)
Name = _aliases[0]; Name = _aliases[0];


if (TypeInfo != null)
if (TypeInfo != null && !TypeInfo.IsAbstract)
{ {
var moduleInstance = ReflectionUtils.CreateObject<IModuleBase>(TypeInfo, service, services); var moduleInstance = ReflectionUtils.CreateObject<IModuleBase>(TypeInfo, service, services);
moduleInstance.OnModuleBuilding(service, this); moduleInstance.OnModuleBuilding(service, this);


+ 13
- 11
src/Discord.Net.Commands/Builders/ParameterBuilder.cs View File

@@ -45,14 +45,7 @@ namespace Discord.Commands.Builders


internal void SetType(Type type) internal void SetType(Type type)
{ {
var readers = Command.Module.Service.GetTypeReaders(type);
if (readers != null)
TypeReader = readers.FirstOrDefault().Value;
else
TypeReader = Command.Module.Service.GetDefaultTypeReader(type);

if (TypeReader == null)
throw new InvalidOperationException($"{type} does not have a TypeReader registered for it. Parameter: {Name} in {Command.PrimaryAlias}");
TypeReader = GetReader(type);


if (type.GetTypeInfo().IsValueType) if (type.GetTypeInfo().IsValueType)
DefaultValue = Activator.CreateInstance(type); DefaultValue = Activator.CreateInstance(type);
@@ -60,7 +53,16 @@ namespace Discord.Commands.Builders
type = ParameterType.GetElementType(); type = ParameterType.GetElementType();
ParameterType = type; ParameterType = type;
} }

private TypeReader GetReader(Type type)
{
var readers = Command.Module.Service.GetTypeReaders(type);
if (readers != null)
return readers.FirstOrDefault().Value;
else
return Command.Module.Service.GetDefaultTypeReader(type);
}

public ParameterBuilder WithSummary(string summary) public ParameterBuilder WithSummary(string summary)
{ {
Summary = summary; Summary = summary;
@@ -100,10 +102,10 @@ namespace Discord.Commands.Builders


internal ParameterInfo Build(CommandInfo info) internal ParameterInfo Build(CommandInfo info)
{ {
if (TypeReader == null)
if ((TypeReader ?? (TypeReader = GetReader(ParameterType))) == null)
throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified"); throw new InvalidOperationException($"No type reader found for type {ParameterType.Name}, one must be specified");


return new ParameterInfo(this, info, Command.Module.Service); return new ParameterInfo(this, info, Command.Module.Service);
} }
} }
}
}

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

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@@ -262,7 +262,7 @@ namespace Discord.Commands
/// <param name="replaceDefault">If <paramref name="reader"/> should replace the default <see cref="TypeReader"/> for <paramref name="type"/> if one exists.</param> /// <param name="replaceDefault">If <paramref name="reader"/> should replace the default <see cref="TypeReader"/> for <paramref name="type"/> if one exists.</param>
public void AddTypeReader(Type type, TypeReader reader, bool replaceDefault) public void AddTypeReader(Type type, TypeReader reader, bool replaceDefault)
{ {
if (replaceDefault && _defaultTypeReaders.ContainsKey(type))
if (replaceDefault && HasDefaultTypeReader(type))
{ {
_defaultTypeReaders.AddOrUpdate(type, reader, (k, v) => reader); _defaultTypeReaders.AddOrUpdate(type, reader, (k, v) => reader);
if (type.GetTypeInfo().IsValueType) if (type.GetTypeInfo().IsValueType)
@@ -281,6 +281,16 @@ namespace Discord.Commands
AddNullableTypeReader(type, reader); AddNullableTypeReader(type, reader);
} }
} }
internal bool HasDefaultTypeReader(Type type)
{
if (_defaultTypeReaders.ContainsKey(type))
return true;

var typeInfo = type.GetTypeInfo();
if (typeInfo.IsEnum)
return true;
return _entityTypeReaders.Any(x => type == x.Item1 || typeInfo.ImplementedInterfaces.Contains(x.Item2));
}
internal void AddNullableTypeReader(Type valueType, TypeReader valueTypeReader) internal void AddNullableTypeReader(Type valueType, TypeReader valueTypeReader)
{ {
var readers = _typeReaders.GetOrAdd(typeof(Nullable<>).MakeGenericType(valueType), x => new ConcurrentDictionary<Type, TypeReader>()); var readers = _typeReaders.GetOrAdd(typeof(Nullable<>).MakeGenericType(valueType), x => new ConcurrentDictionary<Type, TypeReader>());


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

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


namespace Discord.Commands namespace Discord.Commands
{ {
@@ -43,4 +43,4 @@ namespace Discord.Commands
return false; return false;
} }
} }
}
}

+ 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; using System.Diagnostics;


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


public static ParseResult FromError(CommandError error, string reason) public static ParseResult FromError(CommandError error, string reason)
=> new ParseResult(null, null, error, reason); => new ParseResult(null, null, error, reason);
public static ParseResult FromError(Exception ex)
=> FromError(CommandError.Exception, ex.Message);
public static ParseResult FromError(IResult result) public static ParseResult FromError(IResult result)
=> new ParseResult(null, null, result.Error, result.ErrorReason); => 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; using System.Diagnostics;


namespace Discord.Commands namespace Discord.Commands
@@ -18,6 +19,8 @@ namespace Discord.Commands
=> new PreconditionGroupResult(null, null, null); => new PreconditionGroupResult(null, null, null);
public static PreconditionGroupResult FromError(string reason, ICollection<PreconditionResult> preconditions) public static PreconditionGroupResult FromError(string reason, ICollection<PreconditionResult> preconditions)
=> new PreconditionGroupResult(CommandError.UnmetPrecondition, reason, 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? public static new PreconditionGroupResult FromError(IResult result) //needed?
=> new PreconditionGroupResult(result.Error, result.ErrorReason, null); => 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 namespace Discord.Commands
{ {
@@ -20,6 +21,8 @@ namespace Discord.Commands
=> new PreconditionResult(null, null); => new PreconditionResult(null, null);
public static PreconditionResult FromError(string reason) public static PreconditionResult FromError(string reason)
=> new PreconditionResult(CommandError.UnmetPrecondition, reason); => new PreconditionResult(CommandError.UnmetPrecondition, reason);
public static PreconditionResult FromError(Exception ex)
=> new PreconditionResult(CommandError.Exception, ex.Message);
public static PreconditionResult FromError(IResult result) public static PreconditionResult FromError(IResult result)
=> new PreconditionResult(result.Error, result.ErrorReason); => 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; using System.Diagnostics;


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




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


src/Discord.Net.Rest/Entities/Channels/ChannelType.cs → src/Discord.Net.Core/Entities/Channels/ChannelType.cs View File


+ 10
- 1
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -120,6 +120,15 @@ namespace Discord


/// <summary> Gets a collection of all invites to this guild. </summary> /// <summary> Gets a collection of all invites to this guild. </summary>
Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null); Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null);
/// <summary>
/// Gets the vanity invite URL of this guild.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// An awaitable <see cref="Task"/> containing the partial metadata of the vanity invite found within
/// this guild.
/// </returns>
Task<IInviteMetadata> GetVanityInviteAsync(RequestOptions options = null);


/// <summary> Gets the role in this guild with the provided id, or null if not found. </summary> /// <summary> Gets the role in this guild with the provided id, or null if not found. </summary>
IRole GetRole(ulong id); IRole GetRole(ulong id);
@@ -140,7 +149,7 @@ namespace Discord
Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null); Task<int> PruneUsersAsync(int days = 30, bool simulate = false, RequestOptions options = null);


/// <summary> Gets the specified number of audit log entries for this guild. </summary> /// <summary> Gets the specified number of audit log entries for this guild. </summary>
Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch,
Task<IReadOnlyCollection<IAuditLogEntry>> GetAuditLogsAsync(int limit = DiscordConfig.MaxAuditLogEntriesPerBatch,
CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);


/// <summary> Gets the webhook in this guild with the provided id, or null if not found. </summary> /// <summary> Gets the webhook in this guild with the provided id, or null if not found. </summary>


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

@@ -1,5 +1,3 @@
using System.Threading.Tasks;

namespace Discord namespace Discord
{ {
public interface IInvite : IEntity<string>, IDeletable public interface IInvite : IEntity<string>, IDeletable
@@ -11,6 +9,8 @@ namespace Discord


/// <summary> Gets the channel this invite is linked to. </summary> /// <summary> Gets the channel this invite is linked to. </summary>
IChannel Channel { get; } IChannel Channel { get; }
/// <summary> Gets the type of the channel this invite is linked to. </summary>
ChannelType ChannelType { get; }
/// <summary> Gets the id of the channel this invite is linked to. </summary> /// <summary> Gets the id of the channel this invite is linked to. </summary>
ulong ChannelId { get; } ulong ChannelId { get; }
/// <summary> Gets the name of the channel this invite is linked to. </summary> /// <summary> Gets the name of the channel this invite is linked to. </summary>
@@ -19,7 +19,7 @@ namespace Discord
/// <summary> Gets the guild this invite is linked to. </summary> /// <summary> Gets the guild this invite is linked to. </summary>
IGuild Guild { get; } IGuild Guild { get; }
/// <summary> Gets the id of the guild this invite is linked to. </summary> /// <summary> Gets the id of the guild this invite is linked to. </summary>
ulong GuildId { get; }
ulong? GuildId { get; }
/// <summary> Gets the name of the guild this invite is linked to. </summary> /// <summary> Gets the name of the guild this invite is linked to. </summary>
string GuildName { get; } string GuildName { get; }
/// <summary> Gets the approximated count of online members in the guild. </summary> /// <summary> Gets the approximated count of online members in the guild. </summary>


+ 4
- 4
src/Discord.Net.Core/Entities/Invites/IInviteMetadata.cs View File

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


namespace Discord namespace Discord
{ {
@@ -15,8 +15,8 @@ namespace Discord
/// <summary> Gets the max amount of times this invite may be used, or null if there is no limit. </summary> /// <summary> Gets the max amount of times this invite may be used, or null if there is no limit. </summary>
int? MaxUses { get; } int? MaxUses { get; }
/// <summary> Gets the amount of times this invite has been used. </summary> /// <summary> Gets the amount of times this invite has been used. </summary>
int Uses { get; }
int? Uses { get; }
/// <summary> Gets when this invite was created. </summary> /// <summary> Gets when this invite was created. </summary>
DateTimeOffset CreatedAt { get; }
DateTimeOffset? CreatedAt { get; }
} }
}
}

+ 2
- 1
src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs View File

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


namespace Discord namespace Discord
{ {
@@ -30,6 +30,7 @@ namespace Discord
DeafenMembers = 0x00_80_00_00, DeafenMembers = 0x00_80_00_00,
MoveMembers = 0x01_00_00_00, MoveMembers = 0x01_00_00_00,
UseVAD = 0x02_00_00_00, UseVAD = 0x02_00_00_00,
PrioritySpeaker = 0x00_00_01_00,


// More General // More General
ManageRoles = 0x10_00_00_00, ManageRoles = 0x10_00_00_00,


+ 9
- 2
src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs View File

@@ -12,7 +12,7 @@ namespace Discord
/// <summary> Gets a ChannelPermissions that grants all permissions for text channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for text channels. </summary>
public static readonly ChannelPermissions Text = new ChannelPermissions(0b01100_0000000_1111111110001_010001); public static readonly ChannelPermissions Text = new ChannelPermissions(0b01100_0000000_1111111110001_010001);
/// <summary> Gets a ChannelPermissions that grants all permissions for voice channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for voice channels. </summary>
public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000010000_010001);
public static readonly ChannelPermissions Voice = new ChannelPermissions(0b00100_1111110_0000000010100_010001);
/// <summary> Gets a ChannelPermissions that grants all permissions for category channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for category channels. </summary>
public static readonly ChannelPermissions Category = new ChannelPermissions(0b01100_1111110_1111111110001_010001); public static readonly ChannelPermissions Category = new ChannelPermissions(0b01100_1111110_1111111110001_010001);
/// <summary> Gets a ChannelPermissions that grants all permissions for direct message channels. </summary> /// <summary> Gets a ChannelPermissions that grants all permissions for direct message channels. </summary>
@@ -78,6 +78,8 @@ namespace Discord
public bool MoveMembers => Permissions.GetValue(RawValue, ChannelPermission.MoveMembers); public bool MoveMembers => Permissions.GetValue(RawValue, ChannelPermission.MoveMembers);
/// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary> /// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary>
public bool UseVAD => Permissions.GetValue(RawValue, ChannelPermission.UseVAD); public bool UseVAD => Permissions.GetValue(RawValue, ChannelPermission.UseVAD);
/// <summary> If True, a user may use priority speaker in a voice channel. </summary>
public bool PrioritySpeaker => Permissions.GetValue(RawValue, ChannelPermission.PrioritySpeaker);


/// <summary> If True, a user may adjust role permissions. This also implictly grants all other permissions. </summary> /// <summary> If True, a user may adjust role permissions. This also implictly grants all other permissions. </summary>
public bool ManageRoles => Permissions.GetValue(RawValue, ChannelPermission.ManageRoles); public bool ManageRoles => Permissions.GetValue(RawValue, ChannelPermission.ManageRoles);
@@ -106,6 +108,7 @@ namespace Discord
bool? deafenMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? moveMembers = null,
bool? useVoiceActivation = null, bool? useVoiceActivation = null,
bool? prioritySpeaker = null,
bool? manageRoles = null, bool? manageRoles = null,
bool? manageWebhooks = null) bool? manageWebhooks = null)
{ {
@@ -129,6 +132,7 @@ namespace Discord
Permissions.SetValue(ref value, deafenMembers, ChannelPermission.DeafenMembers); Permissions.SetValue(ref value, deafenMembers, ChannelPermission.DeafenMembers);
Permissions.SetValue(ref value, moveMembers, ChannelPermission.MoveMembers); Permissions.SetValue(ref value, moveMembers, ChannelPermission.MoveMembers);
Permissions.SetValue(ref value, useVoiceActivation, ChannelPermission.UseVAD); Permissions.SetValue(ref value, useVoiceActivation, ChannelPermission.UseVAD);
Permissions.SetValue(ref value, prioritySpeaker, ChannelPermission.PrioritySpeaker);
Permissions.SetValue(ref value, manageRoles, ChannelPermission.ManageRoles); Permissions.SetValue(ref value, manageRoles, ChannelPermission.ManageRoles);
Permissions.SetValue(ref value, manageWebhooks, ChannelPermission.ManageWebhooks); Permissions.SetValue(ref value, manageWebhooks, ChannelPermission.ManageWebhooks);


@@ -155,11 +159,12 @@ namespace Discord
bool deafenMembers = false, bool deafenMembers = false,
bool moveMembers = false, bool moveMembers = false,
bool useVoiceActivation = false, bool useVoiceActivation = false,
bool prioritySpeaker = false,
bool manageRoles = false, bool manageRoles = false,
bool manageWebhooks = false) bool manageWebhooks = false)
: this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, : this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages,
embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect,
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, manageRoles, manageWebhooks)
speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, manageRoles, manageWebhooks)
{ } { }


/// <summary> Creates a new ChannelPermissions from this one, changing the provided non-null permissions. </summary> /// <summary> Creates a new ChannelPermissions from this one, changing the provided non-null permissions. </summary>
@@ -182,6 +187,7 @@ namespace Discord
bool? deafenMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? moveMembers = null,
bool? useVoiceActivation = null, bool? useVoiceActivation = null,
bool? prioritySpeaker = null,
bool? manageRoles = null, bool? manageRoles = null,
bool? manageWebhooks = null) bool? manageWebhooks = null)
=> new ChannelPermissions(RawValue, => new ChannelPermissions(RawValue,
@@ -203,6 +209,7 @@ namespace Discord
deafenMembers, deafenMembers,
moveMembers, moveMembers,
useVoiceActivation, useVoiceActivation,
prioritySpeaker,
manageRoles, manageRoles,
manageWebhooks); manageWebhooks);




+ 1
- 0
src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs View File

@@ -35,6 +35,7 @@ namespace Discord
DeafenMembers = 0x00_80_00_00, DeafenMembers = 0x00_80_00_00,
MoveMembers = 0x01_00_00_00, MoveMembers = 0x01_00_00_00,
UseVAD = 0x02_00_00_00, UseVAD = 0x02_00_00_00,
PrioritySpeaker = 0x00_00_01_00,


// General 2 // General 2
ChangeNickname = 0x04_00_00_00, ChangeNickname = 0x04_00_00_00,


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

@@ -12,7 +12,7 @@ namespace Discord
/// <summary> Gets a GuildPermissions that grants all guild permissions for webhook users. </summary> /// <summary> Gets a GuildPermissions that grants all guild permissions for webhook users. </summary>
public static readonly GuildPermissions Webhook = new GuildPermissions(0b00000_0000000_0001101100000_000000); public static readonly GuildPermissions Webhook = new GuildPermissions(0b00000_0000000_0001101100000_000000);
/// <summary> Gets a GuildPermissions that grants all guild permissions. </summary> /// <summary> Gets a GuildPermissions that grants all guild permissions. </summary>
public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_1111111110011_111111);
public static readonly GuildPermissions All = new GuildPermissions(0b11111_1111110_1111111110111_111111);


/// <summary> Gets a packed value representing all the permissions in this GuildPermissions. </summary> /// <summary> Gets a packed value representing all the permissions in this GuildPermissions. </summary>
public ulong RawValue { get; } public ulong RawValue { get; }
@@ -69,6 +69,8 @@ namespace Discord
public bool MoveMembers => Permissions.GetValue(RawValue, GuildPermission.MoveMembers); public bool MoveMembers => Permissions.GetValue(RawValue, GuildPermission.MoveMembers);
/// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary> /// <summary> If True, a user may use voice-activity-detection rather than push-to-talk. </summary>
public bool UseVAD => Permissions.GetValue(RawValue, GuildPermission.UseVAD); public bool UseVAD => Permissions.GetValue(RawValue, GuildPermission.UseVAD);
/// <summary> If True, a user may use priority speaker in a voice channel. </summary>
public bool PrioritySpeaker => Permissions.GetValue(RawValue, ChannelPermission.PrioritySpeaker);


/// <summary> If True, a user may change their own nickname. </summary> /// <summary> If True, a user may change their own nickname. </summary>
public bool ChangeNickname => Permissions.GetValue(RawValue, GuildPermission.ChangeNickname); public bool ChangeNickname => Permissions.GetValue(RawValue, GuildPermission.ChangeNickname);
@@ -108,6 +110,7 @@ namespace Discord
bool? deafenMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? moveMembers = null,
bool? useVoiceActivation = null, bool? useVoiceActivation = null,
bool? prioritySpeaker = null,
bool? changeNickname = null, bool? changeNickname = null,
bool? manageNicknames = null, bool? manageNicknames = null,
bool? manageRoles = null, bool? manageRoles = null,
@@ -139,6 +142,7 @@ namespace Discord
Permissions.SetValue(ref value, deafenMembers, GuildPermission.DeafenMembers); Permissions.SetValue(ref value, deafenMembers, GuildPermission.DeafenMembers);
Permissions.SetValue(ref value, moveMembers, GuildPermission.MoveMembers); Permissions.SetValue(ref value, moveMembers, GuildPermission.MoveMembers);
Permissions.SetValue(ref value, useVoiceActivation, GuildPermission.UseVAD); Permissions.SetValue(ref value, useVoiceActivation, GuildPermission.UseVAD);
Permissions.SetValue(ref value, prioritySpeaker, GuildPermission.PrioritySpeaker);
Permissions.SetValue(ref value, changeNickname, GuildPermission.ChangeNickname); Permissions.SetValue(ref value, changeNickname, GuildPermission.ChangeNickname);
Permissions.SetValue(ref value, manageNicknames, GuildPermission.ManageNicknames); Permissions.SetValue(ref value, manageNicknames, GuildPermission.ManageNicknames);
Permissions.SetValue(ref value, manageRoles, GuildPermission.ManageRoles); Permissions.SetValue(ref value, manageRoles, GuildPermission.ManageRoles);
@@ -173,6 +177,7 @@ namespace Discord
bool deafenMembers = false, bool deafenMembers = false,
bool moveMembers = false, bool moveMembers = false,
bool useVoiceActivation = false, bool useVoiceActivation = false,
bool prioritySpeaker = false,
bool changeNickname = false, bool changeNickname = false,
bool manageNicknames = false, bool manageNicknames = false,
bool manageRoles = false, bool manageRoles = false,
@@ -203,6 +208,7 @@ namespace Discord
deafenMembers: deafenMembers, deafenMembers: deafenMembers,
moveMembers: moveMembers, moveMembers: moveMembers,
useVoiceActivation: useVoiceActivation, useVoiceActivation: useVoiceActivation,
prioritySpeaker: prioritySpeaker,
changeNickname: changeNickname, changeNickname: changeNickname,
manageNicknames: manageNicknames, manageNicknames: manageNicknames,
manageWebhooks: manageWebhooks, manageWebhooks: manageWebhooks,
@@ -234,6 +240,7 @@ namespace Discord
bool? deafenMembers = null, bool? deafenMembers = null,
bool? moveMembers = null, bool? moveMembers = null,
bool? useVoiceActivation = null, bool? useVoiceActivation = null,
bool? prioritySpeaker = null,
bool? changeNickname = null, bool? changeNickname = null,
bool? manageNicknames = null, bool? manageNicknames = null,
bool? manageRoles = null, bool? manageRoles = null,
@@ -242,7 +249,7 @@ namespace Discord
=> new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions,
viewAuditLog, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, viewAuditLog, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles,
readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers,
useVoiceActivation, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis);
useVoiceActivation, prioritySpeaker, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojis);


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




+ 11
- 0
src/Discord.Net.Core/Extensions/MessageExtensions.cs View File

@@ -0,0 +1,11 @@
namespace Discord
{
public static class MessageExtensions
{
public static string GetJumpUrl(this IMessage msg)
{
var channel = msg.Channel;
return $"https://discordapp.com/channels/{(channel is IDMChannel ? "@me" : $"{(channel as ITextChannel).GuildId}")}/{channel.Id}/{msg.Id}";
}
}
}

+ 1
- 1
src/Discord.Net.Core/IDiscordClient.cs View File

@@ -27,7 +27,7 @@ namespace Discord
Task<IReadOnlyCollection<IGuild>> GetGuildsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IReadOnlyCollection<IGuild>> GetGuildsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null, RequestOptions options = null); Task<IGuild> CreateGuildAsync(string name, IVoiceRegion region, Stream jpegIcon = null, RequestOptions options = null);
Task<IInvite> GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null);
Task<IInvite> GetInviteAsync(string inviteId, RequestOptions options = null);


Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null); Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
Task<IUser> GetUserAsync(string username, string discriminator, RequestOptions options = null); Task<IUser> GetUserAsync(string username, string discriminator, RequestOptions options = null);


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

@@ -8,7 +8,7 @@ namespace Discord.API
[JsonProperty("code")] [JsonProperty("code")]
public string Code { get; set; } public string Code { get; set; }
[JsonProperty("guild")] [JsonProperty("guild")]
public InviteGuild Guild { get; set; }
public Optional<InviteGuild> Guild { get; set; }
[JsonProperty("channel")] [JsonProperty("channel")]
public InviteChannel Channel { get; set; } public InviteChannel Channel { get; set; }
[JsonProperty("approximate_presence_count")] [JsonProperty("approximate_presence_count")]


+ 2
- 2
src/Discord.Net.Rest/API/Common/InviteChannel.cs View File

@@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CS1591
using Newtonsoft.Json; using Newtonsoft.Json;


namespace Discord.API namespace Discord.API
@@ -10,6 +10,6 @@ namespace Discord.API
[JsonProperty("name")] [JsonProperty("name")]
public string Name { get; set; } public string Name { get; set; }
[JsonProperty("type")] [JsonProperty("type")]
public string Type { get; set; }
public int Type { get; set; }
} }
} }

+ 5
- 5
src/Discord.Net.Rest/API/Common/InviteMetadata.cs View File

@@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CS1591
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;


@@ -9,15 +9,15 @@ namespace Discord.API
[JsonProperty("inviter")] [JsonProperty("inviter")]
public User Inviter { get; set; } public User Inviter { get; set; }
[JsonProperty("uses")] [JsonProperty("uses")]
public int Uses { get; set; }
public Optional<int> Uses { get; set; }
[JsonProperty("max_uses")] [JsonProperty("max_uses")]
public int MaxUses { get; set; }
public Optional<int> MaxUses { get; set; }
[JsonProperty("max_age")] [JsonProperty("max_age")]
public int MaxAge { get; set; }
public Optional<int> MaxAge { get; set; }
[JsonProperty("temporary")] [JsonProperty("temporary")]
public bool Temporary { get; set; } public bool Temporary { get; set; }
[JsonProperty("created_at")] [JsonProperty("created_at")]
public DateTimeOffset CreatedAt { get; set; }
public Optional<DateTimeOffset> CreatedAt { get; set; }
[JsonProperty("revoked")] [JsonProperty("revoked")]
public bool Revoked { get; set; } public bool Revoked { get; set; }
} }


+ 0
- 7
src/Discord.Net.Rest/API/Rest/GetInviteParams.cs View File

@@ -1,7 +0,0 @@
namespace Discord.API.Rest
{
internal class GetInviteParams
{
public Optional<bool?> WithCounts { get; set; }
}
}

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

@@ -148,7 +148,7 @@ namespace Discord.Rest
Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options) Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options)
=> Task.FromResult<IReadOnlyCollection<IConnection>>(ImmutableArray.Create<IConnection>()); => Task.FromResult<IReadOnlyCollection<IConnection>>(ImmutableArray.Create<IConnection>());


Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options)
Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options)
=> Task.FromResult<IInvite>(null); => Task.FromResult<IInvite>(null);


Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options)


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

@@ -51,13 +51,9 @@ namespace Discord.Rest
} }
public static async Task<RestInviteMetadata> GetInviteAsync(BaseDiscordClient client, public static async Task<RestInviteMetadata> GetInviteAsync(BaseDiscordClient client,
string inviteId, bool withCount, RequestOptions options)
string inviteId, RequestOptions options)
{ {
var args = new GetInviteParams
{
WithCounts = withCount
};
var model = await client.ApiClient.GetInviteAsync(inviteId, args, options).ConfigureAwait(false);
var model = await client.ApiClient.GetInviteAsync(inviteId, options).ConfigureAwait(false);
if (model != null) if (model != null)
return RestInviteMetadata.Create(client, null, null, model); return RestInviteMetadata.Create(client, null, null, model);
return null; return null;


+ 10
- 4
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -906,7 +906,7 @@ namespace Discord.API
} }


//Guild Invites //Guild Invites
public async Task<InviteMetadata> GetInviteAsync(string inviteId, GetInviteParams args, RequestOptions options = null)
public async Task<InviteMetadata> GetInviteAsync(string inviteId, RequestOptions options = null)
{ {
Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId)); Preconditions.NotNullOrEmpty(inviteId, nameof(inviteId));
options = RequestOptions.CreateOrClone(options); options = RequestOptions.CreateOrClone(options);
@@ -919,14 +919,20 @@ namespace Discord.API
if (index >= 0) if (index >= 0)
inviteId = inviteId.Substring(index + 1); inviteId = inviteId.Substring(index + 1);


var withCounts = args.WithCounts.GetValueOrDefault(false);

try try
{ {
return await SendAsync<InviteMetadata>("GET", () => $"invites/{inviteId}?with_counts={withCounts}", new BucketIds(), options: options).ConfigureAwait(false);
return await SendAsync<InviteMetadata>("GET", () => $"invites/{inviteId}?with_counts=true", new BucketIds(), options: options).ConfigureAwait(false);
} }
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; } catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.NotFound) { return null; }
} }
public async Task<InviteMetadata> GetVanityInviteAsync(ulong guildId, RequestOptions options = null)
{
Preconditions.NotEqual(guildId, 0, nameof(guildId));
options = RequestOptions.CreateOrClone(options);

var ids = new BucketIds(guildId: guildId);
return await SendAsync<InviteMetadata>("GET", () => $"guilds/{guildId}/vanity-url", ids, options: options).ConfigureAwait(false);
}
public async Task<IReadOnlyCollection<InviteMetadata>> GetGuildInvitesAsync(ulong guildId, RequestOptions options = null) public async Task<IReadOnlyCollection<InviteMetadata>> GetGuildInvitesAsync(ulong guildId, RequestOptions options = null)
{ {
Preconditions.NotEqual(guildId, 0, nameof(guildId)); Preconditions.NotEqual(guildId, 0, nameof(guildId));


+ 4
- 4
src/Discord.Net.Rest/DiscordRestClient.cs View File

@@ -56,8 +56,8 @@ namespace Discord.Rest
=> ClientHelper.GetConnectionsAsync(this, options); => ClientHelper.GetConnectionsAsync(this, options);


/// <inheritdoc /> /// <inheritdoc />
public Task<RestInviteMetadata> GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null)
=> ClientHelper.GetInviteAsync(this, inviteId, withCount, options);
public Task<RestInviteMetadata> GetInviteAsync(string inviteId, RequestOptions options = null)
=> ClientHelper.GetInviteAsync(this, inviteId, options);


/// <inheritdoc /> /// <inheritdoc />
public Task<RestGuild> GetGuildAsync(ulong id, RequestOptions options = null) public Task<RestGuild> GetGuildAsync(ulong id, RequestOptions options = null)
@@ -131,8 +131,8 @@ namespace Discord.Rest
async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options) async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options)
=> await GetConnectionsAsync(options).ConfigureAwait(false); => await GetConnectionsAsync(options).ConfigureAwait(false);


async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options)
=> await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false);
async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options)
=> await GetInviteAsync(inviteId, options).ConfigureAwait(false);


async Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) async Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options)
{ {


+ 18
- 0
src/Discord.Net.Rest/Entities/AuditLogs/DataTypes/MemberInfo.cs View File

@@ -0,0 +1,18 @@
namespace Discord.Rest
{
public struct MemberInfo
{
internal MemberInfo(string nick, bool? deaf, bool? mute, string avatar_hash)
{
Nickname = nick;
Deaf = deaf;
Mute = mute;
AvatarHash = avatar_hash;
}

public string Nickname { get; }
public bool? Deaf { get; }
public bool? Mute { get; }
public string AvatarHash { get; }
}
}

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

@@ -8,28 +8,42 @@ namespace Discord.Rest
{ {
public class MemberUpdateAuditLogData : IAuditLogData public class MemberUpdateAuditLogData : IAuditLogData
{ {
private MemberUpdateAuditLogData(IUser target, string newNick, string oldNick)
private MemberUpdateAuditLogData(IUser target, MemberInfo before, MemberInfo after)
{ {
Target = target; Target = target;
NewNick = newNick;
OldNick = oldNick;
Before = before;
After = after;
} }


internal static MemberUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry) internal static MemberUpdateAuditLogData Create(BaseDiscordClient discord, Model log, EntryModel entry)
{ {
var changes = entry.Changes.FirstOrDefault(x => x.ChangedProperty == "nick");
var changes = entry.Changes;


var newNick = changes.NewValue?.ToObject<string>();
var oldNick = changes.OldValue?.ToObject<string>();
var nickModel = changes.FirstOrDefault(x => x.ChangedProperty == "nick");
var deafModel = changes.FirstOrDefault(x => x.ChangedProperty == "deaf");
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>();


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


return new MemberUpdateAuditLogData(user, newNick, oldNick);
var before = new MemberInfo(oldNick, oldDeaf, oldMute, oldAvatar);
var after = new MemberInfo(newNick, newDeaf, newMute, newAvatar);

return new MemberUpdateAuditLogData(user, before, after);
} }


public IUser Target { get; } public IUser Target { get; }
public string NewNick { get; }
public string OldNick { get; }
public MemberInfo Before { get; }
public MemberInfo After { get; }
} }
} }

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


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


+ 6
- 0
src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs View File

@@ -210,6 +210,12 @@ namespace Discord.Rest
var models = await client.ApiClient.GetGuildInvitesAsync(guild.Id, options).ConfigureAwait(false); var models = await client.ApiClient.GetGuildInvitesAsync(guild.Id, options).ConfigureAwait(false);
return models.Select(x => RestInviteMetadata.Create(client, guild, null, x)).ToImmutableArray(); return models.Select(x => RestInviteMetadata.Create(client, guild, null, x)).ToImmutableArray();
} }
public static async Task<RestInviteMetadata> GetVanityInviteAsync(IGuild guild, BaseDiscordClient client,
RequestOptions options)
{
var model = await client.ApiClient.GetVanityInviteAsync(guild.Id, options).ConfigureAwait(false);
return RestInviteMetadata.Create(client, guild, null, model);
}


//Roles //Roles
public static async Task<RestRole> CreateRoleAsync(IGuild guild, BaseDiscordClient client, public static async Task<RestRole> CreateRoleAsync(IGuild guild, BaseDiscordClient client,


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

@@ -238,6 +238,15 @@ namespace Discord.Rest
//Invites //Invites
public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
=> GuildHelper.GetInvitesAsync(this, Discord, options); => GuildHelper.GetInvitesAsync(this, Discord, options);
/// <summary>
/// Gets the vanity invite URL of this guild.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A partial metadata of the vanity invite found within this guild.
/// </returns>
public Task<RestInviteMetadata> GetVanityInviteAsync(RequestOptions options = null)
=> GuildHelper.GetVanityInviteAsync(this, Discord, options);


//Roles //Roles
public RestRole GetRole(ulong id) public RestRole GetRole(ulong id)
@@ -397,6 +406,9 @@ namespace Discord.Rest


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


IRole IGuild.GetRole(ulong id) IRole IGuild.GetRole(ulong id)
=> GetRole(id); => GetRole(id);
@@ -433,7 +445,7 @@ namespace Discord.Rest
} }
Task IGuild.DownloadUsersAsync() { throw new NotSupportedException(); } Task IGuild.DownloadUsersAsync() { throw new NotSupportedException(); }


async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogAsync(int limit, CacheMode cacheMode, RequestOptions options)
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
{ {
if (cacheMode == CacheMode.AllowDownload) if (cacheMode == CacheMode.AllowDownload)
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();


+ 8
- 10
src/Discord.Net.Rest/Entities/Invites/RestInvite.cs View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.API.Rest;
using Model = Discord.API.Invite; using Model = Discord.API.Invite;


namespace Discord.Rest namespace Discord.Rest
@@ -9,14 +8,15 @@ namespace Discord.Rest
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class RestInvite : RestEntity<string>, IInvite, IUpdateable public class RestInvite : RestEntity<string>, IInvite, IUpdateable
{ {
public ChannelType ChannelType { get; private set; }
public string ChannelName { get; private set; } public string ChannelName { get; private set; }
public string GuildName { get; private set; } public string GuildName { get; private set; }
public int? PresenceCount { get; private set; } public int? PresenceCount { get; private set; }
public int? MemberCount { get; private set; } public int? MemberCount { get; private set; }
public ulong ChannelId { get; private set; } public ulong ChannelId { get; private set; }
public ulong GuildId { get; private set; }
internal IChannel Channel { get; private set; }
internal IGuild Guild { get; private set; }
public ulong? GuildId { get; private set; }
internal IChannel Channel { get; }
internal IGuild Guild { get; }


public string Code => Id; public string Code => Id;
public string Url => $"{DiscordConfig.InviteUrl}{Code}"; public string Url => $"{DiscordConfig.InviteUrl}{Code}";
@@ -35,20 +35,18 @@ namespace Discord.Rest
} }
internal void Update(Model model) internal void Update(Model model)
{ {
GuildId = model.Guild.Id;
GuildId = model.Guild.IsSpecified ? model.Guild.Value.Id : default(ulong?);
ChannelId = model.Channel.Id; ChannelId = model.Channel.Id;
GuildName = model.Guild.Name;
GuildName = model.Guild.IsSpecified ? model.Guild.Value.Name : null;
ChannelName = model.Channel.Name; ChannelName = model.Channel.Name;
MemberCount = model.MemberCount.IsSpecified ? model.MemberCount.Value : null; MemberCount = model.MemberCount.IsSpecified ? model.MemberCount.Value : null;
PresenceCount = model.PresenceCount.IsSpecified ? model.PresenceCount.Value : null; PresenceCount = model.PresenceCount.IsSpecified ? model.PresenceCount.Value : null;
ChannelType = (ChannelType)model.Channel.Type;
} }
public async Task UpdateAsync(RequestOptions options = null) public async Task UpdateAsync(RequestOptions options = null)
{ {
var args = new GetInviteParams();
if (MemberCount != null || PresenceCount != null)
args.WithCounts = true;
var model = await Discord.ApiClient.GetInviteAsync(Code, args, options).ConfigureAwait(false);
var model = await Discord.ApiClient.GetInviteAsync(Code, options).ConfigureAwait(false);
Update(model); Update(model);
} }
public Task DeleteAsync(RequestOptions options = null) public Task DeleteAsync(RequestOptions options = null)


+ 8
- 8
src/Discord.Net.Rest/Entities/Invites/RestInviteMetadata.cs View File

@@ -1,20 +1,20 @@
using System;
using System;
using Model = Discord.API.InviteMetadata; using Model = Discord.API.InviteMetadata;


namespace Discord.Rest namespace Discord.Rest
{ {
public class RestInviteMetadata : RestInvite, IInviteMetadata public class RestInviteMetadata : RestInvite, IInviteMetadata
{ {
private long _createdAtTicks;
private long? _createdAtTicks;


public bool IsRevoked { get; private set; } public bool IsRevoked { get; private set; }
public bool IsTemporary { get; private set; } public bool IsTemporary { get; private set; }
public int? MaxAge { get; private set; } public int? MaxAge { get; private set; }
public int? MaxUses { get; private set; } public int? MaxUses { get; private set; }
public int Uses { get; private set; }
public int? Uses { get; private set; }
public RestUser Inviter { get; private set; } public RestUser Inviter { get; private set; }


public DateTimeOffset CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks);
public DateTimeOffset? CreatedAt => DateTimeUtils.FromTicks(_createdAtTicks);


internal RestInviteMetadata(BaseDiscordClient discord, IGuild guild, IChannel channel, string id) internal RestInviteMetadata(BaseDiscordClient discord, IGuild guild, IChannel channel, string id)
: base(discord, guild, channel, id) : base(discord, guild, channel, id)
@@ -32,10 +32,10 @@ namespace Discord.Rest
Inviter = model.Inviter != null ? RestUser.Create(Discord, model.Inviter) : null; Inviter = model.Inviter != null ? RestUser.Create(Discord, model.Inviter) : null;
IsRevoked = model.Revoked; IsRevoked = model.Revoked;
IsTemporary = model.Temporary; IsTemporary = model.Temporary;
MaxAge = model.MaxAge != 0 ? model.MaxAge : (int?)null;
MaxUses = model.MaxUses;
Uses = model.Uses;
_createdAtTicks = model.CreatedAt.UtcTicks;
MaxAge = model.MaxAge.IsSpecified ? model.MaxAge.Value : (int?)null;
MaxUses = model.MaxUses.IsSpecified ? model.MaxUses.Value : (int?)null;
Uses = model.Uses.IsSpecified ? model.Uses.Value : (int?)null;
_createdAtTicks = model.CreatedAt.IsSpecified ? model.CreatedAt.Value.UtcTicks : (long?)null;
} }


IUser IInviteMetadata.Inviter => Inviter; IUser IInviteMetadata.Inviter => Inviter;


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

@@ -55,8 +55,8 @@ namespace Discord.WebSocket
public Task<IReadOnlyCollection<RestConnection>> GetConnectionsAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestConnection>> GetConnectionsAsync(RequestOptions options = null)
=> ClientHelper.GetConnectionsAsync(this, options ?? RequestOptions.Default); => ClientHelper.GetConnectionsAsync(this, options ?? RequestOptions.Default);
/// <inheritdoc /> /// <inheritdoc />
public Task<RestInviteMetadata> GetInviteAsync(string inviteId, bool withCount = false, RequestOptions options = null)
=> ClientHelper.GetInviteAsync(this, inviteId, withCount, options ?? RequestOptions.Default);
public Task<RestInviteMetadata> GetInviteAsync(string inviteId, RequestOptions options = null)
=> ClientHelper.GetInviteAsync(this, inviteId, options ?? RequestOptions.Default);
// IDiscordClient // IDiscordClient
async Task<IApplication> IDiscordClient.GetApplicationInfoAsync(RequestOptions options) async Task<IApplication> IDiscordClient.GetApplicationInfoAsync(RequestOptions options)
@@ -70,8 +70,8 @@ namespace Discord.WebSocket
async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options) async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options)
=> await GetConnectionsAsync(options).ConfigureAwait(false); => await GetConnectionsAsync(options).ConfigureAwait(false);


async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options)
=> await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false);
async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options)
=> await GetInviteAsync(inviteId, options).ConfigureAwait(false);


Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IGuild>(GetGuild(id)); => Task.FromResult<IGuild>(GetGuild(id));


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

@@ -328,8 +328,8 @@ namespace Discord.WebSocket
async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options) async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options)
=> await GetConnectionsAsync().ConfigureAwait(false); => await GetConnectionsAsync().ConfigureAwait(false);


async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options)
=> await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false);
async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options)
=> await GetInviteAsync(inviteId, options).ConfigureAwait(false);


Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IGuild>(GetGuild(id)); => Task.FromResult<IGuild>(GetGuild(id));


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

@@ -1513,6 +1513,9 @@ namespace Discord.WebSocket
case "MESSAGE_ACK": case "MESSAGE_ACK":
await _gatewayLogger.DebugAsync("Ignored Dispatch (MESSAGE_ACK)").ConfigureAwait(false); await _gatewayLogger.DebugAsync("Ignored Dispatch (MESSAGE_ACK)").ConfigureAwait(false);
break; break;
case "PRESENCES_REPLACE":
await _gatewayLogger.DebugAsync("Ignored Dispatch (PRESENCES_REPLACE)").ConfigureAwait(false);
break;
case "USER_SETTINGS_UPDATE": case "USER_SETTINGS_UPDATE":
await _gatewayLogger.DebugAsync("Ignored Dispatch (USER_SETTINGS_UPDATE)").ConfigureAwait(false); await _gatewayLogger.DebugAsync("Ignored Dispatch (USER_SETTINGS_UPDATE)").ConfigureAwait(false);
break; break;
@@ -1819,8 +1822,8 @@ namespace Discord.WebSocket
async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options) async Task<IReadOnlyCollection<IConnection>> IDiscordClient.GetConnectionsAsync(RequestOptions options)
=> await GetConnectionsAsync().ConfigureAwait(false); => await GetConnectionsAsync().ConfigureAwait(false);


async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, bool withCount, RequestOptions options)
=> await GetInviteAsync(inviteId, withCount, options).ConfigureAwait(false);
async Task<IInvite> IDiscordClient.GetInviteAsync(string inviteId, RequestOptions options)
=> await GetInviteAsync(inviteId, options).ConfigureAwait(false);


Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options) Task<IGuild> IDiscordClient.GetGuildAsync(ulong id, CacheMode mode, RequestOptions options)
=> Task.FromResult<IGuild>(GetGuild(id)); => Task.FromResult<IGuild>(GetGuild(id));


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

@@ -345,6 +345,15 @@ namespace Discord.WebSocket
//Invites //Invites
public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null) public Task<IReadOnlyCollection<RestInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
=> GuildHelper.GetInvitesAsync(this, Discord, options); => GuildHelper.GetInvitesAsync(this, Discord, options);
/// <summary>
/// Gets the vanity invite URL of this guild.
/// </summary>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A partial metadata of the vanity invite found within this guild.
/// </returns>
public Task<RestInviteMetadata> GetVanityInviteAsync(RequestOptions options = null)
=> GuildHelper.GetVanityInviteAsync(this, Discord, options);


//Roles //Roles
public SocketRole GetRole(ulong id) public SocketRole GetRole(ulong id)
@@ -700,6 +709,9 @@ namespace Discord.WebSocket


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


IRole IGuild.GetRole(ulong id) IRole IGuild.GetRole(ulong id)
=> GetRole(id); => GetRole(id);
@@ -715,7 +727,7 @@ namespace Discord.WebSocket
Task<IGuildUser> IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options) Task<IGuildUser> IGuild.GetOwnerAsync(CacheMode mode, RequestOptions options)
=> Task.FromResult<IGuildUser>(Owner); => Task.FromResult<IGuildUser>(Owner);


async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogAsync(int limit, CacheMode cacheMode, RequestOptions options)
async Task<IReadOnlyCollection<IAuditLogEntry>> IGuild.GetAuditLogsAsync(int limit, CacheMode cacheMode, RequestOptions options)
{ {
if (cacheMode == CacheMode.AllowDownload) if (cacheMode == CacheMode.AllowDownload)
return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray(); return (await GetAuditLogsAsync(limit, options).FlattenAsync().ConfigureAwait(false)).ToImmutableArray();


Loading…
Cancel
Save