diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5ee55c876..5a2142773 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,8 +6,8 @@ env:
CONFIGURATION: Release
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_NOLOGO: 1
- DOTNET_SDK_VERSION: 3.1
- NET_CORE_VERSION: netcoreapp3.1
+ DOTNET_SDK_VERSION: 5.0.100
+ NET_CORE_VERSION: net5.0
NET_FRAMEWORK_VERSION: net48
NODE_JS_VERSION: 12
STEAM_TOKEN_DUMPER_NAME: ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
diff --git a/.travis.yml b/.travis.yml
index 314895d71..354e15e7d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@ git:
depth: 10
# ASF is based on .NET Core platform, we're not building with Mono
-dotnet: 3.1
+dotnet: 5.0
mono: none
env:
@@ -15,7 +15,7 @@ env:
- CONFIGURATION: Release
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
- DOTNET_NOLOGO: 1
- - NET_CORE_VERSION: netcoreapp3.1
+ - NET_CORE_VERSION: net5.0
- STEAM_TOKEN_DUMPER_NAME: ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
- VARIANTS="generic linux-arm linux-arm64 linux-x64 osx-x64 win-x64" # NOTE: When modifying variants, don't forget to update ASF_VARIANT definitions in SharedInfo.cs!
addons:
@@ -100,6 +100,8 @@ script:
set +u # This is needed to continue Travis build
matrix:
+ allow_failures:
+ - os: osx
# We can use fast finish, as we don't need to wait for allow_failures builds to mark build as success
fast_finish: true
include:
@@ -110,5 +112,5 @@ matrix:
dist: bionic
- os: osx
# Ref: https://docs.travis-ci.com/user/reference/osx
- dotnet: 3.1.300 # For OSX, we need absolute dotnet version until https://github.com/dotnet/core-setup/issues/4187 is resolved
+ dotnet: 5.0.100 # For OSX, we need absolute dotnet version until https://github.com/dotnet/core-setup/issues/4187 is resolved
osx_image: xcode11.4
diff --git a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj
index ce8e5e1d8..775e64a53 100644
--- a/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj
+++ b/ArchiSteamFarm.CustomPlugins.ExamplePlugin/ArchiSteamFarm.CustomPlugins.ExamplePlugin.csproj
@@ -7,8 +7,6 @@
all
-
-
diff --git a/ArchiSteamFarm.CustomPlugins.PeriodicGC/ArchiSteamFarm.CustomPlugins.PeriodicGC.csproj b/ArchiSteamFarm.CustomPlugins.PeriodicGC/ArchiSteamFarm.CustomPlugins.PeriodicGC.csproj
index c59fa5c3c..775e64a53 100644
--- a/ArchiSteamFarm.CustomPlugins.PeriodicGC/ArchiSteamFarm.CustomPlugins.PeriodicGC.csproj
+++ b/ArchiSteamFarm.CustomPlugins.PeriodicGC/ArchiSteamFarm.CustomPlugins.PeriodicGC.csproj
@@ -7,7 +7,6 @@
all
-
diff --git a/ArchiSteamFarm/ASF.cs b/ArchiSteamFarm/ASF.cs
index fc78cf226..f5599f2ed 100644
--- a/ArchiSteamFarm/ASF.cs
+++ b/ArchiSteamFarm/ASF.cs
@@ -27,6 +27,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
+using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
@@ -337,7 +338,7 @@ namespace ArchiSteamFarm {
return null;
}
- if (OS.IsUnix) {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
string executable = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.AssemblyName);
if (File.Exists(executable)) {
@@ -436,6 +437,10 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(sender) + " || " + nameof(e));
}
+ if (string.IsNullOrEmpty(e.Name)) {
+ throw new ArgumentNullException(nameof(e.Name));
+ }
+
await OnChangedFile(e.Name, e.FullPath).ConfigureAwait(false);
}
@@ -498,6 +503,10 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(sender) + " || " + nameof(e));
}
+ if (string.IsNullOrEmpty(e.Name)) {
+ throw new ArgumentNullException(nameof(e.Name));
+ }
+
await OnCreatedFile(e.Name, e.FullPath).ConfigureAwait(false);
}
@@ -604,6 +613,10 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(sender) + " || " + nameof(e));
}
+ if (string.IsNullOrEmpty(e.Name)) {
+ throw new ArgumentNullException(nameof(e.Name));
+ }
+
await OnDeletedFile(e.Name, e.FullPath).ConfigureAwait(false);
}
@@ -700,6 +713,10 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(sender) + " || " + nameof(e));
}
+ if (string.IsNullOrEmpty(e.OldName) || string.IsNullOrEmpty(e.Name)) {
+ throw new ArgumentNullException(nameof(e.OldName) + " || " + nameof(e.Name));
+ }
+
await OnDeletedFile(e.OldName, e.OldFullPath).ConfigureAwait(false);
await OnCreatedFile(e.Name, e.FullPath).ConfigureAwait(false);
}
diff --git a/ArchiSteamFarm/Actions.cs b/ArchiSteamFarm/Actions.cs
index 50ae5ca37..f617339ba 100644
--- a/ArchiSteamFarm/Actions.cs
+++ b/ArchiSteamFarm/Actions.cs
@@ -460,7 +460,7 @@ namespace ArchiSteamFarm {
internal void OnDisconnected() => HandledGifts.Clear();
private ulong GetFirstSteamMasterID() {
- ulong steamMasterID = Bot.BotConfig.SteamUserPermissions.Where(kv => (kv.Key > 0) && (kv.Key != Bot.SteamID) && new SteamID(kv.Key).IsIndividualAccount && (kv.Value == BotConfig.EPermission.Master)).Select(kv => kv.Key).OrderBy(steamID => steamID).FirstOrDefault();
+ ulong steamMasterID = Bot.BotConfig.SteamUserPermissions.Where(kv => (kv.Key > 0) && (kv.Key != Bot.SteamID) && new SteamID(kv.Key).IsIndividualAccount && (kv.Value == BotConfig.EPermission.Master)).Select(kv => kv.Key).OrderBy(steamID => steamID).FirstOrDefault()!;
if (steamMasterID > 0) {
return steamMasterID;
diff --git a/ArchiSteamFarm/ArchiCryptoHelper.cs b/ArchiSteamFarm/ArchiCryptoHelper.cs
index 7a3b19656..57cb97a04 100644
--- a/ArchiSteamFarm/ArchiCryptoHelper.cs
+++ b/ArchiSteamFarm/ArchiCryptoHelper.cs
@@ -22,6 +22,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using CryptSharp.Utility;
@@ -152,6 +153,10 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(encrypted));
}
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ return null;
+ }
+
try {
byte[] decryptedData = ProtectedData.Unprotect(
Convert.FromBase64String(encrypted),
@@ -160,10 +165,6 @@ namespace ArchiSteamFarm {
);
return Encoding.UTF8.GetString(decryptedData);
- } catch (PlatformNotSupportedException e) {
- ASF.ArchiLogger.LogGenericWarningException(e);
-
- return null;
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
@@ -199,6 +200,10 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(decrypted));
}
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ return null;
+ }
+
try {
byte[] encryptedData = ProtectedData.Protect(
Encoding.UTF8.GetBytes(decrypted),
@@ -207,10 +212,6 @@ namespace ArchiSteamFarm {
);
return Convert.ToBase64String(encryptedData);
- } catch (PlatformNotSupportedException e) {
- ASF.ArchiLogger.LogGenericWarningException(e);
-
- return null;
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj
index c98e8e32d..471561b8d 100644
--- a/ArchiSteamFarm/ArchiSteamFarm.csproj
+++ b/ArchiSteamFarm/ArchiSteamFarm.csproj
@@ -6,13 +6,6 @@
Exe
-
-
-
-
-
-
-
@@ -34,8 +27,7 @@
-
-
+
diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs
index 8abc2b724..0449bc8c6 100644
--- a/ArchiSteamFarm/ArchiWebHandler.cs
+++ b/ArchiSteamFarm/ArchiWebHandler.cs
@@ -166,7 +166,7 @@ namespace ArchiSteamFarm {
Dictionary<(ulong ClassID, ulong InstanceID), Steam.InventoryResponse.Description> descriptions = new Dictionary<(ulong ClassID, ulong InstanceID), Steam.InventoryResponse.Description>();
- foreach (Steam.InventoryResponse.Description description in response.Content.Descriptions.Where(description => description != null)) {
+ foreach (Steam.InventoryResponse.Description description in response.Content.Descriptions) {
if (description.ClassID == 0) {
throw new NotSupportedException(string.Format(Strings.ErrorObjectIsNull, nameof(description.ClassID)));
}
@@ -180,7 +180,7 @@ namespace ArchiSteamFarm {
descriptions[key] = description;
}
- foreach (Steam.Asset asset in response.Content.Assets.Where(asset => asset != null)) {
+ foreach (Steam.Asset asset in response.Content.Assets) {
if (!descriptions.TryGetValue((asset.ClassID, asset.InstanceID), out Steam.InventoryResponse.Description? description) || assetIDs.Contains(asset.AssetID)) {
continue;
}
diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs
index a91b976ce..db15c2c0b 100755
--- a/ArchiSteamFarm/Bot.cs
+++ b/ArchiSteamFarm/Bot.cs
@@ -2691,7 +2691,7 @@ namespace ArchiSteamFarm {
using SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
- sentryHash = sha.ComputeHash(fileStream);
+ sentryHash = await sha.ComputeHashAsync(fileStream).ConfigureAwait(false);
} catch (Exception e) {
ArchiLogger.LogGenericException(e);
diff --git a/ArchiSteamFarm/BotDatabase.cs b/ArchiSteamFarm/BotDatabase.cs
index e0ff63771..956bd31d1 100644
--- a/ArchiSteamFarm/BotDatabase.cs
+++ b/ArchiSteamFarm/BotDatabase.cs
@@ -124,7 +124,7 @@ namespace ArchiSteamFarm {
bool save = false;
lock (GamesToRedeemInBackground) {
- foreach (DictionaryEntry game in games.Cast().Where(game => !GamesToRedeemInBackground.Contains(game.Key))) {
+ foreach (DictionaryEntry game in games.OfType().Where(game => !GamesToRedeemInBackground.Contains(game.Key))) {
GamesToRedeemInBackground.Add(game.Key, game.Value);
save = true;
}
diff --git a/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs b/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs
index e0770e722..581cefbac 100644
--- a/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs
+++ b/ArchiSteamFarm/Helpers/CrossProcessFileBasedSemaphore.cs
@@ -22,6 +22,7 @@
using System;
using System.Diagnostics;
using System.IO;
+using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Threading;
using System.Threading.Tasks;
@@ -161,9 +162,7 @@ namespace ArchiSteamFarm.Helpers {
if (!Directory.Exists(directoryPath)) {
Directory.CreateDirectory(directoryPath!);
- if (OS.IsUnix) {
- OS.UnixSetFileAccess(directoryPath!, OS.EUnixPermission.Combined777);
- } else {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath!);
try {
@@ -174,15 +173,15 @@ namespace ArchiSteamFarm.Helpers {
// Non-critical, user might have no rights to manage the resource
ASF.ArchiLogger.LogGenericDebuggingException(e);
}
+ } else {
+ OS.UnixSetFileAccess(directoryPath!, OS.EUnixPermission.Combined777);
}
}
try {
using (new FileStream(FilePath, FileMode.CreateNew)) { }
- if (OS.IsUnix) {
- OS.UnixSetFileAccess(FilePath, OS.EUnixPermission.Combined777);
- } else {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
FileInfo fileInfo = new FileInfo(FilePath);
try {
@@ -193,6 +192,8 @@ namespace ArchiSteamFarm.Helpers {
// Non-critical, user might have no rights to manage the resource
ASF.ArchiLogger.LogGenericDebuggingException(e);
}
+ } else {
+ OS.UnixSetFileAccess(FilePath, OS.EUnixPermission.Combined777);
}
} catch (IOException) {
// Ignored, if the file was already created in the meantime by another instance, this is fine
diff --git a/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs b/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs
index a2bd25abb..9b38a3130 100644
--- a/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs
+++ b/ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs
@@ -86,7 +86,11 @@ namespace ArchiSteamFarm.IPC.Integration {
return HttpStatusCode.OK;
}
- IPAddress clientIP = context.Connection.RemoteIpAddress;
+ IPAddress? clientIP = context.Connection.RemoteIpAddress;
+
+ if (clientIP == null) {
+ throw new ArgumentNullException(nameof(context.Connection.RemoteIpAddress));
+ }
if (FailedAuthorizations.TryGetValue(clientIP, out byte attempts)) {
if (attempts >= MaxFailedAuthorizationAttempts) {
diff --git a/ArchiSteamFarm/OS.cs b/ArchiSteamFarm/OS.cs
index e2f557dfc..52f1b76d0 100644
--- a/ArchiSteamFarm/OS.cs
+++ b/ArchiSteamFarm/OS.cs
@@ -35,15 +35,12 @@ namespace ArchiSteamFarm {
// We need to keep this one assigned and not calculated on-demand
internal static readonly string ProcessFileName = Process.GetCurrentProcess().MainModule?.FileName ?? throw new ArgumentNullException(nameof(ProcessFileName));
- internal static bool IsUnix => RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
internal static string Variant => RuntimeInformation.OSDescription.Trim();
- private static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
-
private static Mutex? SingleInstance;
internal static void CoreInit() {
- if (IsWindows && !Console.IsOutputRedirected) {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !Console.IsOutputRedirected) {
// Normally we should use UTF-8 encoding as it's the most correct one for our case, and we already use it on other OSes such as Linux
// However, older Windows versions, mainly 7/8.1 can't into UTF-8 without appropriate console font, and expecting from users to change it manually is unwanted
// As irrational as it can sound, those versions actually can work with unicode encoding instead, as they magically map it into proper chars despite of incorrect font
@@ -74,7 +71,7 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(optimizationMode));
}
- if (IsWindows) {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
if (systemRequired) {
WindowsKeepSystemActive();
}
@@ -126,7 +123,7 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(path));
}
- if (!IsUnix) {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
return;
}
@@ -162,7 +159,7 @@ namespace ArchiSteamFarm {
}
private static void WindowsDisableQuickEditMode() {
- if (!IsWindows) {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
return;
}
@@ -182,7 +179,7 @@ namespace ArchiSteamFarm {
}
private static void WindowsKeepSystemActive() {
- if (!IsWindows) {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
return;
}
diff --git a/ArchiSteamFarm/Plugins/PluginsCore.cs b/ArchiSteamFarm/Plugins/PluginsCore.cs
index f7c609fb2..2972ab973 100644
--- a/ArchiSteamFarm/Plugins/PluginsCore.cs
+++ b/ArchiSteamFarm/Plugins/PluginsCore.cs
@@ -56,7 +56,7 @@ namespace ArchiSteamFarm.Plugins {
return StringComparer.Ordinal;
}
- StringComparer? result = results.FirstOrDefault(comparer => comparer != null);
+ StringComparer? result = results.FirstOrDefault();
return result ?? StringComparer.Ordinal;
}
@@ -427,7 +427,7 @@ namespace ArchiSteamFarm.Plugins {
return null;
}
- return responses.Where(response => response != null).SelectMany(handler => handler).Where(handler => handler != null).ToHashSet();
+ return responses.Where(response => response != null).SelectMany(handlers => handlers ?? Enumerable.Empty()).ToHashSet();
}
internal static async Task OnBotTradeOffer(Bot bot, Steam.TradeOffer tradeOffer) {
diff --git a/ArchiSteamFarm/RuntimeCompatibility.cs b/ArchiSteamFarm/RuntimeCompatibility.cs
index 2922a9e03..7bb480a20 100644
--- a/ArchiSteamFarm/RuntimeCompatibility.cs
+++ b/ArchiSteamFarm/RuntimeCompatibility.cs
@@ -27,7 +27,9 @@ using JetBrains.Annotations;
#if NETFRAMEWORK
using Microsoft.AspNetCore.Hosting;
using System.Collections.Generic;
+using System.IO;
using System.Net.WebSockets;
+using System.Security.Cryptography;
using System.Threading;
#endif
@@ -135,6 +137,8 @@ namespace ArchiSteamFarm {
}
#if NETFRAMEWORK
+ internal static Task ComputeHashAsync(this HashAlgorithm hashAlgorithm, Stream inputStream) => Task.FromResult(hashAlgorithm.ComputeHash(inputStream));
+
internal static IWebHostBuilder ConfigureWebHostDefaults(this IWebHostBuilder builder, Action configure) {
configure(builder);
diff --git a/ArchiSteamFarm/Utilities.cs b/ArchiSteamFarm/Utilities.cs
index e1f7041f4..bb1fa5bf2 100644
--- a/ArchiSteamFarm/Utilities.cs
+++ b/ArchiSteamFarm/Utilities.cs
@@ -217,10 +217,10 @@ namespace ArchiSteamFarm {
}
[PublicAPI]
- public static List SelectElementNodes(this IElement element, string xpath) => element.SelectNodes(xpath).Cast().ToList();
+ public static List SelectElementNodes(this IElement element, string xpath) => element.SelectNodes(xpath).OfType().ToList();
[PublicAPI]
- public static List SelectNodes(this IDocument document, string xpath) => document.Body.SelectNodes(xpath).Cast().ToList();
+ public static List SelectNodes(this IDocument document, string xpath) => document.Body.SelectNodes(xpath).OfType().ToList();
[PublicAPI]
public static IElement? SelectSingleElementNode(this IElement element, string xpath) => (IElement?) element.SelectSingleNode(xpath);
diff --git a/ArchiSteamFarm/WebBrowser.cs b/ArchiSteamFarm/WebBrowser.cs
index 1f6a0408e..74913e89a 100644
--- a/ArchiSteamFarm/WebBrowser.cs
+++ b/ArchiSteamFarm/WebBrowser.cs
@@ -361,32 +361,24 @@ namespace ArchiSteamFarm {
continue;
}
- bool handleError = false;
-
if (response.StatusCode.IsClientErrorCode()) {
if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) {
// We're not handling this error, do not try again
break;
}
- handleError = true;
- } else if (response.StatusCode.IsServerErrorCode()) {
+ // We're handling this error, the content isn't available, deal with it
+ return new StreamResponse(response);
+ }
+
+ if (response.StatusCode.IsServerErrorCode()) {
if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) {
// We're not handling this error, try again
continue;
}
- handleError = true;
- }
-
- if (response.Content == null) {
- if (handleError) {
- // We're handling this error, the content isn't available, deal with it
- return new StreamResponse(response);
- }
-
- // The content isn't available and it's not an error, try again
- continue;
+ // We're handling this error, the content isn't available, deal with it
+ return new StreamResponse(response);
}
return new StreamResponse(response, await response.Content.ReadAsStreamAsync().ConfigureAwait(false));
@@ -416,32 +408,24 @@ namespace ArchiSteamFarm {
continue;
}
- bool handleError = false;
-
if (response.StatusCode.IsClientErrorCode()) {
if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) {
// We're not handling this error, do not try again
break;
}
- handleError = true;
- } else if (response.StatusCode.IsServerErrorCode()) {
+ // We're handling this error, the content isn't available, deal with it
+ return new StringResponse(response);
+ }
+
+ if (response.StatusCode.IsServerErrorCode()) {
if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) {
// We're not handling this error, try again
continue;
}
- handleError = true;
- }
-
- if (response.Content == null) {
- if (handleError) {
- // We're handling this error, the content isn't available, deal with it
- return new StringResponse(response);
- }
-
- // The content isn't available and it's not an error, try again
- continue;
+ // We're handling this error, the content isn't available, deal with it
+ return new StringResponse(response);
}
return new StringResponse(response, await response.Content.ReadAsStringAsync().ConfigureAwait(false));
@@ -758,32 +742,24 @@ namespace ArchiSteamFarm {
continue;
}
- bool handleError = false;
-
if (response.StatusCode.IsClientErrorCode()) {
if (!requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) {
// We're not handling this error, do not try again
break;
}
- handleError = true;
- } else if (response.StatusCode.IsServerErrorCode()) {
+ // We're handling this error, the content isn't available, deal with it
+ return new StreamResponse(response);
+ }
+
+ if (response.StatusCode.IsServerErrorCode()) {
if (!requestOptions.HasFlag(ERequestOptions.ReturnServerErrors)) {
// We're not handling this error, try again
continue;
}
- handleError = true;
- }
-
- if (response.Content == null) {
- if (handleError) {
- // We're handling this error, the content isn't available, deal with it
- return new StreamResponse(response);
- }
-
- // The content isn't available and it's not an error, try again
- continue;
+ // We're handling this error, the content isn't available, deal with it
+ return new StreamResponse(response);
}
return new StreamResponse(response, await response.Content.ReadAsStreamAsync().ConfigureAwait(false));
@@ -861,7 +837,7 @@ namespace ArchiSteamFarm {
request.Content = content;
break;
- case IReadOnlyCollection> dictionary:
+ case IReadOnlyCollection> dictionary:
try {
request.Content = new FormUrlEncodedContent(dictionary);
} catch (UriFormatException) {
@@ -920,7 +896,13 @@ namespace ArchiSteamFarm {
// WARNING: We still have not disposed response by now, make sure to dispose it ASAP if we're not returning it!
if ((response.StatusCode >= HttpStatusCode.Ambiguous) && (response.StatusCode < HttpStatusCode.BadRequest) && (maxRedirections > 0)) {
- Uri redirectUri = response.Headers.Location;
+ Uri? redirectUri = response.Headers.Location;
+
+ if (redirectUri == null) {
+ ArchiLogger.LogNullError(nameof(redirectUri));
+
+ return null;
+ }
if (redirectUri.IsAbsoluteUri) {
switch (redirectUri.Scheme) {
@@ -1002,7 +984,7 @@ namespace ArchiSteamFarm {
throw new ArgumentNullException(nameof(httpResponseMessage));
}
- FinalUri = httpResponseMessage.Headers.Location ?? httpResponseMessage.RequestMessage.RequestUri;
+ FinalUri = httpResponseMessage.Headers.Location ?? httpResponseMessage.RequestMessage?.RequestUri ?? throw new ArgumentNullException(nameof(FinalUri));
StatusCode = httpResponseMessage.StatusCode;
}
diff --git a/ArchiSteamFarm/overlay/linux-arm/ArchiSteamFarm-Service.sh b/ArchiSteamFarm/overlay/linux-arm/ArchiSteamFarm-Service.sh
index 48c49dcf5..307365d65 100755
--- a/ArchiSteamFarm/overlay/linux-arm/ArchiSteamFarm-Service.sh
+++ b/ArchiSteamFarm/overlay/linux-arm/ArchiSteamFarm-Service.sh
@@ -62,28 +62,6 @@ CONFIG_PATH="$(pwd)/${CONFIG_PATH}"
# Kill underlying ASF process on shell process exit
trap "trap - TERM && kill -- -$$" INT TERM
-# TODO: Workaround for https://github.com/JustArchiNET/ArchiSteamFarm/issues/1812
-if [ -n "${DOTNET_RUNNING_IN_CONTAINER-}" ] && [ "$DOTNET_RUNNING_IN_CONTAINER" = "true" ]; then
- (
- loops=6 # Maximum of 60 seconds for unpack
-
- while [ "$loops" -gt 0 ]; do
- sleep 10
-
- if [ -d "/var/tmp/.net" ]; then
- find "/var/tmp/.net" -mindepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
- fixed_path="$(echo "$broken_path" | sed 's/\\/\//g')"
-
- mkdir -p "$(dirname "$fixed_path")"
- mv "$broken_path" "$fixed_path"
- done
- fi
-
- loops="$((loops-1))"
- done
- ) &
-fi
-
while :; do
if [ -f "$CONFIG_PATH" ] && grep -Eq '"Headless":\s+?true' "$CONFIG_PATH"; then
# We're running ASF in headless mode so we don't need STDIN
diff --git a/ArchiSteamFarm/overlay/linux-arm64/ArchiSteamFarm-Service.sh b/ArchiSteamFarm/overlay/linux-arm64/ArchiSteamFarm-Service.sh
index 48c49dcf5..307365d65 100755
--- a/ArchiSteamFarm/overlay/linux-arm64/ArchiSteamFarm-Service.sh
+++ b/ArchiSteamFarm/overlay/linux-arm64/ArchiSteamFarm-Service.sh
@@ -62,28 +62,6 @@ CONFIG_PATH="$(pwd)/${CONFIG_PATH}"
# Kill underlying ASF process on shell process exit
trap "trap - TERM && kill -- -$$" INT TERM
-# TODO: Workaround for https://github.com/JustArchiNET/ArchiSteamFarm/issues/1812
-if [ -n "${DOTNET_RUNNING_IN_CONTAINER-}" ] && [ "$DOTNET_RUNNING_IN_CONTAINER" = "true" ]; then
- (
- loops=6 # Maximum of 60 seconds for unpack
-
- while [ "$loops" -gt 0 ]; do
- sleep 10
-
- if [ -d "/var/tmp/.net" ]; then
- find "/var/tmp/.net" -mindepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
- fixed_path="$(echo "$broken_path" | sed 's/\\/\//g')"
-
- mkdir -p "$(dirname "$fixed_path")"
- mv "$broken_path" "$fixed_path"
- done
- fi
-
- loops="$((loops-1))"
- done
- ) &
-fi
-
while :; do
if [ -f "$CONFIG_PATH" ] && grep -Eq '"Headless":\s+?true' "$CONFIG_PATH"; then
# We're running ASF in headless mode so we don't need STDIN
diff --git a/ArchiSteamFarm/overlay/linux-x64/ArchiSteamFarm-Service.sh b/ArchiSteamFarm/overlay/linux-x64/ArchiSteamFarm-Service.sh
index 48c49dcf5..307365d65 100755
--- a/ArchiSteamFarm/overlay/linux-x64/ArchiSteamFarm-Service.sh
+++ b/ArchiSteamFarm/overlay/linux-x64/ArchiSteamFarm-Service.sh
@@ -62,28 +62,6 @@ CONFIG_PATH="$(pwd)/${CONFIG_PATH}"
# Kill underlying ASF process on shell process exit
trap "trap - TERM && kill -- -$$" INT TERM
-# TODO: Workaround for https://github.com/JustArchiNET/ArchiSteamFarm/issues/1812
-if [ -n "${DOTNET_RUNNING_IN_CONTAINER-}" ] && [ "$DOTNET_RUNNING_IN_CONTAINER" = "true" ]; then
- (
- loops=6 # Maximum of 60 seconds for unpack
-
- while [ "$loops" -gt 0 ]; do
- sleep 10
-
- if [ -d "/var/tmp/.net" ]; then
- find "/var/tmp/.net" -mindepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
- fixed_path="$(echo "$broken_path" | sed 's/\\/\//g')"
-
- mkdir -p "$(dirname "$fixed_path")"
- mv "$broken_path" "$fixed_path"
- done
- fi
-
- loops="$((loops-1))"
- done
- ) &
-fi
-
while :; do
if [ -f "$CONFIG_PATH" ] && grep -Eq '"Headless":\s+?true' "$CONFIG_PATH"; then
# We're running ASF in headless mode so we don't need STDIN
diff --git a/Directory.Build.props b/Directory.Build.props
index a6dfdc8e1..9d0207523 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,6 @@
- 4.3.1.4
+ 5.0.0.0
@@ -36,10 +36,10 @@
- netcoreapp3.1;net48
+ net5.0;net48
- netcoreapp3.1
+ net5.0
diff --git a/Dockerfile b/Dockerfile
index f053f11ea..e16572efd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,13 +8,13 @@ RUN echo "node: $(node --version)" && \
npm ci && \
npm run deploy
-FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
+FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-dotnet
ARG ASF_ARCH=x64
ARG STEAM_TOKEN_DUMPER_TOKEN
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_NOLOGO 1
-ENV NET_CORE_VERSION netcoreapp3.1
+ENV NET_CORE_VERSION net5.0
ENV STEAM_TOKEN_DUMPER_NAME ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -33,7 +33,7 @@ RUN dotnet --info && \
if [ -d "ArchiSteamFarm/overlay/generic" ]; then cp "ArchiSteamFarm/overlay/generic/"* "out/result"; fi && \
if [ -f "out/${STEAM_TOKEN_DUMPER_NAME}/${NET_CORE_VERSION}/${STEAM_TOKEN_DUMPER_NAME}.dll" ]; then mkdir -p "out/result/plugins/${STEAM_TOKEN_DUMPER_NAME}"; cp "out/${STEAM_TOKEN_DUMPER_NAME}/${NET_CORE_VERSION}/${STEAM_TOKEN_DUMPER_NAME}.dll" "out/result/plugins/${STEAM_TOKEN_DUMPER_NAME}"; fi
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim${DOTNET_ARCH} AS runtime
+FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim${DOTNET_ARCH} AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_NOLOGO 1
diff --git a/Dockerfile.Service b/Dockerfile.Service
index 9bea7a6f4..dac3123a1 100644
--- a/Dockerfile.Service
+++ b/Dockerfile.Service
@@ -8,13 +8,13 @@ RUN echo "node: $(node --version)" && \
npm ci && \
npm run deploy
-FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
+FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-dotnet
ARG ASF_ARCH=x64
ARG STEAM_TOKEN_DUMPER_TOKEN
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_NOLOGO 1
-ENV NET_CORE_VERSION netcoreapp3.1
+ENV NET_CORE_VERSION net5.0
ENV STEAM_TOKEN_DUMPER_NAME ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -33,7 +33,7 @@ RUN dotnet --info && \
if [ -d "ArchiSteamFarm/overlay/linux-${ASF_ARCH}" ]; then cp "ArchiSteamFarm/overlay/linux-${ASF_ARCH}/"* "out/result"; fi && \
if [ -f "out/${STEAM_TOKEN_DUMPER_NAME}/${NET_CORE_VERSION}/${STEAM_TOKEN_DUMPER_NAME}.dll" ]; then mkdir -p "out/result/plugins/${STEAM_TOKEN_DUMPER_NAME}"; cp "out/${STEAM_TOKEN_DUMPER_NAME}/${NET_CORE_VERSION}/${STEAM_TOKEN_DUMPER_NAME}.dll" "out/result/plugins/${STEAM_TOKEN_DUMPER_NAME}"; fi
-FROM mcr.microsoft.com/dotnet/core/runtime-deps:3.1-buster-slim${DOTNET_ARCH} AS runtime
+FROM mcr.microsoft.com/dotnet/runtime-deps:5.0-buster-slim${DOTNET_ARCH} AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_NOLOGO 1
diff --git a/appveyor.yml b/appveyor.yml
index 47f0169fc..5d17ea22a 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,11 +6,12 @@ image: Visual Studio 2019
configuration: Release
clone_depth: 10
environment:
- DOTNET_CHANNEL: 3.1
+# DOTNET_CHANNEL: 5.0
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_INSTALL_DIR: C:\Program Files\dotnet
DOTNET_NOLOGO: true
- NET_CORE_VERSION: netcoreapp3.1
+ DOTNET_SDK: 5.0.100
+ NET_CORE_VERSION: net5.0
NET_FRAMEWORK_VERSION: net48
NODE_JS_VERSION: lts
STEAM_TOKEN_DUMPER_NAME: ArchiSteamFarm.OfficialPlugins.SteamTokenDumper
@@ -51,6 +52,13 @@ install:
&([scriptblock]::Create((Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1'))) -Channel "$env:DOTNET_CHANNEL" -InstallDir "$env:DOTNET_INSTALL_DIR" -NoPath
}
+
+
+ if ($env:DOTNET_SDK) {
+ dotnet --info
+
+ &([scriptblock]::Create((Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 'Current' -Version "$env:DOTNET_SDK" -InstallDir "$env:DOTNET_INSTALL_DIR" -NoPath
+ }
- ps: Install-Product node "$env:NODE_JS_VERSION"
before_build:
- pwsh: >-
diff --git a/cc.sh b/cc.sh
index 0d91bc243..6324bbba8 100755
--- a/cc.sh
+++ b/cc.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
set -eu
-TARGET_FRAMEWORK="netcoreapp3.1"
+TARGET_FRAMEWORK="net5.0"
MAIN_PROJECT="ArchiSteamFarm"
STEAM_TOKEN_DUMPER_NAME="${MAIN_PROJECT}.OfficialPlugins.SteamTokenDumper"