Browse Source

Added support for optional model parameters, fixed a few model errors

tags/1.0-rc
RogueException 9 years ago
parent
commit
14bb0f7e2e
37 changed files with 251 additions and 119 deletions
  1. +33
    -30
      src/Discord.Net/API/DiscordRawClient.cs
  2. +8
    -0
      src/Discord.Net/API/IOptional.cs
  3. +26
    -0
      src/Discord.Net/API/Optional.cs
  4. +4
    -4
      src/Discord.Net/API/Rest/CreateChannelInviteParams.cs
  5. +1
    -1
      src/Discord.Net/API/Rest/CreateGuildBanParams.cs
  6. +2
    -1
      src/Discord.Net/API/Rest/CreateGuildChannelParams.cs
  7. +2
    -1
      src/Discord.Net/API/Rest/CreateGuildParams.cs
  8. +3
    -2
      src/Discord.Net/API/Rest/CreateMessageParams.cs
  9. +2
    -1
      src/Discord.Net/API/Rest/GetChannelMessagesParams.cs
  10. +2
    -2
      src/Discord.Net/API/Rest/GetGuildMembersParams.cs
  11. +2
    -2
      src/Discord.Net/API/Rest/ModifyChannelPermissionsParams.cs
  12. +5
    -5
      src/Discord.Net/API/Rest/ModifyCurrentUserParams.cs
  13. +2
    -2
      src/Discord.Net/API/Rest/ModifyGuildChannelParams.cs
  14. +2
    -2
      src/Discord.Net/API/Rest/ModifyGuildChannelsParams.cs
  15. +3
    -3
      src/Discord.Net/API/Rest/ModifyGuildEmbedParams.cs
  16. +3
    -3
      src/Discord.Net/API/Rest/ModifyGuildIntegrationParams.cs
  17. +8
    -7
      src/Discord.Net/API/Rest/ModifyGuildMemberParams.cs
  18. +9
    -9
      src/Discord.Net/API/Rest/ModifyGuildParams.cs
  19. +5
    -5
      src/Discord.Net/API/Rest/ModifyGuildRoleParams.cs
  20. +1
    -1
      src/Discord.Net/API/Rest/ModifyGuildRolesParams.cs
  21. +1
    -1
      src/Discord.Net/API/Rest/ModifyMessageParams.cs
  22. +1
    -1
      src/Discord.Net/API/Rest/ModifyTextChannelParams.cs
  23. +1
    -1
      src/Discord.Net/API/Rest/ModifyVoiceChannelParams.cs
  24. +12
    -11
      src/Discord.Net/API/Rest/UploadFileParams.cs
  25. +3
    -1
      src/Discord.Net/Common/Entities/Guilds/IGuild.cs
  26. +2
    -0
      src/Discord.Net/Common/Entities/Users/IUser.cs
  27. +4
    -0
      src/Discord.Net/Discord.Net.csproj
  28. +5
    -2
      src/Discord.Net/Net/Converters/ImageConverter.cs
  29. +34
    -0
      src/Discord.Net/Net/Converters/OptionalContractResolver.cs
  30. +23
    -0
      src/Discord.Net/Net/Converters/OptionalConverter.cs
  31. +12
    -8
      src/Discord.Net/Net/Rest/DefaultRestClient.cs
  32. +2
    -2
      src/Discord.Net/Net/Rest/IRestClient.cs
  33. +2
    -2
      src/Discord.Net/Net/Rest/RequestQueue/RequestQueueBucket.cs
  34. +7
    -5
      src/Discord.Net/Net/Rest/RequestQueue/RestRequest.cs
  35. +7
    -2
      src/Discord.Net/Rest/Entities/Guilds/Guild.cs
  36. +10
    -2
      src/Discord.Net/Rest/Entities/Users/GuildUser.cs
  37. +2
    -0
      src/Discord.Net/Rest/Entities/Users/User.cs

+ 33
- 30
src/Discord.Net/API/DiscordRawClient.cs View File

@@ -45,11 +45,13 @@ namespace Discord.API
} }


_restClient = restClientProvider(DiscordConfig.ClientAPIUrl, cancelToken); _restClient = restClientProvider(DiscordConfig.ClientAPIUrl, cancelToken);
_restClient.SetHeader("accept", "*/*");
_restClient.SetHeader("authorization", authToken); _restClient.SetHeader("authorization", authToken);
_restClient.SetHeader("user-agent", DiscordConfig.UserAgent); _restClient.SetHeader("user-agent", DiscordConfig.UserAgent);
_requestQueue = new RequestQueue(_restClient); _requestQueue = new RequestQueue(_restClient);


_serializer = new JsonSerializer(); _serializer = new JsonSerializer();
_serializer.Converters.Add(new OptionalConverter());
_serializer.Converters.Add(new ChannelTypeConverter()); _serializer.Converters.Add(new ChannelTypeConverter());
_serializer.Converters.Add(new ImageConverter()); _serializer.Converters.Add(new ImageConverter());
_serializer.Converters.Add(new NullableUInt64Converter()); _serializer.Converters.Add(new NullableUInt64Converter());
@@ -59,58 +61,59 @@ namespace Discord.API
_serializer.Converters.Add(new UInt64Converter()); _serializer.Converters.Add(new UInt64Converter());
_serializer.Converters.Add(new UInt64EntityConverter()); _serializer.Converters.Add(new UInt64EntityConverter());
_serializer.Converters.Add(new UserStatusConverter()); _serializer.Converters.Add(new UserStatusConverter());
_serializer.ContractResolver = new OptionalContractResolver();
} }


//Core //Core
public Task Send(string method, string endpoint, GlobalBucket bucket = GlobalBucket.General) public Task Send(string method, string endpoint, GlobalBucket bucket = GlobalBucket.General)
=> SendInternal(method, endpoint, null, bucket);
=> SendInternal(method, endpoint, null, true, bucket);
public Task Send(string method, string endpoint, object payload, GlobalBucket bucket = GlobalBucket.General) public Task Send(string method, string endpoint, object payload, GlobalBucket bucket = GlobalBucket.General)
=> SendInternal(method, endpoint, payload, bucket);
=> SendInternal(method, endpoint, payload, true, bucket);
public Task Send(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GlobalBucket bucket = GlobalBucket.General) public Task Send(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GlobalBucket bucket = GlobalBucket.General)
=> SendInternal(method, endpoint, multipartArgs, bucket);
=> SendInternal(method, endpoint, multipartArgs, true, bucket);
public async Task<TResponse> Send<TResponse>(string method, string endpoint, GlobalBucket bucket = GlobalBucket.General) public async Task<TResponse> Send<TResponse>(string method, string endpoint, GlobalBucket bucket = GlobalBucket.General)
where TResponse : class where TResponse : class
=> Deserialize<TResponse>(await SendInternal(method, endpoint, null, bucket).ConfigureAwait(false));
=> Deserialize<TResponse>(await SendInternal(method, endpoint, null, false, bucket).ConfigureAwait(false));
public async Task<TResponse> Send<TResponse>(string method, string endpoint, object payload, GlobalBucket bucket = GlobalBucket.General) public async Task<TResponse> Send<TResponse>(string method, string endpoint, object payload, GlobalBucket bucket = GlobalBucket.General)
where TResponse : class where TResponse : class
=> Deserialize<TResponse>(await SendInternal(method, endpoint, payload, bucket).ConfigureAwait(false));
=> Deserialize<TResponse>(await SendInternal(method, endpoint, payload, false, bucket).ConfigureAwait(false));
public async Task<TResponse> Send<TResponse>(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GlobalBucket bucket = GlobalBucket.General) public async Task<TResponse> Send<TResponse>(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GlobalBucket bucket = GlobalBucket.General)
where TResponse : class where TResponse : class
=> Deserialize<TResponse>(await SendInternal(method, endpoint, multipartArgs, bucket).ConfigureAwait(false));
=> Deserialize<TResponse>(await SendInternal(method, endpoint, multipartArgs, false, bucket).ConfigureAwait(false));


public Task Send(string method, string endpoint, GuildBucket bucket, ulong guildId) public Task Send(string method, string endpoint, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, null, bucket, guildId);
=> SendInternal(method, endpoint, null, true, bucket, guildId);
public Task Send(string method, string endpoint, object payload, GuildBucket bucket, ulong guildId) public Task Send(string method, string endpoint, object payload, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, payload, bucket, guildId);
=> SendInternal(method, endpoint, payload, true, bucket, guildId);
public Task Send(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GuildBucket bucket, ulong guildId) public Task Send(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, multipartArgs, bucket, guildId);
=> SendInternal(method, endpoint, multipartArgs, true, bucket, guildId);
public async Task<TResponse> Send<TResponse>(string method, string endpoint, GuildBucket bucket, ulong guildId) public async Task<TResponse> Send<TResponse>(string method, string endpoint, GuildBucket bucket, ulong guildId)
where TResponse : class where TResponse : class
=> Deserialize<TResponse>(await SendInternal(method, endpoint, null, bucket, guildId).ConfigureAwait(false));
=> Deserialize<TResponse>(await SendInternal(method, endpoint, null, false, bucket, guildId).ConfigureAwait(false));
public async Task<TResponse> Send<TResponse>(string method, string endpoint, object payload, GuildBucket bucket, ulong guildId) public async Task<TResponse> Send<TResponse>(string method, string endpoint, object payload, GuildBucket bucket, ulong guildId)
where TResponse : class where TResponse : class
=> Deserialize<TResponse>(await SendInternal(method, endpoint, payload, bucket, guildId).ConfigureAwait(false));
=> Deserialize<TResponse>(await SendInternal(method, endpoint, payload, false, bucket, guildId).ConfigureAwait(false));
public async Task<TResponse> Send<TResponse>(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GuildBucket bucket, ulong guildId) public async Task<TResponse> Send<TResponse>(string method, string endpoint, Stream file, IReadOnlyDictionary<string, string> multipartArgs, GuildBucket bucket, ulong guildId)
where TResponse : class where TResponse : class
=> Deserialize<TResponse>(await SendInternal(method, endpoint, multipartArgs, bucket, guildId).ConfigureAwait(false));
=> Deserialize<TResponse>(await SendInternal(method, endpoint, multipartArgs, false, bucket, guildId).ConfigureAwait(false));


private Task<Stream> SendInternal(string method, string endpoint, object payload, GlobalBucket bucket)
=> SendInternal(method, endpoint, payload, BucketGroup.Global, (int)bucket, 0);
private Task<Stream> SendInternal(string method, string endpoint, object payload, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, payload, BucketGroup.Guild, (int)bucket, guildId);
private Task<Stream> SendInternal(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, GlobalBucket bucket)
=> SendInternal(method, endpoint, multipartArgs, BucketGroup.Global, (int)bucket, 0);
private Task<Stream> SendInternal(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, multipartArgs, BucketGroup.Guild, (int)bucket, guildId);
private Task<Stream> SendInternal(string method, string endpoint, object payload, bool headerOnly, GlobalBucket bucket)
=> SendInternal(method, endpoint, payload, headerOnly, BucketGroup.Global, (int)bucket, 0);
private Task<Stream> SendInternal(string method, string endpoint, object payload, bool headerOnly, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, payload, headerOnly, BucketGroup.Guild, (int)bucket, guildId);
private Task<Stream> SendInternal(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, bool headerOnly, GlobalBucket bucket)
=> SendInternal(method, endpoint, multipartArgs, headerOnly, BucketGroup.Global, (int)bucket, 0);
private Task<Stream> SendInternal(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, bool headerOnly, GuildBucket bucket, ulong guildId)
=> SendInternal(method, endpoint, multipartArgs, headerOnly, BucketGroup.Guild, (int)bucket, guildId);


private async Task<Stream> SendInternal(string method, string endpoint, object payload, BucketGroup group, int bucketId, ulong guildId)
private async Task<Stream> SendInternal(string method, string endpoint, object payload, bool headerOnly, BucketGroup group, int bucketId, ulong guildId)
{ {
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
string json = null; string json = null;
if (payload != null) if (payload != null)
json = Serialize(payload); json = Serialize(payload);
var responseStream = await _requestQueue.Send(new RestRequest(method, endpoint, json), group, bucketId, guildId).ConfigureAwait(false);
int bytes = (int)responseStream.Length;
var responseStream = await _requestQueue.Send(new RestRequest(method, endpoint, json, headerOnly), group, bucketId, guildId).ConfigureAwait(false);
int bytes = headerOnly ? 0 : (int)responseStream.Length;
stopwatch.Stop(); stopwatch.Stop();


double milliseconds = ToMilliseconds(stopwatch); double milliseconds = ToMilliseconds(stopwatch);
@@ -118,11 +121,11 @@ namespace Discord.API


return responseStream; return responseStream;
} }
private async Task<Stream> SendInternal(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, BucketGroup group, int bucketId, ulong guildId)
private async Task<Stream> SendInternal(string method, string endpoint, IReadOnlyDictionary<string, object> multipartArgs, bool headerOnly, BucketGroup group, int bucketId, ulong guildId)
{ {
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
var responseStream = await _requestQueue.Send(new RestRequest(method, endpoint, multipartArgs), group, bucketId, guildId).ConfigureAwait(false);
int bytes = (int)responseStream.Length;
var responseStream = await _requestQueue.Send(new RestRequest(method, endpoint, multipartArgs, headerOnly), group, bucketId, guildId).ConfigureAwait(false);
int bytes = headerOnly ? 0 : (int)responseStream.Length;
stopwatch.Stop(); stopwatch.Stop();


double milliseconds = ToMilliseconds(stopwatch); double milliseconds = ToMilliseconds(stopwatch);
@@ -448,11 +451,11 @@ namespace Discord.API
if (args.Limit <= 0) throw new ArgumentOutOfRangeException(nameof(args.Limit)); if (args.Limit <= 0) throw new ArgumentOutOfRangeException(nameof(args.Limit));
if (args.Offset < 0) throw new ArgumentOutOfRangeException(nameof(args.Offset)); if (args.Offset < 0) throw new ArgumentOutOfRangeException(nameof(args.Offset));


int limit = args.Limit ?? int.MaxValue;
int limit = args.Limit.IsSpecified ? args.Limit.Value : int.MaxValue;
int offset = args.Offset; int offset = args.Offset;


List<GuildMember[]> result; List<GuildMember[]> result;
if (args.Limit != null)
if (args.Limit.IsSpecified)
result = new List<GuildMember[]>((limit + DiscordConfig.MaxUsersPerBatch - 1) / DiscordConfig.MaxUsersPerBatch); result = new List<GuildMember[]>((limit + DiscordConfig.MaxUsersPerBatch - 1) / DiscordConfig.MaxUsersPerBatch);
else else
result = new List<GuildMember[]>(); result = new List<GuildMember[]>();
@@ -488,13 +491,13 @@ namespace Discord.API


await Send("DELETE", $"guilds/{guildId}/members/{userId}").ConfigureAwait(false); await Send("DELETE", $"guilds/{guildId}/members/{userId}").ConfigureAwait(false);
} }
public async Task<GuildMember> ModifyGuildMember(ulong guildId, ulong userId, ModifyGuildMemberParams args)
public async Task ModifyGuildMember(ulong guildId, ulong userId, ModifyGuildMemberParams args)
{ {
if (args == null) throw new ArgumentNullException(nameof(args)); if (args == null) throw new ArgumentNullException(nameof(args));
if (guildId == 0) throw new ArgumentOutOfRangeException(nameof(guildId)); if (guildId == 0) throw new ArgumentOutOfRangeException(nameof(guildId));
if (userId == 0) throw new ArgumentOutOfRangeException(nameof(userId)); if (userId == 0) throw new ArgumentOutOfRangeException(nameof(userId));
return await Send<GuildMember>("PATCH", $"guilds/{guildId}/members/{userId}", args).ConfigureAwait(false);
await Send("PATCH", $"guilds/{guildId}/members/{userId}", args).ConfigureAwait(false);
} }


//Guild Roles //Guild Roles


+ 8
- 0
src/Discord.Net/API/IOptional.cs View File

@@ -0,0 +1,8 @@
namespace Discord.API
{
public interface IOptional
{
object Value { get; }
bool IsSpecified { get; }
}
}

+ 26
- 0
src/Discord.Net/API/Optional.cs View File

@@ -0,0 +1,26 @@
namespace Discord.API
{
public struct Optional<T> : IOptional
{
/// <summary> Gets the value for this paramter, or default(T) if unspecified. </summary>
public T Value { get; }
/// <summary> Returns true if this value has been specified. </summary>
public bool IsSpecified { get; }

object IOptional.Value => Value;

/// <summary> Creates a new Parameter with the provided value. </summary>
public Optional(T value)
{
Value = value;
IsSpecified = true;
}

/// <summary> Implicitly creates a new Parameter from an existing value. </summary>
public static implicit operator Optional<T>(T value) => new Optional<T>(value);
/// <summary> Implicitly creates a new Parameter from an existing value. </summary>
public static implicit operator T(Optional<T> param) => param.Value;

public override string ToString() => IsSpecified ? (Value?.ToString() ?? null) : null;
}
}

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

@@ -5,12 +5,12 @@ namespace Discord.API.Rest
public class CreateChannelInviteParams public class CreateChannelInviteParams
{ {
[JsonProperty("max_age")] [JsonProperty("max_age")]
public int MaxAge { get; set; } = 86400; //24 Hours
public Optional<int> MaxAge { get; set; }
[JsonProperty("max_uses")] [JsonProperty("max_uses")]
public int MaxUses { get; set; } = 0;
public Optional<int> MaxUses { get; set; }
[JsonProperty("temporary")] [JsonProperty("temporary")]
public bool Temporary { get; set; } = false;
public Optional<bool> Temporary { get; set; }
[JsonProperty("xkcdpass")] [JsonProperty("xkcdpass")]
public bool XkcdPass { get; set; } = false;
public Optional<bool> XkcdPass { get; set; }
} }
} }

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

@@ -5,6 +5,6 @@ namespace Discord.API.Rest
public class CreateGuildBanParams public class CreateGuildBanParams
{ {
[JsonProperty("delete-message-days")] [JsonProperty("delete-message-days")]
public int PruneDays { get; set; } = 0;
public Optional<int> PruneDays { get; set; }
} }
} }

+ 2
- 1
src/Discord.Net/API/Rest/CreateGuildChannelParams.cs View File

@@ -8,7 +8,8 @@ namespace Discord.API.Rest
public string Name { get; set; } public string Name { get; set; }
[JsonProperty("type")] [JsonProperty("type")]
public ChannelType Type { get; set; } public ChannelType Type { get; set; }

[JsonProperty("bitrate")] [JsonProperty("bitrate")]
public int Bitrate { get; set; }
public Optional<int> Bitrate { get; set; }
} }
} }

+ 2
- 1
src/Discord.Net/API/Rest/CreateGuildParams.cs View File

@@ -10,7 +10,8 @@ namespace Discord.API.Rest
public string Name { get; set; } public string Name { get; set; }
[JsonProperty("region")] [JsonProperty("region")]
public string Region { get; set; } public string Region { get; set; }

[JsonProperty("icon"), JsonConverter(typeof(ImageConverter))] [JsonProperty("icon"), JsonConverter(typeof(ImageConverter))]
public Stream Icon { get; set; }
public Optional<Stream> Icon { get; set; }
} }
} }

+ 3
- 2
src/Discord.Net/API/Rest/CreateMessageParams.cs View File

@@ -6,9 +6,10 @@ namespace Discord.API.Rest
{ {
[JsonProperty("content")] [JsonProperty("content")]
public string Content { get; set; } = ""; public string Content { get; set; } = "";

[JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)] [JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)]
public string Nonce { get; set; } = null;
public Optional<string> Nonce { get; set; }
[JsonProperty("tts", DefaultValueHandling = DefaultValueHandling.Ignore)] [JsonProperty("tts", DefaultValueHandling = DefaultValueHandling.Ignore)]
public bool IsTTS { get; set; } = false;
public Optional<bool> IsTTS { get; set; }
} }
} }

+ 2
- 1
src/Discord.Net/API/Rest/GetChannelMessagesParams.cs View File

@@ -4,6 +4,7 @@
{ {
public int Limit { get; set; } = DiscordConfig.MaxMessagesPerBatch; public int Limit { get; set; } = DiscordConfig.MaxMessagesPerBatch;
public Direction RelativeDirection { get; set; } = Direction.Before; public Direction RelativeDirection { get; set; } = Direction.Before;
public ulong? RelativeMessageId { get; set; } = null;

public Optional<ulong> RelativeMessageId { get; set; }
} }
} }

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

@@ -2,7 +2,7 @@
{ {
public class GetGuildMembersParams public class GetGuildMembersParams
{ {
public int? Limit { get; set; } = null;
public int Offset { get; set; } = 0;
public Optional<int> Limit { get; set; }
public Optional<int> Offset { get; set; }
} }
} }

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

@@ -5,8 +5,8 @@ namespace Discord.API.Rest
public class ModifyChannelPermissionsParams public class ModifyChannelPermissionsParams
{ {
[JsonProperty("allow")] [JsonProperty("allow")]
public uint Allow { get; set; }
public Optional<uint> Allow { get; set; }
[JsonProperty("deny")] [JsonProperty("deny")]
public uint Deny { get; set; }
public Optional<uint> Deny { get; set; }
} }
} }

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

@@ -7,14 +7,14 @@ namespace Discord.API.Rest
public class ModifyCurrentUserParams public class ModifyCurrentUserParams
{ {
[JsonProperty("username")] [JsonProperty("username")]
public string Username { get; set; }
public Optional<string> Username { get; set; }
[JsonProperty("email")] [JsonProperty("email")]
public string Email { get; set; }
public Optional<string> Email { get; set; }
[JsonProperty("password")] [JsonProperty("password")]
public string Password { get; set; }
public Optional<string> Password { get; set; }
[JsonProperty("new_password")] [JsonProperty("new_password")]
public string NewPassword { get; set; }
public Optional<string> NewPassword { get; set; }
[JsonProperty("avatar"), JsonConverter(typeof(ImageConverter))] [JsonProperty("avatar"), JsonConverter(typeof(ImageConverter))]
public Stream Avatar { get; set; }
public Optional<Stream> Avatar { get; set; }
} }
} }

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

@@ -5,8 +5,8 @@ namespace Discord.API.Rest
public class ModifyGuildChannelParams public class ModifyGuildChannelParams
{ {
[JsonProperty("name")] [JsonProperty("name")]
public string Name { get; set; }
public Optional<string> Name { get; set; }
[JsonProperty("position")] [JsonProperty("position")]
public int Position { get; set; }
public Optional<int> Position { get; set; }
} }
} }

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

@@ -5,8 +5,8 @@ namespace Discord.API.Rest
public class ModifyGuildChannelsParams public class ModifyGuildChannelsParams
{ {
[JsonProperty("id")] [JsonProperty("id")]
public ulong Id { get; set; }
public Optional<ulong> Id { get; set; }
[JsonProperty("position")] [JsonProperty("position")]
public int Position { get; set; }
public Optional<int> Position { get; set; }
} }
} }

+ 3
- 3
src/Discord.Net/API/Rest/ModifyGuildEmbedParams.cs View File

@@ -6,8 +6,8 @@ namespace Discord.API.Rest
public class ModifyGuildEmbedParams public class ModifyGuildEmbedParams
{ {
[JsonProperty("enabled")] [JsonProperty("enabled")]
public bool Enabled { get; set; }
[JsonProperty("channel"), JsonConverter(typeof(UInt64EntityConverter))]
public IVoiceChannel Channel { get; set; }
public Optional<bool> Enabled { get; set; }
[JsonProperty("channel")]
public Optional<IVoiceChannel> Channel { get; set; }
} }
} }

+ 3
- 3
src/Discord.Net/API/Rest/ModifyGuildIntegrationParams.cs View File

@@ -5,10 +5,10 @@ namespace Discord.API.Rest
public class ModifyGuildIntegrationParams public class ModifyGuildIntegrationParams
{ {
[JsonProperty("expire_behavior")] [JsonProperty("expire_behavior")]
public int ExpireBehavior { get; set; }
public Optional<int> ExpireBehavior { get; set; }
[JsonProperty("expire_grace_period")] [JsonProperty("expire_grace_period")]
public int ExpireGracePeriod { get; set; }
public Optional<int> ExpireGracePeriod { get; set; }
[JsonProperty("enable_emoticons")] [JsonProperty("enable_emoticons")]
public bool EnableEmoticons { get; set; }
public Optional<bool> EnableEmoticons { get; set; }
} }
} }

+ 8
- 7
src/Discord.Net/API/Rest/ModifyGuildMemberParams.cs View File

@@ -1,17 +1,18 @@
using Discord.Net.Converters;
using Newtonsoft.Json;
using Newtonsoft.Json;


namespace Discord.API.Rest namespace Discord.API.Rest
{ {
public class ModifyGuildMemberParams public class ModifyGuildMemberParams
{ {
[JsonProperty("roles")] [JsonProperty("roles")]
public ulong[] Roles { get; set; }
public Optional<ulong[]> Roles { get; set; }
[JsonProperty("mute")] [JsonProperty("mute")]
public bool Mute { get; set; }
public Optional<bool> Mute { get; set; }
[JsonProperty("deaf")] [JsonProperty("deaf")]
public bool Deaf { get; set; }
[JsonProperty("channel_id"), JsonConverter(typeof(UInt64EntityConverter))]
public IVoiceChannel VoiceChannel { get; set; }
public Optional<bool> Deaf { get; set; }
[JsonProperty("nick")]
public Optional<string> Nickname { get; set; }
[JsonProperty("channel_id")]
public Optional<IVoiceChannel> VoiceChannel { get; set; }
} }
} }

+ 9
- 9
src/Discord.Net/API/Rest/ModifyGuildParams.cs View File

@@ -7,20 +7,20 @@ namespace Discord.API.Rest
public class ModifyGuildParams public class ModifyGuildParams
{ {
[JsonProperty("name")] [JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("region"), JsonConverterAttribute(typeof(StringEntityConverter))]
public IVoiceRegion Region { get; set; }
public Optional<string> Name { get; set; }
[JsonProperty("region")]
public Optional<IVoiceRegion> Region { get; set; }
[JsonProperty("verification_level")] [JsonProperty("verification_level")]
public int VerificationLevel { get; set; }
public Optional<int> VerificationLevel { get; set; }
[JsonProperty("afk_channel_id")] [JsonProperty("afk_channel_id")]
public ulong? AFKChannelId { get; set; }
public Optional<ulong?> AFKChannelId { get; set; }
[JsonProperty("afk_timeout")] [JsonProperty("afk_timeout")]
public int AFKTimeout { get; set; }
public Optional<int> AFKTimeout { get; set; }
[JsonProperty("icon"), JsonConverter(typeof(ImageConverter))] [JsonProperty("icon"), JsonConverter(typeof(ImageConverter))]
public Stream Icon { get; set; }
public Optional<Stream> Icon { get; set; }
[JsonProperty("owner_id")] [JsonProperty("owner_id")]
public GuildMember Owner { get; set; }
public Optional<GuildMember> Owner { get; set; }
[JsonProperty("splash"), JsonConverter(typeof(ImageConverter))] [JsonProperty("splash"), JsonConverter(typeof(ImageConverter))]
public Stream Splash { get; set; }
public Optional<Stream> Splash { get; set; }
} }
} }

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

@@ -5,14 +5,14 @@ namespace Discord.API.Rest
public class ModifyGuildRoleParams public class ModifyGuildRoleParams
{ {
[JsonProperty("name")] [JsonProperty("name")]
public string Name { get; set; }
public Optional<string> Name { get; set; }
[JsonProperty("permissions")] [JsonProperty("permissions")]
public uint Permissions { get; set; }
public Optional<uint> Permissions { get; set; }
[JsonProperty("position")] [JsonProperty("position")]
public int Position { get; set; }
public Optional<int> Position { get; set; }
[JsonProperty("color")] [JsonProperty("color")]
public uint Color { get; set; }
public Optional<uint> Color { get; set; }
[JsonProperty("hoist")] [JsonProperty("hoist")]
public bool Hoist { get; set; }
public Optional<bool> Hoist { get; set; }
} }
} }

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

@@ -5,6 +5,6 @@ namespace Discord.API.Rest
public class ModifyGuildRolesParams : ModifyGuildRoleParams public class ModifyGuildRolesParams : ModifyGuildRoleParams
{ {
[JsonProperty("id")] [JsonProperty("id")]
public ulong Id { get; set; }
public Optional<ulong> Id { get; set; }
} }
} }

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

@@ -5,6 +5,6 @@ namespace Discord.API.Rest
public class ModifyMessageParams public class ModifyMessageParams
{ {
[JsonProperty("content")] [JsonProperty("content")]
public string Content { get; set; } = "";
public Optional<string> Content { get; set; } = "";
} }
} }

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

@@ -5,6 +5,6 @@ namespace Discord.API.Rest
public class ModifyTextChannelParams : ModifyGuildChannelParams public class ModifyTextChannelParams : ModifyGuildChannelParams
{ {
[JsonProperty("topic")] [JsonProperty("topic")]
public string Topic { get; set; }
public Optional<string> Topic { get; set; }
} }
} }

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

@@ -5,6 +5,6 @@ namespace Discord.API.Rest
public class ModifyVoiceChannelParams : ModifyGuildChannelParams public class ModifyVoiceChannelParams : ModifyGuildChannelParams
{ {
[JsonProperty("bitrate")] [JsonProperty("bitrate")]
public int Bitrate { get; set; }
public Optional<int> Bitrate { get; set; }
} }
} }

+ 12
- 11
src/Discord.Net/API/Rest/UploadFileParams.cs View File

@@ -4,21 +4,22 @@ namespace Discord.API.Rest
{ {
public class UploadFileParams public class UploadFileParams
{ {
public string Content { get; set; } = "";
public string Nonce { get; set; } = null;
public bool IsTTS { get; set; } = false;
public string Filename { get; set; } = "unknown.dat"; public string Filename { get; set; } = "unknown.dat";


public Optional<string> Content { get; set; }
public Optional<string> Nonce { get; set; }
public Optional<bool> IsTTS { get; set; }

public IReadOnlyDictionary<string, string> ToDictionary() public IReadOnlyDictionary<string, string> ToDictionary()
{ {
var dic = new Dictionary<string, string>
{
["content"] = Content,
["tts"] = IsTTS.ToString()
};
if (Nonce != null)
dic.Add("nonce", Nonce);
return dic;
var d = new Dictionary<string, string>();
if (Content.IsSpecified)
d["content"] = Content.Value;
if (IsTTS.IsSpecified)
d["tts"] = IsTTS.Value.ToString();
if (Nonce.IsSpecified)
d["nonce"] = Nonce.Value;
return d;
} }
} }
} }

+ 3
- 1
src/Discord.Net/Common/Entities/Guilds/IGuild.cs View File

@@ -90,7 +90,9 @@ namespace Discord
/// <summary> Gets a collection of all users in this guild. </summary> /// <summary> Gets a collection of all users in this guild. </summary>
Task<IEnumerable<IGuildUser>> GetUsers(); Task<IEnumerable<IGuildUser>> GetUsers();
/// <summary> Gets the user in this guild with the provided id, or null if not found. </summary> /// <summary> Gets the user in this guild with the provided id, or null if not found. </summary>
Task<IGuildUser> GetUser(ulong id);
Task<IGuildUser> GetUser(ulong id);
/// <summary> Gets the current user for this guild. </summary>
Task<IGuildUser> GetCurrentUser();
Task<int> PruneUsers(int days = 30, bool simulate = false); Task<int> PruneUsers(int days = 30, bool simulate = false);
} }
} }

+ 2
- 0
src/Discord.Net/Common/Entities/Users/IUser.cs View File

@@ -12,6 +12,8 @@ namespace Discord
ushort Discriminator { get; } ushort Discriminator { get; }
/// <summary> Returns true if this user is a bot account. </summary> /// <summary> Returns true if this user is a bot account. </summary>
bool IsBot { get; } bool IsBot { get; }
/// <summary> Returns true is this user is the current logged-in account. </summary>
bool IsCurrentUser { get; }
/// <summary> Gets the current status of this user. </summary> /// <summary> Gets the current status of this user. </summary>
UserStatus Status { get; } UserStatus Status { get; }
/// <summary> Gets the username for this user. </summary> /// <summary> Gets the username for this user. </summary>


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

@@ -66,6 +66,8 @@
<Compile Include="API\Common\UserGuild.cs" /> <Compile Include="API\Common\UserGuild.cs" />
<Compile Include="API\Common\VoiceRegion.cs" /> <Compile Include="API\Common\VoiceRegion.cs" />
<Compile Include="API\Common\VoiceState.cs" /> <Compile Include="API\Common\VoiceState.cs" />
<Compile Include="API\IOptional.cs" />
<Compile Include="API\Optional.cs" />
<Compile Include="API\Rest\DeleteMessagesParam.cs" /> <Compile Include="API\Rest\DeleteMessagesParam.cs" />
<Compile Include="API\Rest\GetGuildMembersParams.cs" /> <Compile Include="API\Rest\GetGuildMembersParams.cs" />
<Compile Include="API\Rest\UploadFileParams.cs" /> <Compile Include="API\Rest\UploadFileParams.cs" />
@@ -95,6 +97,8 @@
<Compile Include="API\Rest\ModifyVoiceChannelParams.cs" /> <Compile Include="API\Rest\ModifyVoiceChannelParams.cs" />
<Compile Include="DiscordConfig.cs" /> <Compile Include="DiscordConfig.cs" />
<Compile Include="API\DiscordRawClient.cs" /> <Compile Include="API\DiscordRawClient.cs" />
<Compile Include="Net\Converters\OptionalContractResolver.cs" />
<Compile Include="Net\Converters\OptionalConverter.cs" />
<Compile Include="Net\RateLimitException.cs" /> <Compile Include="Net\RateLimitException.cs" />
<Compile Include="Net\Rest\RequestQueue\BucketGroup.cs" /> <Compile Include="Net\Rest\RequestQueue\BucketGroup.cs" />
<Compile Include="Net\Rest\RequestQueue\GlobalBucket.cs" /> <Compile Include="Net\Rest\RequestQueue\GlobalBucket.cs" />


+ 5
- 2
src/Discord.Net/Net/Converters/ImageConverter.cs View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Discord.API;
using Newtonsoft.Json;
using System; using System;
using System.IO; using System.IO;


@@ -6,7 +7,7 @@ namespace Discord.Net.Converters
{ {
public class ImageConverter : JsonConverter public class ImageConverter : JsonConverter
{ {
public override bool CanConvert(Type objectType) => objectType == typeof(Stream);
public override bool CanConvert(Type objectType) => objectType == typeof(Stream) || objectType == typeof(Optional<Stream>);
public override bool CanRead => true; public override bool CanRead => true;
public override bool CanWrite => true; public override bool CanWrite => true;


@@ -17,6 +18,8 @@ namespace Discord.Net.Converters


public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
if (value is Optional<Stream>)
value = (Optional<Stream>)value;
var stream = value as Stream; var stream = value as Stream;


byte[] bytes = new byte[stream.Length - stream.Position]; byte[] bytes = new byte[stream.Length - stream.Position];


+ 34
- 0
src/Discord.Net/Net/Converters/OptionalContractResolver.cs View File

@@ -0,0 +1,34 @@
using Discord.API;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Linq.Expressions;
using System.Reflection;

namespace Discord.Net.Converters
{
public class OptionalContractResolver : DefaultContractResolver
{
private static readonly PropertyInfo _isSpecified = typeof(IOptional).GetProperty(nameof(IOptional.IsSpecified));

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
var type = property.PropertyType;

if (member.MemberType == MemberTypes.Property)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Optional<>))
{
var parentArg = Expression.Parameter(typeof(object));
var optional = Expression.Property(Expression.Convert(parentArg, property.DeclaringType), member as PropertyInfo);
var isSpecified = Expression.Property(optional, _isSpecified);
var lambda = Expression.Lambda<Func<object, bool>>(isSpecified, parentArg).Compile();
property.ShouldSerialize = x => lambda(x);
}
}

return property;
}
}
}

+ 23
- 0
src/Discord.Net/Net/Converters/OptionalConverter.cs View File

@@ -0,0 +1,23 @@
using Discord.API;
using Newtonsoft.Json;
using System;

namespace Discord.Net.Converters
{
public class OptionalConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Optional<>);
public override bool CanRead => false;
public override bool CanWrite => true;

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new InvalidOperationException();
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, (value as IOptional).Value);
}
}
}

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

@@ -1,5 +1,4 @@
using Newtonsoft.Json;
using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -33,6 +32,8 @@ namespace Discord.Net.Rest
UseProxy = false, UseProxy = false,
PreAuthenticate = false PreAuthenticate = false
}); });

SetHeader("accept-encoding", "gzip, deflate");
} }
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
@@ -54,18 +55,18 @@ namespace Discord.Net.Rest
_client.DefaultRequestHeaders.Add(key, value); _client.DefaultRequestHeaders.Add(key, value);
} }


public async Task<Stream> Send(string method, string endpoint, string json = null)
public async Task<Stream> Send(string method, string endpoint, string json = null, bool headerOnly = false)
{ {
string uri = Path.Combine(_baseUrl, endpoint); string uri = Path.Combine(_baseUrl, endpoint);
using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) using (var restRequest = new HttpRequestMessage(GetMethod(method), uri))
{ {
if (json != null) if (json != null)
restRequest.Content = new StringContent(json, Encoding.UTF8, "application/json"); restRequest.Content = new StringContent(json, Encoding.UTF8, "application/json");
return await SendInternal(restRequest, _cancelToken).ConfigureAwait(false);
return await SendInternal(restRequest, _cancelToken, headerOnly).ConfigureAwait(false);
} }
} }


public async Task<Stream> Send(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams)
public async Task<Stream> Send(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, bool headerOnly = false)
{ {
string uri = Path.Combine(_baseUrl, endpoint); string uri = Path.Combine(_baseUrl, endpoint);
using (var restRequest = new HttpRequestMessage(GetMethod(method), uri)) using (var restRequest = new HttpRequestMessage(GetMethod(method), uri))
@@ -95,11 +96,11 @@ namespace Discord.Net.Rest
} }
} }
restRequest.Content = content; restRequest.Content = content;
return await SendInternal(restRequest, _cancelToken).ConfigureAwait(false);
return await SendInternal(restRequest, _cancelToken, headerOnly).ConfigureAwait(false);
} }
} }


private async Task<Stream> SendInternal(HttpRequestMessage request, CancellationToken cancelToken)
private async Task<Stream> SendInternal(HttpRequestMessage request, CancellationToken cancelToken, bool headerOnly)
{ {
int retryCount = 0; int retryCount = 0;
while (true) while (true)
@@ -125,7 +126,10 @@ namespace Discord.Net.Rest
throw new HttpException(response.StatusCode); throw new HttpException(response.StatusCode);
} }


return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
if (headerOnly)
return null;
else
return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
} }
} }




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

@@ -8,7 +8,7 @@ namespace Discord.Net.Rest
{ {
void SetHeader(string key, string value); void SetHeader(string key, string value);


Task<Stream> Send(string method, string endpoint, string json = null);
Task<Stream> Send(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams);
Task<Stream> Send(string method, string endpoint, string json = null, bool headerOnly = false);
Task<Stream> Send(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, bool headerOnly = false);
} }
} }

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

@@ -83,9 +83,9 @@ namespace Discord.Net.Rest
{ {
Stream stream; Stream stream;
if (request.IsMultipart) if (request.IsMultipart)
stream = await _parent.RestClient.Send(request.Method, request.Endpoint, request.MultipartParams).ConfigureAwait(false);
stream = await _parent.RestClient.Send(request.Method, request.Endpoint, request.MultipartParams, request.HeaderOnly).ConfigureAwait(false);
else else
stream = await _parent.RestClient.Send(request.Method, request.Endpoint, request.Json).ConfigureAwait(false);
stream = await _parent.RestClient.Send(request.Method, request.Endpoint, request.Json, request.HeaderOnly).ConfigureAwait(false);
request.Promise.SetResult(stream); request.Promise.SetResult(stream);
} }
catch (HttpRateLimitException ex) //Preemptive check failed, use Discord's time instead of our own catch (HttpRateLimitException ex) //Preemptive check failed, use Discord's time instead of our own


+ 7
- 5
src/Discord.Net/Net/Rest/RequestQueue/RestRequest.cs View File

@@ -9,29 +9,31 @@ namespace Discord.Net.Rest
public string Method { get; } public string Method { get; }
public string Endpoint { get; } public string Endpoint { get; }
public string Json { get; } public string Json { get; }
public bool HeaderOnly { get; }
public IReadOnlyDictionary<string, object> MultipartParams { get; } public IReadOnlyDictionary<string, object> MultipartParams { get; }
public TaskCompletionSource<Stream> Promise { get; } public TaskCompletionSource<Stream> Promise { get; }


public bool IsMultipart => MultipartParams != null; public bool IsMultipart => MultipartParams != null;


public RestRequest(string method, string endpoint, string json)
: this(method, endpoint)
public RestRequest(string method, string endpoint, string json, bool headerOnly)
: this(method, endpoint, headerOnly)
{ {
Json = json; Json = json;
} }


public RestRequest(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams)
: this(method, endpoint)
public RestRequest(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, bool headerOnly)
: this(method, endpoint, headerOnly)
{ {
MultipartParams = multipartParams; MultipartParams = multipartParams;
} }


private RestRequest(string method, string endpoint)
private RestRequest(string method, string endpoint, bool headerOnly)
{ {
Method = method; Method = method;
Endpoint = endpoint; Endpoint = endpoint;
Json = null; Json = null;
MultipartParams = null; MultipartParams = null;
HeaderOnly = headerOnly;
Promise = new TaskCompletionSource<Stream>(); Promise = new TaskCompletionSource<Stream>();
} }
} }


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

@@ -306,7 +306,6 @@ namespace Discord.Rest
var models = await Discord.BaseClient.GetGuildMembers(Id, args).ConfigureAwait(false); var models = await Discord.BaseClient.GetGuildMembers(Id, args).ConfigureAwait(false);
return models.Select(x => new GuildUser(this, x)); return models.Select(x => new GuildUser(this, x));
} }

/// <summary> Gets the user in this guild with the provided id, or null if not found. </summary> /// <summary> Gets the user in this guild with the provided id, or null if not found. </summary>
public async Task<GuildUser> GetUser(ulong id) public async Task<GuildUser> GetUser(ulong id)
{ {
@@ -315,7 +314,11 @@ namespace Discord.Rest
return new GuildUser(this, model); return new GuildUser(this, model);
return null; return null;
} }

/// <summary> Gets a the current user. </summary>
public async Task<GuildUser> GetCurrentUser()
{
return await GetUser(Discord.CurrentUser.Id).ConfigureAwait(false);
}
public async Task<int> PruneUsers(int days = 30, bool simulate = false) public async Task<int> PruneUsers(int days = 30, bool simulate = false)
{ {
var args = new GuildPruneParams() { Days = days }; var args = new GuildPruneParams() { Days = days };
@@ -367,6 +370,8 @@ namespace Discord.Rest
=> Task.FromResult<IEnumerable<IRole>>(Roles); => Task.FromResult<IEnumerable<IRole>>(Roles);
async Task<IGuildUser> IGuild.GetUser(ulong id) async Task<IGuildUser> IGuild.GetUser(ulong id)
=> await GetUser(id).ConfigureAwait(false); => await GetUser(id).ConfigureAwait(false);
async Task<IGuildUser> IGuild.GetCurrentUser()
=> await GetCurrentUser().ConfigureAwait(false);
async Task<IEnumerable<IGuildUser>> IGuild.GetUsers() async Task<IEnumerable<IGuildUser>> IGuild.GetUsers()
=> await GetUsers().ConfigureAwait(false); => await GetUsers().ConfigureAwait(false);
} }


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

@@ -2,6 +2,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Model = Discord.API.GuildMember; using Model = Discord.API.GuildMember;


@@ -82,8 +83,15 @@ namespace Discord.Rest


var args = new ModifyGuildMemberParams(); var args = new ModifyGuildMemberParams();
func(args); func(args);
var model = await Discord.BaseClient.ModifyGuildMember(Guild.Id, Id, args).ConfigureAwait(false);
Update(model);
await Discord.BaseClient.ModifyGuildMember(Guild.Id, Id, args).ConfigureAwait(false);
if (args.Deaf.IsSpecified)
IsDeaf = args.Deaf;
if (args.Mute.IsSpecified)
IsMute = args.Mute;
if (args.Nickname.IsSpecified)
Nickname = args.Nickname;
if (args.Roles.IsSpecified)
_roles = args.Roles.Value.Select(x => Guild.GetRole(x)).Where(x => x != null).ToImmutableArray();
} }






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

@@ -28,6 +28,8 @@ namespace Discord.Rest
public string Mention => MentionHelper.Mention(this, false); public string Mention => MentionHelper.Mention(this, false);
/// <inheritdoc /> /// <inheritdoc />
public string NicknameMention => MentionHelper.Mention(this, true); public string NicknameMention => MentionHelper.Mention(this, true);
/// <inheritdoc />
public bool IsCurrentUser => Id == Discord.CurrentUser.Id;


internal User(Model model) internal User(Model model)
{ {


Loading…
Cancel
Save