From 9f281c6055ab2b58f19b0031507320e8e2874c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Domeradzki?= Date: Sat, 7 Aug 2021 14:03:46 +0200 Subject: [PATCH] Embrace madness (#2394) * Embrace madness * Remove unused code * Misc * Address Abry's note * Update for Madness 0.3.0 --- ...eamFarm.CustomPlugins.ExamplePlugin.csproj | 1 + .../ExamplePlugin.cs | 2 +- ...rm.OfficialPlugins.SteamTokenDumper.csproj | 4 + .../GlobalCache.cs | 10 +- .../SteamTokenDumperPlugin.cs | 2 +- ArchiSteamFarm.Tests/Bot.cs | 2 +- ArchiSteamFarm/ArchiSteamFarm.csproj | 1 + .../Compatibility/AsyncDisposableWrapper.cs | 39 ---- ArchiSteamFarm/Compatibility/File.cs | 74 ------- ArchiSteamFarm/Compatibility/HashCode.cs | 31 --- ArchiSteamFarm/Compatibility/Path.cs | 129 ----------- .../Compatibility/PathInternalNetCore.cs | 173 --------------- ArchiSteamFarm/Compatibility/StaticHelpers.cs | 207 ------------------ .../SupportedOSPlatformAttribute.cs | 35 --- ArchiSteamFarm/Core/ASF.cs | 19 +- ArchiSteamFarm/Core/OS.cs | 17 +- ArchiSteamFarm/Core/Statistics.cs | 6 +- ArchiSteamFarm/Helpers/SerializableFile.cs | 18 +- ArchiSteamFarm/IPC/ArchiKestrel.cs | 7 +- .../IPC/Controllers/Api/ASFController.cs | 6 +- .../IPC/Controllers/Api/BotController.cs | 2 +- .../IPC/Controllers/Api/NLogController.cs | 2 +- ArchiSteamFarm/IPC/Startup.cs | 7 +- ArchiSteamFarm/IPC/WebUtilities.cs | 2 +- ArchiSteamFarm/NLog/ArchiLogger.cs | 6 +- ArchiSteamFarm/Steam/Bot.cs | 31 ++- ArchiSteamFarm/Steam/Cards/CardsFarmer.cs | 6 +- ArchiSteamFarm/Steam/Cards/Game.cs | 2 +- ArchiSteamFarm/Steam/Exchange/Trading.cs | 2 +- .../Steam/Integration/ArchiWebHandler.cs | 3 +- .../Steam/Integration/SteamChatMessage.cs | 2 +- .../Steam/Integration/SteamSaleEvent.cs | 5 +- ArchiSteamFarm/Steam/Interaction/Actions.cs | 5 +- ArchiSteamFarm/Steam/Interaction/Commands.cs | 6 +- .../Steam/SteamKit2/ServerRecordEndPoint.cs | 2 +- ArchiSteamFarm/Steam/Storage/BotConfig.cs | 6 +- ArchiSteamFarm/Steam/Storage/BotDatabase.cs | 8 +- ArchiSteamFarm/Storage/GlobalConfig.cs | 8 +- ArchiSteamFarm/Storage/GlobalDatabase.cs | 6 +- .../Web/Responses/StreamResponse.cs | 2 +- ArchiSteamFarm/Web/WebBrowser.cs | 16 +- Directory.Packages.props | 1 + 42 files changed, 151 insertions(+), 762 deletions(-) delete mode 100644 ArchiSteamFarm/Compatibility/AsyncDisposableWrapper.cs delete mode 100644 ArchiSteamFarm/Compatibility/File.cs delete mode 100644 ArchiSteamFarm/Compatibility/HashCode.cs delete mode 100644 ArchiSteamFarm/Compatibility/Path.cs delete mode 100644 ArchiSteamFarm/Compatibility/PathInternalNetCore.cs delete mode 100644 ArchiSteamFarm/Compatibility/StaticHelpers.cs delete mode 100644 ArchiSteamFarm/Compatibility/SupportedOSPlatformAttribute.cs diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj index 8ee2913dc..e64e229b7 100644 --- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj +++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj @@ -11,6 +11,7 @@ + diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs index 7c87ebf48..a94a8e8a8 100644 --- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs +++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ExamplePlugin.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Generic; diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper.csproj b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper.csproj index b5600f6af..ce35604ca 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper.csproj +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper.csproj @@ -11,6 +11,10 @@ + + + + diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs index 6f82d9276..70c19df12 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/GlobalCache.cs @@ -20,16 +20,14 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; -using Path = System.IO.Path; -#else -using System.IO; +using JustArchiNET.Madness; +using File = JustArchiNET.Madness.FileMadness.File; #endif using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Threading.Tasks; using ArchiSteamFarm.Core; @@ -86,7 +84,7 @@ namespace ArchiSteamFarm.OfficialPlugins.SteamTokenDumper { GlobalCache? globalCache; try { - string json = await Compatibility.File.ReadAllTextAsync(SharedFilePath).ConfigureAwait(false); + string json = await File.ReadAllTextAsync(SharedFilePath).ConfigureAwait(false); if (string.IsNullOrEmpty(json)) { ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json))); diff --git a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs index c7962a535..2b0e50fa6 100644 --- a/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs +++ b/ArchiSteamFarm.OfficialPlugins.SteamTokenDumper/SteamTokenDumperPlugin.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Concurrent; diff --git a/ArchiSteamFarm.Tests/Bot.cs b/ArchiSteamFarm.Tests/Bot.cs index c8f20d7d3..a95f0cdf3 100644 --- a/ArchiSteamFarm.Tests/Bot.cs +++ b/ArchiSteamFarm.Tests/Bot.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Generic; diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj index 4263e07bd..8a6d2836d 100644 --- a/ArchiSteamFarm/ArchiSteamFarm.csproj +++ b/ArchiSteamFarm/ArchiSteamFarm.csproj @@ -36,6 +36,7 @@ + diff --git a/ArchiSteamFarm/Compatibility/AsyncDisposableWrapper.cs b/ArchiSteamFarm/Compatibility/AsyncDisposableWrapper.cs deleted file mode 100644 index d4f1e0d6a..000000000 --- a/ArchiSteamFarm/Compatibility/AsyncDisposableWrapper.cs +++ /dev/null @@ -1,39 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if NETFRAMEWORK -using System; -using System.Threading.Tasks; - -namespace ArchiSteamFarm.Compatibility { - internal sealed class AsyncDisposableWrapper : IAsyncDisposable { - private readonly IDisposable Disposable; - - internal AsyncDisposableWrapper(IDisposable disposable) => Disposable = disposable ?? throw new ArgumentNullException(nameof(disposable)); - - public ValueTask DisposeAsync() { - Disposable.Dispose(); - - return default(ValueTask); - } - } -} -#endif diff --git a/ArchiSteamFarm/Compatibility/File.cs b/ArchiSteamFarm/Compatibility/File.cs deleted file mode 100644 index c4b3f1b50..000000000 --- a/ArchiSteamFarm/Compatibility/File.cs +++ /dev/null @@ -1,74 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Threading.Tasks; -using JetBrains.Annotations; - -namespace ArchiSteamFarm.Compatibility { - [PublicAPI] - public static class File { - public static Task AppendAllTextAsync(string path, string contents) { -#if NETFRAMEWORK - System.IO.File.AppendAllText(path, contents); - - return Task.CompletedTask; -#else - return System.IO.File.AppendAllTextAsync(path, contents); -#endif - } - - public static void Move(string sourceFileName, string destFileName, bool overwrite) { -#if NETFRAMEWORK - if (overwrite && System.IO.File.Exists(destFileName)) { - System.IO.File.Delete(destFileName); - } - - System.IO.File.Move(sourceFileName, destFileName); -#else - System.IO.File.Move(sourceFileName, destFileName, overwrite); -#endif - } - - public static Task ReadAllBytesAsync(string path) => -#if NETFRAMEWORK - Task.FromResult(System.IO.File.ReadAllBytes(path)); -#else - System.IO.File.ReadAllBytesAsync(path); -#endif - - public static Task ReadAllTextAsync(string path) => -#if NETFRAMEWORK - Task.FromResult(System.IO.File.ReadAllText(path)); -#else - System.IO.File.ReadAllTextAsync(path); -#endif - - public static Task WriteAllTextAsync(string path, string contents) { -#if NETFRAMEWORK - System.IO.File.WriteAllText(path, contents); - - return Task.CompletedTask; -#else - return System.IO.File.WriteAllTextAsync(path, contents); -#endif - } - } -} diff --git a/ArchiSteamFarm/Compatibility/HashCode.cs b/ArchiSteamFarm/Compatibility/HashCode.cs deleted file mode 100644 index 683a812eb..000000000 --- a/ArchiSteamFarm/Compatibility/HashCode.cs +++ /dev/null @@ -1,31 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if NETFRAMEWORK -using JetBrains.Annotations; - -namespace ArchiSteamFarm.Compatibility { - [PublicAPI] - public static class HashCode { - public static int Combine(T1 value1, T2 value2, T3 value3) => (value1, value2, value3).GetHashCode(); - } -} -#endif diff --git a/ArchiSteamFarm/Compatibility/Path.cs b/ArchiSteamFarm/Compatibility/Path.cs deleted file mode 100644 index 0f0fb1efb..000000000 --- a/ArchiSteamFarm/Compatibility/Path.cs +++ /dev/null @@ -1,129 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if NETFRAMEWORK -using System; -using System.Text; -#endif -using JetBrains.Annotations; - -namespace ArchiSteamFarm.Compatibility { - [PublicAPI] - public static class Path { - public static string GetRelativePath(string relativeTo, string path) { -#if NETFRAMEWORK - if (string.IsNullOrEmpty(relativeTo)) { - throw new ArgumentNullException(nameof(relativeTo)); - } - - if (string.IsNullOrEmpty(path)) { - throw new ArgumentNullException(nameof(path)); - } - - StringComparison comparisonType = PathInternalNetCore.StringComparison; - - relativeTo = System.IO.Path.GetFullPath(relativeTo); - path = System.IO.Path.GetFullPath(path); - - // Need to check if the roots are different- if they are we need to return the "to" path. - if (!PathInternalNetCore.AreRootsEqual(relativeTo, path, comparisonType)) { - return path; - } - - int commonLength = PathInternalNetCore.GetCommonPathLength( - relativeTo, path, - comparisonType == StringComparison.OrdinalIgnoreCase - ); - - // If there is nothing in common they can't share the same root, return the "to" path as is. - if (commonLength == 0) { - return path; - } - - // Trailing separators aren't significant for comparison - int relativeToLength = relativeTo.Length; - - if (PathInternalNetCore.EndsInDirectorySeparator(relativeTo)) { - relativeToLength--; - } - - bool pathEndsInSeparator = PathInternalNetCore.EndsInDirectorySeparator(path); - int pathLength = path.Length; - - if (pathEndsInSeparator) { - pathLength--; - } - - // If we have effectively the same path, return "." - if ((relativeToLength == pathLength) && (commonLength >= relativeToLength)) { - return "."; - } - - // We have the same root, we need to calculate the difference now using the - // common Length and Segment count past the length. - // - // Some examples: - // - // C:\Foo C:\Bar L3, S1 -> ..\Bar - // C:\Foo C:\Foo\Bar L6, S0 -> Bar - // C:\Foo\Bar C:\Bar\Bar L3, S2 -> ..\..\Bar\Bar - // C:\Foo\Foo C:\Foo\Bar L7, S1 -> ..\Bar - - StringBuilder sb = new(); //StringBuilderCache.Acquire(Math.Max(relativeTo.Length, path.Length)); - - // Add parent segments for segments past the common on the "from" path - if (commonLength < relativeToLength) { - sb.Append(".."); - - for (int i = commonLength + 1; i < relativeToLength; i++) { - if (PathInternalNetCore.IsDirectorySeparator(relativeTo[i])) { - sb.Append(System.IO.Path.DirectorySeparatorChar); - sb.Append(".."); - } - } - } else if (PathInternalNetCore.IsDirectorySeparator(path[commonLength])) { - // No parent segments and we need to eat the initial separator - // (C:\Foo C:\Foo\Bar case) - commonLength++; - } - - // Now add the rest of the "to" path, adding back the trailing separator - int differenceLength = pathLength - commonLength; - - if (pathEndsInSeparator) { - differenceLength++; - } - - if (differenceLength > 0) { - if (sb.Length > 0) { - sb.Append(System.IO.Path.DirectorySeparatorChar); - } - - sb.Append(path, commonLength, differenceLength); - } - - return sb.ToString(); //StringBuilderCache.GetStringAndRelease(sb); -#else - return System.IO.Path.GetRelativePath(relativeTo, path); -#endif - } - } -} diff --git a/ArchiSteamFarm/Compatibility/PathInternalNetCore.cs b/ArchiSteamFarm/Compatibility/PathInternalNetCore.cs deleted file mode 100644 index afc51b612..000000000 --- a/ArchiSteamFarm/Compatibility/PathInternalNetCore.cs +++ /dev/null @@ -1,173 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if NETFRAMEWORK -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace ArchiSteamFarm.Compatibility { - internal static class PathInternalNetCore { - private const string ExtendedDevicePathPrefix = @"\\?\"; - private const string UncExtendedPathPrefix = @"\\?\UNC\"; - - internal static StringComparison StringComparison => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - - /// - /// Returns true if the two paths have the same root - /// - internal static bool AreRootsEqual(string first, string second, StringComparison comparisonType) { - int firstRootLength = GetRootLength(first); - int secondRootLength = GetRootLength(second); - - return (firstRootLength == secondRootLength) - && (string.Compare( - first, - 0, - second, - 0, - firstRootLength, - comparisonType - ) == 0); - } - - /// - /// Returns true if the path ends in a directory separator. - /// - internal static bool EndsInDirectorySeparator(string path) => (path.Length > 0) && IsDirectorySeparator(path[^1]); - - /// - /// Get the common path length from the start of the string. - /// - internal static int GetCommonPathLength(string first, string second, bool ignoreCase) { - int commonChars = EqualStartingCharacterCount(first, second, ignoreCase); - - // If nothing matches - if (commonChars == 0) { - return commonChars; - } - - // Or we're a full string and equal length or match to a separator - if ((commonChars == first.Length) - && ((commonChars == second.Length) || IsDirectorySeparator(second[commonChars]))) { - return commonChars; - } - - if ((commonChars == second.Length) && IsDirectorySeparator(first[commonChars])) { - return commonChars; - } - - // It's possible we matched somewhere in the middle of a segment e.g. C:\Foodie and C:\Foobar. - while ((commonChars > 0) && !IsDirectorySeparator(first[commonChars - 1])) { - commonChars--; - } - - return commonChars; - } - - /// - /// True if the given character is a directory separator. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static bool IsDirectorySeparator(char c) => (c == System.IO.Path.DirectorySeparatorChar) || (c == System.IO.Path.AltDirectorySeparatorChar); - - /// - /// Gets the count of common characters from the left optionally ignoring case - /// - private static unsafe int EqualStartingCharacterCount(string first, string second, bool ignoreCase) { - if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) { - return 0; - } - - int commonChars = 0; - - fixed (char* f = first) - fixed (char* s = second) { - char* l = f; - char* r = s; - char* leftEnd = l + first.Length; - char* rightEnd = r + second.Length; - - while ((l != leftEnd) && (r != rightEnd) - && ((*l == *r) || (ignoreCase && - (char.ToUpperInvariant(*l) == char.ToUpperInvariant(*r))))) { - commonChars++; - l++; - r++; - } - } - - return commonChars; - } - - /// - /// Gets the length of the root of the path (drive, share, etc.). - /// - private static int GetRootLength(string path) { - int i = 0; - int volumeSeparatorLength = 2; // Length to the colon "C:" - int uncRootLength = 2; // Length to the start of the server name "\\" - - bool extendedSyntax = path.StartsWith(ExtendedDevicePathPrefix, StringComparison.Ordinal); - bool extendedUncSyntax = path.StartsWith(UncExtendedPathPrefix, StringComparison.Ordinal); - - if (extendedSyntax) { - // Shift the position we look for the root from to account for the extended prefix - if (extendedUncSyntax) { - // "\\" -> "\\?\UNC\" - uncRootLength = UncExtendedPathPrefix.Length; - } else { - // "C:" -> "\\?\C:" - volumeSeparatorLength += ExtendedDevicePathPrefix.Length; - } - } - - if ((!extendedSyntax || extendedUncSyntax) && (path.Length > 0) && IsDirectorySeparator(path[0])) { - // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo") - - i = 1; // Drive rooted (\foo) is one character - - if (extendedUncSyntax || ((path.Length > 1) && IsDirectorySeparator(path[1]))) { - // UNC (\\?\UNC\ or \\), scan past the next two directory separators at most - // (e.g. to \\?\UNC\Server\Share or \\Server\Share\) - i = uncRootLength; - int n = 2; // Maximum separators to skip - - while ((i < path.Length) && (!IsDirectorySeparator(path[i]) || (--n > 0))) { - i++; - } - } - } else if ((path.Length >= volumeSeparatorLength) && - (path[volumeSeparatorLength - 1] == System.IO.Path.VolumeSeparatorChar)) { - // Path is at least longer than where we expect a colon, and has a colon (\\?\A:, A:) - // If the colon is followed by a directory separator, move past it - i = volumeSeparatorLength; - - if ((path.Length >= volumeSeparatorLength + 1) && IsDirectorySeparator(path[volumeSeparatorLength])) { - i++; - } - } - - return i; - } - } -} -#endif diff --git a/ArchiSteamFarm/Compatibility/StaticHelpers.cs b/ArchiSteamFarm/Compatibility/StaticHelpers.cs deleted file mode 100644 index 6c4f7dd5b..000000000 --- a/ArchiSteamFarm/Compatibility/StaticHelpers.cs +++ /dev/null @@ -1,207 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if NETFRAMEWORK -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Net.WebSockets; -using System.Security.Cryptography; -using System.Threading; -using System.Threading.Tasks; -using ArchiSteamFarm.Localization; -using Microsoft.AspNetCore.Hosting; -#endif -using System; -using System.Diagnostics; -using JetBrains.Annotations; - -namespace ArchiSteamFarm.Compatibility { - [PublicAPI] - public static class StaticHelpers { -#if NETFRAMEWORK - private static readonly DateTime SavedProcessStartTime = DateTime.UtcNow; -#endif - -#if NETFRAMEWORK - public static bool IsRunningOnMono => Type.GetType("Mono.Runtime") != null; -#else - public static bool IsRunningOnMono => false; -#endif - - public static DateTime ProcessStartTime { - get { -#if NETFRAMEWORK - if (IsRunningOnMono) { - return SavedProcessStartTime; - } -#endif - - using Process process = Process.GetCurrentProcess(); - - return process.StartTime; - } - } - -#if NETFRAMEWORK - public static Task ComputeHashAsync(this HashAlgorithm hashAlgorithm, Stream inputStream) { - if (hashAlgorithm == null) { - throw new ArgumentNullException(nameof(hashAlgorithm)); - } - - return Task.FromResult(hashAlgorithm.ComputeHash(inputStream)); - } - - public static IAsyncDisposable ConfigureAwait(this IDisposable source, bool _) { - if (source == null) { - throw new ArgumentNullException(nameof(source)); - } - - return new AsyncDisposableWrapper(source); - } - - public static IWebHostBuilder ConfigureWebHostDefaults(this IWebHostBuilder builder, Action configure) { - if (configure == null) { - throw new ArgumentNullException(nameof(configure)); - } - - configure(builder); - - return builder; - } - - public static bool Contains(this string input, string value, StringComparison comparisonType) { - if (input == null) { - throw new ArgumentNullException(nameof(input)); - } - - return input.IndexOf(value, comparisonType) >= 0; - } - - // ReSharper disable once UseDeconstructionOnParameter - we actually implement deconstruction here - public static void Deconstruct(this KeyValuePair kv, out TKey key, out TValue value) { - key = kv.Key; - value = kv.Value; - } - - public static ValueTask DisposeAsync(this IDisposable disposable) { - if (disposable == null) { - throw new ArgumentNullException(nameof(disposable)); - } - - disposable.Dispose(); - - return default(ValueTask); - } - - public static int IndexOf(this string source, char value, StringComparison comparisonType) { - if (source == null) { - throw new ArgumentNullException(nameof(source)); - } - - return source.IndexOf(value.ToString(), comparisonType); - } - - public static async Task ReadAsync(this Stream stream, ReadOnlyMemory buffer) { - if (stream == null) { - throw new ArgumentNullException(nameof(stream)); - } - - byte[] byteArray = buffer.ToArray(); - - return await stream.ReadAsync(byteArray, 0, byteArray.Length).ConfigureAwait(false); - } - - public static async Task ReceiveAsync(this WebSocket webSocket, byte[] buffer, CancellationToken cancellationToken) { - if (webSocket == null) { - throw new ArgumentNullException(nameof(webSocket)); - } - - return await webSocket.ReceiveAsync(new ArraySegment(buffer), cancellationToken).ConfigureAwait(false); - } - - public static string Replace(this string source, string oldValue, string? newValue, StringComparison comparisonType) { - if (source == null) { - throw new ArgumentNullException(nameof(source)); - } - - if (oldValue == null) { - throw new ArgumentNullException(nameof(oldValue)); - } - - if (oldValue.Length == 0) { - throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(oldValue)), nameof(oldValue)); - } - - int startIndex = 0; - - while (true) { - if (startIndex >= source.Length) { - return source; - } - - int index = source.IndexOf(oldValue, startIndex, comparisonType); - - if (index < 0) { - return source; - } - - startIndex = index; - - source = source.Remove(index, oldValue.Length); - - if (!string.IsNullOrEmpty(newValue)) { - source = source.Insert(index, newValue!); - startIndex += newValue!.Length; - } - } - } - - public static async Task SendAsync(this WebSocket webSocket, byte[] buffer, WebSocketMessageType messageType, bool endOfMessage, CancellationToken cancellationToken) { - if (webSocket == null) { - throw new ArgumentNullException(nameof(webSocket)); - } - - await webSocket.SendAsync(new ArraySegment(buffer), messageType, endOfMessage, cancellationToken).ConfigureAwait(false); - } - - public static string[] Split(this string text, char separator, StringSplitOptions options = StringSplitOptions.None) { - if (text == null) { - throw new ArgumentNullException(nameof(text)); - } - - return text.Split(new[] { separator }, options); - } - - public static void TrimExcess(this Dictionary _) { } // no-op - - public static async Task WriteAsync(this Stream stream, ReadOnlyMemory buffer) { - if (stream == null) { - throw new ArgumentNullException(nameof(stream)); - } - - byte[] byteArray = buffer.ToArray(); - - await stream.WriteAsync(byteArray, 0, byteArray.Length).ConfigureAwait(false); - } -#endif - } -} diff --git a/ArchiSteamFarm/Compatibility/SupportedOSPlatformAttribute.cs b/ArchiSteamFarm/Compatibility/SupportedOSPlatformAttribute.cs deleted file mode 100644 index dad4d260b..000000000 --- a/ArchiSteamFarm/Compatibility/SupportedOSPlatformAttribute.cs +++ /dev/null @@ -1,35 +0,0 @@ -// _ _ _ ____ _ _____ -// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ -// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ -// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | -// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| -// | -// Copyright 2015-2021 Łukasz "JustArchi" Domeradzki -// Contact: JustArchi@JustArchi.net -// | -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// | -// http://www.apache.org/licenses/LICENSE-2.0 -// | -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if NETFRAMEWORK -using System; -using JetBrains.Annotations; - -namespace ArchiSteamFarm.Compatibility { - [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple = true, Inherited = false)] - [PublicAPI] - public sealed class SupportedOSPlatformAttribute : Attribute { - public string PlatformName { get; } - - public SupportedOSPlatformAttribute(string platformName) => PlatformName = platformName; - } -} -#endif diff --git a/ArchiSteamFarm/Core/ASF.cs b/ArchiSteamFarm/Core/ASF.cs index 4089d4e18..970db3896 100644 --- a/ArchiSteamFarm/Core/ASF.cs +++ b/ArchiSteamFarm/Core/ASF.cs @@ -21,9 +21,9 @@ #if NETFRAMEWORK using System.Runtime.InteropServices; -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; -using Path = System.IO.Path; +using JustArchiNET.Madness; +using File = JustArchiNET.Madness.FileMadness.File; +using Path = JustArchiNET.Madness.PathMadness.Path; #endif using System; using System.Collections.Concurrent; @@ -160,7 +160,7 @@ namespace ArchiSteamFarm.Core { return false; } - return Compatibility.Path.GetRelativePath(".", botName) == botName; + return Path.GetRelativePath(".", botName) == botName; } internal static async Task RestartOrExit() { @@ -941,7 +941,7 @@ namespace ArchiSteamFarm.Core { return false; } - string relativeFilePath = Compatibility.Path.GetRelativePath(targetDirectory, file); + string relativeFilePath = Path.GetRelativePath(targetDirectory, file); if (string.IsNullOrEmpty(relativeFilePath)) { ArchiLogger.LogNullError(nameof(relativeFilePath)); @@ -986,7 +986,8 @@ namespace ArchiSteamFarm.Core { Directory.CreateDirectory(targetBackupDirectory); string targetBackupFile = Path.Combine(targetBackupDirectory, fileName); - Compatibility.File.Move(file, targetBackupFile, true); + + File.Move(file, targetBackupFile, true); } // We can now get rid of directories that are empty @@ -1007,7 +1008,8 @@ namespace ArchiSteamFarm.Core { if (File.Exists(file)) { // This is possible only with files that we decided to leave in place during our backup function string targetBackupFile = file + ".bak"; - Compatibility.File.Move(file, targetBackupFile, true); + + File.Move(file, targetBackupFile, true); } // Check if this file requires its own folder @@ -1021,7 +1023,8 @@ namespace ArchiSteamFarm.Core { } if (!Directory.Exists(directory)) { - Directory.CreateDirectory(directory); + // ReSharper disable once RedundantSuppressNullableWarningExpression - required for .NET Framework + Directory.CreateDirectory(directory!); } // We're not interested in extracting placeholder files (but we still want directories created for them, done above) diff --git a/ArchiSteamFarm/Core/OS.cs b/ArchiSteamFarm/Core/OS.cs index c15d3b559..58bb931d3 100644 --- a/ArchiSteamFarm/Core/OS.cs +++ b/ArchiSteamFarm/Core/OS.cs @@ -20,8 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; +using JustArchiNET.Madness; #else using System.Runtime.Versioning; #endif @@ -44,6 +43,18 @@ namespace ArchiSteamFarm.Core { // We need to keep this one assigned and not calculated on-demand internal static readonly string ProcessFileName = Process.GetCurrentProcess().MainModule?.FileName ?? throw new InvalidOperationException(nameof(ProcessFileName)); + internal static DateTime ProcessStartTime { +#if NETFRAMEWORK + get => RuntimeMadness.ProcessStartTime.ToUniversalTime(); +#else + get { + using Process process = Process.GetCurrentProcess(); + + return process.StartTime.ToUniversalTime(); + } +#endif + } + internal static string Version { get { if (!string.IsNullOrEmpty(BackingVersion)) { @@ -227,7 +238,7 @@ namespace ArchiSteamFarm.Core { } // All windows variants have valid .NET Core build, and generic-netf is supported only on mono - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !StaticHelpers.IsRunningOnMono) { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !RuntimeMadness.IsRunningOnMono) { return false; } diff --git a/ArchiSteamFarm/Core/Statistics.cs b/ArchiSteamFarm/Core/Statistics.cs index 7045b88eb..c0a534bf5 100644 --- a/ArchiSteamFarm/Core/Statistics.cs +++ b/ArchiSteamFarm/Core/Statistics.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Generic; @@ -64,7 +64,11 @@ namespace ArchiSteamFarm.Core { private readonly Bot Bot; private readonly SemaphoreSlim MatchActivelySemaphore = new(1, 1); + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private readonly Timer MatchActivelyTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private readonly SemaphoreSlim RequestsSemaphore = new(1, 1); private DateTime LastAnnouncementCheck; diff --git a/ArchiSteamFarm/Helpers/SerializableFile.cs b/ArchiSteamFarm/Helpers/SerializableFile.cs index e72a093ec..12b4d02f6 100644 --- a/ArchiSteamFarm/Helpers/SerializableFile.cs +++ b/ArchiSteamFarm/Helpers/SerializableFile.cs @@ -19,8 +19,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +#if NETFRAMEWORK +using File = JustArchiNET.Madness.FileMadness.File; +#else using System.IO; +#endif +using System; using System.Threading; using System.Threading.Tasks; using ArchiSteamFarm.Core; @@ -86,17 +90,17 @@ namespace ArchiSteamFarm.Helpers { string newFilePath = FilePath + ".new"; if (File.Exists(FilePath)) { - string currentJson = await Compatibility.File.ReadAllTextAsync(FilePath!).ConfigureAwait(false); + string currentJson = await File.ReadAllTextAsync(FilePath!).ConfigureAwait(false); if (json == currentJson) { return; } - await Compatibility.File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); + await File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); File.Replace(newFilePath, FilePath!, null); } else { - await Compatibility.File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); + await File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); File.Move(newFilePath, FilePath!); } @@ -141,17 +145,17 @@ namespace ArchiSteamFarm.Helpers { try { // We always want to write entire content to temporary file first, in order to never load corrupted data, also when target file doesn't exist if (File.Exists(filePath)) { - string currentJson = await Compatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false); + string currentJson = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); if (json == currentJson) { return true; } - await Compatibility.File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); + await File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); File.Replace(newFilePath, filePath, null); } else { - await Compatibility.File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); + await File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false); File.Move(newFilePath, filePath); } diff --git a/ArchiSteamFarm/IPC/ArchiKestrel.cs b/ArchiSteamFarm/IPC/ArchiKestrel.cs index a79ce6ae7..e04f5cfc3 100644 --- a/ArchiSteamFarm/IPC/ArchiKestrel.cs +++ b/ArchiSteamFarm/IPC/ArchiKestrel.cs @@ -20,9 +20,8 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; -using Path = System.IO.Path; +using JustArchiNET.Madness; +using File = JustArchiNET.Madness.FileMadness.File; #else using Microsoft.Extensions.Hosting; #endif @@ -100,7 +99,7 @@ namespace ArchiSteamFarm.IPC { if (customConfigExists) { if (Debugging.IsDebugConfigured) { try { - string json = await Compatibility.File.ReadAllTextAsync(customConfigPath).ConfigureAwait(false); + string json = await File.ReadAllTextAsync(customConfigPath).ConfigureAwait(false); if (!string.IsNullOrEmpty(json)) { JObject jObject = JObject.Parse(json); diff --git a/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs b/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs index 593c1d75e..a96939a9f 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/ASFController.cs @@ -19,13 +19,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using JustArchiNET.Madness; +#endif using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using System.Threading.Tasks; -using ArchiSteamFarm.Compatibility; using ArchiSteamFarm.Core; using ArchiSteamFarm.IPC.Requests; using ArchiSteamFarm.IPC.Responses; @@ -71,7 +73,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api { uint memoryUsage = (uint) GC.GetTotalMemory(false) / 1024; - ASFResponse result = new(SharedInfo.BuildInfo.Variant, SharedInfo.BuildInfo.CanUpdate, ASF.GlobalConfig, memoryUsage, StaticHelpers.ProcessStartTime, SharedInfo.Version); + ASFResponse result = new(SharedInfo.BuildInfo.Variant, SharedInfo.BuildInfo.CanUpdate, ASF.GlobalConfig, memoryUsage, OS.ProcessStartTime, SharedInfo.Version); return Ok(new GenericResponse(result)); } diff --git a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs index ec0d55bb3..6f5f55b0c 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/BotController.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Generic; diff --git a/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs b/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs index f2f1a116e..7aa6fd3ef 100644 --- a/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs +++ b/ArchiSteamFarm/IPC/Controllers/Api/NLogController.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Concurrent; diff --git a/ArchiSteamFarm/IPC/Startup.cs b/ArchiSteamFarm/IPC/Startup.cs index c918e8bc7..2d310f99d 100644 --- a/ArchiSteamFarm/IPC/Startup.cs +++ b/ArchiSteamFarm/IPC/Startup.cs @@ -20,16 +20,13 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; using Newtonsoft.Json.Converters; -using File = System.IO.File; -using Path = System.IO.Path; -#else -using System.IO; #endif using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Net; using System.Reflection; using ArchiSteamFarm.Core; diff --git a/ArchiSteamFarm/IPC/WebUtilities.cs b/ArchiSteamFarm/IPC/WebUtilities.cs index 4de56e6b6..ca0080e0a 100644 --- a/ArchiSteamFarm/IPC/WebUtilities.cs +++ b/ArchiSteamFarm/IPC/WebUtilities.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.IO; diff --git a/ArchiSteamFarm/NLog/ArchiLogger.cs b/ArchiSteamFarm/NLog/ArchiLogger.cs index 147834ea9..d07f5939a 100644 --- a/ArchiSteamFarm/NLog/ArchiLogger.cs +++ b/ArchiSteamFarm/NLog/ArchiLogger.cs @@ -19,12 +19,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using File = JustArchiNET.Madness.FileMadness.File; +#else +using File = System.IO.File; +#endif using System; using System.Globalization; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; -using ArchiSteamFarm.Compatibility; using ArchiSteamFarm.Core; using ArchiSteamFarm.Localization; using JetBrains.Annotations; diff --git a/ArchiSteamFarm/Steam/Bot.cs b/ArchiSteamFarm/Steam/Bot.cs index 58ddf8842..8c4ee9fb8 100644 --- a/ArchiSteamFarm/Steam/Bot.cs +++ b/ArchiSteamFarm/Steam/Bot.cs @@ -20,9 +20,9 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; -using Path = System.IO.Path; +using JustArchiNET.Madness; +using File = JustArchiNET.Madness.FileMadness.File; +using Path = JustArchiNET.Madness.PathMadness.Path; #endif using System; using System.Collections; @@ -148,7 +148,11 @@ namespace ArchiSteamFarm.Steam { private readonly CallbackManager CallbackManager; private readonly SemaphoreSlim CallbackSemaphore = new(1, 1); private readonly SemaphoreSlim GamesRedeemerInBackgroundSemaphore = new(1, 1); + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private readonly Timer HeartBeatTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private readonly SemaphoreSlim InitializationSemaphore = new(1, 1); private readonly SemaphoreSlim MessagingSemaphore = new(1, 1); private readonly ConcurrentDictionary PastNotifications = new(); @@ -228,19 +232,34 @@ namespace ArchiSteamFarm.Steam { [JsonProperty] private string? AvatarHash; +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private Timer? ConnectionFailureTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private bool FirstTradeSent; + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private Timer? GamesRedeemerInBackgroundTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private byte HeartBeatFailures; private byte InvalidPasswordFailures; private EResult LastLogOnResult; private DateTime LastLogonSessionReplaced; private bool LibraryLocked; private ulong MasterChatGroupID; + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private Timer? PlayingWasBlockedTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private bool ReconnectOnUserInitiated; private bool SendCompleteTypesScheduled; + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private Timer? SendItemsTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private bool SteamParentalActive = true; private SteamSaleEvent? SteamSaleEvent; private string? TwoFactorCode; @@ -1907,7 +1926,7 @@ namespace ArchiSteamFarm.Steam { ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorConverting); try { - string json = await Compatibility.File.ReadAllTextAsync(maFilePath).ConfigureAwait(false); + string json = await File.ReadAllTextAsync(maFilePath).ConfigureAwait(false); if (string.IsNullOrEmpty(json)) { ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json))); @@ -2178,7 +2197,7 @@ namespace ArchiSteamFarm.Steam { if (File.Exists(sentryFilePath)) { try { - byte[] sentryFileContent = await Compatibility.File.ReadAllBytesAsync(sentryFilePath).ConfigureAwait(false); + byte[] sentryFileContent = await File.ReadAllBytesAsync(sentryFilePath).ConfigureAwait(false); sentryFileHash = CryptoHelper.SHAHash(sentryFileContent); } catch (Exception e) { ArchiLogger.LogGenericException(e); @@ -3211,7 +3230,7 @@ namespace ArchiSteamFarm.Steam { } try { - await Compatibility.File.AppendAllTextAsync(filePath, logEntry + Environment.NewLine).ConfigureAwait(false); + await File.AppendAllTextAsync(filePath, logEntry + Environment.NewLine).ConfigureAwait(false); } catch (Exception e) { ArchiLogger.LogGenericException(e); ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.Content, logEntry)); diff --git a/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs b/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs index cf4aee73e..a764d1415 100644 --- a/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs +++ b/ArchiSteamFarm/Steam/Cards/CardsFarmer.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Concurrent; @@ -83,7 +83,11 @@ namespace ArchiSteamFarm.Steam.Cards { private readonly SemaphoreSlim FarmingInitializationSemaphore = new(1, 1); private readonly SemaphoreSlim FarmingResetSemaphore = new(0, 1); private readonly ConcurrentList GamesToFarm = new(); + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private readonly Timer? IdleFarmingTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private readonly ConcurrentDictionary LocallyIgnoredAppIDs = new(); private IEnumerable> SourcesOfIgnoredAppIDs { diff --git a/ArchiSteamFarm/Steam/Cards/Game.cs b/ArchiSteamFarm/Steam/Cards/Game.cs index e0b41dc5d..8e167cf15 100644 --- a/ArchiSteamFarm/Steam/Cards/Game.cs +++ b/ArchiSteamFarm/Steam/Cards/Game.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using HashCode = ArchiSteamFarm.Compatibility.HashCode; +using HashCode = JustArchiNET.Madness.HashCodeMadness.HashCode; #endif using System; using Newtonsoft.Json; diff --git a/ArchiSteamFarm/Steam/Exchange/Trading.cs b/ArchiSteamFarm/Steam/Exchange/Trading.cs index 999187407..23bf2e350 100644 --- a/ArchiSteamFarm/Steam/Exchange/Trading.cs +++ b/ArchiSteamFarm/Steam/Exchange/Trading.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Generic; diff --git a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs index 31ed24c8f..facb17bcb 100644 --- a/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs +++ b/ArchiSteamFarm/Steam/Integration/ArchiWebHandler.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Concurrent; @@ -49,7 +49,6 @@ using JetBrains.Annotations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SteamKit2; -using Formatting = Newtonsoft.Json.Formatting; namespace ArchiSteamFarm.Steam.Integration { public sealed class ArchiWebHandler : IDisposable { diff --git a/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs b/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs index 7f6ec4944..d121d5222 100644 --- a/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs +++ b/ArchiSteamFarm/Steam/Integration/SteamChatMessage.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Buffers; diff --git a/ArchiSteamFarm/Steam/Integration/SteamSaleEvent.cs b/ArchiSteamFarm/Steam/Integration/SteamSaleEvent.cs index 02a5df558..31d0c10ef 100644 --- a/ArchiSteamFarm/Steam/Integration/SteamSaleEvent.cs +++ b/ArchiSteamFarm/Steam/Integration/SteamSaleEvent.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Immutable; @@ -36,7 +36,10 @@ namespace ArchiSteamFarm.Steam.Integration { private const byte MaxSingleQueuesDaily = 3; // This is only a failsafe for infinite queue clearing (in case IsDiscoveryQueueAvailable() would fail us) private readonly Bot Bot; + +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private readonly Timer SaleEventTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() internal SteamSaleEvent(Bot bot) { Bot = bot ?? throw new ArgumentNullException(nameof(bot)); diff --git a/ArchiSteamFarm/Steam/Interaction/Actions.cs b/ArchiSteamFarm/Steam/Interaction/Actions.cs index d9bc7eed3..091d25d99 100644 --- a/ArchiSteamFarm/Steam/Interaction/Actions.cs +++ b/ArchiSteamFarm/Steam/Interaction/Actions.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.Collections.Generic; @@ -53,7 +53,10 @@ namespace ArchiSteamFarm.Steam.Interaction { private readonly ConcurrentHashSet HandledGifts = new(); private readonly SemaphoreSlim TradingSemaphore = new(1, 1); +#pragma warning disable CA2213 // False positive, .NET Framework can't understand DisposeAsync() private Timer? CardsFarmerResumeTimer; +#pragma warning restore CA2213 // False positive, .NET Framework can't understand DisposeAsync() + private bool ProcessingGiftsScheduled; private bool TradingScheduled; diff --git a/ArchiSteamFarm/Steam/Interaction/Commands.cs b/ArchiSteamFarm/Steam/Interaction/Commands.cs index f8b01f3a7..b1710c93b 100644 --- a/ArchiSteamFarm/Steam/Interaction/Commands.cs +++ b/ArchiSteamFarm/Steam/Interaction/Commands.cs @@ -19,6 +19,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using JustArchiNET.Madness; +#endif using System; using System.Collections.Generic; using System.Globalization; @@ -27,7 +30,6 @@ using System.Net.Http; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -using ArchiSteamFarm.Compatibility; using ArchiSteamFarm.Core; using ArchiSteamFarm.Helpers; using ArchiSteamFarm.Localization; @@ -3026,7 +3028,7 @@ namespace ArchiSteamFarm.Steam.Interaction { } ushort memoryInMegabytes = (ushort) (GC.GetTotalMemory(false) / 1024 / 1024); - TimeSpan uptime = DateTime.UtcNow.Subtract(StaticHelpers.ProcessStartTime.ToUniversalTime()); + TimeSpan uptime = DateTime.UtcNow.Subtract(OS.ProcessStartTime); return FormatBotResponse(string.Format(CultureInfo.CurrentCulture, Strings.BotStats, memoryInMegabytes, uptime.ToHumanReadable())); } diff --git a/ArchiSteamFarm/Steam/SteamKit2/ServerRecordEndPoint.cs b/ArchiSteamFarm/Steam/SteamKit2/ServerRecordEndPoint.cs index 948d1f037..319ba20af 100644 --- a/ArchiSteamFarm/Steam/SteamKit2/ServerRecordEndPoint.cs +++ b/ArchiSteamFarm/Steam/SteamKit2/ServerRecordEndPoint.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using HashCode = ArchiSteamFarm.Compatibility.HashCode; +using HashCode = JustArchiNET.Madness.HashCodeMadness.HashCode; #endif using System; using System.ComponentModel; diff --git a/ArchiSteamFarm/Steam/Storage/BotConfig.cs b/ArchiSteamFarm/Steam/Storage/BotConfig.cs index 7e618d17c..3f66e29e1 100644 --- a/ArchiSteamFarm/Steam/Storage/BotConfig.cs +++ b/ArchiSteamFarm/Steam/Storage/BotConfig.cs @@ -20,8 +20,8 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; +using JustArchiNET.Madness; +using File = JustArchiNET.Madness.FileMadness.File; #else using System.IO; #endif @@ -452,7 +452,7 @@ namespace ArchiSteamFarm.Steam.Storage { BotConfig? botConfig; try { - json = await Compatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false); + json = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); if (string.IsNullOrEmpty(json)) { ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json))); diff --git a/ArchiSteamFarm/Steam/Storage/BotDatabase.cs b/ArchiSteamFarm/Steam/Storage/BotDatabase.cs index 7a5cda4ba..02bc185c9 100644 --- a/ArchiSteamFarm/Steam/Storage/BotDatabase.cs +++ b/ArchiSteamFarm/Steam/Storage/BotDatabase.cs @@ -19,11 +19,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using File = JustArchiNET.Madness.FileMadness.File; +#else +using System.IO; +#endif using System; using System.Collections; using System.Collections.Specialized; using System.Globalization; -using System.IO; using System.Linq; using System.Threading.Tasks; using ArchiSteamFarm.Collections; @@ -155,7 +159,7 @@ namespace ArchiSteamFarm.Steam.Storage { BotDatabase? botDatabase; try { - string json = await Compatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false); + string json = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); if (string.IsNullOrEmpty(json)) { ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json))); diff --git a/ArchiSteamFarm/Storage/GlobalConfig.cs b/ArchiSteamFarm/Storage/GlobalConfig.cs index 17deae72b..6e56b3429 100644 --- a/ArchiSteamFarm/Storage/GlobalConfig.cs +++ b/ArchiSteamFarm/Storage/GlobalConfig.cs @@ -19,13 +19,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using File = JustArchiNET.Madness.FileMadness.File; +#else +using System.IO; +#endif using System; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.IO; using System.Net; using System.Threading.Tasks; using ArchiSteamFarm.Core; @@ -378,7 +382,7 @@ namespace ArchiSteamFarm.Storage { GlobalConfig? globalConfig; try { - json = await Compatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false); + json = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); if (string.IsNullOrEmpty(json)) { ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json))); diff --git a/ArchiSteamFarm/Storage/GlobalDatabase.cs b/ArchiSteamFarm/Storage/GlobalDatabase.cs index fe592c5d0..197137eac 100644 --- a/ArchiSteamFarm/Storage/GlobalDatabase.cs +++ b/ArchiSteamFarm/Storage/GlobalDatabase.cs @@ -20,8 +20,8 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; -using File = System.IO.File; +using JustArchiNET.Madness; +using File = JustArchiNET.Madness.FileMadness.File; #else using System.IO; #endif @@ -188,7 +188,7 @@ namespace ArchiSteamFarm.Storage { GlobalDatabase? globalDatabase; try { - string json = await Compatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false); + string json = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); if (string.IsNullOrEmpty(json)) { ASF.ArchiLogger.LogGenericError(string.Format(CultureInfo.CurrentCulture, Strings.ErrorIsEmpty, nameof(json))); diff --git a/ArchiSteamFarm/Web/Responses/StreamResponse.cs b/ArchiSteamFarm/Web/Responses/StreamResponse.cs index e1c72e28e..1535fbd2d 100644 --- a/ArchiSteamFarm/Web/Responses/StreamResponse.cs +++ b/ArchiSteamFarm/Web/Responses/StreamResponse.cs @@ -20,7 +20,7 @@ // limitations under the License. #if NETFRAMEWORK -using ArchiSteamFarm.Compatibility; +using JustArchiNET.Madness; #endif using System; using System.IO; diff --git a/ArchiSteamFarm/Web/WebBrowser.cs b/ArchiSteamFarm/Web/WebBrowser.cs index bb653b9af..b1a6b1e49 100644 --- a/ArchiSteamFarm/Web/WebBrowser.cs +++ b/ArchiSteamFarm/Web/WebBrowser.cs @@ -19,6 +19,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#if NETFRAMEWORK +using JustArchiNET.Madness; +#endif using System; using System.Buffers; using System.Collections.Generic; @@ -31,7 +34,6 @@ using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Xml; -using ArchiSteamFarm.Compatibility; using ArchiSteamFarm.Core; using ArchiSteamFarm.Localization; using ArchiSteamFarm.NLog; @@ -79,9 +81,13 @@ namespace ArchiSteamFarm.Web { HttpClientHandler.UseProxy = true; } - if (!StaticHelpers.IsRunningOnMono) { +#if NETFRAMEWORK + if (!RuntimeMadness.IsRunningOnMono) { HttpClientHandler.MaxConnectionsPerServer = MaxConnections; } +#else + HttpClientHandler.MaxConnectionsPerServer = MaxConnections; +#endif HttpClient = GenerateDisposableHttpClient(extendedTimeout); } @@ -714,9 +720,13 @@ namespace ArchiSteamFarm.Web { ServicePointManager.Expect100Continue = false; // Reuse ports if possible - if (!StaticHelpers.IsRunningOnMono) { +#if NETFRAMEWORK + if (!RuntimeMadness.IsRunningOnMono) { ServicePointManager.ReusePort = true; } +#else + ServicePointManager.ReusePort = true; +#endif } private async Task InternalGet(Uri request, IReadOnlyCollection>? headers = null, Uri? referer = null, ERequestOptions requestOptions = ERequestOptions.None, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) { diff --git a/Directory.Packages.props b/Directory.Packages.props index f43d3752a..04c3ab5cc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -29,6 +29,7 @@ +