[Feature] Add modify current guild member support (#3196)
* refactors & add `ModifyCurrentUserAsync` * i mean, it said "remove", so I removed it
This commit is contained in:
@@ -1475,5 +1475,10 @@ namespace Discord
|
|||||||
/// Gets a mapping of role IDs to the number of users that have each role.
|
/// Gets a mapping of role IDs to the number of users that have each role.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<ImmutableDictionary<ulong, int>> GetRoleUserCountsAsync(RequestOptions options = null);
|
Task<ImmutableDictionary<ulong, int>> GetRoleUserCountsAsync(RequestOptions options = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Modifies the current user in this guild.
|
||||||
|
/// </summary>
|
||||||
|
Task ModifyCurrentUserAsync(Action<SelfGuildUserProperties> props, RequestOptions options = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
namespace Discord;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents properties used to modify the current user's guild-specific information.
|
||||||
|
/// </summary>
|
||||||
|
public class SelfGuildUserProperties : GuildUserProperties
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the banner image of the current user.
|
||||||
|
/// </summary>
|
||||||
|
public Optional<Image?> Banner { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the avatar image of the current user.
|
||||||
|
/// </summary>
|
||||||
|
public Optional<Image?> Avatar { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the user's biography text.
|
||||||
|
/// </summary>
|
||||||
|
public Optional<string> Bio { get; set; }
|
||||||
|
}
|
||||||
18
src/Discord.Net.Rest/API/Rest/ModifyCurrentMemberParams.cs
Normal file
18
src/Discord.Net.Rest/API/Rest/ModifyCurrentMemberParams.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Discord.API.Rest;
|
||||||
|
|
||||||
|
internal class ModifyCurrentMemberParams
|
||||||
|
{
|
||||||
|
[JsonProperty("nick")]
|
||||||
|
public Optional<string> Nickname { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("banner")]
|
||||||
|
public Optional<Image?> Banner { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("avatar")]
|
||||||
|
public Optional<Image?> Avatar { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("bio")]
|
||||||
|
public Optional<string> Bio { get; set; }
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Discord.API.Rest
|
|
||||||
{
|
|
||||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
|
||||||
internal class ModifyCurrentUserNickParams
|
|
||||||
{
|
|
||||||
[JsonProperty("nick")]
|
|
||||||
public string Nickname { get; }
|
|
||||||
|
|
||||||
public ModifyCurrentUserNickParams(string nickname)
|
|
||||||
{
|
|
||||||
Nickname = nickname;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,28 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Discord.API.Rest
|
namespace Discord.API.Rest;
|
||||||
{
|
|
||||||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
|
|
||||||
internal class ModifyGuildMemberParams
|
internal class ModifyGuildMemberParams
|
||||||
{
|
{
|
||||||
[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")]
|
[JsonProperty("roles")]
|
||||||
public Optional<ulong[]> RoleIds { get; set; }
|
public Optional<ulong[]> RoleIds { get; set; }
|
||||||
|
|
||||||
[JsonProperty("channel_id")]
|
[JsonProperty("channel_id")]
|
||||||
public Optional<ulong?> ChannelId { get; set; }
|
public Optional<ulong?> ChannelId { get; set; }
|
||||||
|
|
||||||
[JsonProperty("communication_disabled_until")]
|
[JsonProperty("communication_disabled_until")]
|
||||||
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
|
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
|
||||||
|
|
||||||
[JsonProperty("flags")]
|
[JsonProperty("flags")]
|
||||||
public Optional<GuildUserFlags> Flags { get; set; }
|
public Optional<GuildUserFlags> Flags { get; set; }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -2022,7 +2022,7 @@ namespace Discord.API
|
|||||||
return SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}", ids, options: options);
|
return SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}", ids, options: options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ModifyGuildMemberAsync(ulong guildId, ulong userId, Rest.ModifyGuildMemberParams args, RequestOptions options = null)
|
public async Task ModifyGuildMemberAsync(ulong guildId, ulong userId, ModifyGuildMemberParams args, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
Preconditions.NotEqual(guildId, 0, nameof(guildId));
|
Preconditions.NotEqual(guildId, 0, nameof(guildId));
|
||||||
Preconditions.NotEqual(userId, 0, nameof(userId));
|
Preconditions.NotEqual(userId, 0, nameof(userId));
|
||||||
@@ -2030,17 +2030,19 @@ namespace Discord.API
|
|||||||
options = RequestOptions.CreateOrClone(options);
|
options = RequestOptions.CreateOrClone(options);
|
||||||
|
|
||||||
bool isCurrentUser = userId == CurrentUserId;
|
bool isCurrentUser = userId == CurrentUserId;
|
||||||
|
|
||||||
if (isCurrentUser && args.Nickname.IsSpecified)
|
if (isCurrentUser && args.Nickname.IsSpecified)
|
||||||
{
|
{
|
||||||
var nickArgs = new Rest.ModifyCurrentUserNickParams(args.Nickname.Value ?? "");
|
var nickArgs = new ModifyCurrentMemberParams
|
||||||
await ModifyMyNickAsync(guildId, nickArgs).ConfigureAwait(false);
|
{
|
||||||
args.Nickname = Optional.Create<string>(); //Remove
|
Nickname = args.Nickname
|
||||||
|
};
|
||||||
|
await ModifyCurrentMemberAsync(guildId, nickArgs).ConfigureAwait(false);
|
||||||
|
args.Nickname = Optional.Create<string>(); // Remove so it's not getting updated again
|
||||||
}
|
}
|
||||||
if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.RoleIds.IsSpecified)
|
if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.RoleIds.IsSpecified)
|
||||||
{
|
{
|
||||||
var ids = new BucketIds(guildId: guildId);
|
var ids = new BucketIds(guildId: guildId);
|
||||||
await SendJsonAsync("PATCH", () => $"guilds/{guildId}/members/{userId}", args, ids, options: options).ConfigureAwait(false);
|
await SendJsonAsync<GuildMember>("PATCH", () => $"guilds/{guildId}/members/{userId}", args, ids, options: options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2454,14 +2456,14 @@ namespace Discord.API
|
|||||||
return SendJsonAsync<User>("PATCH", () => "users/@me", args, new BucketIds(), options: options);
|
return SendJsonAsync<User>("PATCH", () => "users/@me", args, new BucketIds(), options: options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ModifyMyNickAsync(ulong guildId, Rest.ModifyCurrentUserNickParams args, RequestOptions options = null)
|
public Task<GuildMember> ModifyCurrentMemberAsync(ulong guildId, ModifyCurrentMemberParams args, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
Preconditions.NotNull(args, nameof(args));
|
Preconditions.NotNull(args, nameof(args));
|
||||||
Preconditions.NotNull(args.Nickname, nameof(args.Nickname));
|
|
||||||
options = RequestOptions.CreateOrClone(options);
|
options = RequestOptions.CreateOrClone(options);
|
||||||
|
|
||||||
var ids = new BucketIds(guildId: guildId);
|
var ids = new BucketIds(guildId: guildId);
|
||||||
return SendJsonAsync("PATCH", () => $"guilds/{guildId}/members/@me/nick", args, ids, options: options);
|
return SendJsonAsync<GuildMember>("PATCH", () => $"guilds/{guildId}/members/@me", args, ids, options: options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Channel> CreateDMChannelAsync(CreateDMChannelParams args, RequestOptions options = null)
|
public Task<Channel> CreateDMChannelAsync(CreateDMChannelParams args, RequestOptions options = null)
|
||||||
|
|||||||
@@ -991,6 +991,15 @@ namespace Discord.Rest
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<MemberSearchResult> SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null)
|
public Task<MemberSearchResult> SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null)
|
||||||
=> GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options);
|
=> GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task ModifyCurrentUserAsync(Action<SelfGuildUserProperties> props, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
var args = new SelfGuildUserProperties();
|
||||||
|
props(args);
|
||||||
|
return UserHelper.ModifyCurrentUserAsync(this, Discord.CurrentUser, Discord, args, options);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Audit logs
|
#region Audit logs
|
||||||
|
|||||||
@@ -148,7 +148,10 @@ namespace Discord.Rest
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null)
|
public async Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null)
|
||||||
{
|
{
|
||||||
var args = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false);
|
var args = new GuildUserProperties();
|
||||||
|
func(args);
|
||||||
|
|
||||||
|
args = await UserHelper.ModifyAsync(Guild, this, Discord, args, options).ConfigureAwait(false);
|
||||||
if (args.Deaf.IsSpecified)
|
if (args.Deaf.IsSpecified)
|
||||||
IsDeafened = args.Deaf.Value;
|
IsDeafened = args.Deaf.Value;
|
||||||
if (args.Mute.IsSpecified)
|
if (args.Mute.IsSpecified)
|
||||||
|
|||||||
@@ -26,16 +26,14 @@ namespace Discord.Rest
|
|||||||
|
|
||||||
return client.ApiClient.ModifySelfAsync(apiArgs, options);
|
return client.ApiClient.ModifySelfAsync(apiArgs, options);
|
||||||
}
|
}
|
||||||
public static async Task<GuildUserProperties> ModifyAsync(IGuildUser user, BaseDiscordClient client, Action<GuildUserProperties> func,
|
|
||||||
|
public static async Task<GuildUserProperties> ModifyAsync(IGuild guild, IUser user, BaseDiscordClient client, GuildUserProperties args,
|
||||||
RequestOptions options)
|
RequestOptions options)
|
||||||
{
|
{
|
||||||
var args = new GuildUserProperties();
|
|
||||||
func(args);
|
|
||||||
|
|
||||||
if (args.TimedOutUntil.IsSpecified && args.TimedOutUntil.Value.Value.Offset > (new TimeSpan(28, 0, 0, 0)))
|
if (args.TimedOutUntil.IsSpecified && args.TimedOutUntil.Value.Value.Offset > (new TimeSpan(28, 0, 0, 0)))
|
||||||
throw new ArgumentOutOfRangeException(nameof(args.TimedOutUntil), "Offset cannot be more than 28 days from the current date.");
|
throw new ArgumentOutOfRangeException(nameof(args.TimedOutUntil), "Offset cannot be more than 28 days from the current date.");
|
||||||
|
|
||||||
var apiArgs = new API.Rest.ModifyGuildMemberParams
|
var apiArgs = new ModifyGuildMemberParams
|
||||||
{
|
{
|
||||||
Deaf = args.Deaf,
|
Deaf = args.Deaf,
|
||||||
Mute = args.Mute,
|
Mute = args.Mute,
|
||||||
@@ -59,13 +57,33 @@ namespace Discord.Rest
|
|||||||
* string.Empty ("") is the only way to reset the user nick in the API,
|
* string.Empty ("") is the only way to reset the user nick in the API,
|
||||||
* a value of null does not. This is a workaround.
|
* a value of null does not. This is a workaround.
|
||||||
*/
|
*/
|
||||||
if (apiArgs.Nickname.IsSpecified && apiArgs.Nickname.Value == null)
|
if (apiArgs.Nickname is { IsSpecified: true, Value: null })
|
||||||
apiArgs.Nickname = new Optional<string>(string.Empty);
|
apiArgs.Nickname = new Optional<string>(string.Empty);
|
||||||
|
|
||||||
await client.ApiClient.ModifyGuildMemberAsync(user.GuildId, user.Id, apiArgs, options).ConfigureAwait(false);
|
await client.ApiClient.ModifyGuildMemberAsync(guild.Id, user.Id, apiArgs, options).ConfigureAwait(false);
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task ModifyCurrentUserAsync(IGuild guild, IUser user, BaseDiscordClient client, SelfGuildUserProperties args, RequestOptions options)
|
||||||
|
{
|
||||||
|
if (args.Nickname.IsSpecified || args.Avatar.IsSpecified || args.Banner.IsSpecified || args.Bio.IsSpecified)
|
||||||
|
{
|
||||||
|
var props = new ModifyCurrentMemberParams
|
||||||
|
{
|
||||||
|
Nickname = args.Nickname,
|
||||||
|
Avatar = args.Avatar.IsSpecified ? args.Avatar.Value?.ToModel() : Optional<ImageModel?>.Unspecified,
|
||||||
|
Banner = args.Banner.IsSpecified ? args.Banner.Value?.ToModel() : Optional<ImageModel?>.Unspecified,
|
||||||
|
Bio = args.Bio
|
||||||
|
};
|
||||||
|
|
||||||
|
await client.ApiClient.ModifyCurrentMemberAsync(guild.Id, props, options).ConfigureAwait(false);
|
||||||
|
|
||||||
|
args.Nickname = Optional<string>.Unspecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ModifyAsync(guild, user, client, args, options);
|
||||||
|
}
|
||||||
|
|
||||||
public static Task KickAsync(IGuildUser user, BaseDiscordClient client, string reason, RequestOptions options)
|
public static Task KickAsync(IGuildUser user, BaseDiscordClient client, string reason, RequestOptions options)
|
||||||
=> client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id, reason, options);
|
=> client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id, reason, options);
|
||||||
|
|
||||||
|
|||||||
@@ -1343,6 +1343,15 @@ namespace Discord.WebSocket
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<MemberSearchResult> SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null)
|
public Task<MemberSearchResult> SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null)
|
||||||
=> GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options);
|
=> GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task ModifyCurrentUserAsync(Action<SelfGuildUserProperties> props, RequestOptions options = null)
|
||||||
|
{
|
||||||
|
var args = new SelfGuildUserProperties();
|
||||||
|
props(args);
|
||||||
|
return UserHelper.ModifyCurrentUserAsync(this, Discord.CurrentUser, Discord, args, options);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Guild Events
|
#region Guild Events
|
||||||
|
|||||||
@@ -241,7 +241,12 @@ namespace Discord.WebSocket
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null)
|
public Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null)
|
||||||
=> UserHelper.ModifyAsync(this, Discord, func, options);
|
{
|
||||||
|
var args = new GuildUserProperties();
|
||||||
|
func(args);
|
||||||
|
return UserHelper.ModifyAsync(Guild, this, Discord, args, options);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task KickAsync(string reason = null, RequestOptions options = null)
|
public Task KickAsync(string reason = null, RequestOptions options = null)
|
||||||
=> UserHelper.KickAsync(this, Discord, reason, options);
|
=> UserHelper.KickAsync(this, Discord, reason, options);
|
||||||
|
|||||||
Reference in New Issue
Block a user