mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-05-29 05:55:21 -04:00
Introduce the foundation for the new username system
This commit is contained in:
parent
bf0d8ab31e
commit
3d2d197904
11 changed files with 56 additions and 32 deletions
|
@ -42,7 +42,7 @@ public partial record Channel
|
|||
json.GetPropertyOrNull("recipients")?
|
||||
.EnumerateArrayOrNull()?
|
||||
.Select(User.Parse)
|
||||
.Select(u => u.Name)
|
||||
.Select(u => u.DisplayName)
|
||||
.Pipe(s => string.Join(", ", s)) ??
|
||||
|
||||
// Fallback
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace DiscordChatExporter.Core.Discord.Data;
|
|||
// https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
public partial record Member(
|
||||
User User,
|
||||
string? Nick,
|
||||
string? DisplayName,
|
||||
string? AvatarUrl,
|
||||
IReadOnlyList<Snowflake> RoleIds) : IHasId
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ public partial record Member
|
|||
public static Member Parse(JsonElement json, Snowflake? guildId = null)
|
||||
{
|
||||
var user = json.GetProperty("user").Pipe(User.Parse);
|
||||
var nick = json.GetPropertyOrNull("nick")?.GetNonWhiteSpaceStringOrNull();
|
||||
var displayName = json.GetPropertyOrNull("nick")?.GetNonWhiteSpaceStringOrNull();
|
||||
|
||||
var roleIds = json
|
||||
.GetPropertyOrNull("roles")?
|
||||
|
@ -43,7 +43,7 @@ public partial record Member
|
|||
|
||||
return new Member(
|
||||
user,
|
||||
nick,
|
||||
displayName,
|
||||
avatarUrl,
|
||||
roleIds
|
||||
);
|
||||
|
|
|
@ -9,13 +9,24 @@ namespace DiscordChatExporter.Core.Discord.Data;
|
|||
public partial record User(
|
||||
Snowflake Id,
|
||||
bool IsBot,
|
||||
int Discriminator,
|
||||
// Remove after Discord migrates all accounts to the new system.
|
||||
// With that, also remove the DiscriminatorFormatted and FullName properties.
|
||||
// Replace existing calls to FullName with Name (not DisplayName).
|
||||
int? Discriminator,
|
||||
string Name,
|
||||
string DisplayName,
|
||||
string AvatarUrl) : IHasId
|
||||
{
|
||||
public string DiscriminatorFormatted => $"{Discriminator:0000}";
|
||||
public string DiscriminatorFormatted => Discriminator is not null
|
||||
? $"{Discriminator:0000}"
|
||||
: "0000";
|
||||
|
||||
public string FullName => $"{Name}#{DiscriminatorFormatted}";
|
||||
// This effectively represents the user's true identity.
|
||||
// In the old system, this is formed from the username and discriminator.
|
||||
// In the new system, the username is already the user's unique identifier.
|
||||
public string FullName => Discriminator is not null
|
||||
? $"{Name}#{DiscriminatorFormatted}"
|
||||
: Name;
|
||||
}
|
||||
|
||||
public partial record User
|
||||
|
@ -24,16 +35,23 @@ public partial record User
|
|||
{
|
||||
var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
|
||||
var isBot = json.GetPropertyOrNull("bot")?.GetBooleanOrNull() ?? false;
|
||||
var discriminator = json.GetProperty("discriminator").GetNonWhiteSpaceString().Pipe(int.Parse);
|
||||
|
||||
var discriminator = json
|
||||
.GetPropertyOrNull("discriminator")?
|
||||
.GetNonWhiteSpaceStringOrNull()?
|
||||
.Pipe(int.Parse)
|
||||
.NullIfDefault();
|
||||
|
||||
var name = json.GetProperty("username").GetNonNullString();
|
||||
var displayName = json.GetPropertyOrNull("global_name")?.GetNonWhiteSpaceStringOrNull() ?? name;
|
||||
|
||||
var avatarUrl =
|
||||
json
|
||||
.GetPropertyOrNull("avatar")?
|
||||
.GetNonWhiteSpaceStringOrNull()?
|
||||
.Pipe(h => ImageCdn.GetUserAvatarUrl(id, h)) ??
|
||||
ImageCdn.GetFallbackUserAvatarUrl(discriminator);
|
||||
ImageCdn.GetFallbackUserAvatarUrl(discriminator ?? 0);
|
||||
|
||||
return new User(id, isBot, discriminator, name, avatarUrl);
|
||||
return new User(id, isBot, discriminator, name, displayName, avatarUrl);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ internal class FromMessageFilter : MessageFilter
|
|||
|
||||
public override bool IsMatch(Message message) =>
|
||||
string.Equals(_value, message.Author.Name, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(_value, message.Author.DisplayName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(_value, message.Author.FullName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(_value, message.Author.Id.ToString(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
|
@ -12,6 +12,7 @@ internal class MentionsMessageFilter : MessageFilter
|
|||
|
||||
public override bool IsMatch(Message message) => message.MentionedUsers.Any(user =>
|
||||
string.Equals(_value, user.Name, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(_value, user.DisplayName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(_value, user.FullName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(_value, user.Id.ToString(), StringComparison.OrdinalIgnoreCase)
|
||||
);
|
||||
|
|
|
@ -249,12 +249,12 @@ internal partial class HtmlMarkdownVisitor : MarkdownVisitor
|
|||
|
||||
var member = mention.TargetId?.Pipe(_context.TryGetMember);
|
||||
var fullName = member?.User.FullName ?? "Unknown";
|
||||
var nick = member?.Nick ?? member?.User.Name ?? "Unknown";
|
||||
var displayName = member?.DisplayName ?? member?.User.DisplayName ?? "Unknown";
|
||||
|
||||
_buffer.Append(
|
||||
// lang=html
|
||||
$"""
|
||||
<span class="chatlog__markdown-mention" title="{HtmlEncode(fullName)}">@{HtmlEncode(nick)}</span>
|
||||
<span class="chatlog__markdown-mention" title="{HtmlEncode(fullName)}">@{HtmlEncode(displayName)}</span>
|
||||
"""
|
||||
);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ internal class JsonMessageWriter : MessageWriter
|
|||
_writer.WriteString("id", user.Id.ToString());
|
||||
_writer.WriteString("name", user.Name);
|
||||
_writer.WriteString("discriminator", user.DiscriminatorFormatted);
|
||||
_writer.WriteString("nickname", Context.TryGetMember(user.Id)?.Nick ?? user.Name);
|
||||
_writer.WriteString("nickname", Context.TryGetMember(user.Id)?.DisplayName ?? user.DisplayName);
|
||||
_writer.WriteString("color", Context.TryGetUserColor(user.Id)?.ToHex());
|
||||
_writer.WriteBoolean("isBot", user.IsBot);
|
||||
|
||||
|
|
|
@ -40,9 +40,9 @@
|
|||
|
||||
var authorMember = Context.TryGetMember(message.Author.Id);
|
||||
var authorColor = Context.TryGetUserColor(message.Author.Id);
|
||||
var authorNick = message.Author.IsBot
|
||||
? message.Author.Name
|
||||
: authorMember?.Nick ?? message.Author.Name;
|
||||
var authorDisplayName = message.Author.IsBot
|
||||
? message.Author.DisplayName
|
||||
: authorMember?.DisplayName ?? message.Author.DisplayName;
|
||||
|
||||
<div id="chatlog__message-container-@message.Id" class="chatlog__message-container @(message.IsPinned ? "chatlog__message-container--pinned" : null)" data-message-id="@message.Id">
|
||||
<div class="chatlog__message">
|
||||
|
@ -71,7 +71,7 @@
|
|||
|
||||
<div class="chatlog__message-primary">
|
||||
@* Author name *@
|
||||
<span class="chatlog__system-notification-author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorNick</span>
|
||||
<span class="chatlog__system-notification-author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorDisplayName</span>
|
||||
|
||||
@* Space out the content *@
|
||||
<span> </span>
|
||||
|
@ -81,7 +81,7 @@
|
|||
@if (message.Kind == MessageKind.RecipientAdd && message.MentionedUsers.Any())
|
||||
{
|
||||
<span>added </span>
|
||||
<a class="chatlog__system-notification-link" title="@message.MentionedUsers.First().FullName">@message.MentionedUsers.First().Name</a>
|
||||
<a class="chatlog__system-notification-link" title="@message.MentionedUsers.First().FullName">@message.MentionedUsers.First().DisplayName</a>
|
||||
<span> to the group.</span>
|
||||
}
|
||||
else if (message.Kind == MessageKind.RecipientRemove && message.MentionedUsers.Any())
|
||||
|
@ -93,7 +93,7 @@
|
|||
else
|
||||
{
|
||||
<span>removed </span>
|
||||
<a class="chatlog__system-notification-link" title="@message.MentionedUsers.First().FullName">@message.MentionedUsers.First().Name</a>
|
||||
<a class="chatlog__system-notification-link" title="@message.MentionedUsers.First().FullName">@message.MentionedUsers.First().DisplayName</a>
|
||||
<span> from the group.</span>
|
||||
}
|
||||
}
|
||||
|
@ -168,12 +168,12 @@
|
|||
{
|
||||
var referencedUserMember = Context.TryGetMember(message.ReferencedMessage.Author.Id);
|
||||
var referencedUserColor = Context.TryGetUserColor(message.ReferencedMessage.Author.Id);
|
||||
var referencedUserNick = message.ReferencedMessage.Author.IsBot
|
||||
? message.ReferencedMessage.Author.Name
|
||||
: referencedUserMember?.Nick ?? message.ReferencedMessage.Author.Name;
|
||||
var referencedUserDisplayName = message.ReferencedMessage.Author.IsBot
|
||||
? message.ReferencedMessage.Author.DisplayName
|
||||
: referencedUserMember?.DisplayName ?? message.ReferencedMessage.Author.DisplayName;
|
||||
|
||||
<img class="chatlog__reply-avatar" src="@await ResolveAssetUrlAsync(referencedUserMember?.AvatarUrl ?? message.ReferencedMessage.Author.AvatarUrl)" alt="Avatar" loading="lazy">
|
||||
<div class="chatlog__reply-author" style="@(referencedUserColor is not null ? $"color: rgb({referencedUserColor.Value.R}, {referencedUserColor.Value.G}, {referencedUserColor.Value.B})" : null)" title="@message.ReferencedMessage.Author.FullName">@referencedUserNick</div>
|
||||
<div class="chatlog__reply-author" style="@(referencedUserColor is not null ? $"color: rgb({referencedUserColor.Value.R}, {referencedUserColor.Value.G}, {referencedUserColor.Value.B})" : null)" title="@message.ReferencedMessage.Author.FullName">@referencedUserDisplayName</div>
|
||||
<div class="chatlog__reply-content">
|
||||
<span class="chatlog__reply-link" onclick="scrollToMessage(event, '@message.ReferencedMessage.Id')">
|
||||
@if (!string.IsNullOrWhiteSpace(message.ReferencedMessage.Content) && !message.ReferencedMessage.IsContentHidden())
|
||||
|
@ -201,12 +201,12 @@
|
|||
{
|
||||
var interactionUserMember = Context.TryGetMember(message.Interaction.User.Id);
|
||||
var interactionUserColor = Context.TryGetUserColor(message.Interaction.User.Id);
|
||||
var interactionUserNick = message.Interaction.User.IsBot
|
||||
? message.Interaction.User.Name
|
||||
: interactionUserMember?.Nick ?? message.Interaction.User.Name;
|
||||
var interactionUserDisplayName = message.Interaction.User.IsBot
|
||||
? message.Interaction.User.DisplayName
|
||||
: interactionUserMember?.DisplayName ?? message.Interaction.User.DisplayName;
|
||||
|
||||
<img class="chatlog__reply-avatar" src="@await ResolveAssetUrlAsync(interactionUserMember?.AvatarUrl ?? message.Interaction.User.AvatarUrl)" alt="Avatar" loading="lazy">
|
||||
<div class="chatlog__reply-author" style="@(interactionUserColor is not null ? $"color: rgb({interactionUserColor.Value.R}, {interactionUserColor.Value.G}, {interactionUserColor.Value.B})" : null)" title="@message.Interaction.User.FullName">@interactionUserNick</div>
|
||||
<div class="chatlog__reply-author" style="@(interactionUserColor is not null ? $"color: rgb({interactionUserColor.Value.R}, {interactionUserColor.Value.G}, {interactionUserColor.Value.B})" : null)" title="@message.Interaction.User.FullName">@interactionUserDisplayName</div>
|
||||
<div class="chatlog__reply-content">
|
||||
used /@message.Interaction.Name
|
||||
</div>
|
||||
|
@ -223,7 +223,7 @@
|
|||
// Header
|
||||
<div class="chatlog__header">
|
||||
@* Author name *@
|
||||
<span class="chatlog__author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorNick</span>
|
||||
<span class="chatlog__author" style="@(authorColor is not null ? $"color: rgb({authorColor.Value.R}, {authorColor.Value.G}, {authorColor.Value.B})" : null)" title="@message.Author.FullName" data-user-id="@message.Author.Id">@authorDisplayName</span>
|
||||
|
||||
@* Bot tag *@
|
||||
@if (message.Author.IsBot)
|
||||
|
|
|
@ -59,9 +59,9 @@ internal partial class PlainTextMarkdownVisitor : MarkdownVisitor
|
|||
await _context.PopulateMemberAsync(mention.TargetId.Value, cancellationToken);
|
||||
|
||||
var member = mention.TargetId?.Pipe(_context.TryGetMember);
|
||||
var name = member?.User.Name ?? "Unknown";
|
||||
var displayName = member?.DisplayName ?? member?.User.DisplayName ?? "Unknown";
|
||||
|
||||
_buffer.Append($"@{name}");
|
||||
_buffer.Append($"@{displayName}");
|
||||
}
|
||||
else if (mention.Kind == MentionKind.Channel)
|
||||
{
|
||||
|
|
|
@ -9,13 +9,13 @@ internal static class PlainTextMessageExtensions
|
|||
public static string GetFallbackContent(this Message message) => message.Kind switch
|
||||
{
|
||||
MessageKind.RecipientAdd => message.MentionedUsers.Any()
|
||||
? $"Added {message.MentionedUsers.First().Name} to the group."
|
||||
? $"Added {message.MentionedUsers.First().DisplayName} to the group."
|
||||
: "Added a recipient.",
|
||||
|
||||
MessageKind.RecipientRemove => message.MentionedUsers.Any()
|
||||
? message.Author.Id == message.MentionedUsers.First().Id
|
||||
? "Left the group."
|
||||
: $"Removed {message.MentionedUsers.First().Name} from the group."
|
||||
: $"Removed {message.MentionedUsers.First().DisplayName} from the group."
|
||||
: "Removed a recipient.",
|
||||
|
||||
MessageKind.Call =>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
|
@ -10,4 +11,7 @@ public static class GenericExtensions
|
|||
!predicate(value)
|
||||
? value
|
||||
: null;
|
||||
|
||||
public static T? NullIfDefault<T>(this T value) where T : struct =>
|
||||
value.NullIf(v => EqualityComparer<T>.Default.Equals(v, default));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue