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 @@
+