diff --git a/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs b/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs index 5ceffef0e..33b311604 100644 --- a/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs +++ b/src/Discord.Net.Core/Entities/Users/GuildUserProperties.cs @@ -41,16 +41,16 @@ namespace Discord /// What roles should the user have? /// /// - /// To add a role to a user: - /// To remove a role from a user: + /// To add a role to a user: + /// To remove a role from a user: /// public Optional> Roles { get; set; } /// /// What roles should the user have? /// /// - /// To add a role to a user: - /// To remove a role from a user: + /// To add a role to a user: + /// To remove a role from a user: /// public Optional> RoleIds { get; set; } /// diff --git a/src/Discord.Net.Core/Entities/Users/IGuildUser.cs b/src/Discord.Net.Core/Entities/Users/IGuildUser.cs index 79e8f5dcc..cd9516395 100644 --- a/src/Discord.Net.Core/Entities/Users/IGuildUser.cs +++ b/src/Discord.Net.Core/Entities/Users/IGuildUser.cs @@ -28,5 +28,14 @@ namespace Discord Task KickAsync(RequestOptions options = null); /// Modifies this user's properties in this guild. Task ModifyAsync(Action func, RequestOptions options = null); + + /// Adds a role to this user in this guild. + Task AddRoleAsync(IRole role, RequestOptions options = null); + /// Adds roles to this user in this guild. + Task AddRolesAsync(IEnumerable roles, RequestOptions options = null); + /// Removes a role from this user in this guild. + Task RemoveRoleAsync(IRole role, RequestOptions options = null); + /// Removes roles from this user in this guild. + Task RemoveRolesAsync(IEnumerable roles, RequestOptions options = null); } } diff --git a/src/Discord.Net.Core/Extensions/GuildUserExtensions.cs b/src/Discord.Net.Core/Extensions/GuildUserExtensions.cs deleted file mode 100644 index 9d152adf9..000000000 --- a/src/Discord.Net.Core/Extensions/GuildUserExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Discord -{ - public static class GuildUserExtensions - { - public static Task AddRolesAsync(this IGuildUser user, params IRole[] roles) - => ChangeRolesAsync(user, add: roles); - public static Task AddRolesAsync(this IGuildUser user, IEnumerable roles) - => ChangeRolesAsync(user, add: roles); - public static Task RemoveRolesAsync(this IGuildUser user, params IRole[] roles) - => ChangeRolesAsync(user, remove: roles); - public static Task RemoveRolesAsync(this IGuildUser user, IEnumerable roles) - => ChangeRolesAsync(user, remove: roles); - public static async Task ChangeRolesAsync(this IGuildUser user, IEnumerable add = null, IEnumerable remove = null) - { - IEnumerable roleIds = user.RoleIds; - if (remove != null) - roleIds = roleIds.Except(remove.Select(x => x.Id)); - if (add != null) - roleIds = roleIds.Concat(add.Select(x => x.Id)); - await user.ModifyAsync(x => x.RoleIds = roleIds.ToArray()).ConfigureAwait(false); - } - } -} diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index b9c0e9fda..2e404003f 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -388,6 +388,26 @@ namespace Discord.API break; } } + public async Task AddRoleAsync(ulong guildId, ulong userId, ulong roleId, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + Preconditions.NotEqual(userId, 0, nameof(userId)); + Preconditions.NotEqual(roleId, 0, nameof(roleId)); + options = RequestOptions.CreateOrClone(options); + + var ids = new BucketIds(guildId: guildId); + await SendAsync("PUT", () => $"guilds/{guildId}/members/{userId}/roles/{roleId}", ids, options: options); + } + public async Task RemoveRoleAsync(ulong guildId, ulong userId, ulong roleId, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + Preconditions.NotEqual(userId, 0, nameof(userId)); + Preconditions.NotEqual(roleId, 0, nameof(roleId)); + options = RequestOptions.CreateOrClone(options); + + var ids = new BucketIds(guildId: guildId); + await SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}/roles/{roleId}", ids, options: options); + } //Channel Messages public async Task GetChannelMessageAsync(ulong channelId, ulong messageId, RequestOptions options = null) diff --git a/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs b/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs index 8de42608d..538f6b80f 100644 --- a/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs +++ b/src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs @@ -84,6 +84,18 @@ namespace Discord.Rest } public Task KickAsync(RequestOptions options = null) => UserHelper.KickAsync(this, Discord, options); + /// + public Task AddRoleAsync(IRole role, RequestOptions options = null) + => AddRolesAsync(new[] { role }, options); + /// + public Task AddRolesAsync(IEnumerable roles, RequestOptions options = null) + => UserHelper.AddRolesAsync(this, Discord, roles, options); + /// + public Task RemoveRoleAsync(IRole role, RequestOptions options = null) + => RemoveRolesAsync(new[] { role }, options); + /// + public Task RemoveRolesAsync(IEnumerable roles, RequestOptions options = null) + => UserHelper.RemoveRolesAsync(this, Discord, roles, options); public ChannelPermissions GetPermissions(IGuildChannel channel) { diff --git a/src/Discord.Net.Rest/Entities/Users/UserHelper.cs b/src/Discord.Net.Rest/Entities/Users/UserHelper.cs index 5189851fd..82e59227d 100644 --- a/src/Discord.Net.Rest/Entities/Users/UserHelper.cs +++ b/src/Discord.Net.Rest/Entities/Users/UserHelper.cs @@ -1,5 +1,6 @@ using Discord.API.Rest; using System; +using System.Collections.Generic; using System.Threading.Tasks; using Model = Discord.API.User; using ImageModel = Discord.API.Image; @@ -63,5 +64,17 @@ namespace Discord.Rest var args = new CreateDMChannelParams(user.Id); return RestDMChannel.Create(client, await client.ApiClient.CreateDMChannelAsync(args, options).ConfigureAwait(false)); } + + public static async Task AddRolesAsync(IGuildUser user, BaseDiscordClient client, IEnumerable roles, RequestOptions options) + { + foreach (var role in roles) + await client.ApiClient.AddRoleAsync(user.Guild.Id, user.Id, role.Id, options); + } + + public static async Task RemoveRolesAsync(IGuildUser user, BaseDiscordClient client, IEnumerable roles, RequestOptions options) + { + foreach (var role in roles) + await client.ApiClient.RemoveRoleAsync(user.Guild.Id, user.Id, role.Id, options); + } } } diff --git a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs index 1b2e10332..e92ebb0b1 100644 --- a/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs +++ b/src/Discord.Net.WebSocket/Entities/Users/SocketGuildUser.cs @@ -109,6 +109,18 @@ namespace Discord.WebSocket => UserHelper.ModifyAsync(this, Discord, func, options); public Task KickAsync(RequestOptions options = null) => UserHelper.KickAsync(this, Discord, options); + /// + public Task AddRoleAsync(IRole role, RequestOptions options = null) + => AddRolesAsync(new[] { role }, options); + /// + public Task AddRolesAsync(IEnumerable roles, RequestOptions options = null) + => UserHelper.AddRolesAsync(this, Discord, roles, options); + /// + public Task RemoveRoleAsync(IRole role, RequestOptions options = null) + => RemoveRolesAsync(new[] { role }, options); + /// + public Task RemoveRolesAsync(IEnumerable roles, RequestOptions options = null) + => UserHelper.RemoveRolesAsync(this, Discord, roles, options); public ChannelPermissions GetPermissions(IGuildChannel channel) => new ChannelPermissions(Permissions.ResolveChannel(Guild, this, channel, GuildPermissions.RawValue));