You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DiscordChatExporter/DiscordChatExporter.Core/Exporting/Writers/CsvMessageWriter.cs

105 lines
3.3 KiB

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using DiscordChatExporter.Core.Discord.Data;
using DiscordChatExporter.Core.Exporting.Writers.MarkdownVisitors;
using DiscordChatExporter.Core.Utils.Extensions;
namespace DiscordChatExporter.Core.Exporting.Writers
{
internal partial class CsvMessageWriter : MessageWriter
{
private readonly TextWriter _writer;
public CsvMessageWriter(Stream stream, ExportContext context)
: base(stream, context)
{
_writer = new StreamWriter(stream);
}
private string FormatMarkdown(string? markdown) =>
PlainTextMarkdownVisitor.Format(Context, markdown ?? "");
public override async ValueTask WritePreambleAsync() =>
await _writer.WriteLineAsync("AuthorID,Author,Date,Content,Attachments,Reactions");
private async ValueTask WriteAttachmentsAsync(IReadOnlyList<Attachment> attachments)
{
var buffer = new StringBuilder();
foreach (var attachment in attachments)
{
buffer
.AppendIfNotEmpty(',')
.Append(await Context.ResolveMediaUrlAsync(attachment.Url));
}
await _writer.WriteAsync(CsvEncode(buffer.ToString()));
}
private async ValueTask WriteReactionsAsync(IReadOnlyList<Reaction> reactions)
{
var buffer = new StringBuilder();
foreach (var reaction in reactions)
{
buffer
.AppendIfNotEmpty(',')
.Append(reaction.Emoji.Name)
.Append(' ')
.Append('(')
.Append(reaction.Count)
.Append(')');
}
await _writer.WriteAsync(CsvEncode(buffer.ToString()));
}
public override async ValueTask WriteMessageAsync(Message message)
{
await base.WriteMessageAsync(message);
// Author ID
await _writer.WriteAsync(CsvEncode(message.Author.Id.ToString()));
await _writer.WriteAsync(',');
// Author name
await _writer.WriteAsync(CsvEncode(message.Author.FullName));
await _writer.WriteAsync(',');
// Message timestamp
await _writer.WriteAsync(CsvEncode(Context.FormatDate(message.Timestamp)));
await _writer.WriteAsync(',');
// Message content
await _writer.WriteAsync(CsvEncode(FormatMarkdown(message.Content)));
await _writer.WriteAsync(',');
// Attachments
await WriteAttachmentsAsync(message.Attachments);
await _writer.WriteAsync(',');
// Reactions
await WriteReactionsAsync(message.Reactions);
// Finish row
await _writer.WriteLineAsync();
}
public override async ValueTask DisposeAsync()
{
await _writer.DisposeAsync();
await base.DisposeAsync();
}
}
internal partial class CsvMessageWriter
{
private static string CsvEncode(string value)
{
value = value.Replace("\"", "\"\"");
return $"\"{value}\"";
}
}
}