mirror of
https://github.com/chylex/Discord-History-Tracker.git
synced 2024-11-25 14:42:44 +01:00
Compare commits
2 Commits
8aeb590bb3
...
65d935cca1
Author | SHA1 | Date | |
---|---|---|---|
65d935cca1 | |||
6e64c86d7a |
@ -9,6 +9,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<ApplicationIcon>./Resources/icon.ico</ApplicationIcon>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:namespace="clr-namespace:DHT.Desktop.Dialogs.CheckBox"
|
||||
mc:Ignorable="d" d:DesignWidth="500"
|
||||
x:Class="DHT.Desktop.Dialogs.CheckBox.CheckBoxDialog"
|
||||
x:DataType="namespace:CheckBoxDialogModel"
|
||||
Title="{Binding Title}"
|
||||
Icon="avares://DiscordHistoryTracker/Resources/icon.ico"
|
||||
Width="500" SizeToContent="Height" CanResize="False"
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:namespace="clr-namespace:DHT.Desktop.Dialogs.Message"
|
||||
mc:Ignorable="d" d:DesignWidth="500"
|
||||
x:Class="DHT.Desktop.Dialogs.Message.MessageDialog"
|
||||
x:DataType="namespace:MessageDialogModel"
|
||||
Title="{Binding Title}"
|
||||
Icon="avares://DiscordHistoryTracker/Resources/icon.ico"
|
||||
Width="500" SizeToContent="Height" CanResize="False"
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:namespace="clr-namespace:DHT.Desktop.Dialogs.Progress"
|
||||
mc:Ignorable="d" d:DesignWidth="500"
|
||||
x:Class="DHT.Desktop.Dialogs.Progress.ProgressDialog"
|
||||
x:DataType="namespace:ProgressDialogModel"
|
||||
Title="{Binding Title}"
|
||||
Icon="avares://DiscordHistoryTracker/Resources/icon.ico"
|
||||
Opened="OnOpened"
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:namespace="clr-namespace:DHT.Desktop.Dialogs.TextBox"
|
||||
mc:Ignorable="d" d:DesignWidth="500"
|
||||
x:Class="DHT.Desktop.Dialogs.TextBox.TextBoxDialog"
|
||||
x:DataType="namespace:TextBoxDialogModel"
|
||||
Title="{Binding Title}"
|
||||
Icon="avares://DiscordHistoryTracker/Resources/icon.ico"
|
||||
Width="500" SizeToContent="Height" CanResize="False"
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:main="clr-namespace:DHT.Desktop.Main"
|
||||
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="295"
|
||||
x:Class="DHT.Desktop.Main.AboutWindow"
|
||||
x:DataType="main:AboutWindowModel"
|
||||
Title="About Discord History Tracker"
|
||||
Icon="avares://DiscordHistoryTracker/Resources/icon.ico"
|
||||
Width="480" Height="295" CanResize="False"
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Class="DHT.Desktop.Main.Controls.AttachmentFilterPanel">
|
||||
x:Class="DHT.Desktop.Main.Controls.AttachmentFilterPanel"
|
||||
x:DataType="controls:AttachmentFilterPanelModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<controls:AttachmentFilterPanelModel />
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Class="DHT.Desktop.Main.Controls.MessageFilterPanel">
|
||||
x:Class="DHT.Desktop.Main.Controls.MessageFilterPanel"
|
||||
x:DataType="controls:MessageFilterPanelModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<controls:MessageFilterPanelModel />
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Class="DHT.Desktop.Main.Controls.ServerConfigurationPanel">
|
||||
x:Class="DHT.Desktop.Main.Controls.ServerConfigurationPanel"
|
||||
x:DataType="controls:ServerConfigurationPanelModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<controls:ServerConfigurationPanelModel />
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Class="DHT.Desktop.Main.Controls.StatusBar">
|
||||
x:Class="DHT.Desktop.Main.Controls.StatusBar"
|
||||
x:DataType="controls:StatusBarModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<controls:StatusBarModel />
|
||||
|
@ -5,6 +5,7 @@
|
||||
xmlns:main="clr-namespace:DHT.Desktop.Main"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.MainWindow"
|
||||
x:DataType="main:MainWindowModel"
|
||||
Title="{Binding Title}"
|
||||
Icon="avares://DiscordHistoryTracker/Resources/icon.ico"
|
||||
Width="800" Height="500"
|
||||
|
@ -5,7 +5,8 @@
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.AdvancedPage">
|
||||
x:Class="DHT.Desktop.Main.Pages.AdvancedPage"
|
||||
x:DataType="pages:AdvancedPageModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:AdvancedPageModel />
|
||||
|
@ -5,7 +5,8 @@
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.AttachmentsPage">
|
||||
x:Class="DHT.Desktop.Main.Pages.AttachmentsPage"
|
||||
x:DataType="pages:AttachmentsPageModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:AttachmentsPageModel />
|
||||
@ -35,7 +36,7 @@
|
||||
<TextBlock Text="{Binding DownloadMessage}" Margin="10 0 0 0" VerticalAlignment="Center" DockPanel.Dock="Left" />
|
||||
<ProgressBar Value="{Binding DownloadProgress}" IsVisible="{Binding IsDownloading}" Margin="15 0" VerticalAlignment="Center" DockPanel.Dock="Right" />
|
||||
</DockPanel>
|
||||
<controls:AttachmentFilterPanel DataContext="{Binding FilterModel}" IsEnabled="{Binding !DataContext.IsDownloading, RelativeSource={RelativeSource AncestorType=UserControl}}" />
|
||||
<controls:AttachmentFilterPanel DataContext="{Binding FilterModel}" IsEnabled="{Binding !IsDownloading, RelativeSource={RelativeSource AncestorType=pages:AttachmentsPageModel}}" />
|
||||
<StackPanel Orientation="Vertical" Spacing="12">
|
||||
<Expander Header="Download Status" IsExpanded="True">
|
||||
<DataGrid ItemsSource="{Binding StatisticsRows}" AutoGenerateColumns="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserSortColumns="False" IsReadOnly="True">
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.DatabasePage">
|
||||
x:Class="DHT.Desktop.Main.Pages.DatabasePage"
|
||||
x:DataType="pages:DatabasePageModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:DatabasePageModel />
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.DebugPage">
|
||||
x:Class="DHT.Desktop.Main.Pages.DebugPage"
|
||||
x:DataType="pages:DebugPageModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:DebugPageModel />
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.TrackingPage">
|
||||
x:Class="DHT.Desktop.Main.Pages.TrackingPage"
|
||||
x:DataType="pages:TrackingPageModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:TrackingPageModel />
|
||||
|
@ -5,7 +5,8 @@
|
||||
xmlns:pages="clr-namespace:DHT.Desktop.Main.Pages"
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Pages.ViewerPage">
|
||||
x:Class="DHT.Desktop.Main.Pages.ViewerPage"
|
||||
x:DataType="pages:ViewerPageModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<pages:ViewerPageModel />
|
||||
|
@ -35,7 +35,7 @@ sealed class ViewerPageModel : BaseModel, IDisposable {
|
||||
set => Change(ref hasFilters, value);
|
||||
}
|
||||
|
||||
private MessageFilterPanelModel FilterModel { get; }
|
||||
public MessageFilterPanelModel FilterModel { get; }
|
||||
|
||||
private readonly Window window;
|
||||
private readonly IDatabaseFile db;
|
||||
|
@ -5,7 +5,8 @@
|
||||
xmlns:controls="clr-namespace:DHT.Desktop.Main.Controls"
|
||||
xmlns:screens="clr-namespace:DHT.Desktop.Main.Screens"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Screens.MainContentScreen">
|
||||
x:Class="DHT.Desktop.Main.Screens.MainContentScreen"
|
||||
x:DataType="screens:MainContentScreenModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<screens:MainContentScreenModel />
|
||||
|
@ -4,7 +4,8 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:screens="clr-namespace:DHT.Desktop.Main.Screens"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="DHT.Desktop.Main.Screens.WelcomeScreen">
|
||||
x:Class="DHT.Desktop.Main.Screens.WelcomeScreen"
|
||||
x:DataType="screens:WelcomeScreenModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<screens:WelcomeScreenModel />
|
||||
|
3
app/Server/Database/Export/Snowflake.cs
Normal file
3
app/Server/Database/Export/Snowflake.cs
Normal file
@ -0,0 +1,3 @@
|
||||
namespace DHT.Server.Database.Export;
|
||||
|
||||
readonly record struct Snowflake(ulong Id);
|
23
app/Server/Database/Export/SnowflakeJsonSerializer.cs
Normal file
23
app/Server/Database/Export/SnowflakeJsonSerializer.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DHT.Server.Database.Export;
|
||||
|
||||
sealed class SnowflakeJsonSerializer : JsonConverter<Snowflake> {
|
||||
public override Snowflake Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
return new Snowflake(ulong.Parse(reader.GetString()!));
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Snowflake value, JsonSerializerOptions options) {
|
||||
writer.WriteStringValue(value.Id.ToString());
|
||||
}
|
||||
|
||||
public override Snowflake ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
return new Snowflake(ulong.Parse(reader.GetString()!));
|
||||
}
|
||||
|
||||
public override void WriteAsPropertyName(Utf8JsonWriter writer, Snowflake value, JsonSerializerOptions options) {
|
||||
writer.WritePropertyName(value.Id.ToString());
|
||||
}
|
||||
}
|
93
app/Server/Database/Export/ViewerJson.cs
Normal file
93
app/Server/Database/Export/ViewerJson.cs
Normal file
@ -0,0 +1,93 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DHT.Server.Database.Export;
|
||||
|
||||
sealed class ViewerJson {
|
||||
public required JsonMeta Meta { get; init; }
|
||||
public required Dictionary<Snowflake, Dictionary<Snowflake, JsonMessage>> Data { get; init; }
|
||||
|
||||
public sealed class JsonMeta {
|
||||
public required Dictionary<Snowflake, JsonUser> Users { get; init; }
|
||||
public required List<Snowflake> Userindex { get; init; }
|
||||
public required List<JsonServer> Servers { get; init; }
|
||||
public required Dictionary<Snowflake, JsonChannel> Channels { get; init; }
|
||||
}
|
||||
|
||||
public sealed class JsonUser {
|
||||
public required string Name { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Avatar { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Tag { get; init; }
|
||||
}
|
||||
|
||||
public sealed class JsonServer {
|
||||
public required string Name { get; init; }
|
||||
public required string Type { get; init; }
|
||||
}
|
||||
|
||||
public sealed class JsonChannel {
|
||||
public required int Server { get; init; }
|
||||
public required string Name { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Parent { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public int? Position { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Topic { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public bool? Nsfw { get; init; }
|
||||
}
|
||||
|
||||
public sealed class JsonMessage {
|
||||
public required int U { get; init; }
|
||||
public required long T { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? M { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public long? Te { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? R { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public JsonMessageAttachment[]? A { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string[]? E { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public JsonMessageReaction[]? Re { get; init; }
|
||||
}
|
||||
|
||||
public sealed class JsonMessageAttachment {
|
||||
public required string Url { get; init; }
|
||||
public required string Name { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public int? Width { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public int? Height { get; set; }
|
||||
}
|
||||
|
||||
public sealed class JsonMessageReaction {
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Id { get; init; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? N { get; init; }
|
||||
|
||||
public required bool A { get; init; }
|
||||
public required int C { get; init; }
|
||||
}
|
||||
}
|
11
app/Server/Database/Export/ViewerJsonContext.cs
Normal file
11
app/Server/Database/Export/ViewerJsonContext.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DHT.Server.Database.Export;
|
||||
|
||||
[JsonSourceGenerationOptions(
|
||||
Converters = new [] { typeof(SnowflakeJsonSerializer) },
|
||||
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
|
||||
GenerationMode = JsonSourceGenerationMode.Default
|
||||
)]
|
||||
[JsonSerializable(typeof(ViewerJson))]
|
||||
sealed partial class ViewerJsonContext : JsonSerializerContext {}
|
@ -42,26 +42,28 @@ public static class ViewerJsonExport {
|
||||
|
||||
perf.Step("Collect database data");
|
||||
|
||||
var value = new {
|
||||
meta = new { users, userindex, servers, channels },
|
||||
data = GenerateMessageList(includedMessages, userIndices, strategy),
|
||||
var value = new ViewerJson {
|
||||
Meta = new ViewerJson.JsonMeta {
|
||||
Users = users,
|
||||
Userindex = userindex,
|
||||
Servers = servers,
|
||||
Channels = channels
|
||||
},
|
||||
Data = GenerateMessageList(includedMessages, userIndices, strategy)
|
||||
};
|
||||
|
||||
perf.Step("Generate value object");
|
||||
|
||||
var opts = new JsonSerializerOptions();
|
||||
opts.Converters.Add(new ViewerJsonSnowflakeSerializer());
|
||||
|
||||
await JsonSerializer.SerializeAsync(stream, value, opts);
|
||||
await JsonSerializer.SerializeAsync(stream, value, ViewerJsonContext.Default.ViewerJson);
|
||||
|
||||
perf.Step("Serialize to JSON");
|
||||
perf.End();
|
||||
}
|
||||
|
||||
private static Dictionary<string, object> GenerateUserList(IDatabaseFile db, HashSet<ulong> userIds, out List<string> userindex, out Dictionary<ulong, object> userIndices) {
|
||||
var users = new Dictionary<string, object>();
|
||||
userindex = new List<string>();
|
||||
userIndices = new Dictionary<ulong, object>();
|
||||
private static Dictionary<Snowflake, ViewerJson.JsonUser> GenerateUserList(IDatabaseFile db, HashSet<ulong> userIds, out List<Snowflake> userindex, out Dictionary<ulong, int> userIndices) {
|
||||
var users = new Dictionary<Snowflake, ViewerJson.JsonUser>();
|
||||
userindex = new List<Snowflake>();
|
||||
userIndices = new Dictionary<ulong, int>();
|
||||
|
||||
foreach (var user in db.GetAllUsers()) {
|
||||
var id = user.Id;
|
||||
@ -69,30 +71,23 @@ public static class ViewerJsonExport {
|
||||
continue;
|
||||
}
|
||||
|
||||
var obj = new Dictionary<string, object> {
|
||||
["name"] = user.Name
|
||||
};
|
||||
|
||||
if (user.AvatarUrl != null) {
|
||||
obj["avatar"] = user.AvatarUrl;
|
||||
}
|
||||
|
||||
if (user.Discriminator != null) {
|
||||
obj["tag"] = user.Discriminator;
|
||||
}
|
||||
|
||||
var idStr = id.ToString();
|
||||
var idSnowflake = new Snowflake(id);
|
||||
userIndices[id] = users.Count;
|
||||
userindex.Add(idStr);
|
||||
users[idStr] = obj;
|
||||
userindex.Add(idSnowflake);
|
||||
|
||||
users[idSnowflake] = new ViewerJson.JsonUser {
|
||||
Name = user.Name,
|
||||
Avatar = user.AvatarUrl,
|
||||
Tag = user.Discriminator
|
||||
};
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
private static List<object> GenerateServerList(IDatabaseFile db, HashSet<ulong> serverIds, out Dictionary<ulong, object> serverIndices) {
|
||||
var servers = new List<object>();
|
||||
serverIndices = new Dictionary<ulong, object>();
|
||||
private static List<ViewerJson.JsonServer> GenerateServerList(IDatabaseFile db, HashSet<ulong> serverIds, out Dictionary<ulong, int> serverIndices) {
|
||||
var servers = new List<ViewerJson.JsonServer>();
|
||||
serverIndices = new Dictionary<ulong, int>();
|
||||
|
||||
foreach (var server in db.GetAllServers()) {
|
||||
var id = server.Id;
|
||||
@ -101,113 +96,78 @@ public static class ViewerJsonExport {
|
||||
}
|
||||
|
||||
serverIndices[id] = servers.Count;
|
||||
servers.Add(new Dictionary<string, object> {
|
||||
["name"] = server.Name,
|
||||
["type"] = ServerTypes.ToJsonViewerString(server.Type),
|
||||
|
||||
servers.Add(new ViewerJson.JsonServer {
|
||||
Name = server.Name,
|
||||
Type = ServerTypes.ToJsonViewerString(server.Type)
|
||||
});
|
||||
}
|
||||
|
||||
return servers;
|
||||
}
|
||||
|
||||
private static Dictionary<string, object> GenerateChannelList(List<Channel> includedChannels, Dictionary<ulong, object> serverIndices) {
|
||||
var channels = new Dictionary<string, object>();
|
||||
private static Dictionary<Snowflake, ViewerJson.JsonChannel> GenerateChannelList(List<Channel> includedChannels, Dictionary<ulong, int> serverIndices) {
|
||||
var channels = new Dictionary<Snowflake, ViewerJson.JsonChannel>();
|
||||
|
||||
foreach (var channel in includedChannels) {
|
||||
var obj = new Dictionary<string, object> {
|
||||
["server"] = serverIndices[channel.Server],
|
||||
["name"] = channel.Name,
|
||||
var channelIdSnowflake = new Snowflake(channel.Id);
|
||||
|
||||
channels[channelIdSnowflake] = new ViewerJson.JsonChannel {
|
||||
Server = serverIndices[channel.Server],
|
||||
Name = channel.Name,
|
||||
Parent = channel.ParentId?.ToString(),
|
||||
Position = channel.Position,
|
||||
Topic = channel.Topic,
|
||||
Nsfw = channel.Nsfw
|
||||
};
|
||||
|
||||
if (channel.ParentId != null) {
|
||||
obj["parent"] = channel.ParentId;
|
||||
}
|
||||
|
||||
if (channel.Position != null) {
|
||||
obj["position"] = channel.Position;
|
||||
}
|
||||
|
||||
if (channel.Topic != null) {
|
||||
obj["topic"] = channel.Topic;
|
||||
}
|
||||
|
||||
if (channel.Nsfw != null) {
|
||||
obj["nsfw"] = channel.Nsfw;
|
||||
}
|
||||
|
||||
channels[channel.Id.ToString()] = obj;
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
private static Dictionary<string, Dictionary<string, object>> GenerateMessageList( List<Message> includedMessages, Dictionary<ulong, object> userIndices, IViewerExportStrategy strategy) {
|
||||
var data = new Dictionary<string, Dictionary<string, object>>();
|
||||
private static Dictionary<Snowflake, Dictionary<Snowflake, ViewerJson.JsonMessage>> GenerateMessageList(List<Message> includedMessages, Dictionary<ulong, int> userIndices, IViewerExportStrategy strategy) {
|
||||
var data = new Dictionary<Snowflake, Dictionary<Snowflake, ViewerJson.JsonMessage>>();
|
||||
|
||||
foreach (var grouping in includedMessages.GroupBy(static message => message.Channel)) {
|
||||
var channel = grouping.Key.ToString();
|
||||
var channelData = new Dictionary<string, object>();
|
||||
var channelIdSnowflake = new Snowflake(grouping.Key);
|
||||
var channelData = new Dictionary<Snowflake, ViewerJson.JsonMessage>();
|
||||
|
||||
foreach (var message in grouping) {
|
||||
var obj = new Dictionary<string, object> {
|
||||
["u"] = userIndices[message.Sender],
|
||||
["t"] = message.Timestamp,
|
||||
};
|
||||
var messageIdSnowflake = new Snowflake(message.Id);
|
||||
|
||||
if (!string.IsNullOrEmpty(message.Text)) {
|
||||
obj["m"] = message.Text;
|
||||
}
|
||||
channelData[messageIdSnowflake] = new ViewerJson.JsonMessage {
|
||||
U = userIndices[message.Sender],
|
||||
T = message.Timestamp,
|
||||
M = string.IsNullOrEmpty(message.Text) ? null : message.Text,
|
||||
Te = message.EditTimestamp,
|
||||
R = message.RepliedToId?.ToString(),
|
||||
|
||||
if (message.EditTimestamp != null) {
|
||||
obj["te"] = message.EditTimestamp;
|
||||
}
|
||||
|
||||
if (message.RepliedToId != null) {
|
||||
obj["r"] = message.RepliedToId.Value;
|
||||
}
|
||||
|
||||
if (!message.Attachments.IsEmpty) {
|
||||
obj["a"] = message.Attachments.Select(attachment => {
|
||||
var a = new Dictionary<string, object> {
|
||||
{ "url", strategy.GetAttachmentUrl(attachment) },
|
||||
{ "name", Uri.TryCreate(attachment.NormalizedUrl, UriKind.Absolute, out var uri) ? Path.GetFileName(uri.LocalPath) : attachment.NormalizedUrl },
|
||||
A = message.Attachments.IsEmpty ? null : message.Attachments.Select(attachment => {
|
||||
var a = new ViewerJson.JsonMessageAttachment {
|
||||
Url = strategy.GetAttachmentUrl(attachment),
|
||||
Name = Uri.TryCreate(attachment.NormalizedUrl, UriKind.Absolute, out var uri) ? Path.GetFileName(uri.LocalPath) : attachment.NormalizedUrl
|
||||
};
|
||||
|
||||
if (attachment is { Width: not null, Height: not null }) {
|
||||
a["width"] = attachment.Width;
|
||||
a["height"] = attachment.Height;
|
||||
a.Width = attachment.Width;
|
||||
a.Height = attachment.Height;
|
||||
}
|
||||
|
||||
return a;
|
||||
}).ToArray();
|
||||
}).ToArray(),
|
||||
|
||||
E = message.Embeds.IsEmpty ? null : message.Embeds.Select(static embed => embed.Json).ToArray(),
|
||||
|
||||
Re = message.Reactions.IsEmpty ? null : message.Reactions.Select(static reaction => new ViewerJson.JsonMessageReaction {
|
||||
Id = reaction.EmojiId?.ToString(),
|
||||
N = reaction.EmojiName,
|
||||
A = reaction.EmojiFlags.HasFlag(EmojiFlags.Animated),
|
||||
C = reaction.Count
|
||||
}).ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
if (!message.Embeds.IsEmpty) {
|
||||
obj["e"] = message.Embeds.Select(static embed => embed.Json).ToArray();
|
||||
}
|
||||
|
||||
if (!message.Reactions.IsEmpty) {
|
||||
obj["re"] = message.Reactions.Select(static reaction => {
|
||||
var r = new Dictionary<string, object>();
|
||||
|
||||
if (reaction.EmojiId != null) {
|
||||
r["id"] = reaction.EmojiId.Value;
|
||||
}
|
||||
|
||||
if (reaction.EmojiName != null) {
|
||||
r["n"] = reaction.EmojiName;
|
||||
}
|
||||
|
||||
r["a"] = reaction.EmojiFlags.HasFlag(EmojiFlags.Animated);
|
||||
r["c"] = reaction.Count;
|
||||
return r;
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
channelData[message.Id.ToString()] = obj;
|
||||
}
|
||||
|
||||
data[channel] = channelData;
|
||||
data[channelIdSnowflake] = channelData;
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace DHT.Server.Database.Export;
|
||||
|
||||
sealed class ViewerJsonSnowflakeSerializer : JsonConverter<ulong> {
|
||||
public override ulong Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
return ulong.Parse(reader.GetString()!);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, ulong value, JsonSerializerOptions options) {
|
||||
writer.WriteStringValue(value.ToString());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user