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));