Self-contained export (#321)

This commit is contained in:
Alexey Golub
2020-07-18 15:45:09 +03:00
committed by GitHub
parent 94a85cdb01
commit ac64d9943a
56 changed files with 813 additions and 581 deletions

View File

@@ -0,0 +1,13 @@
using System.Drawing;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class ColorExtensions
{
public static Color WithAlpha(this Color color, int alpha) => Color.FromArgb(alpha, color);
public static Color ResetAlpha(this Color color) => color.WithAlpha(255);
public static int ToRgb(this Color color) => color.ToArgb() & 0xffffff;
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Globalization;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class DateExtensions
{
public static string ToSnowflake(this DateTimeOffset dateTime)
{
var value = ((ulong) dateTime.ToUnixTimeMilliseconds() - 1420070400000UL) << 22;
return value.ToString();
}
public static string ToLocalString(this DateTimeOffset dateTime, string format) =>
dateTime.ToLocalTime().ToString(format, CultureInfo.InvariantCulture);
}
}

View File

@@ -0,0 +1,14 @@
using System;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class GenericExtensions
{
public static TOut Pipe<TIn, TOut>(this TIn input, Func<TIn, TOut> transform) => transform(input);
public static T? NullIf<T>(this T value, Func<T, bool> predicate) where T : struct =>
!predicate(value)
? value
: (T?) null;
}
}

View File

@@ -0,0 +1,28 @@
using System.IO;
using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class HttpClientExtensions
{
// HACK: ConfigureAwait() is crucial here to enable sync-over-async in HtmlMessageWriter
public static async Task DownloadAsync(this HttpClient httpClient, string uri, string outputFilePath)
{
await using var input = await httpClient.GetStreamAsync(uri).ConfigureAwait(false);
var output = File.Create(outputFilePath);
await input.CopyToAsync(output).ConfigureAwait(false);
await output.DisposeAsync().ConfigureAwait(false);
}
public static async Task<JsonElement> ReadAsJsonAsync(this HttpContent content)
{
await using var stream = await content.ReadAsStreamAsync();
using var doc = await JsonDocument.ParseAsync(stream);
return doc.RootElement.Clone();
}
}
}

View File

@@ -0,0 +1,12 @@
using System.Text.Json;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class JsonElementExtensions
{
public static JsonElement? GetPropertyOrNull(this JsonElement element, string propertyName) =>
element.TryGetProperty(propertyName, out var result) && result.ValueKind != JsonValueKind.Null
? result
: (JsonElement?) null;
}
}

View File

@@ -0,0 +1,12 @@
using System.Text;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class StringExtensions
{
public static StringBuilder AppendIfNotEmpty(this StringBuilder builder, char value) =>
builder.Length > 0
? builder.Append(value)
: builder;
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Text.Json;
namespace DiscordChatExporter.Domain.Internal.Extensions
{
internal static class Utf8JsonWriterExtensions
{
public static void WriteString(this Utf8JsonWriter writer, string propertyName, DateTimeOffset? value)
{
writer.WritePropertyName(propertyName);
if (value != null)
writer.WriteStringValue(value.Value);
else
writer.WriteNullValue();
}
public static void WriteNumber(this Utf8JsonWriter writer, string propertyName, int? value)
{
writer.WritePropertyName(propertyName);
if (value != null)
writer.WriteNumberValue(value.Value);
else
writer.WriteNullValue();
}
}
}