diff --git a/src/Discord.Net/API/Requests.cs b/src/Discord.Net/API/Requests.cs index c1808fbd5..10ca79532 100644 --- a/src/Discord.Net/API/Requests.cs +++ b/src/Discord.Net/API/Requests.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using System.Collections.Generic; +using System.Collections; namespace Discord.API { @@ -43,6 +44,21 @@ namespace Discord.API [JsonProperty("topic", NullValueHandling = NullValueHandling.Ignore)] public string Topic; } + internal sealed class ReorderChannelsRequest : IEnumerable + { + public sealed class Channel + { + [JsonProperty("id")] + public string Id; + [JsonProperty("position")] + public uint Position; + } + private IEnumerable _channels; + public ReorderChannelsRequest(IEnumerable channels) { _channels = channels; } + + public IEnumerator GetEnumerator() =>_channels.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _channels.GetEnumerator(); + } //Invites internal sealed class CreateInviteRequest diff --git a/src/Discord.Net/DiscordAPIClient.cs b/src/Discord.Net/DiscordAPIClient.cs index 2e6b35d85..b92b88d4c 100644 --- a/src/Discord.Net/DiscordAPIClient.cs +++ b/src/Discord.Net/DiscordAPIClient.cs @@ -1,6 +1,7 @@ using Discord.API; using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -85,6 +86,17 @@ namespace Discord var request = new EditChannelRequest { Name = name, Topic = topic }; return _rest.Patch(Endpoints.Channel(channelId), request); } + public Task ReorderChannels(string serverId, int startPos, IEnumerable channelIds) + { + if (serverId == null) throw new ArgumentNullException(nameof(serverId)); + if (channelIds == null) throw new ArgumentNullException(nameof(channelIds)); + if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer."); + + uint pos = (uint)startPos; + var channels = channelIds.Select(x => new ReorderChannelsRequest.Channel { Id = x, Position = pos++ }); + var request = new ReorderChannelsRequest(channels); + return _rest.Patch(Endpoints.ServerChannels(serverId), request); + } public Task GetMessages(string channelId, int count) { if (channelId == null) throw new ArgumentNullException(nameof(channelId)); diff --git a/src/Discord.Net/DiscordClient.API.cs b/src/Discord.Net/DiscordClient.API.cs index 178cb3731..bcbbab09c 100644 --- a/src/Discord.Net/DiscordClient.API.cs +++ b/src/Discord.Net/DiscordClient.API.cs @@ -108,16 +108,58 @@ namespace Discord } /// Edits the provided channel, changing only non-null attributes. - public Task EditChannel(Channel channel, string name = null, string topic = null) - => EditChannel(channel?.Id, name: name, topic: topic); + public Task EditChannel(string channelId, string name = null, string topic = null, int? position = null) + => EditChannel(_channels[channelId], name: name, topic: topic, position: position); /// Edits the provided channel, changing only non-null attributes. - public Task EditChannel(string channelId, string name = null, string topic = null) + public async Task EditChannel(Channel channel, string name = null, string topic = null, int? position = null) { CheckReady(); - if (channelId == null) throw new ArgumentNullException(nameof(channelId)); - if (topic == null) throw new ArgumentNullException(nameof(topic)); + if (channel == null) throw new ArgumentNullException(nameof(channel)); + + await _api.EditChannel(channel.Id, name: name, topic: topic); + + if (position != null) + { + int oldPos = channel.Position; + int newPos = position.Value; + int minPos; + Channel[] channels = channel.Server.Channels.OrderBy(x => x.Position).ToArray(); - return _api.EditChannel(channelId, name: name, topic: topic); + if (oldPos < newPos) //Moving Down + { + minPos = oldPos; + for (int i = oldPos; i < newPos; i++) + channels[i] = channels[i + 1]; + channels[newPos] = channel; + } + else //(oldPos > newPos) Moving Up + { + minPos = newPos; + for (int i = oldPos; i > newPos; i--) + channels[i] = channels[i - 1]; + channels[newPos] = channel; + } + await _api.ReorderChannels(channel.ServerId, minPos, channels.Skip(minPos).Select(x => x.Id)); + } + } + + public Task ReorderChannels(Server server, int startPos, IEnumerable channels) + => ReorderChannels(server.Id, startPos, channels); + public Task ReorderChannels(string serverId, int startPos, IEnumerable channels) + { + if (serverId == null) throw new ArgumentNullException(nameof(serverId)); + if (channels == null) throw new ArgumentNullException(nameof(channels)); + if (startPos < 0) throw new ArgumentOutOfRangeException(nameof(startPos), "startPos must be a positive integer."); + + return _api.ReorderChannels(serverId, startPos, channels.Select(x => + { + if (x is string) + return x as string; + else if (x is Channel) + return (x as Role).Id; + else + throw new ArgumentException("Channels must be a collection of string or Channel.", nameof(channels)); + })); } /// Destroys the provided channel. @@ -243,7 +285,7 @@ namespace Discord else if (x is Role) return (x as Role).Id; else - throw new ArgumentException("Roles must be a collection of strings or roles.", nameof(roles)); + throw new ArgumentException("Roles must be a collection of string or Role.", nameof(roles)); }); return _api.EditMember(serverId, userId, mute, deaf, newRoles);