pull/1314/head
Tyrrrz 5 months ago
parent 789e5af8ba
commit 1fb6156187

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

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

@ -21,21 +21,23 @@ public partial record Channel(
Snowflake? LastMessageId
) : 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 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
is ChannelKind.GuildNewsThread
or ChannelKind.GuildPublicThread
or ChannelKind.GuildPrivateThread;
public bool IsEmpty => LastMessageId is null;
public bool IsEmpty { get; } = LastMessageId is null;
public IEnumerable<Channel> GetParents()
{

@ -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();
}
}

@ -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();
}
}

@ -4,7 +4,7 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds;
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

@ -4,7 +4,7 @@ namespace DiscordChatExporter.Core.Discord.Data.Embeds;
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

@ -2,7 +2,7 @@
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

@ -8,7 +8,7 @@ namespace DiscordChatExporter.Core.Discord.Data;
// https://discord.com/developers/docs/resources/guild#guild-object
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

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

@ -30,15 +30,15 @@ public partial record Message(
Interaction? Interaction
) : IHasId
{
public bool IsSystemNotification =>
public bool IsSystemNotification { get; } =
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
public bool IsReplyLike => IsReply || Interaction is not null;
public bool IsEmpty =>
public bool IsEmpty { get; } =
string.IsNullOrWhiteSpace(Content)
&& !Attachments.Any()
&& !Embeds.Any()

@ -9,7 +9,7 @@ namespace DiscordChatExporter.Core.Discord.Data;
// https://discord.com/developers/docs/resources/sticker#sticker-resource
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

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

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

@ -28,7 +28,9 @@ public partial class DashboardView : UserControl<DashboardViewModel>
)
{
// 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)
container.IsSelected = false;

Loading…
Cancel
Save