mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 07:04:27 +00:00
R# cleanup
This commit is contained in:
parent
39fb21cc83
commit
f8aa8babcf
48 changed files with 1510 additions and 32 deletions
|
@ -263,6 +263,7 @@ namespace ArchiSteamFarm.Tests {
|
|||
CreateItem(2),
|
||||
CreateItem(5)
|
||||
};
|
||||
|
||||
HashSet<Steam.Asset> itemsToReceive = new HashSet<Steam.Asset> {
|
||||
CreateItem(3),
|
||||
CreateItem(4)
|
||||
|
|
|
@ -186,7 +186,12 @@
|
|||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue">False</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AFTER_CONTROL_TRANSFER_STATEMENTS/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AFTER_MULTILINE_STATEMENTS/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_FIELD/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_BLOCK_STATEMENTS/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_CONTROL_TRANSFER_STATEMENTS/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_MULTILINE_STATEMENTS/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BEFORE_SINGLE_LINE_COMMENT/@EntryValue">1</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_BETWEEN_USING_GROUPS/@EntryValue">0</s:Int64>
|
||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_INSIDE_REGION/@EntryValue">0</s:Int64>
|
||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">END_OF_LINE</s:String>
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace ArchiSteamFarm {
|
|||
await Utilities.InParallel(Directory.EnumerateFiles(SharedInfo.ConfigDirectory, "*" + SharedInfo.ConfigExtension).Select(Path.GetFileNameWithoutExtension).Where(botName => !string.IsNullOrEmpty(botName) && IsValidBotName(botName)).OrderBy(botName => botName).Select(Bot.RegisterBot)).ConfigureAwait(false);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -77,6 +78,7 @@ namespace ArchiSteamFarm {
|
|||
internal static bool IsOwner(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -107,6 +109,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// If backup directory from previous update exists, it's a good idea to purge it now
|
||||
string backupDirectory = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.UpdateDirectory);
|
||||
|
||||
if (Directory.Exists(backupDirectory)) {
|
||||
// It's entirely possible that old process is still running, wait a short moment for eventual cleanup
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
@ -115,28 +118,22 @@ namespace ArchiSteamFarm {
|
|||
Directory.Delete(backupDirectory, true);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cleanup from previous update, remove this after next stable
|
||||
try {
|
||||
foreach (string file in Directory.EnumerateFiles(SharedInfo.HomeDirectory, "*.old", SearchOption.AllDirectories)) {
|
||||
File.Delete(file);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
GitHub.ReleaseResponse releaseResponse = await GitHub.GetLatestRelease(Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable).ConfigureAwait(false);
|
||||
|
||||
if (releaseResponse == null) {
|
||||
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(releaseResponse.Tag)) {
|
||||
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -151,18 +148,21 @@ namespace ArchiSteamFarm {
|
|||
if (SharedInfo.Version > newVersion) {
|
||||
ArchiLogger.LogGenericWarning(Strings.WarningPreReleaseVersion);
|
||||
await Task.Delay(15 * 1000).ConfigureAwait(false);
|
||||
|
||||
return SharedInfo.Version;
|
||||
}
|
||||
|
||||
if (!updateOverride && (Program.GlobalConfig.UpdatePeriod == 0)) {
|
||||
ArchiLogger.LogGenericInfo(Strings.UpdateNewVersionAvailable);
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Auto update logic starts here
|
||||
if (releaseResponse.Assets == null) {
|
||||
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -171,11 +171,13 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (binaryAsset == null) {
|
||||
ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssetForThisVersion);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(binaryAsset.DownloadURL)) {
|
||||
ArchiLogger.LogNullError(nameof(binaryAsset.DownloadURL));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -186,6 +188,7 @@ namespace ArchiSteamFarm {
|
|||
ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateDownloadingNewVersion, newVersion, binaryAsset.Size / 1024 / 1024));
|
||||
|
||||
WebBrowser.BinaryResponse response = await Program.WebBrowser.UrlGetToBinaryWithProgress(binaryAsset.DownloadURL).ConfigureAwait(false);
|
||||
|
||||
if (response?.Content == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -198,17 +201,20 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (OS.IsUnix) {
|
||||
string executable = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.AssemblyName);
|
||||
|
||||
if (File.Exists(executable)) {
|
||||
OS.UnixSetFileAccessExecutable(executable);
|
||||
}
|
||||
}
|
||||
|
||||
ArchiLogger.LogGenericInfo(Strings.UpdateFinished);
|
||||
|
||||
return newVersion;
|
||||
} finally {
|
||||
UpdateSemaphore.Release();
|
||||
|
@ -234,6 +240,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Version newVersion = await Update().ConfigureAwait(false);
|
||||
|
||||
if ((newVersion == null) || (newVersion <= SharedInfo.Version)) {
|
||||
return;
|
||||
}
|
||||
|
@ -244,6 +251,7 @@ namespace ArchiSteamFarm {
|
|||
private static async Task<bool> CanHandleWriteEvent(string name) {
|
||||
if (string.IsNullOrEmpty(name)) {
|
||||
ArchiLogger.LogNullError(nameof(name));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -261,6 +269,7 @@ namespace ArchiSteamFarm {
|
|||
private static bool IsValidBotName(string botName) {
|
||||
if (string.IsNullOrEmpty(botName)) {
|
||||
ArchiLogger.LogNullError(nameof(botName));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -270,8 +279,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (botName) {
|
||||
case SharedInfo.ASF:
|
||||
|
||||
return false;
|
||||
default:
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +290,7 @@ namespace ArchiSteamFarm {
|
|||
private static async void OnChanged(object sender, FileSystemEventArgs e) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -288,6 +300,7 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnChangedConfigFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -300,9 +313,11 @@ namespace ArchiSteamFarm {
|
|||
switch (extension) {
|
||||
case SharedInfo.ConfigExtension:
|
||||
await OnChangedConfigFile(name, fullPath).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
case SharedInfo.KeysExtension:
|
||||
await OnChangedKeysFile(name, fullPath).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -310,6 +325,7 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnChangedKeysFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -319,6 +335,7 @@ namespace ArchiSteamFarm {
|
|||
private static async void OnCreated(object sender, FileSystemEventArgs e) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -328,10 +345,12 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnCreatedConfigFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string botName = Path.GetFileNameWithoutExtension(name);
|
||||
|
||||
if (string.IsNullOrEmpty(botName) || (botName[0] == '.')) {
|
||||
return;
|
||||
}
|
||||
|
@ -343,6 +362,7 @@ namespace ArchiSteamFarm {
|
|||
if (botName.Equals(SharedInfo.ASF)) {
|
||||
ArchiLogger.LogGenericInfo(Strings.GlobalConfigChanged);
|
||||
await RestartOrExit().ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -360,6 +380,7 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnCreatedFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -368,9 +389,11 @@ namespace ArchiSteamFarm {
|
|||
switch (extension) {
|
||||
case SharedInfo.ConfigExtension:
|
||||
await OnCreatedConfigFile(name, fullPath).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
case SharedInfo.KeysExtension:
|
||||
await OnCreatedKeysFile(name, fullPath).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -378,10 +401,12 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnCreatedKeysFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string botName = Path.GetFileNameWithoutExtension(name);
|
||||
|
||||
if (string.IsNullOrEmpty(botName) || (botName[0] == '.')) {
|
||||
return;
|
||||
}
|
||||
|
@ -400,6 +425,7 @@ namespace ArchiSteamFarm {
|
|||
private static async void OnDeleted(object sender, FileSystemEventArgs e) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -409,10 +435,12 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnDeletedConfigFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string botName = Path.GetFileNameWithoutExtension(name);
|
||||
|
||||
if (string.IsNullOrEmpty(botName)) {
|
||||
return;
|
||||
}
|
||||
|
@ -429,12 +457,14 @@ namespace ArchiSteamFarm {
|
|||
// Some editors might decide to delete file and re-create it in order to modify it
|
||||
// If that's the case, we wait for maximum of 5 seconds before shutting down
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
if (File.Exists(fullPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArchiLogger.LogGenericError(Strings.ErrorGlobalConfigRemoved);
|
||||
await Program.Exit(1).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -450,6 +480,7 @@ namespace ArchiSteamFarm {
|
|||
private static async Task OnDeletedFile(string name, string fullPath) {
|
||||
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(fullPath)) {
|
||||
ArchiLogger.LogNullError(nameof(name) + " || " + nameof(fullPath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -458,6 +489,7 @@ namespace ArchiSteamFarm {
|
|||
switch (extension) {
|
||||
case SharedInfo.ConfigExtension:
|
||||
await OnDeletedConfigFile(name, fullPath).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -465,6 +497,7 @@ namespace ArchiSteamFarm {
|
|||
private static async void OnRenamed(object sender, RenamedEventArgs e) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -475,6 +508,7 @@ namespace ArchiSteamFarm {
|
|||
private static bool UpdateFromArchive(ZipArchive archive, string targetDirectory) {
|
||||
if ((archive == null) || string.IsNullOrEmpty(targetDirectory)) {
|
||||
ArchiLogger.LogNullError(nameof(archive) + " || " + nameof(targetDirectory));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -487,6 +521,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (string.IsNullOrEmpty(fileName)) {
|
||||
ArchiLogger.LogNullError(nameof(fileName));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -494,6 +529,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (string.IsNullOrEmpty(relativeFilePath)) {
|
||||
ArchiLogger.LogNullError(nameof(relativeFilePath));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -502,18 +538,22 @@ namespace ArchiSteamFarm {
|
|||
switch (relativeDirectoryName) {
|
||||
// Files in those directories we want to keep in their current place
|
||||
case SharedInfo.ConfigDirectory:
|
||||
|
||||
continue;
|
||||
case "":
|
||||
|
||||
switch (fileName) {
|
||||
// Files with those names in root directory we want to keep
|
||||
case SharedInfo.LogFile:
|
||||
case "NLog.config":
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
case null:
|
||||
ArchiLogger.LogNullError(nameof(relativeDirectoryName));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -543,6 +583,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (string.IsNullOrEmpty(directory)) {
|
||||
ArchiLogger.LogNullError(nameof(directory));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
HashSet<MobileAuthenticator.Confirmation> confirmations = await Bot.BotDatabase.MobileAuthenticator.GetConfirmations(acceptedType).ConfigureAwait(false);
|
||||
|
||||
if ((confirmations == null) || (confirmations.Count == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -125,6 +126,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
HashSet<ulong> giftCardIDs = await Bot.ArchiWebHandler.GetDigitalGiftCards().ConfigureAwait(false);
|
||||
|
||||
if ((giftCardIDs == null) || (giftCardIDs.Count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -136,6 +138,7 @@ namespace ArchiSteamFarm {
|
|||
await LimitGiftsRequestsAsync().ConfigureAwait(false);
|
||||
|
||||
bool result = await Bot.ArchiWebHandler.AcceptDigitalGiftCard(giftCardID).ConfigureAwait(false);
|
||||
|
||||
if (result) {
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.Success);
|
||||
} else {
|
||||
|
@ -150,6 +153,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task AcceptGuestPasses(IReadOnlyCollection<ulong> guestPassIDs) {
|
||||
if ((guestPassIDs == null) || (guestPassIDs.Count == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(guestPassIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -160,6 +164,7 @@ namespace ArchiSteamFarm {
|
|||
await LimitGiftsRequestsAsync().ConfigureAwait(false);
|
||||
|
||||
ArchiHandler.RedeemGuestPassResponseCallback response = await Bot.ArchiHandler.RedeemGuestPass(guestPassID).ConfigureAwait(false);
|
||||
|
||||
if (response != null) {
|
||||
if (response.Result == EResult.OK) {
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.Success);
|
||||
|
@ -186,6 +191,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
internal async Task<SemaphoreLock> GetTradingLock() {
|
||||
await TradingSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
return new SemaphoreLock(TradingSemaphore);
|
||||
}
|
||||
|
||||
|
@ -255,12 +261,14 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Utilities.InBackground(() => Bot.CardsFarmer.Resume(true));
|
||||
|
||||
return (true, Strings.BotAutomaticIdlingNowResumed);
|
||||
}
|
||||
|
||||
internal async Task<(bool Success, string Output)> SendTradeOffer(uint appID = Steam.Asset.SteamAppID, byte contextID = Steam.Asset.SteamCommunityContextID, ulong targetSteamID = 0, IReadOnlyCollection<Steam.Asset.EType> wantedTypes = null, IReadOnlyCollection<uint> wantedRealAppIDs = null) {
|
||||
if ((appID == 0) || (contextID == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(contextID));
|
||||
|
||||
return (false, string.Format(Strings.ErrorObjectIsNull, nameof(targetSteamID) + " || " + nameof(appID) + " || " + nameof(contextID)));
|
||||
}
|
||||
|
||||
|
@ -270,6 +278,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (targetSteamID == 0) {
|
||||
targetSteamID = GetFirstSteamMasterID();
|
||||
|
||||
if (targetSteamID == 0) {
|
||||
return (false, Strings.BotLootingMasterNotDefined);
|
||||
}
|
||||
|
@ -295,6 +304,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
HashSet<Steam.Asset> inventory = await Bot.ArchiWebHandler.GetInventory(Bot.SteamID, appID, contextID, true, wantedTypes, wantedRealAppIDs).ConfigureAwait(false);
|
||||
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
return (false, string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
|
||||
}
|
||||
|
@ -328,6 +338,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
SkipFirstShutdown = true;
|
||||
Utilities.InBackground(Bot.Start);
|
||||
|
||||
return (true, Strings.Done);
|
||||
}
|
||||
|
||||
|
@ -337,11 +348,13 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Bot.Stop();
|
||||
|
||||
return (true, Strings.Done);
|
||||
}
|
||||
|
||||
internal static async Task<(bool Success, string Message)> Update() {
|
||||
Version version = await ASF.Update(true).ConfigureAwait(false);
|
||||
|
||||
if (version == null) {
|
||||
return (false, null);
|
||||
}
|
||||
|
@ -351,6 +364,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Utilities.InBackground(ASF.RestartOrExit);
|
||||
|
||||
return (true, version.ToString());
|
||||
}
|
||||
|
||||
|
@ -362,6 +376,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
await GiftsSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
Utilities.InBackground(
|
||||
async () => {
|
||||
await Task.Delay(Program.GlobalConfig.GiftsLimiterDelay * 1000).ConfigureAwait(false);
|
||||
|
|
|
@ -32,18 +32,23 @@ namespace ArchiSteamFarm {
|
|||
internal static string Decrypt(ECryptoMethod cryptoMethod, string encrypted) {
|
||||
if (string.IsNullOrEmpty(encrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(encrypted));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (cryptoMethod) {
|
||||
case ECryptoMethod.PlainText:
|
||||
|
||||
return encrypted;
|
||||
case ECryptoMethod.AES:
|
||||
|
||||
return DecryptAES(encrypted);
|
||||
case ECryptoMethod.ProtectedDataForCurrentUser:
|
||||
|
||||
return DecryptProtectedDataForCurrentUser(encrypted);
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(cryptoMethod), cryptoMethod));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -51,18 +56,23 @@ namespace ArchiSteamFarm {
|
|||
internal static string Encrypt(ECryptoMethod cryptoMethod, string decrypted) {
|
||||
if (string.IsNullOrEmpty(decrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(decrypted));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (cryptoMethod) {
|
||||
case ECryptoMethod.PlainText:
|
||||
|
||||
return decrypted;
|
||||
case ECryptoMethod.AES:
|
||||
|
||||
return EncryptAES(decrypted);
|
||||
case ECryptoMethod.ProtectedDataForCurrentUser:
|
||||
|
||||
return EncryptProtectedDataForCurrentUser(decrypted);
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(cryptoMethod), cryptoMethod));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +80,7 @@ namespace ArchiSteamFarm {
|
|||
internal static void SetEncryptionKey(string key) {
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(key));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -79,20 +90,24 @@ namespace ArchiSteamFarm {
|
|||
private static string DecryptAES(string encrypted) {
|
||||
if (string.IsNullOrEmpty(encrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(encrypted));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] key;
|
||||
|
||||
using (SHA256 sha256 = SHA256.Create()) {
|
||||
key = sha256.ComputeHash(EncryptionKey);
|
||||
}
|
||||
|
||||
byte[] decryptedData = Convert.FromBase64String(encrypted);
|
||||
decryptedData = CryptoHelper.SymmetricDecrypt(decryptedData, key);
|
||||
|
||||
return Encoding.UTF8.GetString(decryptedData);
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +115,7 @@ namespace ArchiSteamFarm {
|
|||
private static string DecryptProtectedDataForCurrentUser(string encrypted) {
|
||||
if (string.IsNullOrEmpty(encrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(encrypted));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -113,9 +129,11 @@ namespace ArchiSteamFarm {
|
|||
return Encoding.UTF8.GetString(decryptedData);
|
||||
} catch (PlatformNotSupportedException e) {
|
||||
ASF.ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -123,20 +141,24 @@ namespace ArchiSteamFarm {
|
|||
private static string EncryptAES(string decrypted) {
|
||||
if (string.IsNullOrEmpty(decrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(decrypted));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] key;
|
||||
|
||||
using (SHA256 sha256 = SHA256.Create()) {
|
||||
key = sha256.ComputeHash(EncryptionKey);
|
||||
}
|
||||
|
||||
byte[] encryptedData = Encoding.UTF8.GetBytes(decrypted);
|
||||
encryptedData = CryptoHelper.SymmetricEncrypt(encryptedData, key);
|
||||
|
||||
return Convert.ToBase64String(encryptedData);
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +166,7 @@ namespace ArchiSteamFarm {
|
|||
private static string EncryptProtectedDataForCurrentUser(string decrypted) {
|
||||
if (string.IsNullOrEmpty(decrypted)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(decrypted));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -157,9 +180,11 @@ namespace ArchiSteamFarm {
|
|||
return Convert.ToBase64String(encryptedData);
|
||||
} catch (PlatformNotSupportedException e) {
|
||||
ASF.ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace ArchiSteamFarm {
|
|||
public override void HandleMsg(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -70,24 +71,31 @@ namespace ArchiSteamFarm {
|
|||
switch (packetMsg.MsgType) {
|
||||
case EMsg.ClientItemAnnouncements:
|
||||
HandleItemAnnouncements(packetMsg);
|
||||
|
||||
break;
|
||||
case EMsg.ClientPlayingSessionState:
|
||||
HandlePlayingSessionState(packetMsg);
|
||||
|
||||
break;
|
||||
case EMsg.ClientPurchaseResponse:
|
||||
HandlePurchaseResponse(packetMsg);
|
||||
|
||||
break;
|
||||
case EMsg.ClientRedeemGuestPassResponse:
|
||||
HandleRedeemGuestPassResponse(packetMsg);
|
||||
|
||||
break;
|
||||
case EMsg.ClientSharedLibraryLockStatus:
|
||||
HandleSharedLibraryLockStatus(packetMsg);
|
||||
|
||||
break;
|
||||
case EMsg.ClientUserNotifications:
|
||||
HandleUserNotifications(packetMsg);
|
||||
|
||||
break;
|
||||
case EMsg.ClientVanityURLChangedNotification:
|
||||
HandleVanityURLChangedNotification(packetMsg);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +103,7 @@ namespace ArchiSteamFarm {
|
|||
internal void AckChatMessage(ulong chatGroupID, ulong chatID, uint timestamp) {
|
||||
if ((chatGroupID == 0) || (chatID == 0) || (timestamp == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(chatGroupID) + " || " + nameof(chatID) + " || " + nameof(timestamp));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -114,6 +123,7 @@ namespace ArchiSteamFarm {
|
|||
internal void AckMessage(ulong steamID, uint timestamp) {
|
||||
if ((steamID == 0) || (timestamp == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(timestamp));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -132,6 +142,7 @@ namespace ArchiSteamFarm {
|
|||
internal void AcknowledgeClanInvite(ulong clanID, bool acceptInvite) {
|
||||
if (clanID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(clanID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -152,6 +163,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<bool> AddFriend(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -167,11 +179,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedPlayerService.SendMessage(x => x.AddFriend(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -181,6 +195,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<ulong> GetClanChatGroupID(ulong steamID) {
|
||||
if ((steamID == 0) || !new SteamID(steamID).IsClanAccount) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -199,11 +214,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedClanChatRoomsService.SendMessage(x => x.GetClanChatRoomInfo(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -212,6 +229,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
CClanChatRooms_GetClanChatRoomInfo_Response body = response.GetDeserializedResponse<CClanChatRooms_GetClanChatRoomInfo_Response>();
|
||||
|
||||
return body.chat_group_summary.chat_group_id;
|
||||
}
|
||||
|
||||
|
@ -227,11 +245,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedPlayerService.SendMessage(x => x.GetGameBadgeLevels(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -240,6 +260,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
CPlayer_GetGameBadgeLevels_Response body = response.GetDeserializedResponse<CPlayer_GetGameBadgeLevels_Response>();
|
||||
|
||||
return body.player_level;
|
||||
}
|
||||
|
||||
|
@ -256,11 +277,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedChatRoomService.SendMessage(x => x.GetMyChatRoomGroups(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -269,6 +292,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
CChatRoom_GetMyChatRoomGroups_Response body = response.GetDeserializedResponse<CChatRoom_GetMyChatRoomGroups_Response>();
|
||||
|
||||
return body.chat_room_groups.Select(chatRoom => chatRoom.group_summary.chat_group_id).ToHashSet();
|
||||
}
|
||||
|
||||
|
@ -285,11 +309,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedEconService.SendMessage(x => x.GetTradeOfferAccessToken(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -298,12 +324,14 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
CEcon_GetTradeOfferAccessToken_Response body = response.GetDeserializedResponse<CEcon_GetTradeOfferAccessToken_Response>();
|
||||
|
||||
return body.trade_offer_access_token;
|
||||
}
|
||||
|
||||
internal async Task<bool> JoinChatRoomGroup(ulong chatGroupID) {
|
||||
if (chatGroupID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(chatGroupID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -319,11 +347,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedChatRoomService.SendMessage(x => x.JoinChatRoomGroup(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -333,6 +363,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task PlayGames(IEnumerable<uint> gameIDs, string gameName = null) {
|
||||
if (gameIDs == null) {
|
||||
ArchiLogger.LogNullError(nameof(gameIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -378,6 +409,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<RedeemGuestPassResponseCallback> RedeemGuestPass(ulong guestPassID) {
|
||||
if (guestPassID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(guestPassID));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -396,6 +428,7 @@ namespace ArchiSteamFarm {
|
|||
return await new AsyncJob<RedeemGuestPassResponseCallback>(Client, request.SourceJobID);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -403,6 +436,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<PurchaseResponseCallback> RedeemKey(string key) {
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
ArchiLogger.LogNullError(nameof(key));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -421,6 +455,7 @@ namespace ArchiSteamFarm {
|
|||
return await new AsyncJob<PurchaseResponseCallback>(Client, request.SourceJobID);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -428,6 +463,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<bool> RemoveFriend(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -443,11 +479,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedPlayerService.SendMessage(x => x.RemoveFriend(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -466,6 +504,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<EResult> SendMessage(ulong steamID, string message) {
|
||||
if ((steamID == 0) || string.IsNullOrEmpty(message)) {
|
||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(message));
|
||||
|
||||
return EResult.Fail;
|
||||
}
|
||||
|
||||
|
@ -486,11 +525,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedFriendMessagesService.SendMessage(x => x.SendMessage(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return EResult.Timeout;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return EResult.Fail;
|
||||
}
|
||||
|
||||
|
@ -500,6 +541,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<EResult> SendMessage(ulong chatGroupID, ulong chatID, string message) {
|
||||
if ((chatGroupID == 0) || (chatID == 0) || string.IsNullOrEmpty(message)) {
|
||||
ArchiLogger.LogNullError(nameof(chatGroupID) + " || " + nameof(chatID) + " || " + nameof(message));
|
||||
|
||||
return EResult.Fail;
|
||||
}
|
||||
|
||||
|
@ -519,11 +561,13 @@ namespace ArchiSteamFarm {
|
|||
response = await UnifiedChatRoomService.SendMessage(x => x.SendChatMessage(request));
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return EResult.Timeout;
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
ArchiLogger.LogNullError(nameof(response));
|
||||
|
||||
return EResult.Fail;
|
||||
}
|
||||
|
||||
|
@ -533,6 +577,7 @@ namespace ArchiSteamFarm {
|
|||
internal void SetCurrentMode(uint chatMode) {
|
||||
if (chatMode == 0) {
|
||||
ArchiLogger.LogNullError(nameof(chatMode));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -547,6 +592,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandleItemAnnouncements(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -557,6 +603,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandlePlayingSessionState(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -567,6 +614,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandlePurchaseResponse(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -577,6 +625,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandleRedeemGuestPassResponse(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -587,6 +636,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandleSharedLibraryLockStatus(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -597,6 +647,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandleUserNotifications(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -607,6 +658,7 @@ namespace ArchiSteamFarm {
|
|||
private void HandleVanityURLChangedNotification(IPacketMsg packetMsg) {
|
||||
if (packetMsg == null) {
|
||||
ArchiLogger.LogNullError(nameof(packetMsg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -632,38 +684,48 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (msg.purchase_receipt_info == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(msg.purchase_receipt_info));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
KeyValue receiptInfo = new KeyValue();
|
||||
|
||||
using (MemoryStream ms = new MemoryStream(msg.purchase_receipt_info)) {
|
||||
if (!receiptInfo.TryReadAsBinary(ms)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(ms));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<KeyValue> lineItems = receiptInfo["lineitems"].Children;
|
||||
|
||||
if (lineItems.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Items = new Dictionary<uint, string>(lineItems.Count);
|
||||
|
||||
foreach (KeyValue lineItem in lineItems) {
|
||||
uint packageID = lineItem["PackageID"].AsUnsignedInteger();
|
||||
|
||||
if (packageID == 0) {
|
||||
// Coupons have PackageID of -1 (don't ask me why)
|
||||
// We'll use ItemAppID in this case
|
||||
packageID = lineItem["ItemAppID"].AsUnsignedInteger();
|
||||
|
||||
if (packageID == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(packageID));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string gameName = lineItem["ItemDescription"].Value;
|
||||
|
||||
if (string.IsNullOrEmpty(gameName)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(gameName));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -749,9 +811,11 @@ namespace ArchiSteamFarm {
|
|||
case EUserNotification.Items:
|
||||
case EUserNotification.ModeratorMessages:
|
||||
case EUserNotification.Trading:
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(type), type));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -272,6 +272,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task AddGamesToRedeemInBackground(IOrderedDictionary gamesToRedeemInBackground) {
|
||||
if ((gamesToRedeemInBackground == null) || (gamesToRedeemInBackground.Count == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(gamesToRedeemInBackground));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -313,6 +314,7 @@ namespace ArchiSteamFarm {
|
|||
return true;
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +332,7 @@ namespace ArchiSteamFarm {
|
|||
return true;
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -337,6 +340,7 @@ namespace ArchiSteamFarm {
|
|||
internal static string FormatBotResponse(string response, string botName) {
|
||||
if (string.IsNullOrEmpty(response) || string.IsNullOrEmpty(botName)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(response) + " || " + nameof(botName));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -346,11 +350,13 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<(uint PlayableAppID, DateTime IgnoredUntil)> GetAppDataForIdling(uint appID, float hoursPlayed, bool allowRecursiveDiscovery = true, bool optimisticDiscovery = true) {
|
||||
if ((appID == 0) || (hoursPlayed < 0)) {
|
||||
ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(hoursPlayed));
|
||||
|
||||
return (0, DateTime.MaxValue);
|
||||
}
|
||||
|
||||
if ((hoursPlayed < CardsFarmer.HoursForRefund) && !BotConfig.IdleRefundableGames) {
|
||||
HashSet<uint> packageIDs = Program.GlobalDatabase.GetPackageIDs(appID);
|
||||
|
||||
if (packageIDs == null) {
|
||||
return (0, DateTime.MaxValue);
|
||||
}
|
||||
|
@ -370,6 +376,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (mostRecent > DateTime.MinValue) {
|
||||
DateTime playableIn = mostRecent.AddDays(CardsFarmer.DaysForRefund);
|
||||
|
||||
if (playableIn > DateTime.UtcNow) {
|
||||
return (0, playableIn);
|
||||
}
|
||||
|
@ -401,32 +408,40 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
KeyValue productInfo = productInfoApp.KeyValues;
|
||||
|
||||
if (productInfo == KeyValue.Invalid) {
|
||||
ArchiLogger.LogNullError(nameof(productInfo));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
KeyValue commonProductInfo = productInfo["common"];
|
||||
|
||||
if (commonProductInfo == KeyValue.Invalid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string releaseState = commonProductInfo["ReleaseState"].Value;
|
||||
|
||||
if (!string.IsNullOrEmpty(releaseState)) {
|
||||
// We must convert this to uppercase, since Valve doesn't stick to any convention and we can have a case mismatch
|
||||
switch (releaseState.ToUpperInvariant()) {
|
||||
case "RELEASED":
|
||||
|
||||
break;
|
||||
case "PRELOADONLY":
|
||||
case "PRERELEASE":
|
||||
|
||||
return (0, DateTime.MaxValue);
|
||||
default:
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(releaseState), releaseState));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string type = commonProductInfo["type"].Value;
|
||||
|
||||
if (string.IsNullOrEmpty(type)) {
|
||||
return (appID, DateTime.MinValue);
|
||||
}
|
||||
|
@ -442,6 +457,7 @@ namespace ArchiSteamFarm {
|
|||
case "SERIES":
|
||||
case "TOOL":
|
||||
case "VIDEO":
|
||||
|
||||
return (appID, DateTime.MinValue);
|
||||
|
||||
// Types that can't be idled
|
||||
|
@ -450,9 +466,11 @@ namespace ArchiSteamFarm {
|
|||
case "DLC":
|
||||
case "GUIDE":
|
||||
case "HARDWARE":
|
||||
|
||||
break;
|
||||
default:
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(type), type));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -461,6 +479,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string listOfDlc = productInfo["extended"]["listofdlc"].Value;
|
||||
|
||||
if (string.IsNullOrEmpty(listOfDlc)) {
|
||||
return (appID, DateTime.MinValue);
|
||||
}
|
||||
|
@ -470,10 +489,12 @@ namespace ArchiSteamFarm {
|
|||
foreach (string dlcAppIDsText in dlcAppIDsTexts) {
|
||||
if (!uint.TryParse(dlcAppIDsText, out uint dlcAppID) || (dlcAppID == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(dlcAppID));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
(uint playableAppID, _) = await GetAppDataForIdling(dlcAppID, hoursPlayed, false, false).ConfigureAwait(false);
|
||||
|
||||
if (playableAppID != 0) {
|
||||
return (playableAppID, DateTime.MinValue);
|
||||
}
|
||||
|
@ -488,12 +509,14 @@ namespace ArchiSteamFarm {
|
|||
internal static HashSet<Bot> GetBots(string args) {
|
||||
if (string.IsNullOrEmpty(args)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string[] botNames = args.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
HashSet<Bot> result = new HashSet<Bot>();
|
||||
|
||||
foreach (string botName in botNames) {
|
||||
if (botName.Equals(SharedInfo.ASF, StringComparison.OrdinalIgnoreCase)) {
|
||||
foreach (Bot bot in Bots.OrderBy(bot => bot.Key).Select(bot => bot.Value)) {
|
||||
|
@ -505,6 +528,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (botName.Contains("..")) {
|
||||
string[] botRange = botName.Split(new[] { ".." }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (botRange.Length == 2) {
|
||||
if (Bots.TryGetValue(botRange[0], out Bot firstBot) && Bots.TryGetValue(botRange[1], out Bot lastBot)) {
|
||||
bool inRange = false;
|
||||
|
@ -534,6 +558,7 @@ namespace ArchiSteamFarm {
|
|||
result.UnionWith(regexMatches);
|
||||
} catch (ArgumentException e) {
|
||||
ASF.ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -553,6 +578,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<Dictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)>> GetPackagesData(IReadOnlyCollection<uint> packageIDs) {
|
||||
if ((packageIDs == null) || (packageIDs.Count == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(packageIDs));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -579,6 +605,7 @@ namespace ArchiSteamFarm {
|
|||
foreach (SteamApps.PICSProductInfoCallback.PICSProductInfo productInfo in productInfoResultSet.Results.SelectMany(productInfoResult => productInfoResult.Packages).Where(productInfoPackages => productInfoPackages.Key != 0).Select(productInfoPackages => productInfoPackages.Value)) {
|
||||
if (productInfo.KeyValues == KeyValue.Invalid) {
|
||||
ArchiLogger.LogNullError(nameof(productInfo));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -586,6 +613,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
try {
|
||||
KeyValue appIDs = productInfo.KeyValues["appids"];
|
||||
|
||||
if (appIDs == KeyValue.Invalid) {
|
||||
continue;
|
||||
}
|
||||
|
@ -595,6 +623,7 @@ namespace ArchiSteamFarm {
|
|||
foreach (string appIDText in appIDs.Children.Select(app => app.Value)) {
|
||||
if (!uint.TryParse(appIDText, out uint appID) || (appID == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -611,6 +640,7 @@ namespace ArchiSteamFarm {
|
|||
internal BotConfig.EPermission GetSteamUserPermission(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return BotConfig.EPermission.None;
|
||||
}
|
||||
|
||||
|
@ -620,6 +650,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<byte?> GetTradeHoldDuration(ulong steamID, ulong tradeID) {
|
||||
if ((steamID == 0) || (tradeID == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(tradeID));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -628,8 +659,10 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Bot targetBot = Bots.Values.FirstOrDefault(bot => bot.SteamID == steamID);
|
||||
|
||||
if (targetBot != null) {
|
||||
string targetTradeToken = await targetBot.ArchiHandler.GetTradeToken().ConfigureAwait(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(targetTradeToken)) {
|
||||
return await ArchiWebHandler.GetTradeHoldDurationForUser(steamID, targetTradeToken).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -640,12 +673,14 @@ namespace ArchiSteamFarm {
|
|||
|
||||
internal async Task<(Dictionary<string, string> UnusedKeys, Dictionary<string, string> UsedKeys)> GetUsedAndUnusedKeys() {
|
||||
IList<Dictionary<string, string>> results = await Utilities.InParallel(new[] { KeysToRedeemUnusedFilePath, KeysToRedeemUsedFilePath }.Select(GetKeysFromFile)).ConfigureAwait(false);
|
||||
|
||||
return (results[0], results[1]);
|
||||
}
|
||||
|
||||
internal async Task IdleGame(CardsFarmer.Game game) {
|
||||
if (game == null) {
|
||||
ArchiLogger.LogNullError(nameof(game));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -655,6 +690,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task IdleGames(IReadOnlyCollection<CardsFarmer.Game> games) {
|
||||
if ((games == null) || (games.Count == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(games));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -664,6 +700,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task ImportKeysToRedeem(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) {
|
||||
ArchiLogger.LogNullError(nameof(filePath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -686,6 +723,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (parsedArgs.Length < 1) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, line));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -713,6 +751,7 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task InitializeSteamConfiguration(ProtocolTypes protocolTypes, uint cellID, IServerListProvider serverListProvider) {
|
||||
if (serverListProvider == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(serverListProvider));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -720,6 +759,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Ensure that we ask for a list of servers if we don't have any saved servers available
|
||||
IEnumerable<ServerRecord> servers = await SteamConfiguration.ServerListProvider.FetchServerListAsync().ConfigureAwait(false);
|
||||
|
||||
if (servers?.Any() != true) {
|
||||
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.Initializing, nameof(SteamDirectory)));
|
||||
|
||||
|
@ -735,6 +775,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsBlacklistedFromIdling(uint appID) {
|
||||
if (appID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -744,6 +785,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsBlacklistedFromTrades(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -753,6 +795,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsFamilySharing(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -762,6 +805,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsMaster(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -771,6 +815,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsPriorityIdling(uint appID) {
|
||||
if (appID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -780,6 +825,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task OnConfigChanged(bool deleted) {
|
||||
if (deleted) {
|
||||
Destroy();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -787,6 +833,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (botConfig == null) {
|
||||
Destroy();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -825,6 +872,7 @@ namespace ArchiSteamFarm {
|
|||
if (BotConfig.ShutdownOnFarmingFinished) {
|
||||
if (farmedSomething || (Program.GlobalConfig.IdleFarmingPeriod == 0)) {
|
||||
Stop();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -850,11 +898,13 @@ namespace ArchiSteamFarm {
|
|||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
await Connect(true).ConfigureAwait(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(callback?.Nonce)) {
|
||||
await Connect(true).ConfigureAwait(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -863,12 +913,14 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
await Connect(true).ConfigureAwait(false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static async Task RegisterBot(string botName) {
|
||||
if (string.IsNullOrEmpty(botName)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botName));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -880,8 +932,10 @@ namespace ArchiSteamFarm {
|
|||
string configFilePath = botPath + SharedInfo.ConfigExtension;
|
||||
|
||||
BotConfig botConfig = await BotConfig.Load(botPath + SharedInfo.ConfigExtension).ConfigureAwait(false);
|
||||
|
||||
if (botConfig == null) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorBotConfigInvalid, configFilePath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -892,8 +946,10 @@ namespace ArchiSteamFarm {
|
|||
string databaseFilePath = botPath + SharedInfo.DatabaseExtension;
|
||||
|
||||
BotDatabase botDatabase = await BotDatabase.CreateOrLoad(databaseFilePath).ConfigureAwait(false);
|
||||
|
||||
if (botDatabase == null) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorDatabaseInvalid, databaseFilePath));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -928,6 +984,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<bool> SendMessage(ulong steamID, string message) {
|
||||
if ((steamID == 0) || string.IsNullOrEmpty(message)) {
|
||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(message));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -965,19 +1022,23 @@ namespace ArchiSteamFarm {
|
|||
switch (result) {
|
||||
case EResult.OK:
|
||||
sent = true;
|
||||
|
||||
break;
|
||||
case EResult.RateLimitExceeded:
|
||||
case EResult.Timeout:
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
continue;
|
||||
default:
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(result), result));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sent) {
|
||||
ArchiLogger.LogGenericWarning(Strings.WarningFailed);
|
||||
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
|
@ -991,6 +1052,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<bool> SendMessage(ulong chatGroupID, ulong chatID, string message) {
|
||||
if ((chatGroupID == 0) || (chatID == 0) || string.IsNullOrEmpty(message)) {
|
||||
ArchiLogger.LogNullError(nameof(chatGroupID) + " || " + nameof(chatID) + " || " + nameof(message));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1028,19 +1090,23 @@ namespace ArchiSteamFarm {
|
|||
switch (result) {
|
||||
case EResult.OK:
|
||||
sent = true;
|
||||
|
||||
break;
|
||||
case EResult.RateLimitExceeded:
|
||||
case EResult.Timeout:
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
continue;
|
||||
default:
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(result), result));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sent) {
|
||||
ArchiLogger.LogGenericWarning(Strings.WarningFailed);
|
||||
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
|
@ -1060,14 +1126,17 @@ namespace ArchiSteamFarm {
|
|||
switch (inputType) {
|
||||
case ASF.EUserInputType.DeviceID:
|
||||
DeviceID = inputValue;
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Login:
|
||||
|
||||
if (BotConfig != null) {
|
||||
BotConfig.SteamLogin = inputValue;
|
||||
}
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Password:
|
||||
|
||||
if (BotConfig != null) {
|
||||
BotConfig.DecryptedSteamPassword = inputValue;
|
||||
}
|
||||
|
@ -1075,8 +1144,10 @@ namespace ArchiSteamFarm {
|
|||
break;
|
||||
case ASF.EUserInputType.SteamGuard:
|
||||
AuthCode = inputValue;
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamParentalCode:
|
||||
|
||||
if (BotConfig != null) {
|
||||
BotConfig.SteamParentalCode = inputValue;
|
||||
}
|
||||
|
@ -1084,9 +1155,11 @@ namespace ArchiSteamFarm {
|
|||
break;
|
||||
case ASF.EUserInputType.TwoFactorAuthentication:
|
||||
TwoFactorCode = inputValue;
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(inputType), inputType));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1132,6 +1205,7 @@ namespace ArchiSteamFarm {
|
|||
internal static IOrderedDictionary ValidateGamesToRedeemInBackground(IOrderedDictionary gamesToRedeemInBackground) {
|
||||
if ((gamesToRedeemInBackground == null) || (gamesToRedeemInBackground.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(gamesToRedeemInBackground));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1141,6 +1215,7 @@ namespace ArchiSteamFarm {
|
|||
bool invalid = false;
|
||||
|
||||
string key = game.Key as string;
|
||||
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
invalid = true;
|
||||
ASF.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, nameof(key)));
|
||||
|
@ -1150,6 +1225,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string name = game.Value as string;
|
||||
|
||||
if (string.IsNullOrEmpty(name)) {
|
||||
invalid = true;
|
||||
ASF.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, nameof(name)));
|
||||
|
@ -1175,6 +1251,7 @@ namespace ArchiSteamFarm {
|
|||
if (!IsPlayingPossible) {
|
||||
ArchiLogger.LogGenericInfo(Strings.BotAccountOccupied);
|
||||
PlayingWasBlocked = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1221,6 +1298,7 @@ namespace ArchiSteamFarm {
|
|||
private static string Escape(string message) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(message));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1230,6 +1308,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<Dictionary<string, string>> GetKeysFromFile(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
ArchiLogger.LogNullError(nameof(filePath));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1249,14 +1328,18 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string[] parsedArgs = line.Split(DefaultBackgroundKeysRedeemerSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (parsedArgs.Length < 3) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, line));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string key = parsedArgs[parsedArgs.Length - 1];
|
||||
|
||||
if (!Utilities.IsValidCdKey(key)) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsInvalid, key));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1268,12 +1351,14 @@ namespace ArchiSteamFarm {
|
|||
return keys;
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCallbacks() {
|
||||
TimeSpan timeSpan = TimeSpan.FromMilliseconds(CallbackSleep);
|
||||
|
||||
while (KeepRunning || SteamClient.IsConnected) {
|
||||
if (!CallbackSemaphore.Wait(0)) {
|
||||
if (Debugging.IsUserDebugging) {
|
||||
|
@ -1296,6 +1381,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task HandleMessage(ulong chatGroupID, ulong chatID, ulong steamID, string message) {
|
||||
if ((chatGroupID == 0) || (chatID == 0) || (steamID == 0) || string.IsNullOrEmpty(message)) {
|
||||
ArchiLogger.LogNullError(nameof(chatGroupID) + " || " + nameof(chatID) + " || " + nameof(steamID) + " || " + nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1312,6 +1398,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task HandleMessage(ulong steamID, string message) {
|
||||
if ((steamID == 0) || string.IsNullOrEmpty(message)) {
|
||||
ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1368,11 +1455,13 @@ namespace ArchiSteamFarm {
|
|||
File.Delete(maFilePath);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (BotDatabase.MobileAuthenticator == null) {
|
||||
ArchiLogger.LogNullError(nameof(BotDatabase.MobileAuthenticator));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1380,10 +1469,13 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!BotDatabase.MobileAuthenticator.HasCorrectDeviceID) {
|
||||
ArchiLogger.LogGenericWarning(Strings.BotAuthenticatorInvalidDeviceID);
|
||||
|
||||
if (string.IsNullOrEmpty(DeviceID)) {
|
||||
string deviceID = Program.GetUserInput(ASF.EUserInputType.DeviceID, BotName);
|
||||
|
||||
if (string.IsNullOrEmpty(deviceID)) {
|
||||
await BotDatabase.SetMobileAuthenticator().ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1411,6 +1503,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
private async Task InitializeFamilySharing() {
|
||||
HashSet<ulong> steamIDs = await ArchiWebHandler.GetFamilySharingSteamIDs().ConfigureAwait(false);
|
||||
|
||||
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1421,6 +1514,7 @@ namespace ArchiSteamFarm {
|
|||
private bool InitLoginAndPassword(bool requiresPassword) {
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
string steamLogin = Program.GetUserInput(ASF.EUserInputType.Login, BotName);
|
||||
|
||||
if (string.IsNullOrEmpty(steamLogin)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1430,6 +1524,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (requiresPassword && string.IsNullOrEmpty(BotConfig.DecryptedSteamPassword)) {
|
||||
string steamPassword = Program.GetUserInput(ASF.EUserInputType.Password, BotName);
|
||||
|
||||
if (string.IsNullOrEmpty(steamPassword)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1480,6 +1575,7 @@ namespace ArchiSteamFarm {
|
|||
private void InitStart() {
|
||||
if (!BotConfig.Enabled) {
|
||||
ArchiLogger.LogGenericInfo(Strings.BotInstanceNotStartingBecauseDisabled);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1490,6 +1586,7 @@ namespace ArchiSteamFarm {
|
|||
private bool IsMasterClanID(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1499,6 +1596,7 @@ namespace ArchiSteamFarm {
|
|||
private static bool IsRefundable(EPaymentMethod method) {
|
||||
if (method == EPaymentMethod.None) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(method));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1507,8 +1605,10 @@ namespace ArchiSteamFarm {
|
|||
case EPaymentMethod.Complimentary: // This is also a flag
|
||||
case EPaymentMethod.GuestPass:
|
||||
case EPaymentMethod.HardwarePromo:
|
||||
|
||||
return false;
|
||||
default:
|
||||
|
||||
if (method.HasFlag(EPaymentMethod.Complimentary)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1545,6 +1645,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
await LoginSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
Utilities.InBackground(
|
||||
async () => {
|
||||
await Task.Delay(Program.GlobalConfig.LoginLimiterDelay * 1000).ConfigureAwait(false);
|
||||
|
@ -1556,6 +1657,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnConnected(SteamClient.ConnectedCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1568,6 +1670,7 @@ namespace ArchiSteamFarm {
|
|||
if (!KeepRunning) {
|
||||
ArchiLogger.LogGenericInfo(Strings.BotDisconnecting);
|
||||
Disconnect();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1607,6 +1710,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!InitLoginAndPassword(string.IsNullOrEmpty(loginKey))) {
|
||||
Stop();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1614,8 +1718,8 @@ namespace ArchiSteamFarm {
|
|||
const string nonAsciiPattern = @"[^\u0000-\u007F]+";
|
||||
|
||||
string username = Regex.Replace(BotConfig.SteamLogin, nonAsciiPattern, "", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
|
||||
string password = BotConfig.DecryptedSteamPassword;
|
||||
|
||||
if (!string.IsNullOrEmpty(password)) {
|
||||
password = Regex.Replace(password, nonAsciiPattern, "", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
@ -1647,6 +1751,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnDisconnected(SteamClient.DisconnectedCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1672,14 +1777,18 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (lastLogOnResult) {
|
||||
case EResult.AccountDisabled:
|
||||
|
||||
// Do not attempt to reconnect, those failures are permanent
|
||||
return;
|
||||
case EResult.Invalid:
|
||||
|
||||
// Invalid means that we didn't get OnLoggedOn() in the first place, so Steam is down
|
||||
// Always reset one-time-only access tokens in this case, as OnLoggedOn() didn't do that for us
|
||||
AuthCode = TwoFactorCode = null;
|
||||
|
||||
break;
|
||||
case EResult.InvalidPassword:
|
||||
|
||||
// If we didn't use login key, it's nearly always rate limiting
|
||||
if (string.IsNullOrEmpty(BotDatabase.LoginKey)) {
|
||||
goto case EResult.RateLimitExceeded;
|
||||
|
@ -1687,16 +1796,19 @@ namespace ArchiSteamFarm {
|
|||
|
||||
await BotDatabase.SetLoginKey().ConfigureAwait(false);
|
||||
ArchiLogger.LogGenericInfo(Strings.BotRemovedExpiredLoginKey);
|
||||
|
||||
break;
|
||||
case EResult.NoConnection:
|
||||
case EResult.ServiceUnavailable:
|
||||
case EResult.Timeout:
|
||||
case EResult.TryAnotherCM:
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
case EResult.RateLimitExceeded:
|
||||
ArchiLogger.LogGenericInfo(string.Format(Strings.BotRateLimitExceeded, TimeSpan.FromMinutes(LoginCooldownInMinutes).ToHumanReadable()));
|
||||
await Task.Delay(LoginCooldownInMinutes * 60 * 1000).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1711,6 +1823,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnFriendsList(SteamFriends.FriendsListCallback callback) {
|
||||
if (callback?.FriendList == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback) + " || " + nameof(callback.FriendList));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1719,14 +1832,17 @@ namespace ArchiSteamFarm {
|
|||
case EAccountType.Clan when IsMasterClanID(friend.SteamID):
|
||||
ArchiHandler.AcknowledgeClanInvite(friend.SteamID, true);
|
||||
await JoinMasterChatGroupID().ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
case EAccountType.Clan:
|
||||
|
||||
if (BotConfig.BotBehaviour.HasFlag(BotConfig.EBotBehaviour.RejectInvalidGroupInvites)) {
|
||||
ArchiHandler.AcknowledgeClanInvite(friend.SteamID, false);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (IsFamilySharing(friend.SteamID)) {
|
||||
await ArchiHandler.AddFriend(friend.SteamID).ConfigureAwait(false);
|
||||
} else if (BotConfig.BotBehaviour.HasFlag(BotConfig.EBotBehaviour.RejectInvalidFriendInvites)) {
|
||||
|
@ -1741,6 +1857,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnGuestPassList(SteamApps.GuestPassListCallback callback) {
|
||||
if (callback?.GuestPasses == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback) + " || " + nameof(callback.GuestPasses));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1749,6 +1866,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
HashSet<ulong> guestPassIDs = callback.GuestPasses.Select(guestPass => guestPass["gid"].AsUnsignedLong()).Where(gid => gid != 0).ToHashSet();
|
||||
|
||||
if (guestPassIDs.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1759,6 +1877,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task OnIncomingChatMessage(CChatRoom_IncomingChatMessage_Notification notification) {
|
||||
if (notification == null) {
|
||||
ArchiLogger.LogNullError(nameof(notification));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1794,6 +1913,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task OnIncomingMessage(CFriendMessages_IncomingMessage_Notification notification) {
|
||||
if (notification == null) {
|
||||
ArchiLogger.LogNullError(nameof(notification));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1833,6 +1953,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnLicenseList(SteamApps.LicenseListCallback callback) {
|
||||
if (callback?.LicenseList == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback) + " || " + nameof(callback.LicenseList));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1881,6 +2002,7 @@ namespace ArchiSteamFarm {
|
|||
private void OnLoggedOff(SteamUser.LoggedOffCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1890,8 +2012,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (callback.Result) {
|
||||
case EResult.LoggedInElsewhere:
|
||||
|
||||
// This result directly indicates that playing was blocked when we got (forcefully) disconnected
|
||||
PlayingWasBlocked = true;
|
||||
|
||||
break;
|
||||
case EResult.LogonSessionReplaced:
|
||||
DateTime now = DateTime.UtcNow;
|
||||
|
@ -1899,10 +2023,12 @@ namespace ArchiSteamFarm {
|
|||
if (now.Subtract(LastLogonSessionReplaced).TotalHours < 1) {
|
||||
ArchiLogger.LogGenericError(Strings.BotLogonSessionReplaced);
|
||||
Stop();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LastLogonSessionReplaced = now;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1913,6 +2039,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnLoggedOn(SteamUser.LoggedOnCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1927,24 +2054,32 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (callback.Result) {
|
||||
case EResult.AccountDisabled:
|
||||
|
||||
// Those failures are permanent, we should Stop() the bot if any of those happen
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.BotUnableToLogin, callback.Result, callback.ExtendedResult));
|
||||
Stop();
|
||||
|
||||
break;
|
||||
case EResult.AccountLogonDenied:
|
||||
string authCode = Program.GetUserInput(ASF.EUserInputType.SteamGuard, BotName);
|
||||
|
||||
if (string.IsNullOrEmpty(authCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SetUserInput(ASF.EUserInputType.SteamGuard, authCode);
|
||||
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
|
||||
if (!HasMobileAuthenticator) {
|
||||
string twoFactorCode = Program.GetUserInput(ASF.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
|
||||
if (string.IsNullOrEmpty(twoFactorCode)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1986,6 +2121,7 @@ namespace ArchiSteamFarm {
|
|||
if (!HasMobileAuthenticator) {
|
||||
// Support and convert 2FA files
|
||||
string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, callback.ClientSteamID.ConvertToUInt64() + ".maFile");
|
||||
|
||||
if (File.Exists(maFilePath)) {
|
||||
await ImportAuthenticator(maFilePath).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -1993,8 +2129,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!string.IsNullOrEmpty(BotConfig.SteamParentalCode) && (BotConfig.SteamParentalCode.Length != 4)) {
|
||||
string steamParentalCode = Program.GetUserInput(ASF.EUserInputType.SteamParentalCode, BotName);
|
||||
|
||||
if (string.IsNullOrEmpty(steamParentalCode) || (steamParentalCode.Length != 4)) {
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2065,9 +2203,11 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
// Unexpected result, shutdown immediately
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.BotUnableToLogin, callback.Result, callback.ExtendedResult));
|
||||
Stop();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2075,6 +2215,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnLoginKey(SteamUser.LoginKeyCallback callback) {
|
||||
if (string.IsNullOrEmpty(callback?.LoginKey)) {
|
||||
ArchiLogger.LogNullError(nameof(callback) + " || " + nameof(callback.LoginKey));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2083,6 +2224,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string loginKey = callback.LoginKey;
|
||||
|
||||
if (BotConfig.PasswordFormat != ArchiCryptoHelper.ECryptoMethod.PlainText) {
|
||||
loginKey = ArchiCryptoHelper.Encrypt(BotConfig.PasswordFormat, loginKey);
|
||||
}
|
||||
|
@ -2094,6 +2236,7 @@ namespace ArchiSteamFarm {
|
|||
private void OnMachineAuth(SteamUser.UpdateMachineAuthCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2107,6 +2250,7 @@ namespace ArchiSteamFarm {
|
|||
fileSize = (int) fileStream.Length;
|
||||
|
||||
fileStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
using (SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider()) {
|
||||
sentryHash = sha.ComputeHash(fileStream);
|
||||
}
|
||||
|
@ -2142,6 +2286,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnPersonaState(SteamFriends.PersonaStateCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2171,6 +2316,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnPlayingSessionState(ArchiHandler.PlayingSessionStateCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2185,15 +2331,18 @@ namespace ArchiSteamFarm {
|
|||
private async void OnServiceMethod(SteamUnifiedMessages.ServiceMethodNotification notification) {
|
||||
if (notification == null) {
|
||||
ArchiLogger.LogNullError(nameof(notification));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (notification.MethodName) {
|
||||
case "ChatRoomClient.NotifyIncomingChatMessage#1":
|
||||
await OnIncomingChatMessage((CChatRoom_IncomingChatMessage_Notification) notification.Body).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
case "FriendMessagesClient.IncomingMessage#1":
|
||||
await OnIncomingMessage((CFriendMessages_IncomingMessage_Notification) notification.Body).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2201,6 +2350,7 @@ namespace ArchiSteamFarm {
|
|||
private async void OnSharedLibraryLockStatus(ArchiHandler.SharedLibraryLockStatusCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2229,6 +2379,7 @@ namespace ArchiSteamFarm {
|
|||
private void OnUserNotifications(ArchiHandler.UserNotificationsCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2279,6 +2430,7 @@ namespace ArchiSteamFarm {
|
|||
private void OnVanityURLChangedCallback(ArchiHandler.VanityURLChangedCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2288,6 +2440,7 @@ namespace ArchiSteamFarm {
|
|||
private void OnWalletUpdate(SteamUser.WalletInfoCallback callback) {
|
||||
if (callback == null) {
|
||||
ArchiLogger.LogNullError(nameof(callback));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2311,12 +2464,15 @@ namespace ArchiSteamFarm {
|
|||
|
||||
while (IsConnectedAndLoggedOn && BotDatabase.HasGamesToRedeemInBackground) {
|
||||
(string key, string name) = BotDatabase.GetGameToRedeemInBackground();
|
||||
|
||||
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(name)) {
|
||||
ArchiLogger.LogNullError(nameof(key) + " || " + nameof(name));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ArchiHandler.PurchaseResponseCallback result = await Actions.RedeemKey(key).ConfigureAwait(false);
|
||||
|
||||
if (result == null) {
|
||||
continue;
|
||||
}
|
||||
|
@ -2346,17 +2502,21 @@ namespace ArchiSteamFarm {
|
|||
case EPurchaseResultDetail.DoesNotOwnRequiredApp:
|
||||
case EPurchaseResultDetail.RestrictedCountry:
|
||||
case EPurchaseResultDetail.Timeout:
|
||||
|
||||
break;
|
||||
case EPurchaseResultDetail.BadActivationCode:
|
||||
case EPurchaseResultDetail.DuplicateActivationCode:
|
||||
case EPurchaseResultDetail.NoDetail: // OK
|
||||
redeemed = true;
|
||||
|
||||
break;
|
||||
case EPurchaseResultDetail.RateLimited:
|
||||
rateLimited = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(result.PurchaseResultDetail), result.PurchaseResultDetail));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2378,6 +2538,7 @@ namespace ArchiSteamFarm {
|
|||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.Content, logEntry));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2442,6 +2603,7 @@ namespace ArchiSteamFarm {
|
|||
private static string UnEscape(string message) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(message));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,8 +153,10 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string decryptedPassword = ArchiCryptoHelper.Decrypt(PasswordFormat, SteamPassword);
|
||||
|
||||
if (string.IsNullOrEmpty(decryptedPassword)) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(SteamPassword)));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -163,6 +165,7 @@ namespace ArchiSteamFarm {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -179,6 +182,7 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty]
|
||||
internal string SteamLogin {
|
||||
get => _SteamLogin;
|
||||
|
||||
set {
|
||||
IsSteamLoginSet = true;
|
||||
_SteamLogin = value;
|
||||
|
@ -191,6 +195,7 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty]
|
||||
internal string SteamParentalCode {
|
||||
get => _SteamParentalCode;
|
||||
|
||||
set {
|
||||
IsSteamParentalCodeSet = true;
|
||||
_SteamParentalCode = value;
|
||||
|
@ -200,6 +205,7 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty]
|
||||
internal string SteamPassword {
|
||||
get => _SteamPassword;
|
||||
|
||||
set {
|
||||
IsSteamPasswordSet = true;
|
||||
_SteamPassword = value;
|
||||
|
@ -214,9 +220,11 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(SteamMasterClanID), Required = Required.DisallowNull)]
|
||||
private string SSteamMasterClanID {
|
||||
get => SteamMasterClanID.ToString();
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value) || !ulong.TryParse(value, out ulong result)) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(SSteamMasterClanID)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -281,6 +289,7 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task<BotConfig> Load(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(filePath));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -294,28 +303,34 @@ namespace ArchiSteamFarm {
|
|||
botConfig = JsonConvert.DeserializeObject<BotConfig>(await RuntimeCompatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false));
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (botConfig == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botConfig));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
(bool valid, string errorMessage) = botConfig.CheckValidation();
|
||||
|
||||
if (!valid) {
|
||||
ASF.ArchiLogger.LogGenericError(errorMessage);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
botConfig.ShouldSerializeEverything = false;
|
||||
botConfig.ShouldSerializeSensitiveDetails = false;
|
||||
|
||||
return botConfig;
|
||||
}
|
||||
|
||||
internal static async Task<bool> Write(string filePath, BotConfig botConfig) {
|
||||
if (string.IsNullOrEmpty(filePath) || (botConfig == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(filePath) + " || " + nameof(botConfig));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -334,6 +349,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
WriteSemaphore.Release();
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task AddBlacklistedFromTradesSteamIDs(IReadOnlyCollection<ulong> steamIDs) {
|
||||
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(steamIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -90,6 +91,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task AddGamesToRedeemInBackground(IOrderedDictionary games) {
|
||||
if ((games == null) || (games.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(games));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -114,6 +116,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task AddIdlingBlacklistedAppIDs(IReadOnlyCollection<uint> appIDs) {
|
||||
if ((appIDs == null) || (appIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,6 +128,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task AddIdlingPriorityAppIDs(IReadOnlyCollection<uint> appIDs) {
|
||||
if ((appIDs == null) || (appIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -136,6 +140,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task CorrectMobileAuthenticatorDeviceID(string deviceID) {
|
||||
if (string.IsNullOrEmpty(deviceID) || (MobileAuthenticator == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(deviceID) + " || " + nameof(MobileAuthenticator));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -147,6 +152,7 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task<BotDatabase> CreateOrLoad(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(filePath));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -160,15 +166,18 @@ namespace ArchiSteamFarm {
|
|||
botDatabase = JsonConvert.DeserializeObject<BotDatabase>(await RuntimeCompatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false));
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (botDatabase == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botDatabase));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
botDatabase.FilePath = filePath;
|
||||
|
||||
return botDatabase;
|
||||
}
|
||||
|
||||
|
@ -190,6 +199,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsBlacklistedFromIdling(uint appID) {
|
||||
if (appID == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -199,6 +209,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsBlacklistedFromTrades(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(steamID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -208,6 +219,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool IsPriorityIdling(uint appID) {
|
||||
if (appID == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -235,6 +247,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task RemoveBlacklistedFromTradesSteamIDs(IReadOnlyCollection<ulong> steamIDs) {
|
||||
if ((steamIDs == null) || (steamIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(steamIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -246,6 +259,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task RemoveGameToRedeemInBackground(string key) {
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(key));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -263,6 +277,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task RemoveIdlingBlacklistedAppIDs(IReadOnlyCollection<uint> appIDs) {
|
||||
if ((appIDs == null) || (appIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -274,6 +289,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task RemoveIdlingPriorityAppIDs(IReadOnlyCollection<uint> appIDs) {
|
||||
if ((appIDs == null) || (appIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appIDs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -306,8 +322,10 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string json = JsonConvert.SerializeObject(this);
|
||||
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(json));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace ArchiSteamFarm.CMsgs {
|
|||
void ISteamSerializable.Deserialize(Stream stream) {
|
||||
if (stream == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(stream));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -44,6 +45,7 @@ namespace ArchiSteamFarm.CMsgs {
|
|||
void ISteamSerializable.Serialize(Stream stream) {
|
||||
if (stream == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(stream));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,7 @@ namespace ArchiSteamFarm {
|
|||
// If we're not farming yet, obviously it's worth it to make a check
|
||||
if (!NowFarming) {
|
||||
await StartFarming().ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -192,6 +193,7 @@ namespace ArchiSteamFarm {
|
|||
if (PermanentlyPaused) {
|
||||
if (!userAction) {
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.IgnoredPermanentPauseEnabled);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -209,6 +211,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
await StartFarming().ConfigureAwait(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -224,6 +227,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!Bot.CanReceiveSteamCards) {
|
||||
await Bot.OnFarmingFinished(false).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -235,24 +239,28 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
bool? isAnythingToFarm = await IsAnythingToFarm().ConfigureAwait(false);
|
||||
if (isAnythingToFarm == null) {
|
||||
|
||||
if (!isAnythingToFarm.HasValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAnythingToFarm.Value) {
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.NothingToIdle);
|
||||
await Bot.OnFarmingFinished(false).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (GamesToFarm.Count == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(GamesToFarm));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the last moment for final check if we can farm
|
||||
if (!Bot.IsPlayingPossible) {
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -263,6 +271,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!Bot.IsPlayingPossible) {
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.PlayingNotAvailable);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -310,12 +319,15 @@ namespace ArchiSteamFarm {
|
|||
private async Task CheckGame(uint appID, string name, float hours, byte badgeLevel) {
|
||||
if ((appID == 0) || string.IsNullOrEmpty(name) || (hours < 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(name) + " || " + nameof(hours));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ushort? cardsRemaining = await GetCardsRemaining(appID).ConfigureAwait(false);
|
||||
|
||||
if (!cardsRemaining.HasValue) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningCouldNotCheckCardsStatus, appID, name));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -337,10 +349,12 @@ namespace ArchiSteamFarm {
|
|||
private async Task CheckPage(HtmlDocument htmlDocument) {
|
||||
if (htmlDocument == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(htmlDocument));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HtmlNodeCollection htmlNodes = htmlDocument.DocumentNode.SelectNodes("//div[@class='badge_row_inner']");
|
||||
|
||||
if (htmlNodes == null) {
|
||||
// No eligible badges whatsoever
|
||||
return;
|
||||
|
@ -350,22 +364,26 @@ namespace ArchiSteamFarm {
|
|||
|
||||
foreach (HtmlNode htmlNode in htmlNodes) {
|
||||
HtmlNode statsNode = htmlNode.SelectSingleNode(".//div[@class='badge_title_stats_content']");
|
||||
|
||||
HtmlNode appIDNode = statsNode?.SelectSingleNode(".//div[@class='card_drop_info_dialog']");
|
||||
|
||||
if (appIDNode == null) {
|
||||
// It's just a badge, nothing more
|
||||
continue;
|
||||
}
|
||||
|
||||
string appIDText = appIDNode.GetAttributeValue("id", null);
|
||||
|
||||
if (string.IsNullOrEmpty(appIDText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appIDText));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] appIDSplitted = appIDText.Split('_');
|
||||
|
||||
if (appIDSplitted.Length < 5) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appIDSplitted));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -373,6 +391,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!uint.TryParse(appIDText, out uint appID) || (appID == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -393,14 +412,18 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Cards
|
||||
HtmlNode progressNode = statsNode.SelectSingleNode(".//span[@class='progress_info_bold']");
|
||||
|
||||
if (progressNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(progressNode));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string progressText = progressNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(progressText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(progressText));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -411,6 +434,7 @@ namespace ArchiSteamFarm {
|
|||
if (progressMatch.Success) {
|
||||
if (!ushort.TryParse(progressMatch.Value, out cardsRemaining) || (cardsRemaining == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(cardsRemaining));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -427,25 +451,32 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// To save us on extra work, check cards earned so far first
|
||||
HtmlNode cardsEarnedNode = statsNode.SelectSingleNode(".//div[@class='card_drop_info_header']");
|
||||
|
||||
if (cardsEarnedNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(cardsEarnedNode));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string cardsEarnedText = cardsEarnedNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(cardsEarnedText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(cardsEarnedText));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Match cardsEarnedMatch = Regex.Match(cardsEarnedText, @"\d+");
|
||||
|
||||
if (!cardsEarnedMatch.Success) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(cardsEarnedMatch));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ushort.TryParse(cardsEarnedMatch.Value, out ushort cardsEarned)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(cardsEarned));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -465,14 +496,18 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Hours
|
||||
HtmlNode timeNode = statsNode.SelectSingleNode(".//div[@class='badge_title_stats_playtime']");
|
||||
|
||||
if (timeNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(timeNode));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string hoursText = timeNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(hoursText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(hoursText));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -483,29 +518,37 @@ namespace ArchiSteamFarm {
|
|||
if (hoursMatch.Success) {
|
||||
if (!float.TryParse(hoursMatch.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out hours) || (hours <= 0.0F)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(hours));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Names
|
||||
HtmlNode nameNode = statsNode.SelectSingleNode("(.//div[@class='card_drop_info_body'])[last()]");
|
||||
|
||||
if (nameNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(nameNode));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
string name = nameNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(name)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(name));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// We handle two cases here - normal one, and no card drops remaining
|
||||
int nameStartIndex = name.IndexOf(" by playing ", StringComparison.Ordinal);
|
||||
|
||||
if (nameStartIndex <= 0) {
|
||||
nameStartIndex = name.IndexOf("You don't have any more drops remaining for ", StringComparison.Ordinal);
|
||||
|
||||
if (nameStartIndex <= 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(nameStartIndex));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -515,8 +558,10 @@ namespace ArchiSteamFarm {
|
|||
nameStartIndex += 12;
|
||||
|
||||
int nameEndIndex = name.LastIndexOf('.');
|
||||
|
||||
if (nameEndIndex <= nameStartIndex) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(nameEndIndex));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -526,29 +571,38 @@ namespace ArchiSteamFarm {
|
|||
byte badgeLevel = 0;
|
||||
|
||||
HtmlNode levelNode = htmlNode.SelectSingleNode(".//div[@class='badge_info_description']/div[2]");
|
||||
|
||||
if (levelNode != null) {
|
||||
// There is no levelNode if we didn't craft that badge yet (level 0)
|
||||
string levelText = levelNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(levelText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(levelText));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int levelIndex = levelText.IndexOf("Level ", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (levelIndex < 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(levelIndex));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
levelIndex += 6;
|
||||
|
||||
if (levelText.Length <= levelIndex) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(levelIndex));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
levelText = levelText.Substring(levelIndex, 1);
|
||||
|
||||
if (!byte.TryParse(levelText, out badgeLevel) || (badgeLevel == 0) || (badgeLevel > 5)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(badgeLevel));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -564,13 +618,16 @@ namespace ArchiSteamFarm {
|
|||
switch (Program.GlobalConfig.OptimizationMode) {
|
||||
case GlobalConfig.EOptimizationMode.MinMemoryUsage:
|
||||
await task.ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (backgroundTasks == null) {
|
||||
backgroundTasks = new List<Task>();
|
||||
}
|
||||
|
||||
backgroundTasks.Add(task);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -585,10 +642,12 @@ namespace ArchiSteamFarm {
|
|||
private async Task CheckPage(byte page) {
|
||||
if (page == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(page));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetBadgePage(page).ConfigureAwait(false);
|
||||
|
||||
if (htmlDocument == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -616,15 +675,18 @@ namespace ArchiSteamFarm {
|
|||
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
||||
GamesToFarm.Remove(game);
|
||||
innerGamesToFarm.Remove(game);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (await FarmSolo(game).ConfigureAwait(false)) {
|
||||
innerGamesToFarm.Remove(game);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
NowFarming = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -635,6 +697,7 @@ namespace ArchiSteamFarm {
|
|||
foreach (Game game in GamesToFarm.OrderByDescending(game => game.HoursPlayed).ToList()) {
|
||||
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
||||
GamesToFarm.Remove(game);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -656,6 +719,7 @@ namespace ArchiSteamFarm {
|
|||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingFinishedForGames, string.Join(", ", innerGamesToFarm.Select(game => game.AppID))));
|
||||
} else {
|
||||
NowFarming = false;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -669,6 +733,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
||||
GamesToFarm.Remove(game);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -677,6 +742,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
NowFarming = false;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -691,6 +757,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<bool> FarmCards(Game game) {
|
||||
if (game == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(game));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -707,6 +774,7 @@ namespace ArchiSteamFarm {
|
|||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdling, game.AppID, game.GameName));
|
||||
|
||||
DateTime startFarmingPeriod = DateTime.UtcNow;
|
||||
|
||||
if (await FarmingResetSemaphore.WaitAsync(Program.GlobalConfig.FarmingDelay * 60 * 1000 + ExtraFarmingDelaySeconds * 1000).ConfigureAwait(false)) {
|
||||
success = KeepFarming;
|
||||
}
|
||||
|
@ -720,39 +788,47 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StoppedIdling, game.AppID, game.GameName));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private async Task<bool> FarmHours(IReadOnlyCollection<Game> games) {
|
||||
if ((games == null) || (games.Count == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(games));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float maxHour = games.Max(game => game.HoursPlayed);
|
||||
|
||||
if (maxHour < 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(maxHour));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (maxHour >= Bot.BotConfig.HoursUntilCardDrops) {
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(maxHour)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
await Bot.IdleGames(games).ConfigureAwait(false);
|
||||
|
||||
bool success = true;
|
||||
|
||||
while (maxHour < Bot.BotConfig.HoursUntilCardDrops) {
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdlingList, string.Join(", ", games.Select(game => game.AppID))));
|
||||
|
||||
DateTime startFarmingPeriod = DateTime.UtcNow;
|
||||
|
||||
if (await FarmingResetSemaphore.WaitAsync(Program.GlobalConfig.FarmingDelay * 60 * 1000 + ExtraFarmingDelaySeconds * 1000).ConfigureAwait(false)) {
|
||||
success = KeepFarming;
|
||||
}
|
||||
|
||||
// Don't forget to update our GamesToFarm hours
|
||||
float timePlayed = (float) DateTime.UtcNow.Subtract(startFarmingPeriod).TotalHours;
|
||||
|
||||
foreach (Game game in games) {
|
||||
game.HoursPlayed += timePlayed;
|
||||
}
|
||||
|
@ -765,12 +841,14 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StoppedIdlingList, string.Join(", ", games.Select(game => game.AppID))));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private async Task<bool> FarmMultiple(IReadOnlyCollection<Game> games) {
|
||||
if ((games == null) || (games.Count == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(games));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -780,12 +858,14 @@ namespace ArchiSteamFarm {
|
|||
|
||||
bool result = await FarmHours(games).ConfigureAwait(false);
|
||||
CurrentGamesFarming.Clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool> FarmSolo(Game game) {
|
||||
if (game == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(game));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -803,35 +883,42 @@ namespace ArchiSteamFarm {
|
|||
GamesToFarm.Remove(game);
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingFinishedForGame, game.AppID, game.GameName, TimeSpan.FromHours(game.HoursPlayed).ToHumanReadable()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<ushort?> GetCardsRemaining(uint appID) {
|
||||
if (appID == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetGameCardsPage(appID).ConfigureAwait(false);
|
||||
|
||||
HtmlNode progressNode = htmlDocument?.DocumentNode.SelectSingleNode("//span[@class='progress_info_bold']");
|
||||
|
||||
if (progressNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string progress = progressNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(progress)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(progress));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Match match = Regex.Match(progress, @"\d+");
|
||||
|
||||
if (!match.Success) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ushort.TryParse(match.Value, out ushort cardsRemaining) || (cardsRemaining == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(cardsRemaining));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -842,23 +929,29 @@ namespace ArchiSteamFarm {
|
|||
// Find the number of badge pages
|
||||
Bot.ArchiLogger.LogGenericInfo(Strings.CheckingFirstBadgePage);
|
||||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetBadgePage(1).ConfigureAwait(false);
|
||||
|
||||
if (htmlDocument == null) {
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.WarningCouldNotCheckBadges);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte maxPages = 1;
|
||||
|
||||
HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("(//a[@class='pagelink'])[last()]");
|
||||
|
||||
if (htmlNode != null) {
|
||||
string lastPage = htmlNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(lastPage)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(lastPage));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!byte.TryParse(lastPage, out maxPages) || (maxPages == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(maxPages));
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -894,46 +987,56 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (GamesToFarm.Count == 0) {
|
||||
ShouldResumeFarming = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ShouldResumeFarming = true;
|
||||
await SortGamesToFarm().ConfigureAwait(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> IsPlayableGame(Game game) {
|
||||
(uint playableAppID, DateTime ignoredUntil) = await Bot.GetAppDataForIdling(game.AppID, game.HoursPlayed).ConfigureAwait(false);
|
||||
|
||||
if (playableAppID == 0) {
|
||||
IgnoredAppIDs[game.AppID] = ignoredUntil < DateTime.MaxValue ? ignoredUntil : DateTime.UtcNow.AddHours(HoursToIgnore);
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingGameNotPossible, game.AppID, game.GameName));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
game.PlayableAppID = playableAppID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool?> ShouldFarm(Game game) {
|
||||
if (game == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(game));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ushort? cardsRemaining = await GetCardsRemaining(game.AppID).ConfigureAwait(false);
|
||||
|
||||
if (!cardsRemaining.HasValue) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningCouldNotCheckCardsStatus, game.AppID, game.GameName));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
game.CardsRemaining = cardsRemaining.Value;
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingStatusForGame, game.AppID, game.GameName, game.CardsRemaining));
|
||||
|
||||
return game.CardsRemaining > 0;
|
||||
}
|
||||
|
||||
|
@ -944,24 +1047,31 @@ namespace ArchiSteamFarm {
|
|||
foreach (BotConfig.EFarmingOrder farmingOrder in Bot.BotConfig.FarmingOrders) {
|
||||
switch (farmingOrder) {
|
||||
case BotConfig.EFarmingOrder.Unordered:
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.AppIDsAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => game.AppID);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.AppIDsDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => game.AppID);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.BadgeLevelsAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => game.BadgeLevel);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.BadgeLevelsDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => game.BadgeLevel);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.CardDropsAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => game.CardsRemaining);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.CardDropsDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => game.CardsRemaining);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.MarketableAscending:
|
||||
case BotConfig.EFarmingOrder.MarketableDescending:
|
||||
|
@ -971,12 +1081,15 @@ namespace ArchiSteamFarm {
|
|||
switch (farmingOrder) {
|
||||
case BotConfig.EFarmingOrder.MarketableAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => marketableAppIDs.Contains(game.AppID));
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.MarketableDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => marketableAppIDs.Contains(game.AppID));
|
||||
|
||||
break;
|
||||
default:
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(farmingOrder), farmingOrder));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -984,18 +1097,23 @@ namespace ArchiSteamFarm {
|
|||
break;
|
||||
case BotConfig.EFarmingOrder.HoursAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => game.HoursPlayed);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.HoursDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => game.HoursPlayed);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.NamesAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => game.GameName);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.NamesDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => game.GameName);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.Random:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => Utilities.RandomNext());
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.RedeemDateTimesAscending:
|
||||
case BotConfig.EFarmingOrder.RedeemDateTimesDescending:
|
||||
|
@ -1023,18 +1141,22 @@ namespace ArchiSteamFarm {
|
|||
switch (farmingOrder) {
|
||||
case BotConfig.EFarmingOrder.RedeemDateTimesAscending:
|
||||
gamesToFarm = gamesToFarm.ThenBy(game => redeemDates[game.AppID]);
|
||||
|
||||
break;
|
||||
case BotConfig.EFarmingOrder.RedeemDateTimesDescending:
|
||||
gamesToFarm = gamesToFarm.ThenByDescending(game => redeemDates[game.AppID]);
|
||||
|
||||
break;
|
||||
default:
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(farmingOrder), farmingOrder));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(farmingOrder), farmingOrder));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,26 +54,31 @@ namespace ArchiSteamFarm.Collections {
|
|||
|
||||
public bool IsProperSubsetOf(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return (otherSet.Count > Count) && IsSubsetOf(otherSet);
|
||||
}
|
||||
|
||||
public bool IsProperSupersetOf(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return (otherSet.Count < Count) && IsSupersetOf(otherSet);
|
||||
}
|
||||
|
||||
public bool IsSubsetOf(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return this.All(otherSet.Contains);
|
||||
}
|
||||
|
||||
public bool IsSupersetOf(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return otherSet.All(Contains);
|
||||
}
|
||||
|
||||
public bool Overlaps(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return otherSet.Any(Contains);
|
||||
}
|
||||
|
||||
|
@ -81,13 +86,14 @@ namespace ArchiSteamFarm.Collections {
|
|||
|
||||
public bool SetEquals(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return (otherSet.Count == Count) && otherSet.All(Contains);
|
||||
}
|
||||
|
||||
public void SymmetricExceptWith(IEnumerable<T> other) {
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
HashSet<T> removed = new HashSet<T>();
|
||||
|
||||
foreach (T item in otherSet.Where(Contains)) {
|
||||
removed.Add(item);
|
||||
Remove(item);
|
||||
|
@ -119,6 +125,7 @@ namespace ArchiSteamFarm.Collections {
|
|||
}
|
||||
|
||||
ReplaceWith(other);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,22 +218,22 @@ namespace ArchiSteamFarm.Collections {
|
|||
public T Current => Enumerator.Current;
|
||||
|
||||
private readonly IEnumerator<T> Enumerator;
|
||||
private readonly SemaphoreSlim SemaphoreSlim;
|
||||
private readonly SemaphoreSlim Semaphore;
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
internal ConcurrentEnumerator(IReadOnlyCollection<T> collection, SemaphoreSlim semaphoreSlim) {
|
||||
if ((collection == null) || (semaphoreSlim == null)) {
|
||||
throw new ArgumentNullException(nameof(collection) + " || " + nameof(semaphoreSlim));
|
||||
internal ConcurrentEnumerator(IReadOnlyCollection<T> collection, SemaphoreSlim semaphore) {
|
||||
if ((collection == null) || (semaphore == null)) {
|
||||
throw new ArgumentNullException(nameof(collection) + " || " + nameof(semaphore));
|
||||
}
|
||||
|
||||
SemaphoreSlim = semaphoreSlim;
|
||||
semaphoreSlim.Wait();
|
||||
Semaphore = semaphore;
|
||||
semaphore.Wait();
|
||||
|
||||
Enumerator = collection.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Dispose() => SemaphoreSlim.Release();
|
||||
public void Dispose() => Semaphore.Release();
|
||||
public bool MoveNext() => Enumerator.MoveNext();
|
||||
public void Reset() => Enumerator.Reset();
|
||||
}
|
||||
|
|
|
@ -30,9 +30,11 @@ namespace ArchiSteamFarm.Collections {
|
|||
|
||||
internal byte MaxCount {
|
||||
get => _MaxCount;
|
||||
|
||||
set {
|
||||
if (value == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,6 +35,7 @@ namespace ArchiSteamFarm {
|
|||
public void WriteLine(string category, string msg) {
|
||||
if (string.IsNullOrEmpty(category) && string.IsNullOrEmpty(msg)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(category) + " && " + nameof(msg));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,12 +41,14 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
List<ReleaseResponse> response = await GetReleasesFromURL(releaseURL).ConfigureAwait(false);
|
||||
|
||||
return response?.FirstOrDefault();
|
||||
}
|
||||
|
||||
internal static async Task<ReleaseResponse> GetRelease(string version) {
|
||||
if (string.IsNullOrEmpty(version)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(version));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -56,16 +58,19 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task<List<ReleaseResponse>> GetReleases(byte count) {
|
||||
if (count == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(count));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string releaseURL = SharedInfo.GithubReleaseURL + "?per_page=" + count;
|
||||
|
||||
return await GetReleasesFromURL(releaseURL).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static MarkdownDocument ExtractChangelogFromBody(string markdownText) {
|
||||
if (string.IsNullOrEmpty(markdownText)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(markdownText));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -84,20 +89,24 @@ namespace ArchiSteamFarm {
|
|||
private static async Task<ReleaseResponse> GetReleaseFromURL(string releaseURL) {
|
||||
if (string.IsNullOrEmpty(nameof(releaseURL))) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(releaseURL));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<ReleaseResponse> objectResponse = await Program.WebBrowser.UrlGetToJsonObject<ReleaseResponse>(releaseURL).ConfigureAwait(false);
|
||||
|
||||
return objectResponse?.Content;
|
||||
}
|
||||
|
||||
private static async Task<List<ReleaseResponse>> GetReleasesFromURL(string releaseURL) {
|
||||
if (string.IsNullOrEmpty(nameof(releaseURL))) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(releaseURL));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<List<ReleaseResponse>> objectResponse = await Program.WebBrowser.UrlGetToJsonObject<List<ReleaseResponse>>(releaseURL).ConfigureAwait(false);
|
||||
|
||||
return objectResponse?.Content;
|
||||
}
|
||||
|
||||
|
@ -123,6 +132,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (Changelog == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(Changelog));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -144,6 +154,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (Changelog == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(Changelog));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ namespace ArchiSteamFarm {
|
|||
uri = new Uri(WebProxyText);
|
||||
} catch (UriFormatException e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -195,6 +196,7 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty]
|
||||
internal string WebProxyPassword {
|
||||
get => _WebProxyPassword;
|
||||
|
||||
set {
|
||||
IsWebProxyPasswordSet = true;
|
||||
_WebProxyPassword = value;
|
||||
|
@ -208,9 +210,11 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(SteamOwnerID), Required = Required.DisallowNull)]
|
||||
private string SSteamOwnerID {
|
||||
get => SteamOwnerID.ToString();
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value) || !ulong.TryParse(value, out ulong result)) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(SSteamOwnerID)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -255,6 +259,7 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task<GlobalConfig> Load(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(filePath));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -268,28 +273,34 @@ namespace ArchiSteamFarm {
|
|||
globalConfig = JsonConvert.DeserializeObject<GlobalConfig>(await RuntimeCompatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false));
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (globalConfig == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(globalConfig));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
(bool valid, string errorMessage) = globalConfig.CheckValidation();
|
||||
|
||||
if (!valid) {
|
||||
ASF.ArchiLogger.LogGenericError(errorMessage);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
globalConfig.ShouldSerializeEverything = false;
|
||||
globalConfig.ShouldSerializeSensitiveDetails = false;
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
internal static async Task<bool> Write(string filePath, GlobalConfig globalConfig) {
|
||||
if (string.IsNullOrEmpty(filePath) || (globalConfig == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(filePath) + " || " + nameof(globalConfig));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -308,6 +319,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
WriteSemaphore.Release();
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task<GlobalDatabase> CreateOrLoad(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(filePath));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -85,21 +86,25 @@ namespace ArchiSteamFarm {
|
|||
globalDatabase = JsonConvert.DeserializeObject<GlobalDatabase>(await RuntimeCompatibility.File.ReadAllTextAsync(filePath).ConfigureAwait(false));
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (globalDatabase == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(globalDatabase));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
globalDatabase.FilePath = filePath;
|
||||
|
||||
return globalDatabase;
|
||||
}
|
||||
|
||||
internal HashSet<uint> GetPackageIDs(uint appID) {
|
||||
if (appID == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -109,6 +114,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task RefreshPackages(Bot bot, IReadOnlyDictionary<uint, uint> packages) {
|
||||
if ((bot == null) || (packages == null) || (packages.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(bot) + " || " + nameof(packages));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -122,6 +128,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Dictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)> packagesData = await bot.GetPackagesData(packageIDs).ConfigureAwait(false);
|
||||
|
||||
if ((packagesData == null) || (packagesData.Count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -149,8 +156,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
private async Task Save() {
|
||||
string json = JsonConvert.SerializeObject(this);
|
||||
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(json));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ namespace ArchiSteamFarm.Helpers {
|
|||
}
|
||||
|
||||
(bool success, T result) = await ResolveFunction().ConfigureAwait(false);
|
||||
|
||||
if (!success) {
|
||||
return (false, InitializedValue);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
IWebHostBuilder builder = new WebHostBuilder();
|
||||
|
||||
string customDirectory = Path.Combine(Directory.GetCurrentDirectory(), SharedInfo.WebsiteDirectory);
|
||||
|
||||
if (Directory.Exists(customDirectory)) {
|
||||
WebsiteDirectory = customDirectory;
|
||||
}
|
||||
|
@ -106,6 +107,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
kestrelWebHost.Dispose();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
uint memoryUsage = (uint) GC.GetTotalMemory(false) / 1024;
|
||||
|
||||
ASFResponse result = new ASFResponse(SharedInfo.BuildInfo.Variant, Program.GlobalConfig, memoryUsage, RuntimeCompatibility.ProcessStartTime, SharedInfo.Version);
|
||||
|
||||
return Ok(new GenericResponse<ASFResponse>(result));
|
||||
}
|
||||
|
||||
|
@ -51,10 +52,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> ASFPost([FromBody] ASFRequest request) {
|
||||
if (request == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(request))));
|
||||
}
|
||||
|
||||
(bool valid, string errorMessage) = request.GlobalConfig.CheckValidation();
|
||||
|
||||
if (!valid) {
|
||||
return BadRequest(new GenericResponse(false, errorMessage));
|
||||
}
|
||||
|
@ -69,6 +72,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
string filePath = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName);
|
||||
|
||||
bool result = await GlobalConfig.Write(filePath, request.GlobalConfig).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse(result));
|
||||
}
|
||||
|
||||
|
@ -79,6 +83,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
[ProducesResponseType(typeof(GenericResponse), 200)]
|
||||
public ActionResult<GenericResponse> ExitPost() {
|
||||
(bool success, string output) = Actions.Exit();
|
||||
|
||||
return Ok(new GenericResponse(success, output));
|
||||
}
|
||||
|
||||
|
@ -89,6 +94,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
[ProducesResponseType(typeof(GenericResponse), 200)]
|
||||
public ActionResult<GenericResponse> RestartPost() {
|
||||
(bool success, string output) = Actions.Restart();
|
||||
|
||||
return Ok(new GenericResponse(success, output));
|
||||
}
|
||||
|
||||
|
|
|
@ -41,15 +41,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> BotDelete(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<bool> results = await Utilities.InParallel(bots.Select(bot => bot.DeleteAllRelatedFiles())).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse(results.All(result => result)));
|
||||
}
|
||||
|
||||
|
@ -61,10 +64,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public ActionResult<GenericResponse<IReadOnlyDictionary<string, Bot>>> BotGet(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, Bot>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if (bots == null) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, Bot>>(false, string.Format(Strings.ErrorIsInvalid, nameof(bots))));
|
||||
}
|
||||
|
@ -81,10 +86,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse<IReadOnlyDictionary<string, bool>>>> BotPost(string botNames, [FromBody] BotRequest request) {
|
||||
if (string.IsNullOrEmpty(botNames) || (request == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames) + " || " + nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, bool>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames) + " || " + nameof(request))));
|
||||
}
|
||||
|
||||
(bool valid, string errorMessage) = request.BotConfig.CheckValidation();
|
||||
|
||||
if (!valid) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, bool>>(false, errorMessage));
|
||||
}
|
||||
|
@ -138,15 +145,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> GamesToRedeemInBackgroundDelete(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<bool> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.DeleteRedeemedKeysFiles))).ConfigureAwait(false);
|
||||
|
||||
return Ok(results.All(result => result) ? new GenericResponse(true) : new GenericResponse(false, Strings.WarningFailed));
|
||||
}
|
||||
|
||||
|
@ -158,10 +168,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>>> GamesToRedeemInBackgroundGet(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, GamesToRedeemInBackgroundResponse>>(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
@ -187,6 +199,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>>> GamesToRedeemInBackgroundPost(string botNames, [FromBody] BotGamesToRedeemInBackgroundRequest request) {
|
||||
if (string.IsNullOrEmpty(botNames) || (request == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames) + " || " + nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames) + " || " + nameof(request))));
|
||||
}
|
||||
|
||||
|
@ -195,11 +208,13 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IOrderedDictionary validGamesToRedeemInBackground = Bot.ValidateGamesToRedeemInBackground(request.GamesToRedeemInBackground);
|
||||
|
||||
if ((validGamesToRedeemInBackground == null) || (validGamesToRedeemInBackground.Count == 0)) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, IOrderedDictionary>>(false, string.Format(Strings.ErrorIsEmpty, nameof(validGamesToRedeemInBackground))));
|
||||
}
|
||||
|
@ -224,15 +239,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> PausePost(string botNames, [FromBody] BotPauseRequest request) {
|
||||
if (string.IsNullOrEmpty(botNames) || (request == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames) + " || " + nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames) + " || " + nameof(request))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<(bool Success, string Output)> results = await Utilities.InParallel(bots.Select(bot => bot.Actions.Pause(request.Permanent, request.ResumeInSeconds))).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
|
||||
|
@ -249,6 +267,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse<IReadOnlyDictionary<string, IReadOnlyDictionary<string, ArchiHandler.PurchaseResponseCallback>>>>> RedeemPost(string botNames, [FromBody] BotRedeemRequest request) {
|
||||
if (string.IsNullOrEmpty(botNames) || (request == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames) + " || " + nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, IReadOnlyDictionary<string, ArchiHandler.PurchaseResponseCallback>>>(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames) + " || " + nameof(request))));
|
||||
}
|
||||
|
||||
|
@ -257,6 +276,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyDictionary<string, IReadOnlyDictionary<string, ArchiHandler.PurchaseResponseCallback>>>(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
@ -287,15 +307,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> ResumePost(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<(bool Success, string Output)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Resume))).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
|
||||
|
@ -307,15 +330,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> StartPost(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<(bool Success, string Output)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Start))).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
|
||||
|
@ -327,15 +353,18 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse>> StopPost(string botNames) {
|
||||
if (string.IsNullOrEmpty(botNames)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(botNames));
|
||||
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.ErrorIsEmpty, nameof(botNames))));
|
||||
}
|
||||
|
||||
HashSet<Bot> bots = Bot.GetBots(botNames);
|
||||
|
||||
if ((bots == null) || (bots.Count == 0)) {
|
||||
return BadRequest(new GenericResponse(false, string.Format(Strings.BotNotFound, botNames)));
|
||||
}
|
||||
|
||||
IList<(bool Success, string Output)> results = await Utilities.InParallel(bots.Select(bot => Task.Run(bot.Actions.Stop))).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse(results.All(result => result.Success), string.Join(Environment.NewLine, results.Select(result => result.Output))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse<string>>> CommandPost(string command) {
|
||||
if (string.IsNullOrEmpty(command)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(command));
|
||||
|
||||
return BadRequest(new GenericResponse<string>(false, string.Format(Strings.ErrorIsEmpty, nameof(command))));
|
||||
}
|
||||
|
||||
|
@ -49,6 +50,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
Bot targetBot = Bot.Bots.OrderBy(bot => bot.Key).Select(bot => bot.Value).FirstOrDefault();
|
||||
|
||||
if (targetBot == null) {
|
||||
return BadRequest(new GenericResponse<string>(false, Strings.ErrorNoBotsDefined));
|
||||
}
|
||||
|
@ -58,6 +60,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
string response = await targetBot.Commands.Response(Program.GlobalConfig.SteamOwnerID, command).ConfigureAwait(false);
|
||||
|
||||
return Ok(new GenericResponse<string>(response));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,8 +55,10 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
try {
|
||||
using (WebSocket webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false)) {
|
||||
SemaphoreSlim sendSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
if (!ActiveLogWebSockets.TryAdd(webSocket, sendSemaphore)) {
|
||||
sendSemaphore.Dispose();
|
||||
|
||||
return new EmptyResult();
|
||||
}
|
||||
|
||||
|
@ -72,10 +74,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
|
||||
if (result.MessageType != WebSocketMessageType.Close) {
|
||||
await webSocket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "You're not supposed to be sending any message but Close!", CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
|
@ -95,6 +99,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
internal static async void OnNewHistoryEntry(object sender, HistoryTarget.NewHistoryEntryArgs newHistoryEntryArgs) {
|
||||
if ((sender == null) || (newHistoryEntryArgs == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(newHistoryEntryArgs));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -109,6 +114,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
private static async Task PostLoggedJsonUpdate(WebSocket webSocket, SemaphoreSlim sendSemaphore, string json) {
|
||||
if ((webSocket == null) || (sendSemaphore == null) || string.IsNullOrEmpty(json)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(webSocket) + " || " + nameof(sendSemaphore) + " || " + nameof(json));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -134,6 +140,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
private static async Task PostLoggedMessageUpdate(WebSocket webSocket, SemaphoreSlim sendSemaphore, string loggedMessage) {
|
||||
if ((webSocket == null) || (sendSemaphore == null) || string.IsNullOrEmpty(loggedMessage)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(webSocket) + " || " + nameof(sendSemaphore) + " || " + nameof(loggedMessage));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public ActionResult<GenericResponse<object>> StructureGet(string structure) {
|
||||
if (string.IsNullOrEmpty(structure)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(structure));
|
||||
|
||||
return BadRequest(new GenericResponse<object>(false, string.Format(Strings.ErrorIsEmpty, nameof(structure))));
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public ActionResult<GenericResponse<TypeResponse>> TypeGet(string type) {
|
||||
if (string.IsNullOrEmpty(type)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(type));
|
||||
|
||||
return BadRequest(new GenericResponse<TypeResponse>(false, string.Format(Strings.ErrorIsEmpty, nameof(type))));
|
||||
}
|
||||
|
||||
|
@ -85,6 +86,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
TypeResponse.TypeProperties properties = new TypeResponse.TypeProperties(baseType, customAttributes.Count > 0 ? customAttributes : null, underlyingType);
|
||||
|
||||
TypeResponse response = new TypeResponse(body, properties);
|
||||
|
||||
return Ok(new GenericResponse<TypeResponse>(response));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,10 +43,12 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public ActionResult<GenericResponse<IReadOnlyCollection<string>>> DirectoryGet(string directory) {
|
||||
if (string.IsNullOrEmpty(directory)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(directory));
|
||||
|
||||
return BadRequest(new GenericResponse<IReadOnlyCollection<string>>(false, string.Format(Strings.ErrorIsEmpty, nameof(directory))));
|
||||
}
|
||||
|
||||
string directoryPath = Path.Combine(ArchiKestrel.WebsiteDirectory, directory);
|
||||
|
||||
if (!Directory.Exists(directoryPath)) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyCollection<string>>(false, string.Format(Strings.ErrorIsInvalid, directory)));
|
||||
}
|
||||
|
@ -60,6 +62,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
HashSet<string> result = files.Select(Path.GetFileName).ToHashSet();
|
||||
|
||||
return Ok(new GenericResponse<IReadOnlyCollection<string>>(result));
|
||||
}
|
||||
|
||||
|
@ -77,11 +80,13 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
List<GitHub.ReleaseResponse> response = await GitHub.GetReleases(count).ConfigureAwait(false);
|
||||
|
||||
if ((response == null) || (response.Count == 0)) {
|
||||
return BadRequest(new GenericResponse<IReadOnlyCollection<GitHub.ReleaseResponse>>(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
|
||||
}
|
||||
|
||||
List<GitHubReleaseResponse> result = response.Select(singleResponse => new GitHubReleaseResponse(singleResponse)).ToList();
|
||||
|
||||
return Ok(new GenericResponse<IReadOnlyCollection<GitHubReleaseResponse>>(result));
|
||||
}
|
||||
|
||||
|
@ -99,6 +104,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
GitHub.ReleaseResponse releaseResponse = await GitHub.GetRelease(version).ConfigureAwait(false);
|
||||
|
||||
if (releaseResponse == null) {
|
||||
return BadRequest(new GenericResponse<GitHubReleaseResponse>(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
|
||||
}
|
||||
|
@ -118,6 +124,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
public async Task<ActionResult<GenericResponse<string>>> SendPost([FromBody] WWWSendRequest request) {
|
||||
if (request == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(request));
|
||||
|
||||
return BadRequest(new GenericResponse<string>(false, string.Format(Strings.ErrorIsEmpty, nameof(request))));
|
||||
}
|
||||
|
||||
|
@ -126,6 +133,7 @@ namespace ArchiSteamFarm.IPC.Controllers.Api {
|
|||
}
|
||||
|
||||
WebBrowser.StringResponse urlResponse = await Program.WebBrowser.UrlGetToString(request.URL).ConfigureAwait(false);
|
||||
|
||||
if (urlResponse?.Content == null) {
|
||||
return BadRequest(new GenericResponse<string>(false, string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries)));
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace ArchiSteamFarm.IPC.Middleware {
|
|||
public async Task InvokeAsync(HttpContext context) {
|
||||
if (context == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(context));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -64,6 +65,7 @@ namespace ArchiSteamFarm.IPC.Middleware {
|
|||
|
||||
if (authenticationStatus != HttpStatusCode.OK) {
|
||||
await context.Response.Generate(authenticationStatus).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,7 @@ namespace ArchiSteamFarm.IPC.Middleware {
|
|||
private static async Task<HttpStatusCode> GetAuthenticationStatus(HttpContext context) {
|
||||
if (context == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(context));
|
||||
|
||||
return HttpStatusCode.InternalServerError;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace ArchiSteamFarm.IPC.Responses {
|
|||
|
||||
if (!string.IsNullOrEmpty(message)) {
|
||||
Message = message;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
|
||||
if ((app == null) || (env == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(app) + " || " + nameof(env));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -48,6 +49,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
|
||||
// Add workaround for missing PathBase feature, https://github.com/aspnet/Hosting/issues/1120
|
||||
PathString pathBase = Configuration.GetSection("Kestrel").GetValue<PathString>("PathBase");
|
||||
|
||||
if (!string.IsNullOrEmpty(pathBase) && (pathBase != "/")) {
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
@ -87,6 +89,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
public void ConfigureServices(IServiceCollection services) {
|
||||
if (services == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(services));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,6 +130,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
|
||||
c.DescribeAllEnumsAsStrings();
|
||||
c.EnableAnnotations();
|
||||
|
||||
c.SwaggerDoc(
|
||||
SharedInfo.ASF, new OpenApiInfo {
|
||||
Contact = new OpenApiContact {
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
internal static async Task Generate(this HttpResponse httpResponse, HttpStatusCode statusCode) {
|
||||
if (httpResponse == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(httpResponse));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -42,6 +43,7 @@ namespace ArchiSteamFarm.IPC {
|
|||
internal static string GetUnifiedName(this Type type) {
|
||||
if (type == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(type));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -51,10 +53,12 @@ namespace ArchiSteamFarm.IPC {
|
|||
internal static Type ParseType(string typeText) {
|
||||
if (string.IsNullOrEmpty(typeText)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(typeText));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Type targetType = Type.GetType(typeText);
|
||||
|
||||
if (targetType != null) {
|
||||
return targetType;
|
||||
}
|
||||
|
|
|
@ -54,11 +54,13 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uint.TryParse(value, out uint amount) || (amount == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(amount));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -73,11 +75,13 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(value, out ulong assetID) || (assetID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(assetID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,6 +96,7 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -110,11 +115,13 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(value, out ulong contextID) || (contextID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(contextID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -176,12 +183,15 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = WebBrowser.StringToHtmlDocument(value);
|
||||
|
||||
if (htmlDocument == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(htmlDocument));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -189,32 +199,42 @@ namespace ArchiSteamFarm.Json {
|
|||
Type = EType.Trade;
|
||||
|
||||
HtmlNode tradeOfferNode = htmlDocument.DocumentNode.SelectSingleNode("//div[@class='tradeoffer']");
|
||||
|
||||
if (tradeOfferNode == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(tradeOfferNode));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string idText = tradeOfferNode.GetAttributeValue("id", null);
|
||||
|
||||
if (string.IsNullOrEmpty(idText)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(idText));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int index = idText.IndexOf('_');
|
||||
|
||||
if (index < 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(index));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
if (idText.Length <= index) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(idText.Length));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
idText = idText.Substring(index);
|
||||
|
||||
if (!ulong.TryParse(idText, out ulong tradeOfferID) || (tradeOfferID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(tradeOfferID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -275,11 +295,13 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(value, out ulong lastAssetID) || (lastAssetID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(lastAssetID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -313,11 +335,13 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(value, out ulong classID) || (classID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(classID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -354,12 +378,15 @@ namespace ArchiSteamFarm.Json {
|
|||
switch (value) {
|
||||
case 0:
|
||||
Success = false;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
Success = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(value), value));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -414,6 +441,7 @@ namespace ArchiSteamFarm.Json {
|
|||
internal bool IsValidSteamItemsRequest(IReadOnlyCollection<Asset.EType> acceptedTypes) {
|
||||
if ((acceptedTypes == null) || (acceptedTypes.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(acceptedTypes));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -471,11 +499,13 @@ namespace ArchiSteamFarm.Json {
|
|||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(value, out ulong tradeOfferID) || (tradeOfferID == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(tradeOfferID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ namespace ArchiSteamFarm {
|
|||
internal bool CorrectDeviceID(string deviceID) {
|
||||
if (string.IsNullOrEmpty(deviceID)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(deviceID));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -76,13 +77,16 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
DeviceID = deviceID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal async Task<string> GenerateToken() {
|
||||
uint time = await GetSteamTime().ConfigureAwait(false);
|
||||
|
||||
if (time == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(time));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -92,45 +96,57 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<Steam.ConfirmationDetails> GetConfirmationDetails(Confirmation confirmation) {
|
||||
if (confirmation == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(confirmation));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!HasCorrectDeviceID) {
|
||||
Bot.ArchiLogger.LogGenericError(Strings.ErrorMobileAuthenticatorInvalidDeviceID);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
uint time = await GetSteamTime().ConfigureAwait(false);
|
||||
|
||||
if (time == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(time));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string confirmationHash = GenerateConfirmationHash(time, "conf");
|
||||
|
||||
if (string.IsNullOrEmpty(confirmationHash)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(confirmationHash));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Steam.ConfirmationDetails response = await Bot.ArchiWebHandler.GetConfirmationDetails(DeviceID, confirmationHash, time, confirmation).ConfigureAwait(false);
|
||||
|
||||
return response?.Success == true ? response : null;
|
||||
}
|
||||
|
||||
internal async Task<HashSet<Confirmation>> GetConfirmations(Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown) {
|
||||
if (!HasCorrectDeviceID) {
|
||||
Bot.ArchiLogger.LogGenericError(Strings.ErrorMobileAuthenticatorInvalidDeviceID);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
uint time = await GetSteamTime().ConfigureAwait(false);
|
||||
|
||||
if (time == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(time));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string confirmationHash = GenerateConfirmationHash(time, "conf");
|
||||
|
||||
if (string.IsNullOrEmpty(confirmationHash)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(confirmationHash));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -139,6 +155,7 @@ namespace ArchiSteamFarm {
|
|||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetConfirmations(DeviceID, confirmationHash, time).ConfigureAwait(false);
|
||||
|
||||
HtmlNodeCollection confirmationNodes = htmlDocument?.DocumentNode.SelectNodes("//div[@class='mobileconf_list_entry']");
|
||||
|
||||
if (confirmationNodes == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -147,40 +164,50 @@ namespace ArchiSteamFarm {
|
|||
|
||||
foreach (HtmlNode confirmationNode in confirmationNodes) {
|
||||
string idText = confirmationNode.GetAttributeValue("data-confid", null);
|
||||
|
||||
if (string.IsNullOrEmpty(idText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(idText));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(idText, out ulong id) || (id == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(id));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string keyText = confirmationNode.GetAttributeValue("data-key", null);
|
||||
|
||||
if (string.IsNullOrEmpty(keyText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(keyText));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(keyText, out ulong key) || (key == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(key));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string typeText = confirmationNode.GetAttributeValue("data-type", null);
|
||||
|
||||
if (string.IsNullOrEmpty(typeText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(typeText));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Enum.TryParse(typeText, out Steam.ConfirmationDetails.EType type) || (type == Steam.ConfirmationDetails.EType.Unknown)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(type));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Enum.IsDefined(typeof(Steam.ConfirmationDetails.EType), type)) {
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(type), type));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -197,27 +224,34 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<bool> HandleConfirmations(IReadOnlyCollection<Confirmation> confirmations, bool accept) {
|
||||
if ((confirmations == null) || (confirmations.Count == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(confirmations));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HasCorrectDeviceID) {
|
||||
Bot.ArchiLogger.LogGenericError(Strings.ErrorMobileAuthenticatorInvalidDeviceID);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint time = await GetSteamTime().ConfigureAwait(false);
|
||||
|
||||
if (time == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(time));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string confirmationHash = GenerateConfirmationHash(time, "conf");
|
||||
|
||||
if (string.IsNullOrEmpty(confirmationHash)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(confirmationHash));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool? result = await Bot.ArchiWebHandler.HandleConfirmations(DeviceID, confirmationHash, time, confirmations, accept).ConfigureAwait(false);
|
||||
|
||||
if (!result.HasValue) {
|
||||
// Request timed out
|
||||
return false;
|
||||
|
@ -233,6 +267,7 @@ namespace ArchiSteamFarm {
|
|||
// We totally ignore actual result returned by those calls, abort only if request timed out
|
||||
foreach (Confirmation confirmation in confirmations) {
|
||||
bool? confirmationResult = await Bot.ArchiWebHandler.HandleConfirmation(DeviceID, confirmationHash, time, confirmation.ID, confirmation.Key, accept).ConfigureAwait(false);
|
||||
|
||||
if (!confirmationResult.HasValue) {
|
||||
return false;
|
||||
}
|
||||
|
@ -246,6 +281,7 @@ namespace ArchiSteamFarm {
|
|||
private string GenerateConfirmationHash(uint time, string tag = null) {
|
||||
if (time == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(time));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -256,15 +292,18 @@ namespace ArchiSteamFarm {
|
|||
} catch (FormatException e) {
|
||||
Bot.ArchiLogger.LogGenericException(e);
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(IdentitySecret)));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte bufferSize = 8;
|
||||
|
||||
if (!string.IsNullOrEmpty(tag)) {
|
||||
bufferSize += (byte) Math.Min(32, tag.Length);
|
||||
}
|
||||
|
||||
byte[] timeArray = BitConverter.GetBytes((long) time);
|
||||
|
||||
if (BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(timeArray);
|
||||
}
|
||||
|
@ -272,11 +311,13 @@ namespace ArchiSteamFarm {
|
|||
byte[] buffer = new byte[bufferSize];
|
||||
|
||||
Array.Copy(timeArray, buffer, 8);
|
||||
|
||||
if (!string.IsNullOrEmpty(tag)) {
|
||||
Array.Copy(Encoding.UTF8.GetBytes(tag), 0, buffer, 8, bufferSize - 8);
|
||||
}
|
||||
|
||||
byte[] hash;
|
||||
|
||||
using (HMACSHA1 hmac = new HMACSHA1(identitySecret)) {
|
||||
hash = hmac.ComputeHash(buffer);
|
||||
}
|
||||
|
@ -287,6 +328,7 @@ namespace ArchiSteamFarm {
|
|||
private string GenerateTokenForTime(uint time) {
|
||||
if (time == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(time));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -297,15 +339,18 @@ namespace ArchiSteamFarm {
|
|||
} catch (FormatException e) {
|
||||
Bot.ArchiLogger.LogGenericException(e);
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, nameof(SharedSecret)));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] timeArray = BitConverter.GetBytes((long) time / CodeInterval);
|
||||
|
||||
if (BitConverter.IsLittleEndian) {
|
||||
Array.Reverse(timeArray);
|
||||
}
|
||||
|
||||
byte[] hash;
|
||||
|
||||
using (HMACSHA1 hmac = new HMACSHA1(sharedSecret)) {
|
||||
hash = hmac.ComputeHash(timeArray);
|
||||
}
|
||||
|
@ -348,6 +393,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
uint serverTime = await Bot.ArchiWebHandler.GetServerTime().ConfigureAwait(false);
|
||||
|
||||
if (serverTime == 0) {
|
||||
return Utilities.GetUnixTime();
|
||||
}
|
||||
|
@ -367,6 +413,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
await ConfirmationsSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
Utilities.InBackground(
|
||||
async () => {
|
||||
await Task.Delay(Program.GlobalConfig.ConfirmationsLimiterDelay * 1000).ConfigureAwait(false);
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogChatMessage(bool echo, string message, ulong chatGroupID = 0, ulong chatID = 0, ulong steamID = 0, [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message) || (((chatGroupID == 0) || (chatID == 0)) && (steamID == 0))) {
|
||||
LogNullError(nameof(message) + " || " + "((" + nameof(chatGroupID) + " || " + nameof(chatID) + ") && " + nameof(steamID) + ")");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -69,6 +70,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal async Task LogFatalException(Exception exception, [CallerMemberName] string previousMethodName = null) {
|
||||
if (exception == null) {
|
||||
LogNullError(nameof(exception));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -85,13 +87,13 @@ namespace ArchiSteamFarm.NLog {
|
|||
try {
|
||||
await RuntimeCompatibility.File.WriteAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false);
|
||||
} catch {
|
||||
// Ignored, we can't do anything with this
|
||||
// Ignored, we can't do anything about this
|
||||
}
|
||||
|
||||
try {
|
||||
Console.Write(message);
|
||||
} catch {
|
||||
// Ignored, we can't do anything with this
|
||||
// Ignored, we can't do anything about this
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
@ -100,17 +102,18 @@ namespace ArchiSteamFarm.NLog {
|
|||
try {
|
||||
await RuntimeCompatibility.File.AppendAllTextAsync(SharedInfo.LogFile, message).ConfigureAwait(false);
|
||||
} catch {
|
||||
// Ignored, we can't do anything with this
|
||||
// Ignored, we can't do anything about this
|
||||
}
|
||||
|
||||
try {
|
||||
Console.Write(message);
|
||||
} catch {
|
||||
// Ignored, we can't do anything with this
|
||||
// Ignored, we can't do anything about this
|
||||
}
|
||||
|
||||
if (exception.InnerException != null) {
|
||||
exception = exception.InnerException;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -121,6 +124,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericDebug(string message, [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -130,6 +134,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericDebuggingException(Exception exception, [CallerMemberName] string previousMethodName = null) {
|
||||
if (exception == null) {
|
||||
LogNullError(nameof(exception));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -143,6 +148,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericError(string message, [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -152,6 +158,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericException(Exception exception, [CallerMemberName] string previousMethodName = null) {
|
||||
if (exception == null) {
|
||||
LogNullError(nameof(exception));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,6 +168,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericInfo(string message, [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -170,6 +178,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericTrace(string message, [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -179,6 +188,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericWarning(string message, [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -188,6 +198,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
internal void LogGenericWarningException(Exception exception, [CallerMemberName] string previousMethodName = null) {
|
||||
if (exception == null) {
|
||||
LogNullError(nameof(exception));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,11 @@ namespace ArchiSteamFarm.NLog {
|
|||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
public byte MaxCount {
|
||||
get => HistoryQueue.MaxCount;
|
||||
|
||||
set {
|
||||
if (value == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -61,6 +63,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
protected override void Write(LogEventInfo logEvent) {
|
||||
if (logEvent == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(logEvent));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
}
|
||||
|
||||
bool reload = false;
|
||||
|
||||
foreach (LoggingRule rule in LogManager.Configuration.LoggingRules.Where(rule => rule.IsLoggingEnabledForLevel(LogLevel.Debug) && !rule.IsLoggingEnabledForLevel(LogLevel.Trace))) {
|
||||
rule.EnableLoggingForLevel(LogLevel.Trace);
|
||||
reload = true;
|
||||
|
@ -57,6 +58,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
IsUsingCustomConfiguration = true;
|
||||
InitConsoleLoggers();
|
||||
LogManager.ConfigurationChanged += OnConfigurationChanged;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -89,7 +91,6 @@ namespace ArchiSteamFarm.NLog {
|
|||
HistoryTarget historyTarget = LogManager.Configuration.AllTargets.OfType<HistoryTarget>().FirstOrDefault();
|
||||
|
||||
if ((historyTarget == null) && !IsUsingCustomConfiguration) {
|
||||
// TODO: We could use some nice HTML layout for this
|
||||
historyTarget = new HistoryTarget("History") {
|
||||
Layout = GeneralLayout,
|
||||
MaxCount = 20
|
||||
|
@ -154,6 +155,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
private static void OnConfigurationChanged(object sender, LoggingConfigurationChangedEventArgs e) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
protected override async void Write(LogEventInfo logEvent) {
|
||||
if (logEvent == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(logEvent));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -89,6 +90,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
private async Task SendGroupMessage(string message, Bot bot = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -106,6 +108,7 @@ namespace ArchiSteamFarm.NLog {
|
|||
private async Task SendPrivateMessage(string message, Bot bot = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,14 +41,18 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (optimizationMode) {
|
||||
case GlobalConfig.EOptimizationMode.MaxPerformance:
|
||||
|
||||
// No specific tuning required for now, ASF is optimized for max performance by default
|
||||
break;
|
||||
case GlobalConfig.EOptimizationMode.MinMemoryUsage:
|
||||
|
||||
// We can disable regex cache which will slightly lower memory usage (for a huge performance hit)
|
||||
Regex.CacheSize = 0;
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(optimizationMode), optimizationMode));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +60,7 @@ namespace ArchiSteamFarm {
|
|||
internal static void UnixSetFileAccessExecutable(string path) {
|
||||
if (string.IsNullOrEmpty(path) || !File.Exists(path)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(path));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -75,6 +80,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!NativeMethods.GetConsoleMode(consoleHandle, out uint consoleMode)) {
|
||||
ASF.ArchiLogger.LogGenericError(Strings.WarningFailed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (GlobalConfig.Headless) {
|
||||
ASF.ArchiLogger.LogGenericWarning(Strings.ErrorUserInputRunningInHeadlessMode);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -85,31 +86,38 @@ namespace ArchiSteamFarm {
|
|||
case ASF.EUserInputType.DeviceID:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputDeviceID, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Login:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamLogin, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Password:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamPassword, botName));
|
||||
result = Utilities.ReadLineMasked();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamGuard:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamGuard, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamParentalCode:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteamParentalCode, botName));
|
||||
result = Utilities.ReadLineMasked();
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.TwoFactorAuthentication:
|
||||
Console.Write(Bot.FormatBotResponse(Strings.UserInputSteam2FA, botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(userInputType), userInputType));
|
||||
Console.Write(Bot.FormatBotResponse(string.Format(Strings.UserInputUnknown, userInputType), botName));
|
||||
result = Console.ReadLine();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -119,6 +127,7 @@ namespace ArchiSteamFarm {
|
|||
} catch (Exception e) {
|
||||
Logging.OnUserInputEnd();
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -134,8 +143,10 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
string executableName = Path.GetFileNameWithoutExtension(ProcessFileName);
|
||||
|
||||
if (string.IsNullOrEmpty(executableName)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(executableName));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -157,6 +168,7 @@ namespace ArchiSteamFarm {
|
|||
private static void HandleCryptKeyArgument(string cryptKey) {
|
||||
if (string.IsNullOrEmpty(cryptKey)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(cryptKey));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -166,6 +178,7 @@ namespace ArchiSteamFarm {
|
|||
private static void HandlePathArgument(string path) {
|
||||
if (string.IsNullOrEmpty(path)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(path));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -217,6 +230,7 @@ namespace ArchiSteamFarm {
|
|||
// Common structure is bin/(x64/)Debug/ArchiSteamFarm.exe, so we allow up to 4 directories up
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
Directory.SetCurrentDirectory("..");
|
||||
|
||||
if (Directory.Exists(SharedInfo.ConfigDirectory)) {
|
||||
break;
|
||||
}
|
||||
|
@ -241,10 +255,12 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (File.Exists(globalConfigFile)) {
|
||||
GlobalConfig = await GlobalConfig.Load(globalConfigFile).ConfigureAwait(false);
|
||||
|
||||
if (GlobalConfig == null) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorGlobalConfigNotLoaded, globalConfigFile));
|
||||
await Task.Delay(5 * 1000).ConfigureAwait(false);
|
||||
await Exit(1).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -270,24 +286,31 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
ResourceSet defaultResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.GetCultureInfo("en-US"), true, true);
|
||||
|
||||
if (defaultResourceSet == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(defaultResourceSet));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<DictionaryEntry> defaultStringObjects = defaultResourceSet.Cast<DictionaryEntry>().ToHashSet();
|
||||
|
||||
if (defaultStringObjects.Count == 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(defaultStringObjects));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceSet currentResourceSet = Strings.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
|
||||
|
||||
if (currentResourceSet == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(currentResourceSet));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<DictionaryEntry> currentStringObjects = currentResourceSet.Cast<DictionaryEntry>().ToHashSet();
|
||||
|
||||
if (currentStringObjects.Count >= defaultStringObjects.Count) {
|
||||
// Either we have 100% finished translation, or we're missing it entirely and using en-US
|
||||
HashSet<DictionaryEntry> testStringObjects = currentStringObjects.ToHashSet();
|
||||
|
@ -317,10 +340,12 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
GlobalDatabase = await GlobalDatabase.CreateOrLoad(globalDatabaseFile).ConfigureAwait(false);
|
||||
|
||||
if (GlobalDatabase == null) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorDatabaseInvalid, globalDatabaseFile));
|
||||
await Task.Delay(5 * 1000).ConfigureAwait(false);
|
||||
await Exit(1).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -372,6 +397,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
LogManager.Flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -388,6 +414,7 @@ namespace ArchiSteamFarm {
|
|||
private static async void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
||||
if (e?.ExceptionObject == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.ExceptionObject));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -398,6 +425,7 @@ namespace ArchiSteamFarm {
|
|||
private static async void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) {
|
||||
if (e?.Exception == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.Exception));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -411,6 +439,7 @@ namespace ArchiSteamFarm {
|
|||
private static void ParsePostInitArgs(IReadOnlyCollection<string> args) {
|
||||
if (args == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -420,17 +449,22 @@ namespace ArchiSteamFarm {
|
|||
switch (arg) {
|
||||
case "--cryptkey" when !cryptKeyNext:
|
||||
cryptKeyNext = true;
|
||||
|
||||
break;
|
||||
case "--no-restart" when !cryptKeyNext:
|
||||
RestartAllowed = false;
|
||||
|
||||
break;
|
||||
case "--process-required" when !cryptKeyNext:
|
||||
ProcessRequired = true;
|
||||
|
||||
break;
|
||||
case "--system-required" when !cryptKeyNext:
|
||||
SystemRequired = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (cryptKeyNext) {
|
||||
cryptKeyNext = false;
|
||||
HandleCryptKeyArgument(arg);
|
||||
|
@ -446,6 +480,7 @@ namespace ArchiSteamFarm {
|
|||
private static void ParsePreInitArgs(IReadOnlyCollection<string> args) {
|
||||
if (args == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -455,8 +490,10 @@ namespace ArchiSteamFarm {
|
|||
switch (arg) {
|
||||
case "--path" when !pathNext:
|
||||
pathNext = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (pathNext) {
|
||||
pathNext = false;
|
||||
HandlePathArgument(arg);
|
||||
|
|
|
@ -94,6 +94,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
const string request = URL + "/Api/HeartBeat";
|
||||
|
||||
Dictionary<string, string> data = new Dictionary<string, string>(2) {
|
||||
{ "SteamID", Bot.SteamID.ToString() },
|
||||
{ "Guid", Program.GlobalDatabase.Guid.ToString("N") }
|
||||
|
@ -123,17 +124,21 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Don't announce if we don't meet conditions
|
||||
string tradeToken;
|
||||
|
||||
if (!await IsEligibleForMatching().ConfigureAwait(false) || string.IsNullOrEmpty(tradeToken = await Bot.ArchiHandler.GetTradeToken().ConfigureAwait(false))) {
|
||||
LastAnnouncementCheck = DateTime.UtcNow;
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<Steam.Asset.EType> acceptedMatchableTypes = Bot.BotConfig.MatchableTypes.Where(type => AcceptedMatchableTypes.Contains(type)).ToHashSet();
|
||||
|
||||
if (acceptedMatchableTypes.Count == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(acceptedMatchableTypes));
|
||||
LastAnnouncementCheck = DateTime.UtcNow;
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -142,6 +147,7 @@ namespace ArchiSteamFarm {
|
|||
// This is actually inventory failure, so we'll stop sending heartbeats but not record it as valid check
|
||||
if (inventory == null) {
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,10 +155,12 @@ namespace ArchiSteamFarm {
|
|||
if (inventory.Count < MinItemsCount) {
|
||||
LastAnnouncementCheck = DateTime.UtcNow;
|
||||
ShouldSendHeartBeats = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const string request = URL + "/Api/Announce";
|
||||
|
||||
Dictionary<string, string> data = new Dictionary<string, string>(9) {
|
||||
{ "SteamID", Bot.SteamID.ToString() },
|
||||
{ "Guid", Program.GlobalDatabase.Guid.ToString("N") },
|
||||
|
@ -179,6 +187,7 @@ namespace ArchiSteamFarm {
|
|||
const string request = URL + "/Api/Bots";
|
||||
|
||||
WebBrowser.ObjectResponse<HashSet<ListedUser>> objectResponse = await Program.WebBrowser.UrlGetToJsonObject<HashSet<ListedUser>>(request).ConfigureAwait(false);
|
||||
|
||||
return objectResponse?.Content;
|
||||
}
|
||||
|
||||
|
@ -186,30 +195,35 @@ namespace ArchiSteamFarm {
|
|||
// Bot must have ASF 2FA
|
||||
if (!Bot.HasMobileAuthenticator) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.HasMobileAuthenticator) + ": " + Bot.HasMobileAuthenticator));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have STM enable in TradingPreferences
|
||||
if (!Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.BotConfig.TradingPreferences) + ": " + Bot.BotConfig.TradingPreferences));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have at least one accepted matchable type set
|
||||
if ((Bot.BotConfig.MatchableTypes.Count == 0) || Bot.BotConfig.MatchableTypes.All(type => !AcceptedMatchableTypes.Contains(type))) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.BotConfig.MatchableTypes) + ": " + Bot.BotConfig.MatchableTypes));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have public inventory
|
||||
if (!await Bot.ArchiWebHandler.HasPublicInventory().ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.ArchiWebHandler.HasPublicInventory) + ": " + false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bot must have valid API key (e.g. not being restricted account)
|
||||
if (!await Bot.ArchiWebHandler.HasValidApiKey().ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.ArchiWebHandler.HasValidApiKey) + ": " + false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -219,17 +233,21 @@ namespace ArchiSteamFarm {
|
|||
private async Task MatchActively() {
|
||||
if (!Bot.IsConnectedAndLoggedOn || Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything) || !Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchActively) || !await IsEligibleForMatching().ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.ErrorAborted);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<Steam.Asset.EType> acceptedMatchableTypes = Bot.BotConfig.MatchableTypes.Where(type => AcceptedMatchableTypes.Contains(type)).ToHashSet();
|
||||
|
||||
if (acceptedMatchableTypes.Count == 0) {
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.ErrorAborted);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await MatchActivelySemaphore.WaitAsync(0).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.ErrorAborted);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -248,6 +266,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!Bot.IsConnectedAndLoggedOn || Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything) || !Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchActively) || !await IsEligibleForMatching().ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.ErrorAborted);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -268,12 +287,15 @@ namespace ArchiSteamFarm {
|
|||
private async Task<bool> MatchActivelyRound(IReadOnlyCollection<Steam.Asset.EType> acceptedMatchableTypes, IDictionary<ulong, (byte Tries, ISet<ulong> GivenAssetIDs, ISet<ulong> ReceivedAssetIDs)> triedSteamIDs) {
|
||||
if ((acceptedMatchableTypes == null) || (acceptedMatchableTypes.Count == 0) || (triedSteamIDs == null)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(acceptedMatchableTypes) + " || " + nameof(triedSteamIDs));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<Steam.Asset> ourInventory = await Bot.ArchiWebHandler.GetInventory(Bot.SteamID, wantedTypes: acceptedMatchableTypes).ConfigureAwait(false);
|
||||
|
||||
if ((ourInventory == null) || (ourInventory.Count == 0)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.ErrorIsEmpty, nameof(ourInventory)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -282,12 +304,15 @@ namespace ArchiSteamFarm {
|
|||
if (Trading.IsEmptyForMatching(fullState, tradableState)) {
|
||||
// User doesn't have any more dupes in the inventory
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.ErrorIsEmpty, nameof(fullState) + " || " + nameof(tradableState)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<ListedUser> listedUsers = await GetListedUsers().ConfigureAwait(false);
|
||||
|
||||
if ((listedUsers == null) || (listedUsers.Count == 0)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.ErrorIsEmpty, nameof(listedUsers)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -298,8 +323,10 @@ namespace ArchiSteamFarm {
|
|||
Bot.ArchiLogger.LogGenericTrace(listedUser.SteamID + "...");
|
||||
|
||||
HashSet<Steam.Asset> theirInventory = await Bot.ArchiWebHandler.GetInventory(listedUser.SteamID, tradable: true, wantedSets: fullState.Keys, skippedSets: skippedSetsThisRound).ConfigureAwait(false);
|
||||
|
||||
if ((theirInventory == null) || (theirInventory.Count == 0)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.ErrorIsEmpty, nameof(theirInventory)));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -333,6 +360,7 @@ namespace ArchiSteamFarm {
|
|||
foreach (KeyValuePair<ulong, uint> pastChange in pastChanges) {
|
||||
if (!ourFullSet.TryGetValue(pastChange.Key, out uint fullAmount) || (fullAmount == 0) || (fullAmount < pastChange.Value)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(fullAmount));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -344,6 +372,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (!ourTradableSet.TryGetValue(pastChange.Key, out uint tradableAmount) || (tradableAmount == 0) || (tradableAmount < pastChange.Value)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(tradableAmount));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -406,6 +435,7 @@ namespace ArchiSteamFarm {
|
|||
// Update their state based on taken items
|
||||
if (!theirItems.TryGetValue(theirItem.Key, out uint theirAmount) || (theirAmount == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(theirAmount));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -418,6 +448,7 @@ namespace ArchiSteamFarm {
|
|||
itemsInTrade += 2;
|
||||
|
||||
match = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -434,6 +465,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (skippedSetsThisTrade.Count == 0) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.ErrorIsEmpty, nameof(skippedSetsThisTrade)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -443,6 +475,7 @@ namespace ArchiSteamFarm {
|
|||
if ((itemsToGive.Count != itemsToReceive.Count) || !Trading.IsFairTypesExchange(itemsToGive, itemsToReceive)) {
|
||||
// Failsafe
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningFailedWithError, Strings.ErrorAborted));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -450,6 +483,7 @@ namespace ArchiSteamFarm {
|
|||
if (itemsToGive.Select(item => item.AssetID).All(previousAttempt.GivenAssetIDs.Contains) && itemsToReceive.Select(item => item.AssetID).All(previousAttempt.ReceivedAssetIDs.Contains)) {
|
||||
// This user didn't respond in our previous round, avoid him for remaining ones
|
||||
triedSteamIDs[listedUser.SteamID] = (byte.MaxValue, previousAttempt.GivenAssetIDs, previousAttempt.ReceivedAssetIDs);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -471,12 +505,14 @@ namespace ArchiSteamFarm {
|
|||
if ((mobileTradeOfferIDs != null) && (mobileTradeOfferIDs.Count > 0) && Bot.HasMobileAuthenticator) {
|
||||
if (!await Bot.Actions.AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, mobileTradeOfferIDs, true).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.WarningFailed);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Bot.ArchiLogger.LogGenericTrace(Strings.WarningFailed);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -514,6 +550,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ActivelyMatchingItemsRound, skippedSetsThisRound.Count));
|
||||
|
||||
return skippedSetsThisRound.Count > 0;
|
||||
}
|
||||
|
||||
|
@ -550,12 +587,15 @@ namespace ArchiSteamFarm {
|
|||
switch (value) {
|
||||
case 0:
|
||||
MatchableTypes.Remove(Steam.Asset.EType.ProfileBackground);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
MatchableTypes.Add(Steam.Asset.EType.ProfileBackground);
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(value), value));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -567,12 +607,15 @@ namespace ArchiSteamFarm {
|
|||
switch (value) {
|
||||
case 0:
|
||||
MatchableTypes.Remove(Steam.Asset.EType.TradingCard);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
MatchableTypes.Add(Steam.Asset.EType.TradingCard);
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(value), value));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -584,12 +627,15 @@ namespace ArchiSteamFarm {
|
|||
switch (value) {
|
||||
case 0:
|
||||
MatchableTypes.Remove(Steam.Asset.EType.Emoticon);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
MatchableTypes.Add(Steam.Asset.EType.Emoticon);
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(value), value));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -601,12 +647,15 @@ namespace ArchiSteamFarm {
|
|||
switch (value) {
|
||||
case 0:
|
||||
MatchableTypes.Remove(Steam.Asset.EType.FoilTradingCard);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
MatchableTypes.Add(Steam.Asset.EType.FoilTradingCard);
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(value), value));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -618,12 +667,15 @@ namespace ArchiSteamFarm {
|
|||
switch (value) {
|
||||
case 0:
|
||||
MatchEverything = false;
|
||||
|
||||
break;
|
||||
case 1:
|
||||
MatchEverything = true;
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(value), value));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace ArchiSteamFarm.SteamKit2 {
|
|||
public Task UpdateServerListAsync(IEnumerable<ServerRecord> endpoints) {
|
||||
if (endpoints == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(endpoints));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@ -47,6 +48,7 @@ namespace ArchiSteamFarm.SteamKit2 {
|
|||
}
|
||||
|
||||
ServerListUpdated?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ using Newtonsoft.Json;
|
|||
using SteamKit2;
|
||||
|
||||
namespace ArchiSteamFarm.SteamKit2 {
|
||||
internal sealed class ServerRecordEndPoint {
|
||||
internal sealed class ServerRecordEndPoint : IEquatable<ServerRecordEndPoint> {
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
internal readonly string Host;
|
||||
|
||||
|
@ -46,9 +46,8 @@ namespace ArchiSteamFarm.SteamKit2 {
|
|||
|
||||
private ServerRecordEndPoint() { }
|
||||
|
||||
public bool Equals(ServerRecordEndPoint other) => (Host == other.Host) && (Port == other.Port) && (ProtocolTypes == other.ProtocolTypes);
|
||||
public override bool Equals(object obj) => (obj != null) && ((obj == this) || (obj is ServerRecordEndPoint serverRecord && Equals(serverRecord)));
|
||||
public override int GetHashCode() => (Host, Port, ProtocolTypes).GetHashCode();
|
||||
|
||||
private bool Equals(ServerRecordEndPoint other) => string.Equals(Host, other.Host) && (Port == other.Port) && (ProtocolTypes == other.ProtocolTypes);
|
||||
public override int GetHashCode() => RuntimeCompatibility.HashCode.Combine(Host, Port, ProtocolTypes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,8 +55,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
for (byte i = 0; (i < MaxSingleQueuesDaily) && (await IsDiscoveryQueueAvailable().ConfigureAwait(false)).GetValueOrDefault(); i++) {
|
||||
HashSet<uint> queue = await Bot.ArchiWebHandler.GenerateNewDiscoveryQueue().ConfigureAwait(false);
|
||||
|
||||
if ((queue == null) || (queue.Count == 0)) {
|
||||
Bot.ArchiLogger.LogGenericTrace(string.Format(Strings.ErrorIsEmpty, nameof(queue)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -69,6 +71,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.WarningFailed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -80,19 +83,23 @@ namespace ArchiSteamFarm {
|
|||
|
||||
private async Task<bool?> IsDiscoveryQueueAvailable() {
|
||||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetDiscoveryQueuePage().ConfigureAwait(false);
|
||||
|
||||
if (htmlDocument == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//div[@class='subtext']");
|
||||
|
||||
if (htmlNode == null) {
|
||||
// Valid, no cards for exploring the queue available
|
||||
return false;
|
||||
}
|
||||
|
||||
string text = htmlNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(text)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -110,6 +117,7 @@ namespace ArchiSteamFarm {
|
|||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetSteamAwardsPage().ConfigureAwait(false);
|
||||
|
||||
HtmlNodeCollection nominationNodes = htmlDocument?.DocumentNode.SelectNodes("//div[@class='vote_nominations store_horizontal_autoslider']");
|
||||
|
||||
if (nominationNodes == null) {
|
||||
// Event ended, error or likewise
|
||||
return;
|
||||
|
@ -117,25 +125,31 @@ namespace ArchiSteamFarm {
|
|||
|
||||
foreach (HtmlNode nominationNode in nominationNodes) {
|
||||
HtmlNode myVoteNode = nominationNode.SelectSingleNode("./div[@class='vote_nomination your_vote']");
|
||||
|
||||
if (myVoteNode != null) {
|
||||
// Already voted
|
||||
continue;
|
||||
}
|
||||
|
||||
string voteIDText = nominationNode.GetAttributeValue("data-voteid", null);
|
||||
|
||||
if (string.IsNullOrEmpty(voteIDText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(voteIDText));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!byte.TryParse(voteIDText, out byte voteID) || (voteID == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(voteID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
HtmlNodeCollection voteNodes = nominationNode.SelectNodes("./div[starts-with(@class, 'vote_nomination')]");
|
||||
|
||||
if (voteNodes == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(voteNodes));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -143,13 +157,16 @@ namespace ArchiSteamFarm {
|
|||
HtmlNode voteNode = voteNodes[Utilities.RandomNext(voteNodes.Count)];
|
||||
|
||||
string appIDText = voteNode.GetAttributeValue("data-vote-appid", null);
|
||||
|
||||
if (string.IsNullOrEmpty(appIDText)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appIDText));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!uint.TryParse(appIDText, out uint appID) || (appID == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace ArchiSteamFarm {
|
|||
internal static (Dictionary<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> FullState, Dictionary<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> TradableState) GetDividedInventoryState(IReadOnlyCollection<Steam.Asset> inventory) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(inventory));
|
||||
|
||||
return (null, null);
|
||||
}
|
||||
|
||||
|
@ -87,6 +88,7 @@ namespace ArchiSteamFarm {
|
|||
internal static Dictionary<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> GetInventoryState(IReadOnlyCollection<Steam.Asset> inventory) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(inventory));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -112,6 +114,7 @@ namespace ArchiSteamFarm {
|
|||
internal static HashSet<Steam.Asset> GetTradableItemsFromInventory(IReadOnlyCollection<Steam.Asset> inventory, IDictionary<ulong, uint> classIDs) {
|
||||
if ((inventory == null) || (inventory.Count == 0) || (classIDs == null) || (classIDs.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(inventory) + " || " + nameof(classIDs));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -141,12 +144,14 @@ namespace ArchiSteamFarm {
|
|||
internal static bool IsEmptyForMatching(IReadOnlyDictionary<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> fullState, IReadOnlyDictionary<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> tradableState) {
|
||||
if ((fullState == null) || (tradableState == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(fullState) + " || " + nameof(tradableState));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> tradableSet in tradableState) {
|
||||
if (!fullState.TryGetValue(tradableSet.Key, out Dictionary<ulong, uint> fullSet) || (fullSet == null) || (fullSet.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(fullSet));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -162,19 +167,24 @@ namespace ArchiSteamFarm {
|
|||
internal static bool IsEmptyForMatching(IReadOnlyDictionary<ulong, uint> fullSet, IReadOnlyDictionary<ulong, uint> tradableSet) {
|
||||
if ((fullSet == null) || (tradableSet == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(fullSet) + " || " + nameof(tradableSet));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<ulong, uint> tradableItem in tradableSet) {
|
||||
switch (tradableItem.Value) {
|
||||
case 0:
|
||||
|
||||
// No tradable items, this should never happen, dictionary should not have this key to begin with
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(tradableItem.Value), tradableItem.Value));
|
||||
|
||||
return false;
|
||||
case 1:
|
||||
|
||||
// Single tradable item, can be matchable or not depending on the rest of the inventory
|
||||
if (!fullSet.TryGetValue(tradableItem.Key, out uint fullAmount) || (fullAmount == 0) || (fullAmount < tradableItem.Value)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(fullAmount));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -186,6 +196,7 @@ namespace ArchiSteamFarm {
|
|||
// A single exclusive tradable item is not matchable, continue
|
||||
continue;
|
||||
default:
|
||||
|
||||
// Any other combination of tradable items is always matchable
|
||||
return false;
|
||||
}
|
||||
|
@ -198,10 +209,12 @@ namespace ArchiSteamFarm {
|
|||
internal static bool IsFairTypesExchange(IReadOnlyCollection<Steam.Asset> itemsToGive, IReadOnlyCollection<Steam.Asset> itemsToReceive) {
|
||||
if ((itemsToGive == null) || (itemsToGive.Count == 0) || (itemsToReceive == null) || (itemsToReceive.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(itemsToGive) + " || " + nameof(itemsToReceive));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Dictionary<uint, Dictionary<Steam.Asset.EType, uint>> itemsToGivePerGame = new Dictionary<uint, Dictionary<Steam.Asset.EType, uint>>();
|
||||
|
||||
foreach (Steam.Asset item in itemsToGive) {
|
||||
if (itemsToGivePerGame.TryGetValue(item.RealAppID, out Dictionary<Steam.Asset.EType, uint> itemsPerType)) {
|
||||
itemsPerType[item.Type] = itemsPerType.TryGetValue(item.Type, out uint amount) ? amount + item.Amount : item.Amount;
|
||||
|
@ -212,6 +225,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Dictionary<uint, Dictionary<Steam.Asset.EType, uint>> itemsToReceivePerGame = new Dictionary<uint, Dictionary<Steam.Asset.EType, uint>>();
|
||||
|
||||
foreach (Steam.Asset item in itemsToReceive) {
|
||||
if (itemsToReceivePerGame.TryGetValue(item.RealAppID, out Dictionary<Steam.Asset.EType, uint> itemsPerType)) {
|
||||
itemsPerType[item.Type] = itemsPerType.TryGetValue(item.Type, out uint amount) ? amount + item.Amount : item.Amount;
|
||||
|
@ -275,16 +289,19 @@ namespace ArchiSteamFarm {
|
|||
private static Dictionary<(uint AppID, Steam.Asset.EType Type), List<uint>> GetInventorySets(IReadOnlyCollection<Steam.Asset> inventory) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(inventory));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<(uint AppID, Steam.Asset.EType Type), Dictionary<ulong, uint>> sets = GetInventoryState(inventory);
|
||||
|
||||
return sets.ToDictionary(set => set.Key, set => set.Value.Values.OrderBy(amount => amount).ToList());
|
||||
}
|
||||
|
||||
private static bool IsTradeNeutralOrBetter(HashSet<Steam.Asset> inventory, IReadOnlyCollection<Steam.Asset> itemsToGive, IReadOnlyCollection<Steam.Asset> itemsToReceive) {
|
||||
if ((inventory == null) || (inventory.Count == 0) || (itemsToGive == null) || (itemsToGive.Count == 0) || (itemsToReceive == null) || (itemsToReceive.Count == 0)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(inventory) + " || " + nameof(itemsToGive) + " || " + nameof(itemsToReceive));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -319,6 +336,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (amountToGive > 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(amountToGive));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -385,6 +403,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
private async Task ParseActiveTrades() {
|
||||
HashSet<Steam.TradeOffer> tradeOffers = await Bot.ArchiWebHandler.GetActiveTradeOffers().ConfigureAwait(false);
|
||||
|
||||
if ((tradeOffers == null) || (tradeOffers.Count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -402,6 +421,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (Bot.HasMobileAuthenticator) {
|
||||
HashSet<ulong> mobileTradeOfferIDs = results.Where(result => (result.TradeResult != null) && (result.TradeResult.Result == ParseTradeResult.EResult.Accepted) && result.RequiresMobileConfirmation).Select(result => result.TradeResult.TradeOfferID).ToHashSet();
|
||||
|
||||
if (mobileTradeOfferIDs.Count > 0) {
|
||||
if (!await Bot.Actions.AcceptConfirmations(true, Steam.ConfirmationDetails.EType.Trade, mobileTradeOfferIDs, true).ConfigureAwait(false)) {
|
||||
return;
|
||||
|
@ -418,11 +438,13 @@ namespace ArchiSteamFarm {
|
|||
private async Task<(ParseTradeResult TradeResult, bool RequiresMobileConfirmation)> ParseTrade(Steam.TradeOffer tradeOffer) {
|
||||
if (tradeOffer == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(tradeOffer));
|
||||
|
||||
return (null, false);
|
||||
}
|
||||
|
||||
if (tradeOffer.State != Steam.TradeOffer.ETradeOfferState.Active) {
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, tradeOffer.State));
|
||||
|
||||
return (null, false);
|
||||
}
|
||||
|
||||
|
@ -430,12 +452,15 @@ namespace ArchiSteamFarm {
|
|||
// We've already seen this trade
|
||||
IgnoredTrades.Add(tradeOffer.TradeOfferID);
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IgnoringTrade, tradeOffer.TradeOfferID));
|
||||
|
||||
return (new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently), false);
|
||||
}
|
||||
|
||||
ParseTradeResult result = await ShouldAcceptTrade(tradeOffer).ConfigureAwait(false);
|
||||
|
||||
if (result == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(result));
|
||||
|
||||
return (null, false);
|
||||
}
|
||||
|
||||
|
@ -456,15 +481,18 @@ namespace ArchiSteamFarm {
|
|||
case ParseTradeResult.EResult.RejectedPermanently when Bot.BotConfig.BotBehaviour.HasFlag(BotConfig.EBotBehaviour.RejectInvalidTrades):
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.RejectingTrade, tradeOffer.TradeOfferID));
|
||||
await Bot.ArchiWebHandler.DeclineTradeOffer(tradeOffer.TradeOfferID).ConfigureAwait(false);
|
||||
|
||||
return (result, false);
|
||||
case ParseTradeResult.EResult.RejectedPermanently:
|
||||
IgnoredTrades.Add(tradeOffer.TradeOfferID);
|
||||
goto case ParseTradeResult.EResult.RejectedTemporarily;
|
||||
case ParseTradeResult.EResult.RejectedTemporarily:
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IgnoringTrade, tradeOffer.TradeOfferID));
|
||||
|
||||
return (result, false);
|
||||
default:
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(result.Result), result.Result));
|
||||
|
||||
return (null, false);
|
||||
}
|
||||
}
|
||||
|
@ -472,6 +500,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<ParseTradeResult> ShouldAcceptTrade(Steam.TradeOffer tradeOffer) {
|
||||
if (tradeOffer == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(tradeOffer));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -490,9 +519,11 @@ namespace ArchiSteamFarm {
|
|||
// Check if it's donation trade
|
||||
switch (tradeOffer.ItemsToGive.Count) {
|
||||
case 0 when tradeOffer.ItemsToReceive.Count == 0:
|
||||
|
||||
// If it's steam issue, temporarily ignore it
|
||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedTemporarily, tradeOffer.ItemsToReceive);
|
||||
case 0:
|
||||
|
||||
// Otherwise react accordingly, depending on our preference
|
||||
bool acceptDonations = Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.AcceptDonations);
|
||||
bool acceptBotTrades = !Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.DontAcceptBotTrades);
|
||||
|
@ -509,6 +540,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Otherwise we either accept donations but not bot trades, or we accept bot trades but not donations
|
||||
bool isBotTrade = (tradeOffer.OtherSteamID64 != 0) && Bot.Bots.Values.Any(bot => bot.SteamID == tradeOffer.OtherSteamID64);
|
||||
|
||||
return new ParseTradeResult(tradeOffer.TradeOfferID, (acceptDonations && !isBotTrade) || (acceptBotTrades && isBotTrade) ? ParseTradeResult.EResult.Accepted : ParseTradeResult.EResult.RejectedPermanently, tradeOffer.ItemsToReceive);
|
||||
}
|
||||
|
||||
|
@ -531,6 +563,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Fetch trade hold duration
|
||||
byte? holdDuration = await Bot.GetTradeHoldDuration(tradeOffer.OtherSteamID64, tradeOffer.TradeOfferID).ConfigureAwait(false);
|
||||
|
||||
if (!holdDuration.HasValue) {
|
||||
// If we can't get trade hold duration, reject trade temporarily
|
||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedTemporarily, tradeOffer.ItemsToReceive);
|
||||
|
@ -558,9 +591,11 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Now check if it's worth for us to do the trade
|
||||
HashSet<Steam.Asset> inventory = await Bot.ArchiWebHandler.GetInventory(Bot.SteamID, wantedSets: wantedSets).ConfigureAwait(false);
|
||||
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
// If we can't check our inventory when not using MatchEverything, this is a temporary failure
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
|
||||
|
||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedTemporarily, tradeOffer.ItemsToReceive);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace ArchiSteamFarm {
|
|||
internal static string GetArgsAsText(string[] args, byte argsToSkip, string delimiter) {
|
||||
if ((args == null) || (args.Length <= argsToSkip) || string.IsNullOrEmpty(delimiter)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(args) + " || " + nameof(argsToSkip) + " || " + nameof(delimiter));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -48,16 +49,19 @@ namespace ArchiSteamFarm {
|
|||
internal static string GetArgsAsText(string text, byte argsToSkip) {
|
||||
if (string.IsNullOrEmpty(text)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(text));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
string[] args = text.Split((char[]) null, argsToSkip + 1, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
return args[args.Length - 1];
|
||||
}
|
||||
|
||||
internal static string GetCookieValue(this CookieContainer cookieContainer, string url, string name) {
|
||||
if ((cookieContainer == null) || string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(cookieContainer) + " || " + nameof(url) + " || " + nameof(name));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -67,10 +71,12 @@ namespace ArchiSteamFarm {
|
|||
uri = new Uri(url);
|
||||
} catch (UriFormatException e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
CookieCollection cookies = cookieContainer.GetCookies(uri);
|
||||
|
||||
return cookies.Count > 0 ? (from Cookie cookie in cookies where cookie.Name.Equals(name) select cookie.Value).FirstOrDefault() : null;
|
||||
}
|
||||
|
||||
|
@ -79,6 +85,7 @@ namespace ArchiSteamFarm {
|
|||
internal static void InBackground(Action action, bool longRunning = false) {
|
||||
if (action == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(action));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -94,6 +101,7 @@ namespace ArchiSteamFarm {
|
|||
internal static void InBackground<T>(Func<T> function, bool longRunning = false) {
|
||||
if (function == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(function));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -109,6 +117,7 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task<IList<T>> InParallel<T>(IEnumerable<Task<T>> tasks) {
|
||||
if (tasks == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(tasks));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -125,6 +134,7 @@ namespace ArchiSteamFarm {
|
|||
break;
|
||||
default:
|
||||
results = await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -134,11 +144,13 @@ namespace ArchiSteamFarm {
|
|||
internal static async Task InParallel(IEnumerable<Task> tasks) {
|
||||
if (tasks == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(tasks));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Program.GlobalConfig.OptimizationMode) {
|
||||
case GlobalConfig.EOptimizationMode.MinMemoryUsage:
|
||||
|
||||
foreach (Task task in tasks) {
|
||||
await task.ConfigureAwait(false);
|
||||
}
|
||||
|
@ -146,6 +158,7 @@ namespace ArchiSteamFarm {
|
|||
break;
|
||||
default:
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +166,7 @@ namespace ArchiSteamFarm {
|
|||
internal static bool IsValidCdKey(string key) {
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(key));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -162,10 +176,12 @@ namespace ArchiSteamFarm {
|
|||
internal static bool IsValidHexadecimalString(string text) {
|
||||
if (string.IsNullOrEmpty(text)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(text));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const byte split = 16;
|
||||
|
||||
for (byte i = 0; i < text.Length; i += split) {
|
||||
string textPart = string.Join("", text.Skip(i).Take(split));
|
||||
|
||||
|
@ -186,6 +202,7 @@ namespace ArchiSteamFarm {
|
|||
internal static int RandomNext(int maxWithout) {
|
||||
if (maxWithout <= 0) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(maxWithout));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -202,6 +219,7 @@ namespace ArchiSteamFarm {
|
|||
StringBuilder result = new StringBuilder();
|
||||
|
||||
ConsoleKeyInfo keyInfo;
|
||||
|
||||
while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Enter) {
|
||||
if (!char.IsControl(keyInfo.KeyChar)) {
|
||||
result.Append(keyInfo.KeyChar);
|
||||
|
@ -221,6 +239,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace ArchiSteamFarm {
|
|||
internal static HtmlDocument StringToHtmlDocument(string html) {
|
||||
if (html == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(html));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -101,6 +102,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<BinaryResponse> UrlGetToBinaryWithProgress(string request, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -126,6 +128,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
while (contentStream.CanRead) {
|
||||
int read = await contentStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
||||
|
||||
if (read == 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -148,10 +151,12 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericDebuggingException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
ArchiLogger.LogGenericDebug("100%");
|
||||
|
||||
return new BinaryResponse(response, ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
@ -168,16 +173,19 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<HtmlDocumentResponse> UrlGetToHtmlDocument(string request, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
StringResponse response = await UrlGetToString(request, referer, maxTries).ConfigureAwait(false);
|
||||
|
||||
return response != null ? new HtmlDocumentResponse(response) : null;
|
||||
}
|
||||
|
||||
internal async Task<ObjectResponse<T>> UrlGetToJsonObject<T>(string request, string referer = null, byte maxTries = MaxTries) where T : class {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -216,6 +224,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<StringResponse> UrlGetToString(string request, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -240,6 +249,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<XmlDocumentResponse> UrlGetToXmlDocument(string request, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -256,6 +266,7 @@ namespace ArchiSteamFarm {
|
|||
xmlDocument.LoadXml(response.Content);
|
||||
} catch (XmlException e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -273,6 +284,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<BasicResponse> UrlHead(string request, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -297,6 +309,7 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<BasicResponse> UrlPost(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -321,16 +334,19 @@ namespace ArchiSteamFarm {
|
|||
internal async Task<HtmlDocumentResponse> UrlPostToHtmlDocument(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
StringResponse response = await UrlPostToString(request, data, referer, maxTries).ConfigureAwait(false);
|
||||
|
||||
return response != null ? new HtmlDocumentResponse(response) : null;
|
||||
}
|
||||
|
||||
internal async Task<ObjectResponse<T>> UrlPostToJsonObject<T>(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, byte maxTries = MaxTries) where T : class {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -369,6 +385,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<HttpResponseMessage> InternalGet(string request, string referer = null, HttpCompletionOption httpCompletionOptions = HttpCompletionOption.ResponseContentRead) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
ArchiLogger.LogNullError(nameof(request));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -378,6 +395,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<HttpResponseMessage> InternalHead(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
ArchiLogger.LogNullError(nameof(request));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -387,6 +405,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<HttpResponseMessage> InternalPost(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
ArchiLogger.LogNullError(nameof(request));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -396,6 +415,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<HttpResponseMessage> InternalRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) {
|
||||
if ((requestUri == null) || (httpMethod == null)) {
|
||||
ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -407,6 +427,7 @@ namespace ArchiSteamFarm {
|
|||
request.Content = new FormUrlEncodedContent(data);
|
||||
} catch (UriFormatException e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -423,6 +444,7 @@ namespace ArchiSteamFarm {
|
|||
response = await HttpClient.SendAsync(request, httpCompletionOption).ConfigureAwait(false);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericDebuggingException(e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -451,13 +473,17 @@ namespace ArchiSteamFarm {
|
|||
switch (redirectUri.Scheme) {
|
||||
case "http":
|
||||
case "https":
|
||||
|
||||
break;
|
||||
case "steammobile":
|
||||
|
||||
// Those redirections are invalid, but we're aware of that and we have extra logic for them
|
||||
return response;
|
||||
default:
|
||||
|
||||
// We have no clue about those, but maybe HttpClient can handle them for us
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(redirectUri.Scheme), redirectUri.Scheme));
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -465,6 +491,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
response.Dispose();
|
||||
|
||||
return await InternalRequest(redirectUri, httpMethod, data, referer, httpCompletionOption, --maxRedirections).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
@ -480,6 +507,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task<StringResponse> UrlPostToString(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, byte maxTries = MaxTries) {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue