mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2025-06-07 09:54:50 -04:00
Add csv exporting (#44)
This commit is contained in:
parent
e0284e281c
commit
e1e8c73613
5 changed files with 97 additions and 1 deletions
|
@ -15,6 +15,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CsvHelper" Version="7.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="Onova" Version="2.1.0" />
|
<PackageReference Include="Onova" Version="2.1.0" />
|
||||||
<PackageReference Include="Tyrrrz.Extensions" Version="1.5.0" />
|
<PackageReference Include="Tyrrrz.Extensions" Version="1.5.0" />
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
{
|
{
|
||||||
PlainText,
|
PlainText,
|
||||||
HtmlDark,
|
HtmlDark,
|
||||||
HtmlLight
|
HtmlLight,
|
||||||
|
Csv
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,8 @@ namespace DiscordChatExporter.Core.Models
|
||||||
return "html";
|
return "html";
|
||||||
if (format == ExportFormat.HtmlLight)
|
if (format == ExportFormat.HtmlLight)
|
||||||
return "html";
|
return "html";
|
||||||
|
if (format == ExportFormat.Csv)
|
||||||
|
return "csv";
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(format));
|
throw new ArgumentOutOfRangeException(nameof(format));
|
||||||
}
|
}
|
||||||
|
@ -24,6 +26,8 @@ namespace DiscordChatExporter.Core.Models
|
||||||
return "HTML (Dark)";
|
return "HTML (Dark)";
|
||||||
if (format == ExportFormat.HtmlLight)
|
if (format == ExportFormat.HtmlLight)
|
||||||
return "HTML (Light)";
|
return "HTML (Light)";
|
||||||
|
if (format == ExportFormat.Csv)
|
||||||
|
return "Comma Seperated Values (CSV)";
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(format));
|
throw new ArgumentOutOfRangeException(nameof(format));
|
||||||
}
|
}
|
||||||
|
|
85
DiscordChatExporter.Core/Services/ExportService.Csv.cs
Normal file
85
DiscordChatExporter.Core/Services/ExportService.Csv.cs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CsvHelper;
|
||||||
|
using DiscordChatExporter.Core.Models;
|
||||||
|
using Tyrrrz.Extensions;
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Services
|
||||||
|
{
|
||||||
|
public partial class ExportService
|
||||||
|
{
|
||||||
|
private string FormatMessageContentCsv(Message message)
|
||||||
|
{
|
||||||
|
var content = message.Content;
|
||||||
|
|
||||||
|
// New lines
|
||||||
|
content = content.Replace("\n", ", ");
|
||||||
|
|
||||||
|
// User mentions (<@id> and <@!id>)
|
||||||
|
foreach (var mentionedUser in message.MentionedUsers)
|
||||||
|
content = Regex.Replace(content, $"<@!?{mentionedUser.Id}>", $"@{mentionedUser}");
|
||||||
|
|
||||||
|
// Role mentions (<@&id>)
|
||||||
|
foreach (var mentionedRole in message.MentionedRoles)
|
||||||
|
content = content.Replace($"<@&{mentionedRole.Id}>", $"@{mentionedRole.Name}");
|
||||||
|
|
||||||
|
// Channel mentions (<#id>)
|
||||||
|
foreach (var mentionedChannel in message.MentionedChannels)
|
||||||
|
content = content.Replace($"<#{mentionedChannel.Id}>", $"#{mentionedChannel.Name}");
|
||||||
|
|
||||||
|
// Custom emojis (<:name:id>)
|
||||||
|
content = Regex.Replace(content, "<(:.*?:)\\d*>", "$1");
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExportAsCsvAsync(ChannelChatLog log, TextWriter output)
|
||||||
|
{
|
||||||
|
using (var writer = new CsvWriter(output))
|
||||||
|
{
|
||||||
|
// Generation info
|
||||||
|
writer.WriteComment("https://github.com/Tyrrrz/DiscordChatExporter");
|
||||||
|
|
||||||
|
// Guild and channel info
|
||||||
|
writer.WriteComment($"Guild: {log.Guild.Name}");
|
||||||
|
writer.WriteComment($"Channel: {log.Channel.Name}");
|
||||||
|
writer.WriteComment($"Topic: {log.Channel.Topic}");
|
||||||
|
writer.WriteComment($"Messages: {log.TotalMessageCount:N0}");
|
||||||
|
|
||||||
|
// Headers
|
||||||
|
writer.WriteField("Author");
|
||||||
|
writer.WriteField("Date");
|
||||||
|
writer.WriteField("Content");
|
||||||
|
writer.WriteField("Attachments");
|
||||||
|
await writer.NextRecordAsync();
|
||||||
|
|
||||||
|
// Chat log
|
||||||
|
foreach (var group in log.MessageGroups)
|
||||||
|
{
|
||||||
|
// Messages
|
||||||
|
foreach (var msg in group.Messages)
|
||||||
|
{
|
||||||
|
// Author
|
||||||
|
writer.WriteField(msg.Author.FullName, true);
|
||||||
|
|
||||||
|
// Date
|
||||||
|
var timeStampFormatted = msg.TimeStamp.ToString(_settingsService.DateFormat);
|
||||||
|
writer.WriteField(timeStampFormatted);
|
||||||
|
|
||||||
|
// Content
|
||||||
|
var contentFormatted = msg.Content.IsNotBlank() ? FormatMessageContentCsv(msg) : null;
|
||||||
|
writer.WriteField(contentFormatted, true);
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
var attachmentsFormatted = msg.Attachments.Select(a => a.Url).JoinToString(",");
|
||||||
|
writer.WriteField(attachmentsFormatted, true);
|
||||||
|
|
||||||
|
await writer.NextRecordAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,11 @@ namespace DiscordChatExporter.Core.Services
|
||||||
await ExportAsHtmlAsync(log, output, css);
|
await ExportAsHtmlAsync(log, output, css);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (format == ExportFormat.Csv)
|
||||||
|
{
|
||||||
|
await ExportAsCsvAsync(log, output);
|
||||||
|
}
|
||||||
|
|
||||||
else throw new ArgumentOutOfRangeException(nameof(format));
|
else throw new ArgumentOutOfRangeException(nameof(format));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue