diff --git a/DiscordChatExporter/Container.cs b/DiscordChatExporter/Container.cs index 7cf8ae5..ddb24da 100644 --- a/DiscordChatExporter/Container.cs +++ b/DiscordChatExporter/Container.cs @@ -14,6 +14,7 @@ namespace DiscordChatExporter // Services SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); + SimpleIoc.Default.Register(); SimpleIoc.Default.Register(); // View models diff --git a/DiscordChatExporter/DiscordChatExporter.csproj b/DiscordChatExporter/DiscordChatExporter.csproj index 52be983..deaa1da 100644 --- a/DiscordChatExporter/DiscordChatExporter.csproj +++ b/DiscordChatExporter/DiscordChatExporter.csproj @@ -91,6 +91,8 @@ + + diff --git a/DiscordChatExporter/Models/ChannelChatLog.cs b/DiscordChatExporter/Models/ChannelChatLog.cs index 620b249..19c3cb7 100644 --- a/DiscordChatExporter/Models/ChannelChatLog.cs +++ b/DiscordChatExporter/Models/ChannelChatLog.cs @@ -9,13 +9,13 @@ namespace DiscordChatExporter.Models public Channel Channel { get; } - public IReadOnlyList Messages { get; } + public IReadOnlyList MessageGroups { get; } - public ChannelChatLog(Guild guild, Channel channel, IEnumerable messages) + public ChannelChatLog(Guild guild, Channel channel, IEnumerable messageGroups) { Guild = guild; Channel = channel; - Messages = messages.ToArray(); + MessageGroups = messageGroups.ToArray(); } } } \ No newline at end of file diff --git a/DiscordChatExporter/Services/ExportService.cs b/DiscordChatExporter/Services/ExportService.cs index e9c2b81..ea2227b 100644 --- a/DiscordChatExporter/Services/ExportService.cs +++ b/DiscordChatExporter/Services/ExportService.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; +using System.IO; using System.Reflection; using System.Resources; using System.Text.RegularExpressions; @@ -19,7 +17,7 @@ namespace DiscordChatExporter.Services _settingsService = settingsService; } - public void Export(string filePath, ChannelChatLog channelChatLog, Theme theme) + public void Export(string filePath, ChannelChatLog log, Theme theme) { var doc = GetTemplate(); var style = GetStyle(theme); @@ -31,25 +29,24 @@ namespace DiscordChatExporter.Services // Title var titleHtml = doc.DocumentNode.Element("html").Element("head").Element("title"); - titleHtml.InnerHtml = $"{channelChatLog.Guild.Name} - {channelChatLog.Channel.Name}"; + titleHtml.InnerHtml = $"{log.Guild.Name} - {log.Channel.Name}"; // Info var infoHtml = doc.GetElementbyId("info"); var infoLeftHtml = infoHtml.AppendChild(HtmlNode.CreateNode("
")); infoLeftHtml.AppendChild(HtmlNode.CreateNode( - $"")); + $"")); var infoRightHtml = infoHtml.AppendChild(HtmlNode.CreateNode("
")); infoRightHtml.AppendChild(HtmlNode.CreateNode( - $"
{channelChatLog.Guild.Name}
")); + $"
{log.Guild.Name}
")); infoRightHtml.AppendChild(HtmlNode.CreateNode( - $"
{channelChatLog.Channel.Name}
")); + $"
{log.Channel.Name}
")); infoRightHtml.AppendChild(HtmlNode.CreateNode( - $"
{channelChatLog.Messages.Count:N0} messages
")); + $"
{log.MessageGroups.Count:N0} messages
")); // Log var logHtml = doc.GetElementbyId("log"); - var messageGroups = GroupMessages(channelChatLog.Messages); - foreach (var messageGroup in messageGroups) + foreach (var messageGroup in log.MessageGroups) { // Container var messageHtml = logHtml.AppendChild(HtmlNode.CreateNode("
")); @@ -171,48 +168,6 @@ namespace DiscordChatExporter.Services return $"{size:0.#} {units[unit]}"; } - private static IEnumerable GroupMessages(IEnumerable messages) - { - var result = new List(); - - // Group adjacent messages by timestamp and author - var groupBuffer = new List(); - foreach (var message in messages) - { - var groupFirst = groupBuffer.FirstOrDefault(); - - // Group break condition - var breakCondition = - groupFirst != null && - ( - message.Author.Id != groupFirst.Author.Id || - (message.TimeStamp - groupFirst.TimeStamp).TotalHours > 1 || - message.TimeStamp.Hour != groupFirst.TimeStamp.Hour - ); - - // If condition is true - flush buffer - if (breakCondition) - { - var group = new MessageGroup(groupFirst.Author, groupFirst.TimeStamp, groupBuffer); - result.Add(group); - groupBuffer.Clear(); - } - - // Add message to buffer - groupBuffer.Add(message); - } - - // Add what's remaining in buffer - if (groupBuffer.Any()) - { - var groupFirst = groupBuffer.First(); - var group = new MessageGroup(groupFirst.Author, groupFirst.TimeStamp, groupBuffer); - result.Add(group); - } - - return result; - } - private static string FormatMessageContent(string content) { // Encode HTML diff --git a/DiscordChatExporter/Services/IExportService.cs b/DiscordChatExporter/Services/IExportService.cs index af7eef5..a0cc54b 100644 --- a/DiscordChatExporter/Services/IExportService.cs +++ b/DiscordChatExporter/Services/IExportService.cs @@ -4,6 +4,6 @@ namespace DiscordChatExporter.Services { public interface IExportService { - void Export(string filePath, ChannelChatLog channelChatLog, Theme theme); + void Export(string filePath, ChannelChatLog log, Theme theme); } } \ No newline at end of file diff --git a/DiscordChatExporter/Services/IMessageGroupService.cs b/DiscordChatExporter/Services/IMessageGroupService.cs new file mode 100644 index 0000000..256faeb --- /dev/null +++ b/DiscordChatExporter/Services/IMessageGroupService.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using DiscordChatExporter.Models; + +namespace DiscordChatExporter.Services +{ + public interface IMessageGroupService + { + IEnumerable GroupMessages(IEnumerable messages); + } +} \ No newline at end of file diff --git a/DiscordChatExporter/Services/ISettingsService.cs b/DiscordChatExporter/Services/ISettingsService.cs index 5479fb1..2c6bc0b 100644 --- a/DiscordChatExporter/Services/ISettingsService.cs +++ b/DiscordChatExporter/Services/ISettingsService.cs @@ -7,6 +7,7 @@ namespace DiscordChatExporter.Services string Token { get; set; } Theme Theme { get; set; } string DateFormat { get; set; } + int MessageGroupLimit { get; set; } void Load(); void Save(); diff --git a/DiscordChatExporter/Services/MessageGroupService.cs b/DiscordChatExporter/Services/MessageGroupService.cs new file mode 100644 index 0000000..7dd05c3 --- /dev/null +++ b/DiscordChatExporter/Services/MessageGroupService.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; +using System.Linq; +using DiscordChatExporter.Models; + +namespace DiscordChatExporter.Services +{ + public class MessageGroupService : IMessageGroupService + { + private readonly ISettingsService _settingsService; + + public MessageGroupService(ISettingsService settingsService) + { + _settingsService = settingsService; + } + + public IEnumerable GroupMessages(IEnumerable messages) + { + var groupLimit = _settingsService.MessageGroupLimit; + var result = new List(); + + // Group adjacent messages by timestamp and author + var groupBuffer = new List(); + foreach (var message in messages) + { + var groupFirst = groupBuffer.FirstOrDefault(); + + // Group break condition + var breakCondition = + groupFirst != null && + ( + message.Author.Id != groupFirst.Author.Id || + (message.TimeStamp - groupFirst.TimeStamp).TotalHours > 1 || + message.TimeStamp.Hour != groupFirst.TimeStamp.Hour || + groupBuffer.Count >= groupLimit + ); + + // If condition is true - flush buffer + if (breakCondition) + { + var group = new MessageGroup(groupFirst.Author, groupFirst.TimeStamp, groupBuffer); + result.Add(group); + groupBuffer.Clear(); + } + + // Add message to buffer + groupBuffer.Add(message); + } + + // Add what's remaining in buffer + if (groupBuffer.Any()) + { + var groupFirst = groupBuffer.First(); + var group = new MessageGroup(groupFirst.Author, groupFirst.TimeStamp, groupBuffer); + result.Add(group); + } + + return result; + } + } +} \ No newline at end of file diff --git a/DiscordChatExporter/Services/SettingsService.cs b/DiscordChatExporter/Services/SettingsService.cs index bb5ba92..998606a 100644 --- a/DiscordChatExporter/Services/SettingsService.cs +++ b/DiscordChatExporter/Services/SettingsService.cs @@ -8,6 +8,7 @@ namespace DiscordChatExporter.Services public string Token { get; set; } public Theme Theme { get; set; } public string DateFormat { get; set; } = "dd-MMM-yy hh:mm"; + public int MessageGroupLimit { get; set; } = 20; public SettingsService() { diff --git a/DiscordChatExporter/ViewModels/ISettingsViewModel.cs b/DiscordChatExporter/ViewModels/ISettingsViewModel.cs index 1968287..49000d1 100644 --- a/DiscordChatExporter/ViewModels/ISettingsViewModel.cs +++ b/DiscordChatExporter/ViewModels/ISettingsViewModel.cs @@ -7,5 +7,7 @@ namespace DiscordChatExporter.ViewModels { IReadOnlyList AvailableThemes { get; } Theme Theme { get; set; } + string DateFormat { get; set; } + int MessageGroupLimit { get; set; } } } \ No newline at end of file diff --git a/DiscordChatExporter/ViewModels/MainViewModel.cs b/DiscordChatExporter/ViewModels/MainViewModel.cs index 4d903fd..178b909 100644 --- a/DiscordChatExporter/ViewModels/MainViewModel.cs +++ b/DiscordChatExporter/ViewModels/MainViewModel.cs @@ -17,6 +17,7 @@ namespace DiscordChatExporter.ViewModels { private readonly ISettingsService _settingsService; private readonly IDataService _dataService; + private readonly IMessageGroupService _messageGroupService; private readonly IExportService _exportService; private readonly Dictionary> _guildChannelsMap; @@ -85,10 +86,12 @@ namespace DiscordChatExporter.ViewModels public RelayCommand ShowSettingsCommand { get; } public RelayCommand ShowAboutCommand { get; } - public MainViewModel(ISettingsService settingsService, IDataService dataService, IExportService exportService) + public MainViewModel(ISettingsService settingsService, IDataService dataService, + IMessageGroupService messageGroupService, IExportService exportService) { _settingsService = settingsService; _dataService = dataService; + _messageGroupService = messageGroupService; _exportService = exportService; _guildChannelsMap = new Dictionary>(); @@ -166,8 +169,11 @@ namespace DiscordChatExporter.ViewModels // Get messages var messages = await _dataService.GetChannelMessagesAsync(_cachedToken, channel.Id); + // Group them + var messageGroups = _messageGroupService.GroupMessages(messages); + // Create log - var chatLog = new ChannelChatLog(SelectedGuild, channel, messages); + var chatLog = new ChannelChatLog(SelectedGuild, channel, messageGroups); // Export _exportService.Export(sfd.FileName, chatLog, _settingsService.Theme); diff --git a/DiscordChatExporter/ViewModels/SettingsViewModel.cs b/DiscordChatExporter/ViewModels/SettingsViewModel.cs index 4de5070..51add4d 100644 --- a/DiscordChatExporter/ViewModels/SettingsViewModel.cs +++ b/DiscordChatExporter/ViewModels/SettingsViewModel.cs @@ -4,6 +4,7 @@ using System.Linq; using DiscordChatExporter.Models; using DiscordChatExporter.Services; using GalaSoft.MvvmLight; +using Tyrrrz.Extensions; namespace DiscordChatExporter.ViewModels { @@ -25,6 +26,12 @@ namespace DiscordChatExporter.ViewModels set => _settingsService.DateFormat = value; } + public int MessageGroupLimit + { + get => _settingsService.MessageGroupLimit; + set => _settingsService.MessageGroupLimit = value.ClampMin(0); + } + public SettingsViewModel(ISettingsService settingsService) { _settingsService = settingsService; diff --git a/DiscordChatExporter/Views/SettingsDialog.ammy b/DiscordChatExporter/Views/SettingsDialog.ammy index 8d00b1a..52bf77c 100644 --- a/DiscordChatExporter/Views/SettingsDialog.ammy +++ b/DiscordChatExporter/Views/SettingsDialog.ammy @@ -23,6 +23,13 @@ UserControl "DiscordChatExporter.Views.SettingsDialog" { Text: bind DateFormat } + // Group limit + TextBox { + Margin: "16 8 16 8" + HintAssist.Hint: "Message group limit" + HintAssist.IsFloating: true + Text: bind MessageGroupLimit + } // Save Button {