Switch from DateTime to DateTimeOffset

This commit is contained in:
Alexey Golub 2019-04-11 01:20:52 +03:00
parent 4bfb2ec7fd
commit 6d9bc3625f
20 changed files with 122 additions and 79 deletions

View file

@ -12,9 +12,11 @@ namespace DiscordChatExporter.Cli.Verbs.Options
[Option('o', "output", Default = null, HelpText = "Output file or directory path.")] [Option('o', "output", Default = null, HelpText = "Output file or directory path.")]
public string OutputPath { get; set; } public string OutputPath { get; set; }
// HACK: CommandLineParser doesn't support DateTimeOffset
[Option("after", Default = null, HelpText = "Limit to messages sent after this date.")] [Option("after", Default = null, HelpText = "Limit to messages sent after this date.")]
public DateTime? After { get; set; } public DateTime? After { get; set; }
// HACK: CommandLineParser doesn't support DateTimeOffset
[Option("before", Default = null, HelpText = "Limit to messages sent before this date.")] [Option("before", Default = null, HelpText = "Limit to messages sent before this date.")]
public DateTime? Before { get; set; } public DateTime? Before { get; set; }

View file

@ -9,21 +9,21 @@ namespace DiscordChatExporter.Core.Models
public Channel Channel { get; } public Channel Channel { get; }
public DateTime? From { get; } public DateTimeOffset? After { get; }
public DateTime? To { get; } public DateTimeOffset? Before { get; }
public IReadOnlyList<Message> Messages { get; } public IReadOnlyList<Message> Messages { get; }
public Mentionables Mentionables { get; } public Mentionables Mentionables { get; }
public ChatLog(Guild guild, Channel channel, DateTime? from, DateTime? to, public ChatLog(Guild guild, Channel channel, DateTimeOffset? after, DateTimeOffset? before,
IReadOnlyList<Message> messages, Mentionables mentionables) IReadOnlyList<Message> messages, Mentionables mentionables)
{ {
Guild = guild; Guild = guild;
Channel = channel; Channel = channel;
From = from; After = after;
To = to; Before = before;
Messages = messages; Messages = messages;
Mentionables = mentionables; Mentionables = mentionables;
} }

View file

@ -12,7 +12,7 @@ namespace DiscordChatExporter.Core.Models
public string Url { get; } public string Url { get; }
public DateTime? Timestamp { get; } public DateTimeOffset? Timestamp { get; }
public Color Color { get; } public Color Color { get; }
@ -28,7 +28,7 @@ namespace DiscordChatExporter.Core.Models
public EmbedFooter Footer { get; } public EmbedFooter Footer { get; }
public Embed(string title, string url, DateTime? timestamp, Color color, EmbedAuthor author, string description, public Embed(string title, string url, DateTimeOffset? timestamp, Color color, EmbedAuthor author, string description,
IReadOnlyList<EmbedField> fields, EmbedImage thumbnail, EmbedImage image, EmbedFooter footer) IReadOnlyList<EmbedField> fields, EmbedImage thumbnail, EmbedImage image, EmbedFooter footer)
{ {
Title = title; Title = title;

View file

@ -15,9 +15,9 @@ namespace DiscordChatExporter.Core.Models
public User Author { get; } public User Author { get; }
public DateTime Timestamp { get; } public DateTimeOffset Timestamp { get; }
public DateTime? EditedTimestamp { get; } public DateTimeOffset? EditedTimestamp { get; }
public string Content { get; } public string Content { get; }
@ -29,8 +29,8 @@ namespace DiscordChatExporter.Core.Models
public IReadOnlyList<User> MentionedUsers { get; } public IReadOnlyList<User> MentionedUsers { get; }
public Message(string id, string channelId, MessageType type, User author, DateTime timestamp, public Message(string id, string channelId, MessageType type, User author, DateTimeOffset timestamp,
DateTime? editedTimestamp, string content, IReadOnlyList<Attachment> attachments, DateTimeOffset? editedTimestamp, string content, IReadOnlyList<Attachment> attachments,
IReadOnlyList<Embed> embeds, IReadOnlyList<Reaction> reactions, IReadOnlyList<User> mentionedUsers) IReadOnlyList<Embed> embeds, IReadOnlyList<Reaction> reactions, IReadOnlyList<User> mentionedUsers)
{ {
Id = id; Id = id;

View file

@ -22,7 +22,8 @@ namespace DiscordChatExporter.Core.Rendering
_dateFormat = dateFormat; _dateFormat = dateFormat;
} }
private string FormatDate(DateTime date) => date.ToString(_dateFormat, CultureInfo.InvariantCulture); private string FormatDate(DateTimeOffset date) =>
date.ToLocalTime().ToString(_dateFormat, CultureInfo.InvariantCulture);
private string FormatMarkdown(Node node) private string FormatMarkdown(Node node)
{ {

View file

@ -10,11 +10,11 @@ namespace DiscordChatExporter.Core.Rendering
{ {
public User Author { get; } public User Author { get; }
public DateTime Timestamp { get; } public DateTimeOffset Timestamp { get; }
public IReadOnlyList<Message> Messages { get; } public IReadOnlyList<Message> Messages { get; }
public MessageGroup(User author, DateTime timestamp, IReadOnlyList<Message> messages) public MessageGroup(User author, DateTimeOffset timestamp, IReadOnlyList<Message> messages)
{ {
Author = author; Author = author;
Timestamp = timestamp; Timestamp = timestamp;

View file

@ -29,7 +29,8 @@ namespace DiscordChatExporter.Core.Rendering
private string HtmlEncode(string s) => WebUtility.HtmlEncode(s); private string HtmlEncode(string s) => WebUtility.HtmlEncode(s);
private string FormatDate(DateTime date) => date.ToString(_dateFormat, CultureInfo.InvariantCulture); private string FormatDate(DateTimeOffset date) =>
date.ToLocalTime().ToString(_dateFormat, CultureInfo.InvariantCulture);
private IEnumerable<MessageGroup> GroupMessages(IEnumerable<Message> messages) => private IEnumerable<MessageGroup> GroupMessages(IEnumerable<Message> messages) =>
messages.GroupContiguous((buffer, message) => messages.GroupContiguous((buffer, message) =>
@ -182,7 +183,7 @@ namespace DiscordChatExporter.Core.Rendering
var model = new ScriptObject(); var model = new ScriptObject();
model.SetValue("Model", _chatLog, true); model.SetValue("Model", _chatLog, true);
model.Import(nameof(GroupMessages), new Func<IEnumerable<Message>, IEnumerable<MessageGroup>>(GroupMessages)); model.Import(nameof(GroupMessages), new Func<IEnumerable<Message>, IEnumerable<MessageGroup>>(GroupMessages));
model.Import(nameof(FormatDate), new Func<DateTime, string>(FormatDate)); model.Import(nameof(FormatDate), new Func<DateTimeOffset, string>(FormatDate));
model.Import(nameof(FormatMarkdown), new Func<string, string>(FormatMarkdown)); model.Import(nameof(FormatMarkdown), new Func<string, string>(FormatMarkdown));
context.PushGlobal(model); context.PushGlobal(model);

View file

@ -22,21 +22,22 @@ namespace DiscordChatExporter.Core.Rendering
_dateFormat = dateFormat; _dateFormat = dateFormat;
} }
private string FormatDate(DateTime date) => date.ToString(_dateFormat, CultureInfo.InvariantCulture); private string FormatDate(DateTimeOffset date) =>
date.ToLocalTime().ToString(_dateFormat, CultureInfo.InvariantCulture);
private string FormatDateRange(DateTime? from, DateTime? to) private string FormatDateRange(DateTimeOffset? after, DateTimeOffset? before)
{ {
// Both 'from' and 'to' // Both 'after' and 'before'
if (from.HasValue && to.HasValue) if (after != null && before != null)
return $"{FormatDate(from.Value)} to {FormatDate(to.Value)}"; return $"{FormatDate(after.Value)} to {FormatDate(before.Value)}";
// Just 'from' // Just 'after'
if (from.HasValue) if (after != null)
return $"after {FormatDate(from.Value)}"; return $"after {FormatDate(after.Value)}";
// Just 'to' // Just 'before'
if (to.HasValue) if (before != null)
return $"before {FormatDate(to.Value)}"; return $"before {FormatDate(before.Value)}";
// Neither // Neither
return null; return null;
@ -113,7 +114,7 @@ namespace DiscordChatExporter.Core.Rendering
await writer.WriteLineAsync($"Channel: {_chatLog.Channel.Name}"); await writer.WriteLineAsync($"Channel: {_chatLog.Channel.Name}");
await writer.WriteLineAsync($"Topic: {_chatLog.Channel.Topic}"); await writer.WriteLineAsync($"Topic: {_chatLog.Channel.Topic}");
await writer.WriteLineAsync($"Messages: {_chatLog.Messages.Count:N0}"); await writer.WriteLineAsync($"Messages: {_chatLog.Messages.Count:N0}");
await writer.WriteLineAsync($"Range: {FormatDateRange(_chatLog.From, _chatLog.To)}"); await writer.WriteLineAsync($"Range: {FormatDateRange(_chatLog.After, _chatLog.Before)}");
await writer.WriteLineAsync('='.Repeat(62)); await writer.WriteLineAsync('='.Repeat(62));
await writer.WriteLineAsync(); await writer.WriteLineAsync();

View file

@ -43,14 +43,14 @@
<div class="info__channel-message-count">{{ Model.Messages | array.size | object.format "N0" }} messages</div> <div class="info__channel-message-count">{{ Model.Messages | array.size | object.format "N0" }} messages</div>
{{~ if Model.From || Model.To ~}} {{~ if Model.After || Model.Before ~}}
<div class="info__channel-date-range"> <div class="info__channel-date-range">
{{~ if Model.From && Model.To ~}} {{~ if Model.After && Model.Before ~}}
Between {{ Model.From | FormatDate | html.escape }} and {{ Model.To | FormatDate | html.escape }} Between {{ Model.After | FormatDate | html.escape }} and {{ Model.Before | FormatDate | html.escape }}
{{~ else if Model.From ~}} {{~ else if Model.After ~}}
After {{ Model.From | FormatDate | html.escape }} After {{ Model.After | FormatDate | html.escape }}
{{~ else if Model.To ~}} {{~ else if Model.Before ~}}
Before {{ Model.To | FormatDate | html.escape }} Before {{ Model.Before | FormatDate | html.escape }}
{{~ end ~}} {{~ end ~}}
</div> </div>
{{~ end ~}} {{~ end ~}}

View file

@ -117,7 +117,7 @@ namespace DiscordChatExporter.Core.Services
var title = json["title"]?.Value<string>(); var title = json["title"]?.Value<string>();
var description = json["description"]?.Value<string>(); var description = json["description"]?.Value<string>();
var url = json["url"]?.Value<string>(); var url = json["url"]?.Value<string>();
var timestamp = json["timestamp"]?.Value<DateTime>(); var timestamp = json["timestamp"]?.Value<DateTimeOffset>();
// Get color // Get color
var color = json["color"] != null var color = json["color"] != null
@ -164,8 +164,8 @@ namespace DiscordChatExporter.Core.Services
// Get basic data // Get basic data
var id = json["id"].Value<string>(); var id = json["id"].Value<string>();
var channelId = json["channel_id"].Value<string>(); var channelId = json["channel_id"].Value<string>();
var timestamp = json["timestamp"].Value<DateTime>(); var timestamp = json["timestamp"].Value<DateTimeOffset>();
var editedTimestamp = json["edited_timestamp"]?.Value<DateTime?>(); var editedTimestamp = json["edited_timestamp"]?.Value<DateTimeOffset?>();
var content = json["content"].Value<string>(); var content = json["content"].Value<string>();
var type = (MessageType) json["type"].Value<int>(); var type = (MessageType) json["type"].Value<int>();

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
@ -8,6 +9,7 @@ using DiscordChatExporter.Core.Models;
using DiscordChatExporter.Core.Services.Exceptions; using DiscordChatExporter.Core.Services.Exceptions;
using DiscordChatExporter.Core.Services.Internal; using DiscordChatExporter.Core.Services.Internal;
using Failsafe; using Failsafe;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Tyrrrz.Extensions; using Tyrrrz.Extensions;
@ -64,7 +66,12 @@ namespace DiscordChatExporter.Core.Services
var raw = await response.Content.ReadAsStringAsync(); var raw = await response.Content.ReadAsStringAsync();
// Parse // Parse
return JToken.Parse(raw); using (var reader = new JsonTextReader(new StringReader(raw)))
{
reader.DateParseHandling = DateParseHandling.DateTimeOffset;
return JToken.Load(reader);
}
} }
} }
}); });
@ -123,24 +130,24 @@ namespace DiscordChatExporter.Core.Services
} }
public async Task<IReadOnlyList<Message>> GetChannelMessagesAsync(AuthToken token, string channelId, public async Task<IReadOnlyList<Message>> GetChannelMessagesAsync(AuthToken token, string channelId,
DateTime? from = null, DateTime? to = null, IProgress<double> progress = null) DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
{ {
var result = new List<Message>(); var result = new List<Message>();
// Get the last message // Get the last message
var response = await GetApiResponseAsync(token, "channels", $"{channelId}/messages", var response = await GetApiResponseAsync(token, "channels", $"{channelId}/messages",
"limit=1", $"before={to?.ToSnowflake()}"); "limit=1", $"before={before?.ToSnowflake()}");
var lastMessage = response.Select(ParseMessage).FirstOrDefault(); var lastMessage = response.Select(ParseMessage).FirstOrDefault();
// If the last message doesn't exist or it's outside of range - return // If the last message doesn't exist or it's outside of range - return
if (lastMessage == null || lastMessage.Timestamp < from) if (lastMessage == null || lastMessage.Timestamp < after)
{ {
progress?.Report(1); progress?.Report(1);
return result; return result;
} }
// Get other messages // Get other messages
var offsetId = from?.ToSnowflake() ?? "0"; var offsetId = after?.ToSnowflake() ?? "0";
while (true) while (true)
{ {
// Get message batch // Get message batch
@ -215,19 +222,19 @@ namespace DiscordChatExporter.Core.Services
} }
public async Task<ChatLog> GetChatLogAsync(AuthToken token, Guild guild, Channel channel, public async Task<ChatLog> GetChatLogAsync(AuthToken token, Guild guild, Channel channel,
DateTime? from = null, DateTime? to = null, IProgress<double> progress = null) DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
{ {
// Get messages // Get messages
var messages = await GetChannelMessagesAsync(token, channel.Id, from, to, progress); var messages = await GetChannelMessagesAsync(token, channel.Id, after, before, progress);
// Get mentionables // Get mentionables
var mentionables = await GetMentionablesAsync(token, guild.Id, messages); var mentionables = await GetMentionablesAsync(token, guild.Id, messages);
return new ChatLog(guild, channel, from, to, messages, mentionables); return new ChatLog(guild, channel, after, before, messages, mentionables);
} }
public async Task<ChatLog> GetChatLogAsync(AuthToken token, Channel channel, public async Task<ChatLog> GetChatLogAsync(AuthToken token, Channel channel,
DateTime? from = null, DateTime? to = null, IProgress<double> progress = null) DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
{ {
// Get guild // Get guild
var guild = channel.GuildId == Guild.DirectMessages.Id var guild = channel.GuildId == Guild.DirectMessages.Id
@ -235,17 +242,17 @@ namespace DiscordChatExporter.Core.Services
: await GetGuildAsync(token, channel.GuildId); : await GetGuildAsync(token, channel.GuildId);
// Get the chat log // Get the chat log
return await GetChatLogAsync(token, guild, channel, from, to, progress); return await GetChatLogAsync(token, guild, channel, after, before, progress);
} }
public async Task<ChatLog> GetChatLogAsync(AuthToken token, string channelId, public async Task<ChatLog> GetChatLogAsync(AuthToken token, string channelId,
DateTime? from = null, DateTime? to = null, IProgress<double> progress = null) DateTimeOffset? after = null, DateTimeOffset? before = null, IProgress<double> progress = null)
{ {
// Get channel // Get channel
var channel = await GetChannelAsync(token, channelId); var channel = await GetChannelAsync(token, channelId);
// Get the chat log // Get the chat log
return await GetChatLogAsync(token, channel, from, to, progress); return await GetChatLogAsync(token, channel, after, before, progress);
} }
public void Dispose() public void Dispose()

View file

@ -58,7 +58,7 @@ namespace DiscordChatExporter.Core.Services
{ {
// Create partitions by grouping up to X contiguous messages into separate chat logs // Create partitions by grouping up to X contiguous messages into separate chat logs
var partitions = chatLog.Messages.GroupContiguous(g => g.Count < partitionLimit.Value) var partitions = chatLog.Messages.GroupContiguous(g => g.Count < partitionLimit.Value)
.Select(g => new ChatLog(chatLog.Guild, chatLog.Channel, chatLog.From, chatLog.To, g, chatLog.Mentionables)) .Select(g => new ChatLog(chatLog.Guild, chatLog.Channel, chatLog.After, chatLog.Before, g, chatLog.Mentionables))
.ToArray(); .ToArray();
// Split file path into components // Split file path into components

View file

@ -14,7 +14,7 @@ namespace DiscordChatExporter.Core.Services.Helpers
Path.GetExtension(path) == null; Path.GetExtension(path) == null;
public static string GetDefaultExportFileName(ExportFormat format, Guild guild, Channel channel, public static string GetDefaultExportFileName(ExportFormat format, Guild guild, Channel channel,
DateTime? from = null, DateTime? to = null) DateTimeOffset? after = null, DateTimeOffset? before = null)
{ {
var result = new StringBuilder(); var result = new StringBuilder();
@ -22,24 +22,24 @@ namespace DiscordChatExporter.Core.Services.Helpers
result.Append($"{guild.Name} - {channel.Name} [{channel.Id}]"); result.Append($"{guild.Name} - {channel.Name} [{channel.Id}]");
// Append date range // Append date range
if (from != null || to != null) if (after != null || before != null)
{ {
result.Append(" ("); result.Append(" (");
// Both 'from' and 'to' are set // Both 'after' and 'before' are set
if (from != null && to != null) if (after != null && before != null)
{ {
result.Append($"{from:yyyy-MM-dd} to {to:yyyy-MM-dd}"); result.Append($"{after:yyyy-MM-dd} to {before:yyyy-MM-dd}");
} }
// Only 'from' is set // Only 'after' is set
else if (from != null) else if (after != null)
{ {
result.Append($"after {from:yyyy-MM-dd}"); result.Append($"after {after:yyyy-MM-dd}");
} }
// Only 'to' is set // Only 'before' is set
else else
{ {
result.Append($"before {to:yyyy-MM-dd}"); result.Append($"before {before:yyyy-MM-dd}");
} }
result.Append(")"); result.Append(")");

View file

@ -5,10 +5,10 @@ namespace DiscordChatExporter.Core.Services.Internal
{ {
internal static class Extensions internal static class Extensions
{ {
public static string ToSnowflake(this DateTime dateTime) public static string ToSnowflake(this DateTimeOffset date)
{ {
const long epoch = 62135596800000; const long epoch = 62135596800000;
var unixTime = dateTime.ToUniversalTime().Ticks / TimeSpan.TicksPerMillisecond - epoch; var unixTime = date.ToUniversalTime().Ticks / TimeSpan.TicksPerMillisecond - epoch;
var value = ((ulong) unixTime - 1420070400000UL) << 22; var value = ((ulong) unixTime - 1420070400000UL) << 22;
return value.ToString(); return value.ToString();
} }

View file

@ -0,0 +1,28 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace DiscordChatExporter.Gui.Converters
{
[ValueConversion(typeof(DateTimeOffset), typeof(DateTime))]
public class DateTimeOffsetToDateTimeConverter : IValueConverter
{
public static DateTimeOffsetToDateTimeConverter Instance { get; } = new DateTimeOffsetToDateTimeConverter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DateTimeOffset date)
return date.DateTime;
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DateTime date)
return new DateTimeOffset(date);
return null;
}
}
}

View file

@ -12,8 +12,10 @@ namespace DiscordChatExporter.Gui.Converters
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
var format = value as ExportFormat?; if (value is ExportFormat format)
return format?.GetDisplayName(); return format.GetDisplayName();
return null;
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

View file

@ -59,6 +59,7 @@
<Compile Include="Behaviors\ChannelViewModelMultiSelectionListBoxBehavior.cs" /> <Compile Include="Behaviors\ChannelViewModelMultiSelectionListBoxBehavior.cs" />
<Compile Include="Behaviors\MultiSelectionListBoxBehavior.cs" /> <Compile Include="Behaviors\MultiSelectionListBoxBehavior.cs" />
<Compile Include="Bootstrapper.cs" /> <Compile Include="Bootstrapper.cs" />
<Compile Include="Converters\DateTimeOffsetToDateTimeConverter.cs" />
<Compile Include="Converters\ExportFormatToStringConverter.cs" /> <Compile Include="Converters\ExportFormatToStringConverter.cs" />
<Compile Include="ViewModels\Components\ChannelViewModel.cs" /> <Compile Include="ViewModels\Components\ChannelViewModel.cs" />
<Compile Include="ViewModels\Components\GuildViewModel.cs" /> <Compile Include="ViewModels\Components\GuildViewModel.cs" />

View file

@ -27,9 +27,9 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
public ExportFormat SelectedFormat { get; set; } = ExportFormat.HtmlDark; public ExportFormat SelectedFormat { get; set; } = ExportFormat.HtmlDark;
public DateTime? From { get; set; } public DateTimeOffset? After { get; set; }
public DateTime? To { get; set; } public DateTimeOffset? Before { get; set; }
public int? PartitionLimit { get; set; } public int? PartitionLimit { get; set; }
@ -54,11 +54,11 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
_settingsService.LastExportFormat = SelectedFormat; _settingsService.LastExportFormat = SelectedFormat;
_settingsService.LastPartitionLimit = PartitionLimit; _settingsService.LastPartitionLimit = PartitionLimit;
// Clamp 'from' and 'to' values // Clamp 'after' and 'before' values
if (From > To) if (After > Before)
From = To; After = Before;
if (To < From) if (Before < After)
To = From; Before = After;
// If single channel - prompt file path // If single channel - prompt file path
if (IsSingleChannel) if (IsSingleChannel)
@ -67,7 +67,7 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
var channel = Channels.Single(); var channel = Channels.Single();
// Generate default file name // Generate default file name
var defaultFileName = ExportHelper.GetDefaultExportFileName(SelectedFormat, Guild, channel, From, To); var defaultFileName = ExportHelper.GetDefaultExportFileName(SelectedFormat, Guild, channel, After, Before);
// Generate filter // Generate filter
var ext = SelectedFormat.GetFileExtension(); var ext = SelectedFormat.GetFileExtension();

View file

@ -267,7 +267,7 @@ namespace DiscordChatExporter.Gui.ViewModels
{ {
// Generate default file name // Generate default file name
var fileName = ExportHelper.GetDefaultExportFileName(dialog.SelectedFormat, dialog.Guild, var fileName = ExportHelper.GetDefaultExportFileName(dialog.SelectedFormat, dialog.Guild,
channel, dialog.From, dialog.To); channel, dialog.After, dialog.Before);
// Combine paths // Combine paths
filePath = Path.Combine(filePath, fileName); filePath = Path.Combine(filePath, fileName);
@ -275,7 +275,7 @@ namespace DiscordChatExporter.Gui.ViewModels
// Get chat log // Get chat log
var chatLog = await _dataService.GetChatLogAsync(token, dialog.Guild, channel, var chatLog = await _dataService.GetChatLogAsync(token, dialog.Guild, channel,
dialog.From, dialog.To, operation); dialog.After, dialog.Before, operation);
// Export // Export
await _exportService.ExportChatLogAsync(chatLog, filePath, dialog.SelectedFormat, await _exportService.ExportChatLogAsync(chatLog, filePath, dialog.SelectedFormat,

View file

@ -86,8 +86,8 @@
Margin="16,8" Margin="16,8"
materialDesign:HintAssist.Hint="From (optional)" materialDesign:HintAssist.Hint="From (optional)"
materialDesign:HintAssist.IsFloating="True" materialDesign:HintAssist.IsFloating="True"
DisplayDateEnd="{Binding To}" DisplayDateEnd="{Binding Before, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
SelectedDate="{Binding From}" SelectedDate="{Binding After, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
ToolTip="If this is set, only messages sent after this date will be exported" /> ToolTip="If this is set, only messages sent after this date will be exported" />
<DatePicker <DatePicker
Grid.Row="0" Grid.Row="0"
@ -95,8 +95,8 @@
Margin="16,8" Margin="16,8"
materialDesign:HintAssist.Hint="To (optional)" materialDesign:HintAssist.Hint="To (optional)"
materialDesign:HintAssist.IsFloating="True" materialDesign:HintAssist.IsFloating="True"
DisplayDateStart="{Binding From}" DisplayDateStart="{Binding After, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
SelectedDate="{Binding To}" SelectedDate="{Binding Before, Converter={x:Static converters:DateTimeOffsetToDateTimeConverter.Instance}}"
ToolTip="If this is set, only messages sent before this date will be exported" /> ToolTip="If this is set, only messages sent before this date will be exported" />
</Grid> </Grid>