This commit is contained in:
Tyrrrz 2024-11-06 19:36:34 +02:00
parent 789e5af8ba
commit 1fb6156187
15 changed files with 47 additions and 43 deletions

View file

@ -7,7 +7,7 @@ namespace DiscordChatExporter.Core.Discord.Data;
// https://discord.com/developers/docs/resources/application#application-object // https://discord.com/developers/docs/resources/application#application-object
public partial record Application(Snowflake Id, string Name, ApplicationFlags Flags) public partial record Application(Snowflake Id, string Name, ApplicationFlags Flags)
{ {
public bool IsMessageContentIntentEnabled => public bool IsMessageContentIntentEnabled { get; } =
Flags.HasFlag(ApplicationFlags.GatewayMessageContent) Flags.HasFlag(ApplicationFlags.GatewayMessageContent)
|| Flags.HasFlag(ApplicationFlags.GatewayMessageContentLimited); || Flags.HasFlag(ApplicationFlags.GatewayMessageContentLimited);
} }

View file

@ -18,7 +18,7 @@ public partial record Attachment(
FileSize FileSize FileSize FileSize
) : IHasId ) : IHasId
{ {
public string FileExtension => Path.GetExtension(FileName); public string FileExtension { get; } = Path.GetExtension(FileName);
public bool IsImage => public bool IsImage =>
string.Equals(FileExtension, ".jpg", StringComparison.OrdinalIgnoreCase) string.Equals(FileExtension, ".jpg", StringComparison.OrdinalIgnoreCase)
@ -41,7 +41,7 @@ public partial record Attachment(
|| string.Equals(FileExtension, ".flac", StringComparison.OrdinalIgnoreCase) || string.Equals(FileExtension, ".flac", StringComparison.OrdinalIgnoreCase)
|| string.Equals(FileExtension, ".m4a", StringComparison.OrdinalIgnoreCase); || string.Equals(FileExtension, ".m4a", StringComparison.OrdinalIgnoreCase);
public bool IsSpoiler => FileName.StartsWith("SPOILER_", StringComparison.Ordinal); public bool IsSpoiler { get; } = FileName.StartsWith("SPOILER_", StringComparison.Ordinal);
} }
public partial record Attachment public partial record Attachment

View file

@ -21,21 +21,23 @@ public partial record Channel(
Snowflake? LastMessageId Snowflake? LastMessageId
) : IHasId ) : IHasId
{ {
public bool IsDirect => Kind is ChannelKind.DirectTextChat or ChannelKind.DirectGroupTextChat; public bool IsDirect { get; } =
Kind is ChannelKind.DirectTextChat or ChannelKind.DirectGroupTextChat;
public bool IsGuild => !IsDirect; public bool IsGuild => !IsDirect;
public bool IsCategory => Kind == ChannelKind.GuildCategory; public bool IsCategory { get; } = Kind == ChannelKind.GuildCategory;
public bool IsVoice => Kind is ChannelKind.GuildVoiceChat or ChannelKind.GuildStageVoice; public bool IsVoice { get; } =
Kind is ChannelKind.GuildVoiceChat or ChannelKind.GuildStageVoice;
public bool IsThread => public bool IsThread { get; } =
Kind Kind
is ChannelKind.GuildNewsThread is ChannelKind.GuildNewsThread
or ChannelKind.GuildPublicThread or ChannelKind.GuildPublicThread
or ChannelKind.GuildPrivateThread; or ChannelKind.GuildPrivateThread;
public bool IsEmpty => LastMessageId is null; public bool IsEmpty { get; } = LastMessageId is null;
public IEnumerable<Channel> GetParents() public IEnumerable<Channel> GetParents()
{ {

View file

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;
namespace DiscordChatExporter.Core.Discord.Data;
public record ChannelConnection(Channel Channel, IReadOnlyList<ChannelConnection> Children)
{
public static IReadOnlyList<ChannelConnection> BuildTree(IReadOnlyList<Channel> channels)
{
IReadOnlyList<ChannelConnection> GetChildren(Channel parent) =>
channels
.Where(c => c.Parent?.Id == parent.Id)
.Select(c => new ChannelConnection(c, GetChildren(c)))
.ToArray();
return channels
.Where(c => c.Parent is null)
.Select(c => new ChannelConnection(c, GetChildren(c)))
.ToArray();
}
}

View file

@ -1,21 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace DiscordChatExporter.Core.Discord.Data;
public record ChannelNode(Channel Channel, IReadOnlyList<ChannelNode> Children)
{
public static IReadOnlyList<ChannelNode> BuildTree(IReadOnlyList<Channel> channels)
{
IReadOnlyList<ChannelNode> GetChildren(Channel parent) =>
channels
.Where(c => c.Parent?.Id == parent.Id)
.Select(c => new ChannelNode(c, GetChildren(c)))
.ToArray();
return channels
.Where(c => c.Parent is null)
.Select(c => new ChannelNode(c, GetChildren(c)))
.ToArray();
}
}

View file

@ -4,7 +4,7 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds;
public partial record SpotifyTrackEmbedProjection(string TrackId) public partial record SpotifyTrackEmbedProjection(string TrackId)
{ {
public string Url => $"https://open.spotify.com/embed/track/{TrackId}"; public string Url { get; } = $"https://open.spotify.com/embed/track/{TrackId}";
} }
public partial record SpotifyTrackEmbedProjection public partial record SpotifyTrackEmbedProjection

View file

@ -4,7 +4,7 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds;
public partial record TwitchClipEmbedProjection(string ClipId) public partial record TwitchClipEmbedProjection(string ClipId)
{ {
public string Url => $"https://clips.twitch.tv/embed?clip={ClipId}&parent=localhost"; public string Url { get; } = $"https://clips.twitch.tv/embed?clip={ClipId}&parent=localhost";
} }
public partial record TwitchClipEmbedProjection public partial record TwitchClipEmbedProjection

View file

@ -2,7 +2,7 @@
public partial record YouTubeVideoEmbedProjection(string VideoId) public partial record YouTubeVideoEmbedProjection(string VideoId)
{ {
public string Url => $"https://www.youtube.com/embed/{VideoId}"; public string Url { get; } = $"https://www.youtube.com/embed/{VideoId}";
} }
public partial record YouTubeVideoEmbedProjection public partial record YouTubeVideoEmbedProjection

View file

@ -8,7 +8,7 @@ namespace DiscordChatExporter.Core.Discord.Data;
// https://discord.com/developers/docs/resources/guild#guild-object // https://discord.com/developers/docs/resources/guild#guild-object
public partial record Guild(Snowflake Id, string Name, string IconUrl) : IHasId public partial record Guild(Snowflake Id, string Name, string IconUrl) : IHasId
{ {
public bool IsDirect => Id == DirectMessages.Id; public bool IsDirect { get; } = Id == DirectMessages.Id;
} }
public partial record Guild public partial record Guild

View file

@ -15,7 +15,7 @@ public partial record Member(
IReadOnlyList<Snowflake> RoleIds IReadOnlyList<Snowflake> RoleIds
) : IHasId ) : IHasId
{ {
public Snowflake Id => User.Id; public Snowflake Id { get; } = User.Id;
} }
public partial record Member public partial record Member

View file

@ -30,15 +30,15 @@ public partial record Message(
Interaction? Interaction Interaction? Interaction
) : IHasId ) : IHasId
{ {
public bool IsSystemNotification => public bool IsSystemNotification { get; } =
Kind is >= MessageKind.RecipientAdd and <= MessageKind.ThreadCreated; Kind is >= MessageKind.RecipientAdd and <= MessageKind.ThreadCreated;
public bool IsReply => Kind == MessageKind.Reply; public bool IsReply { get; } = Kind == MessageKind.Reply;
// App interactions are rendered as replies in the Discord client, but they are not actually replies // App interactions are rendered as replies in the Discord client, but they are not actually replies
public bool IsReplyLike => IsReply || Interaction is not null; public bool IsReplyLike => IsReply || Interaction is not null;
public bool IsEmpty => public bool IsEmpty { get; } =
string.IsNullOrWhiteSpace(Content) string.IsNullOrWhiteSpace(Content)
&& !Attachments.Any() && !Attachments.Any()
&& !Embeds.Any() && !Embeds.Any()

View file

@ -9,7 +9,7 @@ namespace DiscordChatExporter.Core.Discord.Data;
// https://discord.com/developers/docs/resources/sticker#sticker-resource // https://discord.com/developers/docs/resources/sticker#sticker-resource
public partial record Sticker(Snowflake Id, string Name, StickerFormat Format, string SourceUrl) public partial record Sticker(Snowflake Id, string Name, StickerFormat Format, string SourceUrl)
{ {
public bool IsImage => Format != StickerFormat.Lottie; public bool IsImage { get; } = Format != StickerFormat.Lottie;
} }
public partial record Sticker public partial record Sticker

View file

@ -18,7 +18,7 @@ public partial record User(
string AvatarUrl string AvatarUrl
) : IHasId ) : IHasId
{ {
public string DiscriminatorFormatted => public string DiscriminatorFormatted { get; } =
Discriminator is not null ? $"{Discriminator:0000}" : "0000"; Discriminator is not null ? $"{Discriminator:0000}" : "0000";
// This effectively represents the user's true identity. // This effectively represents the user's true identity.

View file

@ -53,7 +53,7 @@ public partial class DashboardViewModel : ViewModelBase
private Guild? _selectedGuild; private Guild? _selectedGuild;
[ObservableProperty] [ObservableProperty]
private IReadOnlyList<ChannelNode>? _availableChannels; private IReadOnlyList<ChannelConnection>? _availableChannels;
public DashboardViewModel( public DashboardViewModel(
ViewModelManager viewModelManager, ViewModelManager viewModelManager,
@ -88,7 +88,7 @@ public partial class DashboardViewModel : ViewModelBase
public bool IsProgressIndeterminate => IsBusy && Progress.Current.Fraction is <= 0 or >= 1; public bool IsProgressIndeterminate => IsBusy && Progress.Current.Fraction is <= 0 or >= 1;
public ObservableCollection<ChannelNode> SelectedChannels { get; } = []; public ObservableCollection<ChannelConnection> SelectedChannels { get; } = [];
[RelayCommand] [RelayCommand]
private void Initialize() private void Initialize()
@ -190,7 +190,7 @@ public partial class DashboardViewModel : ViewModelBase
} }
// Build a hierarchy of channels // Build a hierarchy of channels
var channelTree = ChannelNode.BuildTree( var channelTree = ChannelConnection.BuildTree(
channels channels
.OrderByDescending(c => c.IsDirect ? c.LastMessageId : null) .OrderByDescending(c => c.IsDirect ? c.LastMessageId : null)
.ThenBy(c => c.Position) .ThenBy(c => c.Position)

View file

@ -28,7 +28,9 @@ public partial class DashboardView : UserControl<DashboardViewModel>
) )
{ {
// Hack: unselect categories because they cannot be exported // Hack: unselect categories because they cannot be exported
foreach (var item in args.AddedItems.OfType<ChannelNode>().Where(x => x.Channel.IsCategory)) foreach (
var item in args.AddedItems.OfType<ChannelConnection>().Where(x => x.Channel.IsCategory)
)
{ {
if (AvailableChannelsTreeView.TreeContainerFromItem(item) is TreeViewItem container) if (AvailableChannelsTreeView.TreeContainerFromItem(item) is TreeViewItem container)
container.IsSelected = false; container.IsSelected = false;