Skip to content

Commit 80fbbc2

Browse files
authored
[Feature] Add modify current guild member support (#3196)
* refactors & add `ModifyCurrentUserAsync` * i mean, it said "remove", so I removed it
1 parent dade9b2 commit 80fbbc2

File tree

11 files changed

+132
-54
lines changed

11 files changed

+132
-54
lines changed

src/Discord.Net.Core/Entities/Guilds/IGuild.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,5 +1475,10 @@ Task<IReadOnlyCollection<IApplicationCommand>> BulkOverwriteApplicationCommandsA
14751475
/// Gets a mapping of role IDs to the number of users that have each role.
14761476
/// </summary>
14771477
Task<ImmutableDictionary<ulong, int>> GetRoleUserCountsAsync(RequestOptions options = null);
1478+
1479+
/// <summary>
1480+
/// Modifies the current user in this guild.
1481+
/// </summary>
1482+
Task ModifyCurrentUserAsync(Action<SelfGuildUserProperties> props, RequestOptions options = null);
14781483
}
14791484
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace Discord;
2+
3+
/// <summary>
4+
/// Represents properties used to modify the current user's guild-specific information.
5+
/// </summary>
6+
public class SelfGuildUserProperties : GuildUserProperties
7+
{
8+
/// <summary>
9+
/// Gets or sets the banner image of the current user.
10+
/// </summary>
11+
public Optional<Image?> Banner { get; set; }
12+
13+
/// <summary>
14+
/// Gets or sets the avatar image of the current user.
15+
/// </summary>
16+
public Optional<Image?> Avatar { get; set; }
17+
18+
/// <summary>
19+
/// Gets or sets the user's biography text.
20+
/// </summary>
21+
public Optional<string> Bio { get; set; }
22+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Discord.API.Rest;
4+
5+
internal class ModifyCurrentMemberParams
6+
{
7+
[JsonProperty("nick")]
8+
public Optional<string> Nickname { get; set; }
9+
10+
[JsonProperty("banner")]
11+
public Optional<Image?> Banner { get; set; }
12+
13+
[JsonProperty("avatar")]
14+
public Optional<Image?> Avatar { get; set; }
15+
16+
[JsonProperty("bio")]
17+
public Optional<string> Bio { get; set; }
18+
}

src/Discord.Net.Rest/API/Rest/ModifyCurrentUserNickParams.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
using Newtonsoft.Json;
22
using System;
33

4-
namespace Discord.API.Rest
4+
namespace Discord.API.Rest;
5+
6+
internal class ModifyGuildMemberParams
57
{
6-
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
7-
internal class ModifyGuildMemberParams
8-
{
9-
[JsonProperty("mute")]
10-
public Optional<bool> Mute { get; set; }
11-
[JsonProperty("deaf")]
12-
public Optional<bool> Deaf { get; set; }
13-
[JsonProperty("nick")]
14-
public Optional<string> Nickname { get; set; }
15-
[JsonProperty("roles")]
16-
public Optional<ulong[]> RoleIds { get; set; }
17-
[JsonProperty("channel_id")]
18-
public Optional<ulong?> ChannelId { get; set; }
19-
[JsonProperty("communication_disabled_until")]
20-
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
21-
22-
[JsonProperty("flags")]
23-
public Optional<GuildUserFlags> Flags { get; set; }
24-
}
8+
[JsonProperty("mute")]
9+
public Optional<bool> Mute { get; set; }
10+
11+
[JsonProperty("deaf")]
12+
public Optional<bool> Deaf { get; set; }
13+
14+
[JsonProperty("nick")]
15+
public Optional<string> Nickname { get; set; }
16+
17+
[JsonProperty("roles")]
18+
public Optional<ulong[]> RoleIds { get; set; }
19+
20+
[JsonProperty("channel_id")]
21+
public Optional<ulong?> ChannelId { get; set; }
22+
23+
[JsonProperty("communication_disabled_until")]
24+
public Optional<DateTimeOffset?> TimedOutUntil { get; set; }
25+
26+
[JsonProperty("flags")]
27+
public Optional<GuildUserFlags> Flags { get; set; }
2528
}

src/Discord.Net.Rest/DiscordRestApiClient.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,25 +2022,27 @@ public Task RemoveGuildMemberAsync(ulong guildId, ulong userId, string reason, R
20222022
return SendAsync("DELETE", () => $"guilds/{guildId}/members/{userId}", ids, options: options);
20232023
}
20242024

2025-
public async Task ModifyGuildMemberAsync(ulong guildId, ulong userId, Rest.ModifyGuildMemberParams args, RequestOptions options = null)
2025+
public async Task ModifyGuildMemberAsync(ulong guildId, ulong userId, ModifyGuildMemberParams args, RequestOptions options = null)
20262026
{
20272027
Preconditions.NotEqual(guildId, 0, nameof(guildId));
20282028
Preconditions.NotEqual(userId, 0, nameof(userId));
20292029
Preconditions.NotNull(args, nameof(args));
20302030
options = RequestOptions.CreateOrClone(options);
20312031

20322032
bool isCurrentUser = userId == CurrentUserId;
2033-
20342033
if (isCurrentUser && args.Nickname.IsSpecified)
20352034
{
2036-
var nickArgs = new Rest.ModifyCurrentUserNickParams(args.Nickname.Value ?? "");
2037-
await ModifyMyNickAsync(guildId, nickArgs).ConfigureAwait(false);
2038-
args.Nickname = Optional.Create<string>(); //Remove
2035+
var nickArgs = new ModifyCurrentMemberParams
2036+
{
2037+
Nickname = args.Nickname
2038+
};
2039+
await ModifyCurrentMemberAsync(guildId, nickArgs).ConfigureAwait(false);
2040+
args.Nickname = Optional.Create<string>(); // Remove so it's not getting updated again
20392041
}
20402042
if (!isCurrentUser || args.Deaf.IsSpecified || args.Mute.IsSpecified || args.RoleIds.IsSpecified)
20412043
{
20422044
var ids = new BucketIds(guildId: guildId);
2043-
await SendJsonAsync("PATCH", () => $"guilds/{guildId}/members/{userId}", args, ids, options: options).ConfigureAwait(false);
2045+
await SendJsonAsync<GuildMember>("PATCH", () => $"guilds/{guildId}/members/{userId}", args, ids, options: options).ConfigureAwait(false);
20442046
}
20452047
}
20462048

@@ -2454,14 +2456,14 @@ public Task<User> ModifySelfAsync(Rest.ModifyCurrentUserParams args, RequestOpti
24542456
return SendJsonAsync<User>("PATCH", () => "users/@me", args, new BucketIds(), options: options);
24552457
}
24562458

2457-
public Task ModifyMyNickAsync(ulong guildId, Rest.ModifyCurrentUserNickParams args, RequestOptions options = null)
2459+
public Task<GuildMember> ModifyCurrentMemberAsync(ulong guildId, ModifyCurrentMemberParams args, RequestOptions options = null)
24582460
{
24592461
Preconditions.NotNull(args, nameof(args));
2460-
Preconditions.NotNull(args.Nickname, nameof(args.Nickname));
2462+
24612463
options = RequestOptions.CreateOrClone(options);
24622464

24632465
var ids = new BucketIds(guildId: guildId);
2464-
return SendJsonAsync("PATCH", () => $"guilds/{guildId}/members/@me/nick", args, ids, options: options);
2466+
return SendJsonAsync<GuildMember>("PATCH", () => $"guilds/{guildId}/members/@me", args, ids, options: options);
24652467
}
24662468

24672469
public Task<Channel> CreateDMChannelAsync(CreateDMChannelParams args, RequestOptions options = null)

src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,15 @@ public Task<IReadOnlyCollection<RestGuildUser>> SearchUsersAsync(string query, i
991991
/// <inheritdoc />
992992
public Task<MemberSearchResult> SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null)
993993
=> GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options);
994+
995+
/// <inheritdoc />
996+
public Task ModifyCurrentUserAsync(Action<SelfGuildUserProperties> props, RequestOptions options = null)
997+
{
998+
var args = new SelfGuildUserProperties();
999+
props(args);
1000+
return UserHelper.ModifyCurrentUserAsync(this, Discord.CurrentUser, Discord, args, options);
1001+
}
1002+
9941003
#endregion
9951004

9961005
#region Audit logs

src/Discord.Net.Rest/Entities/Users/RestGuildUser.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,10 @@ public override async Task UpdateAsync(RequestOptions options = null)
148148
/// <inheritdoc />
149149
public async Task ModifyAsync(Action<GuildUserProperties> func, RequestOptions options = null)
150150
{
151-
var args = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false);
151+
var args = new GuildUserProperties();
152+
func(args);
153+
154+
args = await UserHelper.ModifyAsync(Guild, this, Discord, args, options).ConfigureAwait(false);
152155
if (args.Deaf.IsSpecified)
153156
IsDeafened = args.Deaf.Value;
154157
if (args.Mute.IsSpecified)

src/Discord.Net.Rest/Entities/Users/UserHelper.cs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,14 @@ public static Task<Model> ModifyAsync(ISelfUser user, BaseDiscordClient client,
2626

2727
return client.ApiClient.ModifySelfAsync(apiArgs, options);
2828
}
29-
public static async Task<GuildUserProperties> ModifyAsync(IGuildUser user, BaseDiscordClient client, Action<GuildUserProperties> func,
29+
30+
public static async Task<GuildUserProperties> ModifyAsync(IGuild guild, IUser user, BaseDiscordClient client, GuildUserProperties args,
3031
RequestOptions options)
3132
{
32-
var args = new GuildUserProperties();
33-
func(args);
34-
3533
if (args.TimedOutUntil.IsSpecified && args.TimedOutUntil.Value.Value.Offset > (new TimeSpan(28, 0, 0, 0)))
3634
throw new ArgumentOutOfRangeException(nameof(args.TimedOutUntil), "Offset cannot be more than 28 days from the current date.");
3735

38-
var apiArgs = new API.Rest.ModifyGuildMemberParams
36+
var apiArgs = new ModifyGuildMemberParams
3937
{
4038
Deaf = args.Deaf,
4139
Mute = args.Mute,
@@ -59,13 +57,33 @@ public static async Task<GuildUserProperties> ModifyAsync(IGuildUser user, BaseD
5957
* string.Empty ("") is the only way to reset the user nick in the API,
6058
* a value of null does not. This is a workaround.
6159
*/
62-
if (apiArgs.Nickname.IsSpecified && apiArgs.Nickname.Value == null)
60+
if (apiArgs.Nickname is { IsSpecified: true, Value: null })
6361
apiArgs.Nickname = new Optional<string>(string.Empty);
6462

65-
await client.ApiClient.ModifyGuildMemberAsync(user.GuildId, user.Id, apiArgs, options).ConfigureAwait(false);
63+
await client.ApiClient.ModifyGuildMemberAsync(guild.Id, user.Id, apiArgs, options).ConfigureAwait(false);
6664
return args;
6765
}
6866

67+
public static async Task ModifyCurrentUserAsync(IGuild guild, IUser user, BaseDiscordClient client, SelfGuildUserProperties args, RequestOptions options)
68+
{
69+
if (args.Nickname.IsSpecified || args.Avatar.IsSpecified || args.Banner.IsSpecified || args.Bio.IsSpecified)
70+
{
71+
var props = new ModifyCurrentMemberParams
72+
{
73+
Nickname = args.Nickname,
74+
Avatar = args.Avatar.IsSpecified ? args.Avatar.Value?.ToModel() : Optional<ImageModel?>.Unspecified,
75+
Banner = args.Banner.IsSpecified ? args.Banner.Value?.ToModel() : Optional<ImageModel?>.Unspecified,
76+
Bio = args.Bio
77+
};
78+
79+
await client.ApiClient.ModifyCurrentMemberAsync(guild.Id, props, options).ConfigureAwait(false);
80+
81+
args.Nickname = Optional<string>.Unspecified;
82+
}
83+
84+
await ModifyAsync(guild, user, client, args, options);
85+
}
86+
6987
public static Task KickAsync(IGuildUser user, BaseDiscordClient client, string reason, RequestOptions options)
7088
=> client.ApiClient.RemoveGuildMemberAsync(user.GuildId, user.Id, reason, options);
7189

src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,15 @@ public Task<IReadOnlyCollection<RestGuildUser>> SearchUsersAsync(string query, i
13431343
/// <inheritdoc />
13441344
public Task<MemberSearchResult> SearchUsersAsyncV2(int limit = DiscordConfig.MaxUsersPerBatch, MemberSearchPropertiesV2 args = null, RequestOptions options = null)
13451345
=> GuildHelper.SearchUsersAsyncV2(this, Discord, limit, args, options);
1346+
1347+
/// <inheritdoc />
1348+
public Task ModifyCurrentUserAsync(Action<SelfGuildUserProperties> props, RequestOptions options = null)
1349+
{
1350+
var args = new SelfGuildUserProperties();
1351+
props(args);
1352+
return UserHelper.ModifyCurrentUserAsync(this, Discord.CurrentUser, Discord, args, options);
1353+
}
1354+
13461355
#endregion
13471356

13481357
#region Guild Events

0 commit comments

Comments
 (0)