Load mentions for users that left the guild

pull/1017/head
Tyrrrz 2 years ago
parent bbe18368fa
commit 8f40acdda7

@ -23,19 +23,6 @@ public partial record Channel(
public partial record Channel public partial record Channel
{ {
private static ChannelCategory GetFallbackCategory(ChannelKind channelKind) => new(
Snowflake.Zero,
channelKind switch
{
ChannelKind.GuildTextChat => "Text",
ChannelKind.DirectTextChat => "Private",
ChannelKind.DirectGroupTextChat => "Group",
ChannelKind.GuildNews => "News",
_ => "Default"
},
null
);
public static Channel Parse(JsonElement json, ChannelCategory? categoryHint = null, int? positionHint = null) public static Channel Parse(JsonElement json, ChannelCategory? categoryHint = null, int? positionHint = null)
{ {
var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);
@ -45,7 +32,7 @@ public partial record Channel
json.GetPropertyOrNull("guild_id")?.GetNonWhiteSpaceStringOrNull()?.Pipe(Snowflake.Parse) ?? json.GetPropertyOrNull("guild_id")?.GetNonWhiteSpaceStringOrNull()?.Pipe(Snowflake.Parse) ??
Guild.DirectMessages.Id; Guild.DirectMessages.Id;
var category = categoryHint ?? GetFallbackCategory(kind); var category = categoryHint ?? ChannelCategory.CreateDefault(kind);
var name = var name =
// Guild channel // Guild channel

@ -7,6 +7,19 @@ namespace DiscordChatExporter.Core.Discord.Data;
public record ChannelCategory(Snowflake Id, string Name, int? Position) : IHasId public record ChannelCategory(Snowflake Id, string Name, int? Position) : IHasId
{ {
public static ChannelCategory CreateDefault(ChannelKind channelKind) => new(
Snowflake.Zero,
channelKind switch
{
ChannelKind.GuildTextChat => "Text",
ChannelKind.DirectTextChat => "Private",
ChannelKind.DirectGroupTextChat => "Group",
ChannelKind.GuildNews => "News",
_ => "Default"
},
null
);
public static ChannelCategory Parse(JsonElement json, int? positionHint = null) public static ChannelCategory Parse(JsonElement json, int? positionHint = null)
{ {
var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse); var id = json.GetProperty("id").GetNonWhiteSpaceString().Pipe(Snowflake.Parse);

@ -20,6 +20,8 @@ public partial record Member(
public partial record Member public partial record Member
{ {
public static Member CreateDefault(User user) => new(user, null, null, Array.Empty<Snowflake>());
public static Member Parse(JsonElement json, Snowflake? guildId = null) public static Member Parse(JsonElement json, Snowflake? guildId = null)
{ {
var user = json.GetProperty("user").Pipe(User.Parse); var user = json.GetProperty("user").Pipe(User.Parse);

@ -150,6 +150,14 @@ public class DiscordClient
: null; : null;
} }
public async ValueTask<User?> TryGetUserAsync(
Snowflake userId,
CancellationToken cancellationToken = default)
{
var response = await TryGetJsonResponseAsync($"users/{userId}", cancellationToken);
return response?.Pipe(User.Parse);
}
public async IAsyncEnumerable<Guild> GetUserGuildsAsync( public async IAsyncEnumerable<Guild> GetUserGuildsAsync(
[EnumeratorCancellation] CancellationToken cancellationToken = default) [EnumeratorCancellation] CancellationToken cancellationToken = default)
{ {

@ -34,7 +34,7 @@ public class ChannelExporter
{ {
// Resolve members for referenced users // Resolve members for referenced users
foreach (var user in message.GetReferencedUsers()) foreach (var user in message.GetReferencedUsers())
await context.PopulateMemberAsync(user.Id, cancellationToken); await context.PopulateMemberAsync(user, cancellationToken);
// Export the message // Export the message
if (request.MessageFilter.IsMatch(message)) if (request.MessageFilter.IsMatch(message))

@ -20,6 +20,7 @@ internal class ExportContext
private readonly ExportAssetDownloader _assetDownloader; private readonly ExportAssetDownloader _assetDownloader;
public DiscordClient Discord { get; } public DiscordClient Discord { get; }
public ExportRequest Request { get; } public ExportRequest Request { get; }
public ExportContext(DiscordClient discord, public ExportContext(DiscordClient discord,
@ -43,18 +44,35 @@ internal class ExportContext
_roles[role.Id] = role; _roles[role.Id] = role;
} }
// Because members are not pulled in bulk, we need to populate them on demand // Because members cannot be pulled in bulk, we need to populate them on demand
public async ValueTask PopulateMemberAsync(Snowflake id, CancellationToken cancellationToken = default) private async ValueTask PopulateMemberAsync(
Snowflake id,
User? fallbackUser,
CancellationToken cancellationToken = default)
{ {
if (_members.ContainsKey(id)) if (_members.ContainsKey(id))
return; return;
var member = await Discord.TryGetGuildMemberAsync(Request.Guild.Id, id, cancellationToken); var member = await Discord.TryGetGuildMemberAsync(Request.Guild.Id, id, cancellationToken);
// User may have left the guild since they were mentioned
if (member is null)
{
var user = fallbackUser ?? await Discord.TryGetUserAsync(id, cancellationToken);
if (user is not null)
member = Member.CreateDefault(user);
}
// Store the result even if it's null, to avoid re-fetching non-existing members // Store the result even if it's null, to avoid re-fetching non-existing members
_members[id] = member; _members[id] = member;
} }
public async ValueTask PopulateMemberAsync(Snowflake id, CancellationToken cancellationToken = default) =>
await PopulateMemberAsync(id, null, cancellationToken);
public async ValueTask PopulateMemberAsync(User user, CancellationToken cancellationToken = default) =>
await PopulateMemberAsync(user.Id, user, cancellationToken);
public string FormatDate(DateTimeOffset instant) => Request.DateFormat switch public string FormatDate(DateTimeOffset instant) => Request.DateFormat switch
{ {
"unix" => instant.ToUnixTimeSeconds().ToString(), "unix" => instant.ToUnixTimeSeconds().ToString(),

Loading…
Cancel
Save