Split output file into multiple partitions (#116)

This commit is contained in:
Alexey Golub 2018-11-03 22:53:20 +02:00 committed by GitHub
parent aa53cecd4e
commit a0359b1e43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 133 additions and 19 deletions

View file

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace DiscordChatExporter.Core.Models
{
@ -31,5 +33,45 @@ namespace DiscordChatExporter.Core.Models
throw new ArgumentOutOfRangeException(nameof(format));
}
public static IReadOnlyList<ChatLog> SplitIntoPartitions(this ChatLog chatLog, int partitionLimit)
{
// If chat log has fewer messages than the limit - just return chat log in a list
if (chatLog.Messages.Count <= partitionLimit)
return new[] {chatLog};
var result = new List<ChatLog>();
// Loop through messages
var buffer = new List<Message>();
foreach (var message in chatLog.Messages)
{
// Add message to buffer
buffer.Add(message);
// If reached the limit - split and reset buffer
if (buffer.Count >= partitionLimit)
{
// Add to result
var chatLogPartition = new ChatLog(chatLog.Guild, chatLog.Channel, chatLog.From, chatLog.To, buffer,
chatLog.Mentionables);
result.Add(chatLogPartition);
// Reset the buffer instead of clearing to avoid mutations on existing references
buffer = new List<Message>();
}
}
// Add what's remaining in buffer
if (buffer.Any())
{
// Add to result
var chatLogPartition = new ChatLog(chatLog.Guild, chatLog.Channel, chatLog.From, chatLog.To, buffer,
chatLog.Mentionables);
result.Add(chatLogPartition);
}
return result;
}
}
}

View file

@ -32,10 +32,10 @@ namespace DiscordChatExporter.Core.Services
private IEnumerable<MessageGroup> GroupMessages(IEnumerable<Message> messages)
{
// Group adjacent messages by timestamp and author
var groupBuffer = new List<Message>();
var buffer = new List<Message>();
foreach (var message in messages)
{
var groupFirst = groupBuffer.FirstOrDefault();
var groupFirst = buffer.FirstOrDefault();
// Group break condition
var breakCondition =
@ -44,27 +44,29 @@ namespace DiscordChatExporter.Core.Services
message.Author.Id != groupFirst.Author.Id ||
(message.Timestamp - groupFirst.Timestamp).TotalHours > 1 ||
message.Timestamp.Hour != groupFirst.Timestamp.Hour ||
groupBuffer.Count >= _messageGroupLimit
buffer.Count >= _messageGroupLimit
);
// If condition is true - flush buffer
if (breakCondition)
{
var group = new MessageGroup(groupFirst.Author, groupFirst.Timestamp, groupBuffer.ToArray());
groupBuffer.Clear();
var group = new MessageGroup(groupFirst.Author, groupFirst.Timestamp, buffer);
// Reset the buffer instead of clearing to avoid mutations on existing references
buffer = new List<Message>();
yield return group;
}
// Add message to buffer
groupBuffer.Add(message);
buffer.Add(message);
}
// Add what's remaining in buffer
if (groupBuffer.Any())
if (buffer.Any())
{
var groupFirst = groupBuffer.First();
var group = new MessageGroup(groupFirst.Author, groupFirst.Timestamp, groupBuffer.ToArray());
var groupFirst = buffer.First();
var group = new MessageGroup(groupFirst.Author, groupFirst.Timestamp, buffer);
yield return group;
}

View file

@ -1,4 +1,5 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using DiscordChatExporter.Core.Models;
using Scriban;
using Scriban.Runtime;
@ -15,7 +16,7 @@ namespace DiscordChatExporter.Core.Services
_settingsService = settingsService;
}
public void ExportChatLog(ChatLog chatLog, string filePath, ExportFormat format)
private void ExportChatLogSingle(ChatLog chatLog, string filePath, ExportFormat format)
{
// Create template loader
var loader = new TemplateLoader();
@ -55,5 +56,47 @@ namespace DiscordChatExporter.Core.Services
template.Render(context);
}
}
private void ExportChatLogPartitions(IReadOnlyList<ChatLog> partitions, string filePath, ExportFormat format)
{
// Split file path into components
var dirPath = Path.GetDirectoryName(filePath);
var fileNameWithoutExt = Path.GetFileNameWithoutExtension(filePath);
var fileExt = Path.GetExtension(filePath);
// Export each partition separately
var partitionNumber = 1;
foreach (var partition in partitions)
{
// Compose new file name
var partitionFilePath = $"{fileNameWithoutExt}-{partitionNumber}{fileExt}";
// Compose full file path
if (dirPath.IsNotBlank())
partitionFilePath = Path.Combine(dirPath, partitionFilePath);
// Export
ExportChatLogSingle(partition, partitionFilePath, format);
// Increment partition number
partitionNumber++;
}
}
public void ExportChatLog(ChatLog chatLog, string filePath, ExportFormat format,
int? partitionLimit = null)
{
// If partitioning is disabled or there are fewer messages in chat log than the limit - process it without partitioning
if (partitionLimit == null || chatLog.Messages.Count <= partitionLimit)
{
ExportChatLogSingle(chatLog, filePath, format);
}
// Otherwise split into partitions and export separately
else
{
var partitions = chatLog.SplitIntoPartitions(partitionLimit.Value);
ExportChatLogPartitions(partitions, filePath, format);
}
}
}
}

View file

@ -4,6 +4,7 @@ namespace DiscordChatExporter.Core.Services
{
public interface IExportService
{
void ExportChatLog(ChatLog chatLog, string filePath, ExportFormat format);
void ExportChatLog(ChatLog chatLog, string filePath, ExportFormat format,
int? partitionLimit = null);
}
}

View file

@ -11,6 +11,7 @@ namespace DiscordChatExporter.Core.Services
AuthToken LastToken { get; set; }
ExportFormat LastExportFormat { get; set; }
int? LastPartitionLimit { get; set; }
void Load();
void Save();

View file

@ -12,6 +12,7 @@ namespace DiscordChatExporter.Core.Services
public AuthToken LastToken { get; set; }
public ExportFormat LastExportFormat { get; set; } = ExportFormat.HtmlDark;
public int? LastPartitionLimit { get; set; }
public SettingsService()
{