| @@ -535,7 +535,7 @@ namespace Discord.API | |||||
| Preconditions.NotEqual(args.AFKChannelId, 0, nameof(args.AFKChannelId)); | Preconditions.NotEqual(args.AFKChannelId, 0, nameof(args.AFKChannelId)); | ||||
| Preconditions.AtLeast(args.AFKTimeout, 0, nameof(args.AFKTimeout)); | Preconditions.AtLeast(args.AFKTimeout, 0, nameof(args.AFKTimeout)); | ||||
| Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name)); | Preconditions.NotNullOrEmpty(args.Name, nameof(args.Name)); | ||||
| Preconditions.NotNull(args.Owner, nameof(args.Owner)); | |||||
| Preconditions.GreaterThan(args.OwnerId, 0, nameof(args.OwnerId)); | |||||
| Preconditions.NotNull(args.Region, nameof(args.Region)); | Preconditions.NotNull(args.Region, nameof(args.Region)); | ||||
| Preconditions.AtLeast(args.VerificationLevel, 0, nameof(args.VerificationLevel)); | Preconditions.AtLeast(args.VerificationLevel, 0, nameof(args.VerificationLevel)); | ||||
| @@ -831,7 +831,21 @@ namespace Discord.API | |||||
| int limit = args.Limit; | int limit = args.Limit; | ||||
| ulong? relativeId = args.RelativeMessageId.IsSpecified ? args.RelativeMessageId.Value : (ulong?)null; | ulong? relativeId = args.RelativeMessageId.IsSpecified ? args.RelativeMessageId.Value : (ulong?)null; | ||||
| string relativeDir = args.RelativeDirection == Direction.After ? "after" : "before"; | |||||
| string relativeDir; | |||||
| switch (args.RelativeDirection) | |||||
| { | |||||
| case Direction.Before: | |||||
| default: | |||||
| relativeDir = "before"; | |||||
| break; | |||||
| case Direction.After: | |||||
| relativeDir = "after"; | |||||
| break; | |||||
| case Direction.Around: | |||||
| relativeDir = "around"; | |||||
| break; | |||||
| } | |||||
| int runs = (limit + DiscordConfig.MaxMessagesPerBatch - 1) / DiscordConfig.MaxMessagesPerBatch; | int runs = (limit + DiscordConfig.MaxMessagesPerBatch - 1) / DiscordConfig.MaxMessagesPerBatch; | ||||
| int lastRunCount = limit - (runs - 1) * DiscordConfig.MaxMessagesPerBatch; | int lastRunCount = limit - (runs - 1) * DiscordConfig.MaxMessagesPerBatch; | ||||
| @@ -1079,7 +1093,7 @@ namespace Discord.API | |||||
| public async Task<Channel> CreateDMChannelAsync(CreateDMChannelParams args, RequestOptions options = null) | public async Task<Channel> CreateDMChannelAsync(CreateDMChannelParams args, RequestOptions options = null) | ||||
| { | { | ||||
| Preconditions.NotNull(args, nameof(args)); | Preconditions.NotNull(args, nameof(args)); | ||||
| Preconditions.NotEqual(args.RecipientId, 0, nameof(args.RecipientId)); | |||||
| Preconditions.GreaterThan(args.RecipientId, 0, nameof(args.Recipient)); | |||||
| return await SendAsync<Channel>("POST", $"users/@me/channels", args, options: options).ConfigureAwait(false); | return await SendAsync<Channel>("POST", $"users/@me/channels", args, options: options).ConfigureAwait(false); | ||||
| } | } | ||||
| @@ -6,5 +6,7 @@ namespace Discord.API.Rest | |||||
| { | { | ||||
| [JsonProperty("recipient_id")] | [JsonProperty("recipient_id")] | ||||
| public ulong RecipientId { get; set; } | public ulong RecipientId { get; set; } | ||||
| [JsonIgnore] | |||||
| public IUser Recipient { set { RecipientId = value.Id; } } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,5 +1,6 @@ | |||||
| using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | |||||
| namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
| { | { | ||||
| @@ -7,5 +8,7 @@ namespace Discord.API.Rest | |||||
| { | { | ||||
| [JsonProperty("messages")] | [JsonProperty("messages")] | ||||
| public IEnumerable<ulong> MessageIds { get; set; } | public IEnumerable<ulong> MessageIds { get; set; } | ||||
| [JsonIgnore] | |||||
| public IEnumerable<IMessage> Messages { set { MessageIds = value.Select(x => x.Id); } } | |||||
| } | } | ||||
| } | } | ||||
| @@ -6,5 +6,6 @@ | |||||
| public Direction RelativeDirection { get; set; } = Direction.Before; | public Direction RelativeDirection { get; set; } = Direction.Before; | ||||
| public Optional<ulong> RelativeMessageId { get; set; } | public Optional<ulong> RelativeMessageId { get; set; } | ||||
| public Optional<IMessage> RelativeMessage { set { RelativeMessageId = value.IsSpecified ? value.Value.Id : Optional.Create<ulong>(); } } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,5 +1,4 @@ | |||||
| using Discord.Net.Converters; | |||||
| using Newtonsoft.Json; | |||||
| using Newtonsoft.Json; | |||||
| namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
| { | { | ||||
| @@ -7,7 +6,10 @@ namespace Discord.API.Rest | |||||
| { | { | ||||
| [JsonProperty("enabled")] | [JsonProperty("enabled")] | ||||
| public Optional<bool> Enabled { get; set; } | public Optional<bool> Enabled { get; set; } | ||||
| [JsonProperty("channel")] | [JsonProperty("channel")] | ||||
| public Optional<IVoiceChannel> Channel { get; set; } | |||||
| public Optional<ulong> ChannelId { get; set; } | |||||
| [JsonIgnore] | |||||
| public Optional<IVoiceChannel> Channel { set { ChannelId = value.IsSpecified ? value.Value.Id : Optional.Create<ulong>(); } } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,18 +1,26 @@ | |||||
| using Newtonsoft.Json; | using Newtonsoft.Json; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
| { | { | ||||
| public class ModifyGuildMemberParams | public class ModifyGuildMemberParams | ||||
| { | { | ||||
| [JsonProperty("roles")] | |||||
| public Optional<ulong[]> Roles { get; set; } | |||||
| [JsonProperty("mute")] | [JsonProperty("mute")] | ||||
| public Optional<bool> Mute { get; set; } | public Optional<bool> Mute { get; set; } | ||||
| [JsonProperty("deaf")] | [JsonProperty("deaf")] | ||||
| public Optional<bool> Deaf { get; set; } | public Optional<bool> Deaf { get; set; } | ||||
| [JsonProperty("nick")] | [JsonProperty("nick")] | ||||
| public Optional<string> Nickname { get; set; } | public Optional<string> Nickname { get; set; } | ||||
| [JsonProperty("roles")] | |||||
| public Optional<IEnumerable<ulong>> RoleIds { get; set; } | |||||
| [JsonIgnore] | |||||
| public Optional<IEnumerable<IRole>> Roles { set { RoleIds = value.IsSpecified ? Optional.Create(value.Value.Select(x => x.Id)) : Optional.Create<IEnumerable<ulong>>(); } } | |||||
| [JsonProperty("channel_id")] | [JsonProperty("channel_id")] | ||||
| public Optional<IVoiceChannel> VoiceChannel { get; set; } | |||||
| public Optional<ulong> VoiceChannelId { get; set; } | |||||
| [JsonIgnore] | |||||
| public Optional<IVoiceChannel> VoiceChannel { set { VoiceChannelId = value.IsSpecified ? value.Value.Id : Optional.Create<ulong>(); } } | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,5 +1,4 @@ | |||||
| using Discord.Net.Converters; | |||||
| using Newtonsoft.Json; | |||||
| using Newtonsoft.Json; | |||||
| using System.IO; | using System.IO; | ||||
| namespace Discord.API.Rest | namespace Discord.API.Rest | ||||
| @@ -12,15 +11,21 @@ namespace Discord.API.Rest | |||||
| public Optional<IVoiceRegion> Region { get; set; } | public Optional<IVoiceRegion> Region { get; set; } | ||||
| [JsonProperty("verification_level")] | [JsonProperty("verification_level")] | ||||
| public Optional<int> VerificationLevel { get; set; } | public Optional<int> VerificationLevel { get; set; } | ||||
| [JsonProperty("afk_channel_id")] | |||||
| public Optional<ulong?> AFKChannelId { get; set; } | |||||
| [JsonProperty("afk_timeout")] | [JsonProperty("afk_timeout")] | ||||
| public Optional<int> AFKTimeout { get; set; } | public Optional<int> AFKTimeout { get; set; } | ||||
| [JsonProperty("icon"), Image] | [JsonProperty("icon"), Image] | ||||
| public Optional<Stream> Icon { get; set; } | public Optional<Stream> Icon { get; set; } | ||||
| [JsonProperty("owner_id")] | |||||
| public Optional<GuildMember> Owner { get; set; } | |||||
| [JsonProperty("splash"), Image] | [JsonProperty("splash"), Image] | ||||
| public Optional<Stream> Splash { get; set; } | public Optional<Stream> Splash { get; set; } | ||||
| [JsonProperty("afk_channel_id")] | |||||
| public Optional<ulong?> AFKChannelId { get; set; } | |||||
| [JsonIgnore] | |||||
| public Optional<IVoiceChannel> AFKChannel { set { OwnerId = value.IsSpecified ? value.Value.Id : Optional.Create<ulong>(); } } | |||||
| [JsonProperty("owner_id")] | |||||
| public Optional<ulong> OwnerId { get; set; } | |||||
| [JsonIgnore] | |||||
| public Optional<IGuildUser> Owner { set { OwnerId = value.IsSpecified ? value.Value.Id : Optional.Create<ulong>(); } } | |||||
| } | } | ||||
| } | } | ||||
| @@ -124,7 +124,7 @@ namespace Discord | |||||
| args.Nickname = new Optional<string>(); //Remove | args.Nickname = new Optional<string>(); //Remove | ||||
| } | } | ||||
| if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.Roles.IsSpecified) | |||||
| if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.RoleIds.IsSpecified) | |||||
| { | { | ||||
| await Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, Id, args).ConfigureAwait(false); | await Discord.ApiClient.ModifyGuildMemberAsync(Guild.Id, Id, args).ConfigureAwait(false); | ||||
| if (args.Deaf.IsSpecified) | if (args.Deaf.IsSpecified) | ||||
| @@ -133,8 +133,8 @@ namespace Discord | |||||
| IsMute = args.Mute.Value; | IsMute = args.Mute.Value; | ||||
| if (args.Nickname.IsSpecified) | if (args.Nickname.IsSpecified) | ||||
| Nickname = args.Nickname.Value ?? ""; | Nickname = args.Nickname.Value ?? ""; | ||||
| if (args.Roles.IsSpecified) | |||||
| Roles = args.Roles.Value.Select(x => Guild.GetRole(x)).Where(x => x != null).ToImmutableArray(); | |||||
| if (args.RoleIds.IsSpecified) | |||||
| Roles = args.RoleIds.Value.Select(x => Guild.GetRole(x)).Where(x => x != null).ToImmutableArray(); | |||||
| } | } | ||||
| } | } | ||||
| public async Task KickAsync() | public async Task KickAsync() | ||||
| @@ -153,7 +153,7 @@ namespace Discord | |||||
| public async Task<IDMChannel> CreateDMChannelAsync() | public async Task<IDMChannel> CreateDMChannelAsync() | ||||
| { | { | ||||
| var args = new CreateDMChannelParams { RecipientId = Id }; | |||||
| var args = new CreateDMChannelParams { Recipient = this }; | |||||
| var model = await Discord.ApiClient.CreateDMChannelAsync(args).ConfigureAwait(false); | var model = await Discord.ApiClient.CreateDMChannelAsync(args).ConfigureAwait(false); | ||||
| return new DMChannel(Discord, User, model); | return new DMChannel(Discord, User, model); | ||||
| @@ -1,47 +0,0 @@ | |||||
| using Newtonsoft.Json; | |||||
| using System; | |||||
| namespace Discord.Net.Converters | |||||
| { | |||||
| public class DirectionConverter : JsonConverter | |||||
| { | |||||
| public static readonly DirectionConverter Instance = new DirectionConverter(); | |||||
| public override bool CanConvert(Type objectType) => true; | |||||
| public override bool CanRead => true; | |||||
| public override bool CanWrite => true; | |||||
| public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | |||||
| { | |||||
| switch ((string)reader.Value) | |||||
| { | |||||
| case "before": | |||||
| return Direction.Before; | |||||
| case "after": | |||||
| return Direction.After; | |||||
| case "around": | |||||
| return Direction.Around; | |||||
| default: | |||||
| throw new JsonSerializationException("Unknown direction"); | |||||
| } | |||||
| } | |||||
| public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | |||||
| { | |||||
| switch ((Direction)value) | |||||
| { | |||||
| case Direction.Before: | |||||
| writer.WriteValue("before"); | |||||
| break; | |||||
| case Direction.After: | |||||
| writer.WriteValue("after"); | |||||
| break; | |||||
| case Direction.Around: | |||||
| writer.WriteValue("around"); | |||||
| break; | |||||
| default: | |||||
| throw new JsonSerializationException("Invalid direction"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -77,8 +77,6 @@ namespace Discord.Net.Converters | |||||
| return PermissionTargetConverter.Instance; | return PermissionTargetConverter.Instance; | ||||
| if (type == typeof(UserStatus)) | if (type == typeof(UserStatus)) | ||||
| return UserStatusConverter.Instance; | return UserStatusConverter.Instance; | ||||
| if (type == typeof(Direction)) | |||||
| return DirectionConverter.Instance; | |||||
| //Special | //Special | ||||
| if (type == typeof(Stream) && propInfo.GetCustomAttribute<ImageAttribute>() != null) | if (type == typeof(Stream) && propInfo.GetCustomAttribute<ImageAttribute>() != null) | ||||
| @@ -7,6 +7,7 @@ namespace Discord | |||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
| public struct Optional<T> | public struct Optional<T> | ||||
| { | { | ||||
| public static Optional<T> Unspecified => default(Optional<T>); | |||||
| private readonly T _value; | private readonly T _value; | ||||
| /// <summary> Gets the value for this paramter. </summary> | /// <summary> Gets the value for this paramter. </summary> | ||||
| @@ -28,7 +29,7 @@ namespace Discord | |||||
| _value = value; | _value = value; | ||||
| IsSpecified = true; | IsSpecified = true; | ||||
| } | } | ||||
| public T GetValueOrDefault() => _value; | public T GetValueOrDefault() => _value; | ||||
| public T GetValueOrDefault(T defaultValue) => IsSpecified ? _value : defaultValue; | public T GetValueOrDefault(T defaultValue) => IsSpecified ? _value : defaultValue; | ||||
| @@ -46,4 +47,9 @@ namespace Discord | |||||
| public static implicit operator Optional<T>(T value) => new Optional<T>(value); | public static implicit operator Optional<T>(T value) => new Optional<T>(value); | ||||
| public static explicit operator T(Optional<T> value) => value.Value; | public static explicit operator T(Optional<T> value) => value.Value; | ||||
| } | } | ||||
| public static class Optional | |||||
| { | |||||
| public static Optional<T> Create<T>() => Optional<T>.Unspecified; | |||||
| public static Optional<T> Create<T>(T value) => new Optional<T>(value); | |||||
| } | |||||
| } | } | ||||