mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-06 17:10:13 +00:00
async/dispose code review
This commit is contained in:
@@ -86,6 +86,7 @@ namespace ArchiSteamFarm {
|
|||||||
PublicInventorySemaphore.Dispose();
|
PublicInventorySemaphore.Dispose();
|
||||||
SessionSemaphore.Dispose();
|
SessionSemaphore.Dispose();
|
||||||
TradeTokenSemaphore.Dispose();
|
TradeTokenSemaphore.Dispose();
|
||||||
|
WebBrowser.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<bool> AcceptTradeOffer(ulong tradeID) {
|
internal async Task<bool> AcceptTradeOffer(ulong tradeID) {
|
||||||
|
|||||||
@@ -231,22 +231,24 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
// Those are objects that are always being created if constructor doesn't throw exception
|
// Those are objects that are always being created if constructor doesn't throw exception
|
||||||
ArchiWebHandler.Dispose();
|
|
||||||
CallbackSemaphore.Dispose();
|
CallbackSemaphore.Dispose();
|
||||||
CardsFarmer.Dispose();
|
|
||||||
HeartBeatTimer.Dispose();
|
|
||||||
InitializationSemaphore.Dispose();
|
InitializationSemaphore.Dispose();
|
||||||
LootingSemaphore.Dispose();
|
LootingSemaphore.Dispose();
|
||||||
PICSSemaphore.Dispose();
|
PICSSemaphore.Dispose();
|
||||||
Trading.Dispose();
|
|
||||||
|
|
||||||
// Those are objects that might be null and the check should be in-place
|
// Those are objects that might be null and the check should be in-place
|
||||||
|
ArchiWebHandler?.Dispose();
|
||||||
|
BotDatabase?.Dispose();
|
||||||
|
CardsFarmer?.Dispose();
|
||||||
CardsFarmerResumeTimer?.Dispose();
|
CardsFarmerResumeTimer?.Dispose();
|
||||||
ConnectionFailureTimer?.Dispose();
|
ConnectionFailureTimer?.Dispose();
|
||||||
FamilySharingInactivityTimer?.Dispose();
|
FamilySharingInactivityTimer?.Dispose();
|
||||||
|
HeartBeatTimer?.Dispose();
|
||||||
|
PlayingWasBlockedTimer?.Dispose();
|
||||||
SendItemsTimer?.Dispose();
|
SendItemsTimer?.Dispose();
|
||||||
Statistics?.Dispose();
|
Statistics?.Dispose();
|
||||||
SteamSaleEvent?.Dispose();
|
SteamSaleEvent?.Dispose();
|
||||||
|
Trading?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<bool> AcceptConfirmations(bool accept, Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown, ulong acceptedSteamID = 0, HashSet<ulong> acceptedTradeIDs = null) {
|
internal async Task<bool> AcceptConfirmations(bool accept, Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown, ulong acceptedSteamID = 0, HashSet<ulong> acceptedTradeIDs = null) {
|
||||||
@@ -803,13 +805,13 @@ namespace ArchiSteamFarm {
|
|||||||
return await ResponseBlacklistAdd(steamID, args[1], args[2]).ConfigureAwait(false);
|
return await ResponseBlacklistAdd(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseBlacklistAdd(steamID, args[1]);
|
return await ResponseBlacklistAdd(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!BLRM":
|
case "!BLRM":
|
||||||
if (args.Length > 2) {
|
if (args.Length > 2) {
|
||||||
return await ResponseBlacklistRemove(steamID, args[1], args[2]).ConfigureAwait(false);
|
return await ResponseBlacklistRemove(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseBlacklistRemove(steamID, args[1]);
|
return await ResponseBlacklistRemove(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!FARM":
|
case "!FARM":
|
||||||
return await ResponseFarm(steamID, args[1]).ConfigureAwait(false);
|
return await ResponseFarm(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!INPUT":
|
case "!INPUT":
|
||||||
@@ -825,13 +827,13 @@ namespace ArchiSteamFarm {
|
|||||||
return await ResponseIdleQueueAdd(steamID, args[1], args[2]).ConfigureAwait(false);
|
return await ResponseIdleQueueAdd(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseIdleQueueAdd(steamID, args[1]);
|
return await ResponseIdleQueueAdd(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!IQRM":
|
case "!IQRM":
|
||||||
if (args.Length > 2) {
|
if (args.Length > 2) {
|
||||||
return await ResponseIdleQueueRemove(steamID, args[1], args[2]).ConfigureAwait(false);
|
return await ResponseIdleQueueRemove(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseIdleQueueRemove(steamID, args[1]);
|
return await ResponseIdleQueueRemove(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!LOOT":
|
case "!LOOT":
|
||||||
return await ResponseLoot(steamID, args[1]).ConfigureAwait(false);
|
return await ResponseLoot(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!LOOT^":
|
case "!LOOT^":
|
||||||
@@ -1156,7 +1158,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImportAuthenticator(string maFilePath) {
|
private async Task ImportAuthenticator(string maFilePath) {
|
||||||
if (HasMobileAuthenticator || !File.Exists(maFilePath)) {
|
if (HasMobileAuthenticator || !File.Exists(maFilePath)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1164,7 +1166,8 @@ namespace ArchiSteamFarm {
|
|||||||
ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorConverting);
|
ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorConverting);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BotDatabase.MobileAuthenticator = JsonConvert.DeserializeObject<MobileAuthenticator>(File.ReadAllText(maFilePath));
|
MobileAuthenticator authenticator = JsonConvert.DeserializeObject<MobileAuthenticator>(File.ReadAllText(maFilePath));
|
||||||
|
await BotDatabase.SetMobileAuthenticator(authenticator).ConfigureAwait(false);
|
||||||
File.Delete(maFilePath);
|
File.Delete(maFilePath);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ArchiLogger.LogGenericException(e);
|
ArchiLogger.LogGenericException(e);
|
||||||
@@ -1183,14 +1186,14 @@ namespace ArchiSteamFarm {
|
|||||||
if (string.IsNullOrEmpty(DeviceID)) {
|
if (string.IsNullOrEmpty(DeviceID)) {
|
||||||
string deviceID = Program.GetUserInput(ASF.EUserInputType.DeviceID, BotName);
|
string deviceID = Program.GetUserInput(ASF.EUserInputType.DeviceID, BotName);
|
||||||
if (string.IsNullOrEmpty(deviceID)) {
|
if (string.IsNullOrEmpty(deviceID)) {
|
||||||
BotDatabase.MobileAuthenticator = null;
|
await BotDatabase.SetMobileAuthenticator().ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetUserInput(ASF.EUserInputType.DeviceID, deviceID);
|
SetUserInput(ASF.EUserInputType.DeviceID, deviceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.CorrectMobileAuthenticatorDeviceID(DeviceID);
|
await BotDatabase.CorrectMobileAuthenticatorDeviceID(DeviceID).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorImportFinished);
|
ArchiLogger.LogGenericInfo(Strings.BotAuthenticatorImportFinished);
|
||||||
@@ -1584,7 +1587,7 @@ namespace ArchiSteamFarm {
|
|||||||
goto case EResult.RateLimitExceeded;
|
goto case EResult.RateLimitExceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.LoginKey = null;
|
await BotDatabase.SetLoginKey().ConfigureAwait(false);
|
||||||
ArchiLogger.LogGenericInfo(Strings.BotRemovedExpiredLoginKey);
|
ArchiLogger.LogGenericInfo(Strings.BotRemovedExpiredLoginKey);
|
||||||
break;
|
break;
|
||||||
case EResult.NoConnection:
|
case EResult.NoConnection:
|
||||||
@@ -1821,15 +1824,15 @@ namespace ArchiSteamFarm {
|
|||||||
ArchiLogger.LogGenericWarning(Strings.BotAccountLocked);
|
ArchiLogger.LogGenericWarning(Strings.BotAccountLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback.CellID != 0) {
|
if ((callback.CellID != 0) && (callback.CellID != Program.GlobalDatabase.CellID)) {
|
||||||
Program.GlobalDatabase.CellID = callback.CellID;
|
await Program.GlobalDatabase.SetCellID(callback.CellID).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasMobileAuthenticator) {
|
if (!HasMobileAuthenticator) {
|
||||||
// Support and convert 2FA files
|
// Support and convert 2FA files
|
||||||
string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, callback.ClientSteamID.ConvertToUInt64() + ".maFile");
|
string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, callback.ClientSteamID.ConvertToUInt64() + ".maFile");
|
||||||
if (File.Exists(maFilePath)) {
|
if (File.Exists(maFilePath)) {
|
||||||
ImportAuthenticator(maFilePath);
|
await ImportAuthenticator(maFilePath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1896,7 +1899,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLoginKey(SteamUser.LoginKeyCallback callback) {
|
private async void OnLoginKey(SteamUser.LoginKeyCallback callback) {
|
||||||
if (string.IsNullOrEmpty(callback?.LoginKey)) {
|
if (string.IsNullOrEmpty(callback?.LoginKey)) {
|
||||||
ArchiLogger.LogNullError(nameof(callback) + " || " + nameof(callback.LoginKey));
|
ArchiLogger.LogNullError(nameof(callback) + " || " + nameof(callback.LoginKey));
|
||||||
return;
|
return;
|
||||||
@@ -1907,7 +1910,7 @@ namespace ArchiSteamFarm {
|
|||||||
loginKey = CryptoHelper.Encrypt(BotConfig.PasswordFormat, loginKey);
|
loginKey = CryptoHelper.Encrypt(BotConfig.PasswordFormat, loginKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.LoginKey = loginKey;
|
await BotDatabase.SetLoginKey(loginKey).ConfigureAwait(false);
|
||||||
SteamUser.AcceptNewLoginKey(callback);
|
SteamUser.AcceptNewLoginKey(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2431,7 +2434,7 @@ namespace ArchiSteamFarm {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseBlacklistAdd(ulong steamID, string targetsText) {
|
private async Task<string> ResponseBlacklistAdd(ulong steamID, string targetsText) {
|
||||||
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
||||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
||||||
return null;
|
return null;
|
||||||
@@ -2456,7 +2459,7 @@ namespace ArchiSteamFarm {
|
|||||||
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targetIDs)));
|
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targetIDs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.AddBlacklistedFromTradesSteamIDs(targetIDs);
|
await BotDatabase.AddBlacklistedFromTradesSteamIDs(targetIDs).ConfigureAwait(false);
|
||||||
return FormatBotResponse(Strings.Done);
|
return FormatBotResponse(Strings.Done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2471,7 +2474,7 @@ namespace ArchiSteamFarm {
|
|||||||
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Task<string>> tasks = bots.Select(bot => Task.Run(() => bot.ResponseBlacklistAdd(steamID, targetsText)));
|
IEnumerable<Task<string>> tasks = bots.Select(bot => bot.ResponseBlacklistAdd(steamID, targetsText));
|
||||||
ICollection<string> results;
|
ICollection<string> results;
|
||||||
|
|
||||||
switch (Program.GlobalConfig.OptimizationMode) {
|
switch (Program.GlobalConfig.OptimizationMode) {
|
||||||
@@ -2502,7 +2505,7 @@ namespace ArchiSteamFarm {
|
|||||||
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Task<string>> tasks = bots.Select(bot => Task.Run(() => bot.ResponseBlacklistRemove(steamID, targetsText)));
|
IEnumerable<Task<string>> tasks = bots.Select(bot => bot.ResponseBlacklistRemove(steamID, targetsText));
|
||||||
ICollection<string> results;
|
ICollection<string> results;
|
||||||
|
|
||||||
switch (Program.GlobalConfig.OptimizationMode) {
|
switch (Program.GlobalConfig.OptimizationMode) {
|
||||||
@@ -2522,7 +2525,7 @@ namespace ArchiSteamFarm {
|
|||||||
return responses.Count > 0 ? string.Join("", responses) : null;
|
return responses.Count > 0 ? string.Join("", responses) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseBlacklistRemove(ulong steamID, string targetsText) {
|
private async Task<string> ResponseBlacklistRemove(ulong steamID, string targetsText) {
|
||||||
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
||||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
||||||
return null;
|
return null;
|
||||||
@@ -2547,7 +2550,7 @@ namespace ArchiSteamFarm {
|
|||||||
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targetIDs)));
|
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(targetIDs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.RemoveBlacklistedFromTradesSteamIDs(targetIDs);
|
await BotDatabase.RemoveBlacklistedFromTradesSteamIDs(targetIDs).ConfigureAwait(false);
|
||||||
return FormatBotResponse(Strings.Done);
|
return FormatBotResponse(Strings.Done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2671,7 +2674,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseIdleQueueAdd(ulong steamID, string targetsText) {
|
private async Task<string> ResponseIdleQueueAdd(ulong steamID, string targetsText) {
|
||||||
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
||||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
||||||
return null;
|
return null;
|
||||||
@@ -2696,7 +2699,7 @@ namespace ArchiSteamFarm {
|
|||||||
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs)));
|
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.AddIdlingPriorityAppIDs(appIDs);
|
await BotDatabase.AddIdlingPriorityAppIDs(appIDs).ConfigureAwait(false);
|
||||||
return FormatBotResponse(Strings.Done);
|
return FormatBotResponse(Strings.Done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2711,7 +2714,7 @@ namespace ArchiSteamFarm {
|
|||||||
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Task<string>> tasks = bots.Select(bot => Task.Run(() => bot.ResponseIdleQueueAdd(steamID, targetsText)));
|
IEnumerable<Task<string>> tasks = bots.Select(bot => bot.ResponseIdleQueueAdd(steamID, targetsText));
|
||||||
ICollection<string> results;
|
ICollection<string> results;
|
||||||
|
|
||||||
switch (Program.GlobalConfig.OptimizationMode) {
|
switch (Program.GlobalConfig.OptimizationMode) {
|
||||||
@@ -2742,7 +2745,7 @@ namespace ArchiSteamFarm {
|
|||||||
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
return IsOwner(steamID) ? FormatStaticResponse(string.Format(Strings.BotNotFound, botNames)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Task<string>> tasks = bots.Select(bot => Task.Run(() => bot.ResponseIdleQueueRemove(steamID, targetsText)));
|
IEnumerable<Task<string>> tasks = bots.Select(bot => bot.ResponseIdleQueueRemove(steamID, targetsText));
|
||||||
ICollection<string> results;
|
ICollection<string> results;
|
||||||
|
|
||||||
switch (Program.GlobalConfig.OptimizationMode) {
|
switch (Program.GlobalConfig.OptimizationMode) {
|
||||||
@@ -2762,7 +2765,7 @@ namespace ArchiSteamFarm {
|
|||||||
return responses.Count > 0 ? string.Join("", responses) : null;
|
return responses.Count > 0 ? string.Join("", responses) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseIdleQueueRemove(ulong steamID, string targetsText) {
|
private async Task<string> ResponseIdleQueueRemove(ulong steamID, string targetsText) {
|
||||||
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
if ((steamID == 0) || string.IsNullOrEmpty(targetsText)) {
|
||||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(targetsText));
|
||||||
return null;
|
return null;
|
||||||
@@ -2787,7 +2790,7 @@ namespace ArchiSteamFarm {
|
|||||||
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs)));
|
return FormatBotResponse(string.Format(Strings.ErrorIsEmpty, nameof(appIDs)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BotDatabase.RemoveIdlingPriorityAppIDs(appIDs);
|
await BotDatabase.RemoveIdlingPriorityAppIDs(appIDs).ConfigureAwait(false);
|
||||||
return FormatBotResponse(Strings.Done);
|
return FormatBotResponse(Strings.Done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4104,7 +4107,7 @@ namespace ArchiSteamFarm {
|
|||||||
if (!HasMobileAuthenticator) {
|
if (!HasMobileAuthenticator) {
|
||||||
string maFilePath = BotPath + ".maFile";
|
string maFilePath = BotPath + ".maFile";
|
||||||
if (File.Exists(maFilePath)) {
|
if (File.Exists(maFilePath)) {
|
||||||
ImportAuthenticator(maFilePath);
|
await ImportAuthenticator(maFilePath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,49 +26,25 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal sealed class BotDatabase {
|
internal sealed class BotDatabase : IDisposable {
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
private readonly ConcurrentHashSet<ulong> BlacklistedFromTradesSteamIDs = new ConcurrentHashSet<ulong>();
|
private readonly ConcurrentHashSet<ulong> BlacklistedFromTradesSteamIDs = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
private readonly object FileLock = new object();
|
private readonly SemaphoreSlim FileSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
private readonly ConcurrentHashSet<uint> IdlingPriorityAppIDs = new ConcurrentHashSet<uint>();
|
private readonly ConcurrentHashSet<uint> IdlingPriorityAppIDs = new ConcurrentHashSet<uint>();
|
||||||
|
|
||||||
internal string LoginKey {
|
[JsonProperty(PropertyName = "_LoginKey")]
|
||||||
get => _LoginKey;
|
internal string LoginKey { get; private set; }
|
||||||
|
|
||||||
set {
|
[JsonProperty(PropertyName = "_MobileAuthenticator")]
|
||||||
if (_LoginKey == value) {
|
internal MobileAuthenticator MobileAuthenticator { get; private set; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_LoginKey = value;
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal MobileAuthenticator MobileAuthenticator {
|
|
||||||
get => _MobileAuthenticator;
|
|
||||||
|
|
||||||
set {
|
|
||||||
if (_MobileAuthenticator == value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_MobileAuthenticator = value;
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty]
|
|
||||||
private string _LoginKey;
|
|
||||||
|
|
||||||
[JsonProperty]
|
|
||||||
private MobileAuthenticator _MobileAuthenticator;
|
|
||||||
|
|
||||||
private string FilePath;
|
private string FilePath;
|
||||||
|
|
||||||
@@ -79,43 +55,51 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
Save();
|
Save().Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This constructor is used only by deserializer
|
// This constructor is used only by deserializer
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
||||||
private BotDatabase() { }
|
private BotDatabase() { }
|
||||||
|
|
||||||
internal void AddBlacklistedFromTradesSteamIDs(HashSet<ulong> steamIDs) {
|
public void Dispose() {
|
||||||
|
// Those are objects that are always being created if constructor doesn't throw exception
|
||||||
|
FileSemaphore.Dispose();
|
||||||
|
|
||||||
|
// Those are objects that might be null and the check should be in-place
|
||||||
|
MobileAuthenticator?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task AddBlacklistedFromTradesSteamIDs(HashSet<ulong> steamIDs) {
|
||||||
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(steamIDs));
|
ASF.ArchiLogger.LogNullError(nameof(steamIDs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BlacklistedFromTradesSteamIDs.AddRange(steamIDs)) {
|
if (BlacklistedFromTradesSteamIDs.AddRange(steamIDs)) {
|
||||||
Save();
|
await Save().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddIdlingPriorityAppIDs(HashSet<uint> appIDs) {
|
internal async Task AddIdlingPriorityAppIDs(HashSet<uint> appIDs) {
|
||||||
if ((appIDs == null) || (appIDs.Count == 0)) {
|
if ((appIDs == null) || (appIDs.Count == 0)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IdlingPriorityAppIDs.AddRange(appIDs)) {
|
if (IdlingPriorityAppIDs.AddRange(appIDs)) {
|
||||||
Save();
|
await Save().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void CorrectMobileAuthenticatorDeviceID(string deviceID) {
|
internal async Task CorrectMobileAuthenticatorDeviceID(string deviceID) {
|
||||||
if (string.IsNullOrEmpty(deviceID) || (MobileAuthenticator == null)) {
|
if (string.IsNullOrEmpty(deviceID) || (MobileAuthenticator == null)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(deviceID) + " || " + nameof(MobileAuthenticator));
|
ASF.ArchiLogger.LogNullError(nameof(deviceID) + " || " + nameof(MobileAuthenticator));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MobileAuthenticator.CorrectDeviceID(deviceID)) {
|
if (MobileAuthenticator.CorrectDeviceID(deviceID)) {
|
||||||
Save();
|
await Save().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,49 +154,69 @@ namespace ArchiSteamFarm {
|
|||||||
return botDatabase;
|
return botDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RemoveBlacklistedFromTradesSteamIDs(HashSet<ulong> steamIDs) {
|
internal async Task RemoveBlacklistedFromTradesSteamIDs(HashSet<ulong> steamIDs) {
|
||||||
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(steamIDs));
|
ASF.ArchiLogger.LogNullError(nameof(steamIDs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BlacklistedFromTradesSteamIDs.RemoveRange(steamIDs)) {
|
if (BlacklistedFromTradesSteamIDs.RemoveRange(steamIDs)) {
|
||||||
Save();
|
await Save().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void RemoveIdlingPriorityAppIDs(HashSet<uint> appIDs) {
|
internal async Task RemoveIdlingPriorityAppIDs(HashSet<uint> appIDs) {
|
||||||
if ((appIDs == null) || (appIDs.Count == 0)) {
|
if ((appIDs == null) || (appIDs.Count == 0)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IdlingPriorityAppIDs.RemoveRange(appIDs)) {
|
if (IdlingPriorityAppIDs.RemoveRange(appIDs)) {
|
||||||
Save();
|
await Save().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Save() {
|
internal async Task SetLoginKey(string value = null) {
|
||||||
|
if (value == LoginKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginKey = value;
|
||||||
|
await Save().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task SetMobileAuthenticator(MobileAuthenticator value = null) {
|
||||||
|
if (value == MobileAuthenticator) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MobileAuthenticator = value;
|
||||||
|
await Save().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Save() {
|
||||||
string json = JsonConvert.SerializeObject(this);
|
string json = JsonConvert.SerializeObject(this);
|
||||||
if (string.IsNullOrEmpty(json)) {
|
if (string.IsNullOrEmpty(json)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(json));
|
ASF.ArchiLogger.LogNullError(nameof(json));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (FileLock) {
|
string newFilePath = FilePath + ".new";
|
||||||
string newFilePath = FilePath + ".new";
|
|
||||||
|
|
||||||
try {
|
await FileSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
File.WriteAllText(newFilePath, json);
|
|
||||||
|
|
||||||
if (File.Exists(FilePath)) {
|
try {
|
||||||
File.Replace(newFilePath, FilePath, null);
|
await File.WriteAllTextAsync(newFilePath, json).ConfigureAwait(false);
|
||||||
} else {
|
|
||||||
File.Move(newFilePath, FilePath);
|
if (File.Exists(FilePath)) {
|
||||||
}
|
File.Replace(newFilePath, FilePath, null);
|
||||||
} catch (Exception e) {
|
} else {
|
||||||
ASF.ArchiLogger.LogGenericException(e);
|
File.Move(newFilePath, FilePath);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
ASF.ArchiLogger.LogGenericException(e);
|
||||||
|
} finally {
|
||||||
|
FileSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ namespace ArchiSteamFarm {
|
|||||||
EventSemaphore.Dispose();
|
EventSemaphore.Dispose();
|
||||||
FarmingInitializationSemaphore.Dispose();
|
FarmingInitializationSemaphore.Dispose();
|
||||||
FarmingResetSemaphore.Dispose();
|
FarmingResetSemaphore.Dispose();
|
||||||
|
GamesToFarm.Dispose();
|
||||||
|
|
||||||
// Those are objects that might be null and the check should be in-place
|
// Those are objects that might be null and the check should be in-place
|
||||||
IdleFarmingTimer?.Dispose();
|
IdleFarmingTimer?.Dispose();
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ namespace ArchiSteamFarm {
|
|||||||
internal sealed class ConcurrentSortedHashSet<T> : IDisposable, IReadOnlyCollection<T>, ISet<T> {
|
internal sealed class ConcurrentSortedHashSet<T> : IDisposable, IReadOnlyCollection<T>, ISet<T> {
|
||||||
public int Count {
|
public int Count {
|
||||||
get {
|
get {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.Count;
|
return BackingCollection.Count;
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,159 +44,159 @@ namespace ArchiSteamFarm {
|
|||||||
public bool IsReadOnly => false;
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
private readonly HashSet<T> BackingCollection = new HashSet<T>();
|
private readonly HashSet<T> BackingCollection = new HashSet<T>();
|
||||||
private readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim CollectionSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
public bool Add(T item) {
|
public bool Add(T item) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.Add(item);
|
return BackingCollection.Add(item);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear() {
|
public void Clear() {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.Clear();
|
BackingCollection.Clear();
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(T item) {
|
public bool Contains(T item) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.Contains(item);
|
return BackingCollection.Contains(item);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(T[] array, int arrayIndex) {
|
public void CopyTo(T[] array, int arrayIndex) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.CopyTo(array, arrayIndex);
|
BackingCollection.CopyTo(array, arrayIndex);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() => SemaphoreSlim.Dispose();
|
public void Dispose() => CollectionSemaphore.Dispose();
|
||||||
|
|
||||||
public void ExceptWith(IEnumerable<T> other) {
|
public void ExceptWith(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.ExceptWith(other);
|
BackingCollection.ExceptWith(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<T> GetEnumerator() => new ConcurrentEnumerator<T>(BackingCollection, SemaphoreSlim);
|
public IEnumerator<T> GetEnumerator() => new ConcurrentEnumerator<T>(BackingCollection, CollectionSemaphore);
|
||||||
|
|
||||||
public void IntersectWith(IEnumerable<T> other) {
|
public void IntersectWith(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.IntersectWith(other);
|
BackingCollection.IntersectWith(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsProperSubsetOf(IEnumerable<T> other) {
|
public bool IsProperSubsetOf(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.IsProperSubsetOf(other);
|
return BackingCollection.IsProperSubsetOf(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsProperSupersetOf(IEnumerable<T> other) {
|
public bool IsProperSupersetOf(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.IsProperSupersetOf(other);
|
return BackingCollection.IsProperSupersetOf(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSubsetOf(IEnumerable<T> other) {
|
public bool IsSubsetOf(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.IsSubsetOf(other);
|
return BackingCollection.IsSubsetOf(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsSupersetOf(IEnumerable<T> other) {
|
public bool IsSupersetOf(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.IsSupersetOf(other);
|
return BackingCollection.IsSupersetOf(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Overlaps(IEnumerable<T> other) {
|
public bool Overlaps(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.Overlaps(other);
|
return BackingCollection.Overlaps(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(T item) {
|
public bool Remove(T item) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.Remove(item);
|
return BackingCollection.Remove(item);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SetEquals(IEnumerable<T> other) {
|
public bool SetEquals(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return BackingCollection.SetEquals(other);
|
return BackingCollection.SetEquals(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SymmetricExceptWith(IEnumerable<T> other) {
|
public void SymmetricExceptWith(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.SymmetricExceptWith(other);
|
BackingCollection.SymmetricExceptWith(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnionWith(IEnumerable<T> other) {
|
public void UnionWith(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.UnionWith(other);
|
BackingCollection.UnionWith(other);
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ namespace ArchiSteamFarm {
|
|||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
internal void ReplaceWith(IEnumerable<T> other) {
|
internal void ReplaceWith(IEnumerable<T> other) {
|
||||||
SemaphoreSlim.Wait();
|
CollectionSemaphore.Wait();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BackingCollection.Clear();
|
BackingCollection.Clear();
|
||||||
@@ -213,7 +213,7 @@ namespace ArchiSteamFarm {
|
|||||||
BackingCollection.Add(item);
|
BackingCollection.Add(item);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
SemaphoreSlim.Release();
|
CollectionSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,24 +42,11 @@ namespace ArchiSteamFarm {
|
|||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal readonly InMemoryServerListProvider ServerListProvider = new InMemoryServerListProvider();
|
internal readonly InMemoryServerListProvider ServerListProvider = new InMemoryServerListProvider();
|
||||||
|
|
||||||
private readonly object FileLock = new object();
|
private readonly SemaphoreSlim FileSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private readonly SemaphoreSlim PackagesRefreshSemaphore = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim PackagesRefreshSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
internal uint CellID {
|
[JsonProperty(PropertyName = "_CellID", Required = Required.DisallowNull)]
|
||||||
get => _CellID;
|
internal uint CellID { get; private set; }
|
||||||
set {
|
|
||||||
if ((value == 0) || (_CellID == value)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_CellID = value;
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
|
||||||
private uint _CellID;
|
|
||||||
|
|
||||||
private string FilePath;
|
private string FilePath;
|
||||||
|
|
||||||
@@ -70,13 +57,20 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
Save();
|
Save().Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This constructor is used only by deserializer
|
// This constructor is used only by deserializer
|
||||||
private GlobalDatabase() => ServerListProvider.ServerListUpdated += OnServerListUpdated;
|
private GlobalDatabase() => ServerListProvider.ServerListUpdated += OnServerListUpdated;
|
||||||
|
|
||||||
public void Dispose() => ServerListProvider.ServerListUpdated -= OnServerListUpdated;
|
public void Dispose() {
|
||||||
|
// Events we registered
|
||||||
|
ServerListProvider.ServerListUpdated -= OnServerListUpdated;
|
||||||
|
|
||||||
|
// Those are objects that are always being created if constructor doesn't throw exception
|
||||||
|
FileSemaphore.Dispose();
|
||||||
|
PackagesRefreshSemaphore.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
internal static GlobalDatabase Load(string filePath) {
|
internal static GlobalDatabase Load(string filePath) {
|
||||||
if (string.IsNullOrEmpty(filePath)) {
|
if (string.IsNullOrEmpty(filePath)) {
|
||||||
@@ -136,35 +130,46 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Save();
|
await Save().ConfigureAwait(false);
|
||||||
} finally {
|
} finally {
|
||||||
PackagesRefreshSemaphore.Release();
|
PackagesRefreshSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnServerListUpdated(object sender, EventArgs e) => Save();
|
internal async Task SetCellID(uint value = 0) {
|
||||||
|
if (value == CellID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
private void Save() {
|
CellID = value;
|
||||||
|
await Save().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnServerListUpdated(object sender, EventArgs e) => await Save().ConfigureAwait(false);
|
||||||
|
|
||||||
|
private async Task Save() {
|
||||||
string json = JsonConvert.SerializeObject(this);
|
string json = JsonConvert.SerializeObject(this);
|
||||||
if (string.IsNullOrEmpty(json)) {
|
if (string.IsNullOrEmpty(json)) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(json));
|
ASF.ArchiLogger.LogNullError(nameof(json));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (FileLock) {
|
string newFilePath = FilePath + ".new";
|
||||||
string newFilePath = FilePath + ".new";
|
|
||||||
|
|
||||||
try {
|
await FileSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
File.WriteAllText(newFilePath, json);
|
|
||||||
|
|
||||||
if (File.Exists(FilePath)) {
|
try {
|
||||||
File.Replace(newFilePath, FilePath, null);
|
File.WriteAllText(newFilePath, json);
|
||||||
} else {
|
|
||||||
File.Move(newFilePath, FilePath);
|
if (File.Exists(FilePath)) {
|
||||||
}
|
File.Replace(newFilePath, FilePath, null);
|
||||||
} catch (Exception e) {
|
} else {
|
||||||
ASF.ArchiLogger.LogGenericException(e);
|
File.Move(newFilePath, FilePath);
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
ASF.ArchiLogger.LogGenericException(e);
|
||||||
|
} finally {
|
||||||
|
FileSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,16 +38,8 @@ namespace ArchiSteamFarm {
|
|||||||
internal readonly ProtocolTypes ProtocolTypes;
|
internal readonly ProtocolTypes ProtocolTypes;
|
||||||
|
|
||||||
internal ServerRecordEndPoint(string host, ushort port, ProtocolTypes protocolTypes) {
|
internal ServerRecordEndPoint(string host, ushort port, ProtocolTypes protocolTypes) {
|
||||||
if (string.IsNullOrEmpty(host)) {
|
if (string.IsNullOrEmpty(host) || (port == 0) || (protocolTypes == 0)) {
|
||||||
throw new ArgumentNullException(nameof(host));
|
throw new ArgumentNullException(nameof(host) + " || " + nameof(port) + " || " + nameof(protocolTypes));
|
||||||
}
|
|
||||||
|
|
||||||
if (port == 0) {
|
|
||||||
throw new ArgumentNullException(nameof(port));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (protocolTypes == 0) {
|
|
||||||
throw new ArgumentNullException(nameof(protocolTypes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Host = host;
|
Host = host;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace ArchiSteamFarm {
|
|||||||
private const string URL = "https://" + SharedInfo.StatisticsServer;
|
private const string URL = "https://" + SharedInfo.StatisticsServer;
|
||||||
|
|
||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
private readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim RequestsSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private DateTime LastAnnouncementCheck = DateTime.MinValue;
|
private DateTime LastAnnouncementCheck = DateTime.MinValue;
|
||||||
private DateTime LastHeartBeat = DateTime.MinValue;
|
private DateTime LastHeartBeat = DateTime.MinValue;
|
||||||
@@ -49,7 +49,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
internal Statistics(Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
|
internal Statistics(Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
|
||||||
|
|
||||||
public void Dispose() => Semaphore.Dispose();
|
public void Dispose() => RequestsSemaphore.Dispose();
|
||||||
|
|
||||||
internal async Task OnHeartBeat() {
|
internal async Task OnHeartBeat() {
|
||||||
// Request persona update if needed
|
// Request persona update if needed
|
||||||
@@ -62,7 +62,7 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Semaphore.WaitAsync().ConfigureAwait(false);
|
await RequestsSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!ShouldSendHeartBeats || (DateTime.UtcNow < LastHeartBeat.AddMinutes(MinHeartBeatTTL))) {
|
if (!ShouldSendHeartBeats || (DateTime.UtcNow < LastHeartBeat.AddMinutes(MinHeartBeatTTL))) {
|
||||||
@@ -80,7 +80,7 @@ namespace ArchiSteamFarm {
|
|||||||
LastHeartBeat = DateTime.UtcNow;
|
LastHeartBeat = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Semaphore.Release();
|
RequestsSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Semaphore.WaitAsync().ConfigureAwait(false);
|
await RequestsSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (DateTime.UtcNow < LastAnnouncementCheck.AddHours(MinAnnouncementCheckTTL)) {
|
if (DateTime.UtcNow < LastAnnouncementCheck.AddHours(MinAnnouncementCheckTTL)) {
|
||||||
@@ -154,7 +154,7 @@ namespace ArchiSteamFarm {
|
|||||||
ShouldSendHeartBeats = true;
|
ShouldSendHeartBeats = true;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Semaphore.Release();
|
RequestsSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ using Newtonsoft.Json;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal sealed class WebBrowser {
|
internal sealed class WebBrowser : IDisposable {
|
||||||
internal const byte MaxTries = 5; // Defines maximum number of recommended tries for a single request
|
internal const byte MaxTries = 5; // Defines maximum number of recommended tries for a single request
|
||||||
|
|
||||||
private const byte ExtendedTimeoutMultiplier = 10; // Defines multiplier of timeout for WebBrowsers dealing with huge data (ASF update)
|
private const byte ExtendedTimeoutMultiplier = 10; // Defines multiplier of timeout for WebBrowsers dealing with huge data (ASF update)
|
||||||
@@ -63,6 +63,8 @@ namespace ArchiSteamFarm {
|
|||||||
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(SharedInfo.AssemblyName + "/" + SharedInfo.Version);
|
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(SharedInfo.AssemblyName + "/" + SharedInfo.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose() => HttpClient.Dispose();
|
||||||
|
|
||||||
internal static void Init() {
|
internal static void Init() {
|
||||||
// Set max connection limit from default of 2 to desired value
|
// Set max connection limit from default of 2 to desired value
|
||||||
ServicePointManager.DefaultConnectionLimit = MaxConnections;
|
ServicePointManager.DefaultConnectionLimit = MaxConnections;
|
||||||
|
|||||||
Reference in New Issue
Block a user