Skip to content

Commit df717e6

Browse files
Misha-133dimson-nquinchs
authored
[Feature] Support for the new username system (#2696)
* update a lot of stuff * update CDN for new avatar calculation * whoops, forgot to commit * handle `null` values * Remove duplicate line Co-authored-by: Dmitry <[email protected]> * updates * Apply suggestions from code review Co-authored-by: Quin Lynch <[email protected]> * Apply suggestion Co-authored-by: Quin Lynch <[email protected]> * update `SocketThreadUSer` --------- Co-authored-by: Dmitry <[email protected]> Co-authored-by: Quin Lynch <[email protected]>
1 parent 9ddd922 commit df717e6

File tree

22 files changed

+113
-39
lines changed

22 files changed

+113
-39
lines changed

src/Discord.Net.Commands/Readers/UserTypeReader.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ public override async Task<TypeReaderResult> ReadAsync(ICommandContext context,
5959
}
6060
}
6161

62+
//By global (display) name
63+
{
64+
await channelUsers
65+
.Where(x => string.Equals(input, x.GlobalName, StringComparison.OrdinalIgnoreCase))
66+
.ForEachAsync(channelUser => AddResult(results, channelUser as T, channelUser.GlobalName == input ? 0.65f : 0.55f))
67+
.ConfigureAwait(false);
68+
69+
foreach (var guildUser in guildUsers.Where(x => string.Equals(input, x.GlobalName, StringComparison.OrdinalIgnoreCase)))
70+
AddResult(results, guildUser as T, guildUser.GlobalName == input ? 0.60f : 0.50f);
71+
}
72+
6273
//By Username (0.5-0.6)
6374
{
6475
await channelUsers

src/Discord.Net.Core/CDN.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public static string GetUserBannerUrl(ulong userId, string bannerId, ushort size
7272
string extension = FormatToExtension(format, bannerId);
7373
return $"{DiscordConfig.CDNUrl}banners/{userId}/{bannerId}.{extension}?size={size}";
7474
}
75+
7576
/// <summary>
7677
/// Returns the default user avatar URL.
7778
/// </summary>
@@ -83,6 +84,19 @@ public static string GetDefaultUserAvatarUrl(ushort discriminator)
8384
{
8485
return $"{DiscordConfig.CDNUrl}embed/avatars/{discriminator % 5}.png";
8586
}
87+
88+
/// <summary>
89+
/// Returns the default user avatar URL.
90+
/// </summary>
91+
/// <param name="userId">The Id of a user.</param>
92+
/// <returns>
93+
/// A URL pointing to the user's default avatar when one isn't set.
94+
/// </returns>
95+
public static string GetDefaultUserAvatarUrl(ulong userId)
96+
{
97+
return $"{DiscordConfig.CDNUrl}embed/avatars/{(userId >> 22) % 6}.png";
98+
}
99+
86100
/// <summary>
87101
/// Returns an icon URL.
88102
/// </summary>

src/Discord.Net.Core/Entities/Users/IUser.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ public interface IUser : ISnowflakeEntity, IMentionable, IPresence
4747
/// </returns>
4848
string GetDefaultAvatarUrl();
4949
/// <summary>
50-
/// Gets the per-username unique ID for this user.
50+
/// Gets the per-username unique ID for this user. This will return "0000" for users who have migrated to new username system.
5151
/// </summary>
5252
string Discriminator { get; }
5353
/// <summary>
54-
/// Gets the per-username unique ID for this user.
54+
/// Gets the per-username unique ID for this user. This will return 0 for users who have migrated to new username system.
5555
/// </summary>
5656
ushort DiscriminatorValue { get; }
5757
/// <summary>
@@ -87,6 +87,14 @@ public interface IUser : ISnowflakeEntity, IMentionable, IPresence
8787
/// </returns>
8888
UserProperties? PublicFlags { get; }
8989

90+
/// <summary>
91+
/// Gets the user's display name, if it is set. For bots, this will get the application name.
92+
/// </summary>
93+
/// <remarks>
94+
/// This property will be <see langword="null"/> if user has no display name set.
95+
/// </remarks>
96+
string GlobalName { get; }
97+
9098
/// <summary>
9199
/// Creates the direct message channel of this user.
92100
/// </summary>

src/Discord.Net.Core/Extensions/EmbedBuilderExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static EmbedBuilder WithColor(this EmbedBuilder builder, float r, float g
2727

2828
/// <summary> Fills the embed author field with the provided user's full username and avatar URL. </summary>
2929
public static EmbedBuilder WithAuthor(this EmbedBuilder builder, IUser user) =>
30-
builder.WithAuthor($"{user.Username}#{user.Discriminator}", user.GetAvatarUrl() ?? user.GetDefaultAvatarUrl());
30+
builder.WithAuthor(user.DiscriminatorValue != 0 ? $"{user.Username}#{user.Discriminator}" : user.Username, user.GetAvatarUrl() ?? user.GetDefaultAvatarUrl());
3131

3232
/// <summary> Converts a <see cref="EmbedType.Rich"/> <see cref="IEmbed"/> object to a <see cref="EmbedBuilder"/>. </summary>
3333
/// <exception cref="InvalidOperationException">The embed type is not <see cref="EmbedType.Rich"/>.</exception>

src/Discord.Net.Core/Format.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,18 @@ public static string StripMarkDown(string text)
108108
}
109109

110110
/// <summary>
111-
/// Formats a user's username + discriminator.
111+
/// Formats a user's username and optional discriminator.
112112
/// </summary>
113113
/// <param name="doBidirectional">To format the string in bidirectional unicode or not</param>
114114
/// <param name="user">The user whose username and discriminator to format</param>
115-
/// <returns>The username + discriminator</returns>
115+
/// <returns>The username + optional discriminator.</returns>
116116
public static string UsernameAndDiscriminator(IUser user, bool doBidirectional)
117117
{
118-
return doBidirectional
119-
? $"\u2066{user.Username}\u2069#{user.Discriminator}"
120-
: $"{user.Username}#{user.Discriminator}";
118+
if (user.DiscriminatorValue != 0)
119+
return doBidirectional
120+
? $"\u2066{user.Username}\u2069#{user.Discriminator}"
121+
: $"{user.Username}#{user.Discriminator}";
122+
return user.Username;
121123
}
122124
}
123125
}

src/Discord.Net.Core/Utils/MentionUtils.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ public static class MentionUtils
1212
private const char SanitizeChar = '\x200b';
1313

1414
//If the system can't be positive a user doesn't have a nickname, assume useNickname = true (source: Jake)
15-
internal static string MentionUser(string id, bool useNickname = true) => useNickname ? $"<@!{id}>" : $"<@{id}>";
15+
internal static string MentionUser(string id) => $"<@{id}>";
1616
/// <summary>
1717
/// Returns a mention string based on the user ID.
1818
/// </summary>
1919
/// <returns>
2020
/// A user mention string (e.g. &lt;@80351110224678912&gt;).
2121
/// </returns>
22-
public static string MentionUser(ulong id) => MentionUser(id.ToString(), true);
22+
public static string MentionUser(ulong id) => MentionUser(id.ToString());
2323
internal static string MentionChannel(string id) => $"<#{id}>";
2424
/// <summary>
2525
/// Returns a mention string based on the channel ID.
@@ -192,19 +192,19 @@ internal static string ResolveUserMention(ITag tag, TagHandling mode)
192192
return "";
193193
case TagHandling.FullName:
194194
if (user != null)
195-
return $"@{user.Username}#{user.Discriminator}";
195+
return user.DiscriminatorValue != 0 ? $"@{user.Username}#{user.Discriminator}" : user.Username;
196196
else
197197
return "";
198198
case TagHandling.FullNameNoPrefix:
199199
if (user != null)
200-
return $"{user.Username}#{user.Discriminator}";
200+
return user.DiscriminatorValue != 0 ? $"@{user.Username}#{user.Discriminator}" : user.Username;
201201
else
202202
return "";
203203
case TagHandling.Sanitize:
204204
if (guildUser != null && guildUser.Nickname == null)
205-
return MentionUser($"{SanitizeChar}{tag.Key}", false);
205+
return MentionUser($"{SanitizeChar}{tag.Key}");
206206
else
207-
return MentionUser($"{SanitizeChar}{tag.Key}", true);
207+
return MentionUser($"{SanitizeChar}{tag.Key}");
208208
}
209209
}
210210
return "";

src/Discord.Net.Rest/API/Common/User.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ internal class User
1919
[JsonProperty("accent_color")]
2020
public Optional<uint?> AccentColor { get; set; }
2121

22+
[JsonProperty("global_name")]
23+
public Optional<string> GlobalName { get; set; }
24+
2225
//CurrentUser
2326
[JsonProperty("verified")]
2427
public Optional<bool> Verified { get; set; }

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ public class RestGuildUser : RestUser, IGuildUser
1919
private long? _timedOutTicks;
2020
private long? _joinedAtTicks;
2121
private ImmutableArray<ulong> _roleIds;
22-
/// <inheritdoc />
23-
public string DisplayName => Nickname ?? Username;
22+
23+
/// <inheritdoc cref="IGuildUser.DisplayName"/>
24+
public string DisplayName => Nickname ?? GlobalName ?? Username;
25+
2426
/// <inheritdoc />
2527
public string Nickname { get; private set; }
2628
/// <inheritdoc/>

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public class RestUser : RestEntity<ulong>, IUser, IUpdateable
3030
public Color? AccentColor { get; private set; }
3131
/// <inheritdoc />
3232
public UserProperties? PublicFlags { get; private set; }
33+
/// <inheritdoc />
34+
public string GlobalName { get; internal set; }
3335

3436
/// <inheritdoc />
3537
public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id);
@@ -85,13 +87,15 @@ internal virtual void Update(Model model)
8587
if (model.AccentColor.IsSpecified)
8688
AccentColor = model.AccentColor.Value;
8789
if (model.Discriminator.IsSpecified)
88-
DiscriminatorValue = ushort.Parse(model.Discriminator.Value, NumberStyles.None, CultureInfo.InvariantCulture);
90+
DiscriminatorValue = ushort.Parse(model.Discriminator.GetValueOrDefault(null) ?? "0", NumberStyles.None, CultureInfo.InvariantCulture);
8991
if (model.Bot.IsSpecified)
9092
IsBot = model.Bot.Value;
9193
if (model.Username.IsSpecified)
9294
Username = model.Username.Value;
9395
if (model.PublicFlags.IsSpecified)
9496
PublicFlags = model.PublicFlags.Value;
97+
if (model.GlobalName.IsSpecified)
98+
GlobalName = model.GlobalName.Value;
9599
}
96100

97101
/// <inheritdoc />
@@ -121,7 +125,9 @@ public string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size =
121125

122126
/// <inheritdoc />
123127
public string GetDefaultAvatarUrl()
124-
=> CDN.GetDefaultUserAvatarUrl(DiscriminatorValue);
128+
=> DiscriminatorValue != 0
129+
? CDN.GetDefaultUserAvatarUrl(DiscriminatorValue)
130+
: CDN.GetDefaultUserAvatarUrl(Id);
125131

126132
/// <summary>
127133
/// Gets the Username#Discriminator of the user.

src/Discord.Net.Rest/Extensions/EntityExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,10 @@ public static API.Message ToMessage(this API.InteractionResponse model, IDiscord
201201
Username = command.User.Username,
202202
Avatar = command.User.AvatarId,
203203
Bot = command.User.IsBot,
204-
Discriminator = command.User.Discriminator,
204+
Discriminator = command.User.Discriminator == "0000" ? Optional<string>.Unspecified : command.User.Discriminator,
205205
PublicFlags = command.User.PublicFlags.HasValue ? command.User.PublicFlags.Value : Optional<UserProperties>.Unspecified,
206206
Id = command.User.Id,
207+
GlobalName = command.User.GlobalName,
207208
}
208209
};
209210
}

0 commit comments

Comments
 (0)