From 8ef5f8120ffdaaa0669b8ff6d9c8dc601ac78439 Mon Sep 17 00:00:00 2001 From: Alex Gravely Date: Mon, 5 Nov 2018 18:34:09 -0500 Subject: [PATCH] feature: add Add Guild Member endpoint (#1183) * Add AddGuildMember Oauth endpoint support * Concat RoleIds if already exists. * Use local ids variable. --- .../Entities/Guilds/IGuild.cs | 12 ++++ .../Entities/Users/AddGuildUserProperties.cs | 62 +++++++++++++++++++ .../API/Rest/AddGuildMemberParams.cs | 19 ++++++ src/Discord.Net.Rest/DiscordRestApiClient.cs | 19 ++++++ .../Entities/Guilds/GuildHelper.cs | 28 +++++++++ .../Entities/Guilds/RestGuild.cs | 8 +++ .../Entities/Guilds/SocketGuild.cs | 8 +++ 7 files changed, 156 insertions(+) create mode 100644 src/Discord.Net.Core/Entities/Users/AddGuildUserProperties.cs create mode 100644 src/Discord.Net.Rest/API/Rest/AddGuildMemberParams.cs diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index c321cd2e3..a7206bd59 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -535,6 +535,18 @@ namespace Discord /// Task CreateRoleAsync(string name, GuildPermissions? permissions = null, Color? color = null, bool isHoisted = false, RequestOptions options = null); + /// + /// Adds a user to this guild. + /// + /// + /// This method requires you have an OAuth2 access token for the user, requested with the guilds.join scope, and that the bot have the MANAGE_INVITES permission in the guild. + /// + /// The snowflake identifier of the user. + /// The OAuth2 access token for the user, requested with the guilds.join scope. + /// The delegate containing the properties to be applied to the user upon being added to the guild. + /// The options to be used when sending the request. + /// A guild user associated with the specified ; null if the user is already in the guild. + Task AddGuildUserAsync(ulong userId, string accessToken, Action func = null, RequestOptions options = null); /// /// Gets a collection of all users in this guild. /// diff --git a/src/Discord.Net.Core/Entities/Users/AddGuildUserProperties.cs b/src/Discord.Net.Core/Entities/Users/AddGuildUserProperties.cs new file mode 100644 index 000000000..e380d9027 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Users/AddGuildUserProperties.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; + +namespace Discord +{ + /// + /// Properties that are used to add a new to the guild with the following parameters. + /// + /// + public class AddGuildUserProperties + { + /// + /// Gets or sets the user's nickname. + /// + /// + /// To clear the user's nickname, this value can be set to null or + /// . + /// + public Optional Nickname { get; set; } + /// + /// Gets or sets whether the user should be muted in a voice channel. + /// + /// + /// If this value is set to true, no user will be able to hear this user speak in the guild. + /// + public Optional Mute { get; set; } + /// + /// Gets or sets whether the user should be deafened in a voice channel. + /// + /// + /// If this value is set to true, this user will not be able to hear anyone speak in the guild. + /// + public Optional Deaf { get; set; } + /// + /// Gets or sets the roles the user should have. + /// + /// + /// + /// To add a role to a user: + /// + /// + /// + /// To remove a role from a user: + /// + /// + /// + public Optional> Roles { get; set; } + /// + /// Gets or sets the roles the user should have. + /// + /// + /// + /// 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.Rest/API/Rest/AddGuildMemberParams.cs b/src/Discord.Net.Rest/API/Rest/AddGuildMemberParams.cs new file mode 100644 index 000000000..ef6229edb --- /dev/null +++ b/src/Discord.Net.Rest/API/Rest/AddGuildMemberParams.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace Discord.API.Rest +{ + [JsonObject(MemberSerialization = MemberSerialization.OptIn)] + internal class AddGuildMemberParams + { + [JsonProperty("access_token")] + public string AccessToken { get; set; } + [JsonProperty("nick")] + public Optional Nickname { get; set; } + [JsonProperty("roles")] + public Optional RoleIds { get; set; } + [JsonProperty("mute")] + public Optional IsMuted { get; set; } + [JsonProperty("deaf")] + public Optional IsDeafened { get; set; } + } +} diff --git a/src/Discord.Net.Rest/DiscordRestApiClient.cs b/src/Discord.Net.Rest/DiscordRestApiClient.cs index 7ed57ed6f..57d7c718a 100644 --- a/src/Discord.Net.Rest/DiscordRestApiClient.cs +++ b/src/Discord.Net.Rest/DiscordRestApiClient.cs @@ -994,6 +994,25 @@ namespace Discord.API } //Guild Members + public async Task AddGuildMemberAsync(ulong guildId, ulong userId, AddGuildMemberParams args, RequestOptions options = null) + { + Preconditions.NotEqual(guildId, 0, nameof(guildId)); + Preconditions.NotEqual(userId, 0, nameof(userId)); + Preconditions.NotNull(args, nameof(args)); + Preconditions.NotNullOrWhitespace(args.AccessToken, nameof(args.AccessToken)); + + if (args.RoleIds.IsSpecified) + { + foreach (var roleId in args.RoleIds.Value) + Preconditions.NotEqual(roleId, 0, nameof(roleId)); + } + + options = RequestOptions.CreateOrClone(options); + + var ids = new BucketIds(guildId: guildId); + + return await SendJsonAsync("PUT", () => $"guilds/{guildId}/members/{userId}", args, ids, options: options); + } public async Task GetGuildMemberAsync(ulong guildId, ulong userId, RequestOptions options = null) { Preconditions.NotEqual(guildId, 0, nameof(guildId)); diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 7b77dafc7..c31fa89f2 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -257,6 +257,34 @@ namespace Discord.Rest } //Users + public static async Task AddGuildUserAsync(IGuild guild, BaseDiscordClient client, ulong userId, string accessToken, + Action func, RequestOptions options) + { + var args = new AddGuildUserProperties(); + func?.Invoke(args); + + if (args.Roles.IsSpecified) + { + var ids = args.Roles.Value.Select(r => r.Id); + + if (args.RoleIds.IsSpecified) + args.RoleIds.Value.Concat(ids); + else + args.RoleIds = Optional.Create(ids); + } + var apiArgs = new AddGuildMemberParams + { + AccessToken = accessToken, + Nickname = args.Nickname, + IsDeafened = args.Deaf, + IsMuted = args.Mute, + RoleIds = args.RoleIds.IsSpecified ? args.RoleIds.Value.Distinct().ToArray() : Optional.Create() + }; + + var model = await client.ApiClient.AddGuildMemberAsync(guild.Id, userId, apiArgs, options); + + return model is null ? null : RestGuildUser.Create(client, guild, model); + } public static async Task GetUserAsync(IGuild guild, BaseDiscordClient client, ulong id, RequestOptions options) { diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 8cd81f218..bd70bf96b 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -537,6 +537,10 @@ namespace Discord.Rest public IAsyncEnumerable> GetUsersAsync(RequestOptions options = null) => GuildHelper.GetUsersAsync(this, Discord, null, null, options); + /// + public Task AddGuildUserAsync(ulong id, string accessToken, Action func = null, RequestOptions options = null) + => GuildHelper.AddGuildUserAsync(this, Discord, id, accessToken, func, options); + /// /// Gets a user from this guild. /// @@ -800,6 +804,10 @@ namespace Discord.Rest async Task IGuild.CreateRoleAsync(string name, GuildPermissions? permissions, Color? color, bool isHoisted, RequestOptions options) => await CreateRoleAsync(name, permissions, color, isHoisted, options).ConfigureAwait(false); + /// + async Task IGuild.AddGuildUserAsync(ulong userId, string accessToken, Action func, RequestOptions options) + => await AddGuildUserAsync(userId, accessToken, func, options); + /// async Task IGuild.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) { diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index ce8cd08de..412f3acff 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -669,6 +669,10 @@ namespace Discord.WebSocket } //Users + /// + public Task AddGuildUserAsync(ulong id, string accessToken, Action func = null, RequestOptions options = null) + => GuildHelper.AddGuildUserAsync(this, Discord, id, accessToken, func, options); + /// /// Gets a user from this guild. /// @@ -1096,6 +1100,10 @@ namespace Discord.WebSocket /// Task> IGuild.GetUsersAsync(CacheMode mode, RequestOptions options) => Task.FromResult>(Users); + + /// + async Task IGuild.AddGuildUserAsync(ulong userId, string accessToken, Action func, RequestOptions options) + => await AddGuildUserAsync(userId, accessToken, func, options); /// Task IGuild.GetUserAsync(ulong id, CacheMode mode, RequestOptions options) => Task.FromResult(GetUser(id));