mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-05-01 02:02:22 +00:00
Add PowerKit and replace custom utility extensions (#1525)
Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class AsyncCollectionExtensions
|
||||
{
|
||||
extension<T>(IAsyncEnumerable<T> asyncEnumerable)
|
||||
{
|
||||
private async ValueTask<IReadOnlyList<T>> CollectAsync()
|
||||
{
|
||||
var list = new List<T>();
|
||||
|
||||
await foreach (var i in asyncEnumerable)
|
||||
list.Add(i);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public ValueTaskAwaiter<IReadOnlyList<T>> GetAwaiter() =>
|
||||
asyncEnumerable.CollectAsync().GetAwaiter();
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class CollectionExtensions
|
||||
{
|
||||
extension<T>(T obj)
|
||||
{
|
||||
public IEnumerable<T> ToSingletonEnumerable()
|
||||
{
|
||||
yield return obj;
|
||||
}
|
||||
}
|
||||
|
||||
extension<T>(IEnumerable<T?> source)
|
||||
where T : class
|
||||
{
|
||||
public IEnumerable<T> WhereNotNull()
|
||||
{
|
||||
foreach (var o in source)
|
||||
{
|
||||
if (o is not null)
|
||||
yield return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension<T>(IEnumerable<T?> source)
|
||||
where T : struct
|
||||
{
|
||||
public IEnumerable<T> WhereNotNull()
|
||||
{
|
||||
foreach (var o in source)
|
||||
{
|
||||
if (o is not null)
|
||||
yield return o.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class ColorExtensions
|
||||
{
|
||||
extension(Color color)
|
||||
{
|
||||
public Color WithAlpha(int alpha) => Color.FromArgb(alpha, color);
|
||||
|
||||
public Color ResetAlpha() => color.WithAlpha(255);
|
||||
|
||||
public int ToRgb() => color.ToArgb() & 0xffffff;
|
||||
|
||||
public string ToHex() => $"#{color.R:X2}{color.G:X2}{color.B:X2}";
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class ExceptionExtensions
|
||||
{
|
||||
extension(Exception exception)
|
||||
{
|
||||
private void PopulateChildren(ICollection<Exception> children)
|
||||
{
|
||||
if (exception is AggregateException aggregateException)
|
||||
{
|
||||
foreach (var innerException in aggregateException.InnerExceptions)
|
||||
{
|
||||
children.Add(innerException);
|
||||
PopulateChildren(innerException, children);
|
||||
}
|
||||
}
|
||||
else if (exception.InnerException is not null)
|
||||
{
|
||||
children.Add(exception.InnerException);
|
||||
PopulateChildren(exception.InnerException, children);
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<Exception> GetSelfAndChildren()
|
||||
{
|
||||
var children = new List<Exception> { exception };
|
||||
PopulateChildren(exception, children);
|
||||
return children;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class GenericExtensions
|
||||
{
|
||||
extension<TIn>(TIn input)
|
||||
{
|
||||
public TOut Pipe<TOut>(Func<TIn, TOut> transform) => transform(input);
|
||||
}
|
||||
|
||||
extension<T>(T value)
|
||||
where T : struct
|
||||
{
|
||||
public T? NullIf(Func<T, bool> predicate) => !predicate(value) ? value : null;
|
||||
|
||||
public T? NullIfDefault() =>
|
||||
value.NullIf(v => EqualityComparer<T>.Default.Equals(v, default));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class HttpExtensions
|
||||
{
|
||||
extension(HttpHeaders headers)
|
||||
{
|
||||
public string? TryGetValue(string name) =>
|
||||
headers.TryGetValues(name, out var values) ? string.Concat(values) : null;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class PathExtensions
|
||||
{
|
||||
// This is a union of invalid characters from Windows (NTFS/FAT32), Linux (ext4/XFS), and macOS (HFS+/APFS).
|
||||
// We use this instead of Path.GetInvalidFileNameChars() because that only returns OS-specific characters,
|
||||
// not filesystem-specific characters. It's possible to use, for example, an NTFS drive on Linux,
|
||||
// which would make some additional characters invalid that are otherwise valid on Linux.
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/1452
|
||||
private static readonly char[] InvalidFileNameChars =
|
||||
[
|
||||
'\0', // Null character - invalid on all filesystems
|
||||
'/', // Path separator on Unix and Windows
|
||||
'\\', // Path separator on Windows
|
||||
':', // Reserved on Windows (drive letters, NTFS streams)
|
||||
'*', // Wildcard on Windows
|
||||
'?', // Wildcard on Windows
|
||||
'"', // Reserved on Windows
|
||||
'<', // Redirection on Windows
|
||||
'>', // Redirection on Windows
|
||||
'|', // Pipe on Windows
|
||||
];
|
||||
|
||||
extension(Path)
|
||||
{
|
||||
public static string EscapeFileName(string path)
|
||||
{
|
||||
var buffer = new StringBuilder(path.Length);
|
||||
|
||||
foreach (var c in path)
|
||||
buffer.Append(!InvalidFileNameChars.Contains(c) ? c : '_');
|
||||
|
||||
// File names cannot end with a dot on Windows
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/977
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
while (buffer.Length > 0 && buffer[^1] == '.')
|
||||
buffer.Remove(buffer.Length - 1, 1);
|
||||
}
|
||||
|
||||
return buffer.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System.Text;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
extension(string str)
|
||||
{
|
||||
public string? NullIfWhiteSpace() => !string.IsNullOrWhiteSpace(str) ? str : null;
|
||||
|
||||
public string Truncate(int charCount) => str.Length > charCount ? str[..charCount] : str;
|
||||
|
||||
public string ToSpaceSeparatedWords()
|
||||
{
|
||||
var builder = new StringBuilder(str.Length * 2);
|
||||
|
||||
foreach (var c in str)
|
||||
{
|
||||
if (char.IsUpper(c) && builder.Length > 0)
|
||||
builder.Append(' ');
|
||||
|
||||
builder.Append(c);
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
extension(StringBuilder builder)
|
||||
{
|
||||
public StringBuilder AppendIfNotEmpty(char value) =>
|
||||
builder.Length > 0 ? builder.Append(value) : builder;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils.Extensions;
|
||||
|
||||
public static class TimeSpanExtensions
|
||||
{
|
||||
extension(TimeSpan value)
|
||||
{
|
||||
public TimeSpan Clamp(TimeSpan min, TimeSpan max)
|
||||
{
|
||||
if (value < min)
|
||||
return min;
|
||||
|
||||
if (value > max)
|
||||
return max;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ using System.Net.Http;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Threading.Tasks;
|
||||
using DiscordChatExporter.Core.Utils.Extensions;
|
||||
using Polly;
|
||||
using Polly.Retry;
|
||||
using PowerKit.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils;
|
||||
|
||||
@@ -24,7 +24,7 @@ public static class Http
|
||||
|
||||
private static bool IsRetryableException(Exception exception) =>
|
||||
exception
|
||||
.GetSelfAndChildren()
|
||||
.GetSelfAndDescendants()
|
||||
.Any(ex =>
|
||||
ex is TimeoutException or SocketException or AuthenticationException
|
||||
|| ex is HttpRequestException hrex
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using DiscordChatExporter.Core.Utils.Extensions;
|
||||
using PowerKit.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Core.Utils;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user