2021-09-07 18:18:35 -04:00
|
|
|
|
using System;
|
2021-09-14 17:33:53 -04:00
|
|
|
|
using System.Collections.Generic;
|
2021-09-07 18:18:35 -04:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
2023-02-11 16:12:15 -05:00
|
|
|
|
using System.Reflection;
|
2021-09-07 18:18:35 -04:00
|
|
|
|
using System.Text.Json;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using AngleSharp.Dom;
|
|
|
|
|
using AngleSharp.Html.Dom;
|
2023-02-13 10:07:02 -05:00
|
|
|
|
using AsyncKeyedLock;
|
2021-09-07 18:18:35 -04:00
|
|
|
|
using CliFx.Infrastructure;
|
|
|
|
|
using DiscordChatExporter.Cli.Commands;
|
|
|
|
|
using DiscordChatExporter.Cli.Tests.Utils;
|
|
|
|
|
using DiscordChatExporter.Core.Discord;
|
|
|
|
|
using DiscordChatExporter.Core.Exporting;
|
|
|
|
|
using JsonExtensions;
|
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
namespace DiscordChatExporter.Cli.Tests.Infra;
|
2021-12-08 16:50:21 -05:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
public static class ExportWrapper
|
2021-09-07 18:18:35 -04:00
|
|
|
|
{
|
2024-08-26 10:23:29 -04:00
|
|
|
|
private static readonly AsyncKeyedLocker<string> Locker = new();
|
2023-02-12 11:47:43 -05:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
private static readonly string DirPath = Path.Combine(
|
2023-08-22 14:17:19 -04:00
|
|
|
|
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
|
|
|
|
|
?? Directory.GetCurrentDirectory(),
|
2023-02-11 16:12:15 -05:00
|
|
|
|
"ExportCache"
|
2021-12-08 16:50:21 -05:00
|
|
|
|
);
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
static ExportWrapper()
|
|
|
|
|
{
|
2023-02-12 06:13:53 -05:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Directory.Delete(DirPath, true);
|
|
|
|
|
}
|
2023-08-22 14:17:19 -04:00
|
|
|
|
catch (DirectoryNotFoundException) { }
|
2023-02-12 06:13:53 -05:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
Directory.CreateDirectory(DirPath);
|
|
|
|
|
}
|
2021-09-14 17:33:53 -04:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
private static async ValueTask<string> ExportAsync(Snowflake channelId, ExportFormat format)
|
2021-12-08 16:50:21 -05:00
|
|
|
|
{
|
2023-02-13 09:42:03 -05:00
|
|
|
|
var fileName = channelId.ToString() + '.' + format.GetFileExtension();
|
|
|
|
|
var filePath = Path.Combine(DirPath, fileName);
|
|
|
|
|
|
2023-07-03 11:35:28 -04:00
|
|
|
|
using var _ = await Locker.LockAsync(filePath);
|
|
|
|
|
using var console = new FakeConsole();
|
|
|
|
|
|
|
|
|
|
// Perform the export only if it hasn't been done before
|
|
|
|
|
if (!File.Exists(filePath))
|
2021-12-08 16:50:21 -05:00
|
|
|
|
{
|
2023-07-03 11:35:28 -04:00
|
|
|
|
await new ExportChannelsCommand
|
2021-09-07 18:18:35 -04:00
|
|
|
|
{
|
2023-07-03 11:35:28 -04:00
|
|
|
|
Token = Secrets.DiscordToken,
|
2024-01-11 15:21:53 -05:00
|
|
|
|
ChannelIds = [channelId],
|
2023-07-03 11:35:28 -04:00
|
|
|
|
ExportFormat = format,
|
2023-09-07 07:34:08 -04:00
|
|
|
|
OutputPath = filePath,
|
|
|
|
|
Locale = "en-US",
|
|
|
|
|
IsUtcNormalizationEnabled = true
|
2023-07-03 11:35:28 -04:00
|
|
|
|
}.ExecuteAsync(console);
|
2023-02-12 11:47:43 -05:00
|
|
|
|
}
|
2023-07-03 11:35:28 -04:00
|
|
|
|
|
|
|
|
|
return await File.ReadAllTextAsync(filePath);
|
2021-12-08 16:50:21 -05:00
|
|
|
|
}
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2023-08-22 14:17:19 -04:00
|
|
|
|
public static async ValueTask<IHtmlDocument> ExportAsHtmlAsync(Snowflake channelId) =>
|
|
|
|
|
Html.Parse(await ExportAsync(channelId, ExportFormat.HtmlDark));
|
2021-09-08 10:36:25 -04:00
|
|
|
|
|
2023-08-22 14:17:19 -04:00
|
|
|
|
public static async ValueTask<JsonElement> ExportAsJsonAsync(Snowflake channelId) =>
|
|
|
|
|
Json.Parse(await ExportAsync(channelId, ExportFormat.Json));
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
public static async ValueTask<string> ExportAsPlainTextAsync(Snowflake channelId) =>
|
2022-06-30 12:07:11 -04:00
|
|
|
|
await ExportAsync(channelId, ExportFormat.PlainText);
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2023-02-11 16:12:15 -05:00
|
|
|
|
public static async ValueTask<string> ExportAsCsvAsync(Snowflake channelId) =>
|
2022-06-30 12:07:11 -04:00
|
|
|
|
await ExportAsync(channelId, ExportFormat.Csv);
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2023-08-22 14:17:19 -04:00
|
|
|
|
public static async ValueTask<IReadOnlyList<IElement>> GetMessagesAsHtmlAsync(
|
|
|
|
|
Snowflake channelId
|
|
|
|
|
) => (await ExportAsHtmlAsync(channelId)).QuerySelectorAll("[data-message-id]").ToArray();
|
2021-12-08 16:50:21 -05:00
|
|
|
|
|
2023-08-22 14:17:19 -04:00
|
|
|
|
public static async ValueTask<IReadOnlyList<JsonElement>> GetMessagesAsJsonAsync(
|
|
|
|
|
Snowflake channelId
|
|
|
|
|
) => (await ExportAsJsonAsync(channelId)).GetProperty("messages").EnumerateArray().ToArray();
|
2021-12-08 16:50:21 -05:00
|
|
|
|
|
2023-08-22 14:17:19 -04:00
|
|
|
|
public static async ValueTask<IElement> GetMessageAsHtmlAsync(
|
|
|
|
|
Snowflake channelId,
|
|
|
|
|
Snowflake messageId
|
|
|
|
|
)
|
2021-12-08 16:50:21 -05:00
|
|
|
|
{
|
2024-04-26 21:17:46 -04:00
|
|
|
|
var message = (await GetMessagesAsHtmlAsync(channelId)).SingleOrDefault(e =>
|
|
|
|
|
string.Equals(
|
|
|
|
|
e.GetAttribute("data-message-id"),
|
|
|
|
|
messageId.ToString(),
|
|
|
|
|
StringComparison.OrdinalIgnoreCase
|
|
|
|
|
)
|
2023-05-20 00:09:19 -04:00
|
|
|
|
);
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2021-12-08 16:50:21 -05:00
|
|
|
|
if (message is null)
|
2021-09-08 10:36:25 -04:00
|
|
|
|
{
|
2021-12-08 16:50:21 -05:00
|
|
|
|
throw new InvalidOperationException(
|
2023-11-17 11:37:52 -05:00
|
|
|
|
$"Message #{messageId} not found in the export of channel #{channelId}."
|
2021-09-14 17:33:53 -04:00
|
|
|
|
);
|
2021-12-08 16:50:21 -05:00
|
|
|
|
}
|
2021-09-08 10:36:25 -04:00
|
|
|
|
|
2021-12-08 16:50:21 -05:00
|
|
|
|
return message;
|
|
|
|
|
}
|
2021-09-08 10:36:25 -04:00
|
|
|
|
|
2023-08-22 14:17:19 -04:00
|
|
|
|
public static async ValueTask<JsonElement> GetMessageAsJsonAsync(
|
|
|
|
|
Snowflake channelId,
|
|
|
|
|
Snowflake messageId
|
|
|
|
|
)
|
2021-12-08 16:50:21 -05:00
|
|
|
|
{
|
2024-04-26 21:17:46 -04:00
|
|
|
|
var message = (await GetMessagesAsJsonAsync(channelId)).SingleOrDefault(j =>
|
|
|
|
|
string.Equals(
|
|
|
|
|
j.GetProperty("id").GetString(),
|
|
|
|
|
messageId.ToString(),
|
|
|
|
|
StringComparison.OrdinalIgnoreCase
|
|
|
|
|
)
|
2023-05-20 00:09:19 -04:00
|
|
|
|
);
|
2021-09-07 18:18:35 -04:00
|
|
|
|
|
2021-12-08 16:50:21 -05:00
|
|
|
|
if (message.ValueKind == JsonValueKind.Undefined)
|
2021-09-07 18:18:35 -04:00
|
|
|
|
{
|
2021-12-08 16:50:21 -05:00
|
|
|
|
throw new InvalidOperationException(
|
2023-11-17 11:37:52 -05:00
|
|
|
|
$"Message #{messageId} not found in the export of channel #{channelId}."
|
2021-09-14 17:33:53 -04:00
|
|
|
|
);
|
2021-09-07 18:18:35 -04:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-08 16:50:21 -05:00
|
|
|
|
return message;
|
2021-09-07 18:18:35 -04:00
|
|
|
|
}
|
2023-08-22 14:17:19 -04:00
|
|
|
|
}
|