mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 07:04:27 +00:00
R# cleanup, small code improvements
This commit is contained in:
parent
ec95dc41ce
commit
b98268a465
19 changed files with 143 additions and 296 deletions
|
@ -55,8 +55,8 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin {
|
|||
|
||||
// ReSharper disable once UseDeconstruction - deconstruction is not available in .NET Framework
|
||||
foreach (KeyValuePair<string, JToken> configProperty in additionalConfigProperties) {
|
||||
// It's a good idea to prefix your custom properties with the name of your plugin, so there will be no possible conflict of ASF or other plugins using the same name, neither now or in the future
|
||||
switch (configProperty.Key) {
|
||||
// It's a good idea to prefix your custom properties with the name of your plugin, so there will be no possible conflict of ASF or other plugins using the same name, neither now or in the future
|
||||
case nameof(ExamplePlugin) + "TestProperty" when configProperty.Value.Type == JTokenType.Boolean:
|
||||
bool exampleBooleanValue = configProperty.Value.Value<bool>();
|
||||
ASF.ArchiLogger.LogGenericInfo(nameof(ExamplePlugin) + "TestProperty boolean property has been found with a value of: " + exampleBooleanValue);
|
||||
|
@ -75,21 +75,15 @@ namespace ArchiSteamFarm.CustomPlugins.ExamplePlugin {
|
|||
// If you do not recognize the command, just return null/empty and allow ASF to gracefully return "unknown command" to user on usual basis
|
||||
public async Task<string> OnBotCommand(Bot bot, ulong steamID, string message, string[] args) {
|
||||
// In comparison with OnBotMessage(), we're using asynchronous CatAPI call here, so we declare our method as async and return the message as usual
|
||||
// Notice how we handle access here as well, it'll work only for FamilySharing+
|
||||
switch (args[0].ToUpperInvariant()) {
|
||||
// Notice how we handle access here as well, it'll work only for FamilySharing+
|
||||
case "CAT" when bot.HasPermission(steamID, BotConfig.EPermission.FamilySharing):
|
||||
|
||||
// Notice how we can decide whether to use bot's AWH WebBrowser or ASF's one. For Steam-related requests, AWH's one should always be used, for third-party requests like those it doesn't really matter
|
||||
// Still, it makes sense to pass AWH's one, so in case you get some errors or alike, you know from which bot instance they come from. It's similar to using Bot's ArchiLogger compared to ASF's one
|
||||
string randomCatURL = await CatAPI.GetRandomCatURL(bot.ArchiWebHandler.WebBrowser).ConfigureAwait(false);
|
||||
|
||||
if (string.IsNullOrEmpty(randomCatURL)) {
|
||||
return "God damn it, we're out of cats, care to notify my master? Thanks!";
|
||||
}
|
||||
|
||||
return randomCatURL;
|
||||
return !string.IsNullOrEmpty(randomCatURL) ? randomCatURL : "God damn it, we're out of cats, care to notify my master? Thanks!";
|
||||
default:
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -567,6 +567,8 @@ limitations under the License.</s:String>
|
|||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Int64 x:Key="/Default/Environment/UnitTesting/ParallelProcessesCount/@EntryValue">8</s:Int64>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Archi/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=BGR_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=bot_0027s/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=broadcasted/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Domeradzki/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=splitted/@EntryIndexedValue">True</s:Boolean>
|
||||
|
|
|
@ -81,10 +81,8 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (fileType) {
|
||||
case EFileType.Config:
|
||||
|
||||
return Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName);
|
||||
case EFileType.Database:
|
||||
|
||||
return Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalDatabaseFileName);
|
||||
default:
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(fileType), fileType));
|
||||
|
@ -350,10 +348,8 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (botName) {
|
||||
case SharedInfo.ASF:
|
||||
|
||||
return false;
|
||||
default:
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -687,28 +683,22 @@ namespace ArchiSteamFarm {
|
|||
ArchiLogger.LogNullError(nameof(relativeDirectoryName));
|
||||
|
||||
return false;
|
||||
|
||||
// No directory, root folder
|
||||
case "":
|
||||
|
||||
// No directory, root folder
|
||||
switch (fileName) {
|
||||
// Files with those names in root directory we want to keep
|
||||
case SharedInfo.LogFile:
|
||||
case "NLog.config":
|
||||
|
||||
// Files with those names in root directory we want to keep
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// Files in those directories we want to keep in their current place
|
||||
case SharedInfo.ConfigDirectory:
|
||||
case SharedInfo.PluginsDirectory:
|
||||
case SharedInfo.UpdateDirectory:
|
||||
|
||||
// Files in those directories we want to keep in their current place
|
||||
continue;
|
||||
default:
|
||||
|
||||
// Files in subdirectories of those directories we want to keep as well
|
||||
if (Utilities.RelativeDirectoryStartsWith(relativeDirectoryName, SharedInfo.ConfigDirectory, SharedInfo.PluginsDirectory, SharedInfo.UpdateDirectory)) {
|
||||
continue;
|
||||
|
@ -758,7 +748,6 @@ namespace ArchiSteamFarm {
|
|||
// We're not interested in extracting placeholder files (but we still want directories created for them, done above)
|
||||
switch (zipFile.Name) {
|
||||
case ".gitkeep":
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
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));
|
||||
|
@ -62,13 +59,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
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));
|
||||
|
|
|
@ -851,7 +851,6 @@ namespace ArchiSteamFarm {
|
|||
case EUserNotification.Items:
|
||||
case EUserNotification.ModeratorMessages:
|
||||
case EUserNotification.Trading:
|
||||
|
||||
break;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(type), type));
|
||||
|
|
|
@ -2463,12 +2463,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (result.State) {
|
||||
case ESteamApiKeyState.AccessDenied:
|
||||
|
||||
// We succeeded in fetching API key, but it resulted in access denied
|
||||
// Return empty result, API key is unavailable permanently
|
||||
return (true, "");
|
||||
case ESteamApiKeyState.NotRegisteredYet:
|
||||
|
||||
// We succeeded in fetching API key, and it resulted in no key registered yet
|
||||
// Let's try to register a new key
|
||||
if (!await RegisterApiKey().ConfigureAwait(false)) {
|
||||
|
@ -2491,16 +2489,13 @@ namespace ArchiSteamFarm {
|
|||
|
||||
goto case ESteamApiKeyState.Registered;
|
||||
case ESteamApiKeyState.Registered:
|
||||
|
||||
// We succeeded in fetching API key, and it resulted in registered key
|
||||
// Cache the result, this is the API key we want
|
||||
return (true, result.Key);
|
||||
case ESteamApiKeyState.Timeout:
|
||||
|
||||
// Request timed out, bad luck, we'll try again later
|
||||
return (false, null);
|
||||
default:
|
||||
|
||||
// We got an unhandled error, this should never happen
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(result.State), result.State));
|
||||
|
||||
|
@ -2554,17 +2549,13 @@ namespace ArchiSteamFarm {
|
|||
switch (userPrivacy.Settings.Profile) {
|
||||
case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.FriendsOnly:
|
||||
case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private:
|
||||
|
||||
return (true, false);
|
||||
case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Public:
|
||||
|
||||
switch (userPrivacy.Settings.Inventory) {
|
||||
case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.FriendsOnly:
|
||||
case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Private:
|
||||
|
||||
return (true, false);
|
||||
case Steam.UserPrivacy.PrivacySettings.EPrivacySetting.Public:
|
||||
|
||||
return (true, true);
|
||||
default:
|
||||
Bot.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(userPrivacy.Settings.Inventory), userPrivacy.Settings.Inventory));
|
||||
|
|
|
@ -452,10 +452,8 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (permission) {
|
||||
case BotConfig.EPermission.FamilySharing when SteamFamilySharingIDs.Contains(steamID):
|
||||
|
||||
return true;
|
||||
default:
|
||||
|
||||
return BotConfig.SteamUserPermissions.TryGetValue(steamID, out BotConfig.EPermission realPermission) && (realPermission >= permission);
|
||||
}
|
||||
}
|
||||
|
@ -620,11 +618,9 @@ namespace ArchiSteamFarm {
|
|||
// 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));
|
||||
|
@ -641,7 +637,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// We must convert this to uppercase, since Valve doesn't stick to any convention and we can have a case mismatch
|
||||
switch (type.ToUpperInvariant()) {
|
||||
// Types that can be idled
|
||||
case "APPLICATION":
|
||||
case "EPISODE":
|
||||
case "GAME":
|
||||
|
@ -650,16 +645,14 @@ namespace ArchiSteamFarm {
|
|||
case "SERIES":
|
||||
case "TOOL":
|
||||
case "VIDEO":
|
||||
|
||||
// Types that can be idled
|
||||
return (appID, DateTime.MinValue);
|
||||
|
||||
// Types that can't be idled
|
||||
case "ADVERTISING":
|
||||
case "DEMO":
|
||||
case "DLC":
|
||||
case "GUIDE":
|
||||
case "HARDWARE":
|
||||
|
||||
// Types that can't be idled
|
||||
break;
|
||||
default:
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(type), type));
|
||||
|
@ -710,25 +703,18 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (fileType) {
|
||||
case EFileType.Config:
|
||||
|
||||
return botPath + SharedInfo.ConfigExtension;
|
||||
case EFileType.Database:
|
||||
|
||||
return botPath + SharedInfo.DatabaseExtension;
|
||||
case EFileType.KeysToRedeem:
|
||||
|
||||
return botPath + SharedInfo.KeysExtension;
|
||||
case EFileType.KeysToRedeemUnused:
|
||||
|
||||
return botPath + SharedInfo.KeysExtension + SharedInfo.KeysUnusedExtension;
|
||||
case EFileType.KeysToRedeemUsed:
|
||||
|
||||
return botPath + SharedInfo.KeysExtension + SharedInfo.KeysUsedExtension;
|
||||
case EFileType.MobileAuthenticator:
|
||||
|
||||
return botPath + SharedInfo.MobileAuthenticatorExtension;
|
||||
case EFileType.SentryFile:
|
||||
|
||||
return botPath + SharedInfo.SentryHashExtension;
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(fileType), fileType));
|
||||
|
@ -1326,14 +1312,12 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
case ASF.EUserInputType.Login:
|
||||
|
||||
if (BotConfig != null) {
|
||||
BotConfig.SteamLogin = inputValue;
|
||||
}
|
||||
|
||||
break;
|
||||
case ASF.EUserInputType.Password:
|
||||
|
||||
if (BotConfig != null) {
|
||||
BotConfig.DecryptedSteamPassword = inputValue;
|
||||
}
|
||||
|
@ -1344,7 +1328,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
case ASF.EUserInputType.SteamParentalCode:
|
||||
|
||||
if (BotConfig != null) {
|
||||
BotConfig.SteamParentalCode = inputValue;
|
||||
}
|
||||
|
@ -1844,27 +1827,21 @@ namespace ArchiSteamFarm {
|
|||
return steamID == BotConfig.SteamMasterClanID;
|
||||
}
|
||||
|
||||
private static bool IsRefundable(EPaymentMethod method) {
|
||||
if (method == EPaymentMethod.None) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(method));
|
||||
private static bool IsRefundable(EPaymentMethod paymentMethod) {
|
||||
if (paymentMethod == EPaymentMethod.None) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(paymentMethod));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
switch (paymentMethod) {
|
||||
case EPaymentMethod.ActivationCode:
|
||||
case EPaymentMethod.Complimentary: // This is also a flag
|
||||
case EPaymentMethod.GuestPass:
|
||||
case EPaymentMethod.HardwarePromo:
|
||||
|
||||
return false;
|
||||
default:
|
||||
|
||||
if (method.HasFlag(EPaymentMethod.Complimentary)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !paymentMethod.HasFlag(EPaymentMethod.Complimentary);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1889,7 +1866,9 @@ namespace ArchiSteamFarm {
|
|||
return;
|
||||
}
|
||||
|
||||
await ArchiHandler.JoinChatRoomGroup(MasterChatGroupID).ConfigureAwait(false);
|
||||
if (!await ArchiHandler.JoinChatRoomGroup(MasterChatGroupID).ConfigureAwait(false)) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(ArchiHandler.JoinChatRoomGroup)));
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task LimitLoginRequestsAsync() {
|
||||
|
@ -2052,18 +2031,15 @@ 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;
|
||||
|
@ -2144,9 +2120,10 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (HasPermission(friend.SteamID, BotConfig.EPermission.FamilySharing)) {
|
||||
await ArchiHandler.AddFriend(friend.SteamID).ConfigureAwait(false);
|
||||
if (!await ArchiHandler.AddFriend(friend.SteamID).ConfigureAwait(false)) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(ArchiHandler.AddFriend)));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2154,13 +2131,17 @@ namespace ArchiSteamFarm {
|
|||
bool acceptFriendRequest = await PluginsCore.OnBotFriendRequest(this, friend.SteamID).ConfigureAwait(false);
|
||||
|
||||
if (acceptFriendRequest) {
|
||||
await ArchiHandler.AddFriend(friend.SteamID).ConfigureAwait(false);
|
||||
if (!await ArchiHandler.AddFriend(friend.SteamID).ConfigureAwait(false)) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(ArchiHandler.AddFriend)));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (BotConfig.BotBehaviour.HasFlag(BotConfig.EBotBehaviour.RejectInvalidFriendInvites)) {
|
||||
await ArchiHandler.RemoveFriend(friend.SteamID).ConfigureAwait(false);
|
||||
if (!await ArchiHandler.RemoveFriend(friend.SteamID).ConfigureAwait(false)) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(ArchiHandler.RemoveFriend)));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2326,7 +2307,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (callback.Result) {
|
||||
case EResult.LoggedInElsewhere:
|
||||
|
||||
// This result directly indicates that playing was blocked when we got (forcefully) disconnected
|
||||
PlayingWasBlocked = true;
|
||||
|
||||
|
@ -2368,7 +2348,6 @@ 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();
|
||||
|
@ -2387,7 +2366,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
|
||||
if (!HasMobileAuthenticator) {
|
||||
string twoFactorCode = await Logging.GetUserInput(ASF.EUserInputType.TwoFactorAuthentication, BotName).ConfigureAwait(false);
|
||||
|
||||
|
@ -2485,7 +2463,10 @@ namespace ArchiSteamFarm {
|
|||
if (BotConfig.SteamMasterClanID != 0) {
|
||||
Utilities.InBackground(
|
||||
async () => {
|
||||
await ArchiWebHandler.JoinGroup(BotConfig.SteamMasterClanID).ConfigureAwait(false);
|
||||
if (!await ArchiWebHandler.JoinGroup(BotConfig.SteamMasterClanID).ConfigureAwait(false)) {
|
||||
ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(ArchiWebHandler.JoinGroup)));
|
||||
}
|
||||
|
||||
await JoinMasterChatGroupID().ConfigureAwait(false);
|
||||
}
|
||||
);
|
||||
|
@ -2514,7 +2495,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
// Unexpected result, shutdown immediately
|
||||
ArchiLogger.LogGenericError(string.Format(Strings.BotUnableToLogin, callback.Result, callback.ExtendedResult));
|
||||
Stop();
|
||||
|
@ -2817,7 +2797,6 @@ namespace ArchiSteamFarm {
|
|||
case EPurchaseResultDetail.DoesNotOwnRequiredApp:
|
||||
case EPurchaseResultDetail.RestrictedCountry:
|
||||
case EPurchaseResultDetail.Timeout:
|
||||
|
||||
break;
|
||||
case EPurchaseResultDetail.BadActivationCode:
|
||||
case EPurchaseResultDetail.DuplicateActivationCode:
|
||||
|
|
|
@ -572,6 +572,12 @@ namespace ArchiSteamFarm {
|
|||
|
||||
name = WebUtility.HtmlDecode(name.Substring(nameStartIndex, nameEndIndex - nameStartIndex));
|
||||
|
||||
if (string.IsNullOrEmpty(name)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(name));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Levels
|
||||
byte badgeLevel = 0;
|
||||
|
||||
|
@ -626,7 +632,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (backgroundTasks == null) {
|
||||
backgroundTasks = new List<Task>();
|
||||
}
|
||||
|
@ -1058,7 +1063,6 @@ 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);
|
||||
|
|
|
@ -89,85 +89,58 @@ namespace ArchiSteamFarm {
|
|||
|
||||
return null;
|
||||
case 1:
|
||||
|
||||
switch (args[0].ToUpperInvariant()) {
|
||||
case "2FA":
|
||||
|
||||
return await Response2FA(steamID).ConfigureAwait(false);
|
||||
case "2FANO":
|
||||
|
||||
return await Response2FAConfirm(steamID, false).ConfigureAwait(false);
|
||||
case "2FAOK":
|
||||
|
||||
return await Response2FAConfirm(steamID, true).ConfigureAwait(false);
|
||||
case "BALANCE":
|
||||
|
||||
return ResponseWalletBalance(steamID);
|
||||
case "BGR":
|
||||
|
||||
return ResponseBackgroundGamesRedeemer(steamID);
|
||||
case "BL":
|
||||
|
||||
return ResponseBlacklist(steamID);
|
||||
case "EXIT":
|
||||
|
||||
return ResponseExit(steamID);
|
||||
case "FARM":
|
||||
|
||||
return await ResponseFarm(steamID).ConfigureAwait(false);
|
||||
case "HELP":
|
||||
|
||||
return ResponseHelp(steamID);
|
||||
case "IB":
|
||||
|
||||
return ResponseIdleBlacklist(steamID);
|
||||
case "IQ":
|
||||
|
||||
return ResponseIdleQueue(steamID);
|
||||
case "LEVEL":
|
||||
|
||||
return await ResponseLevel(steamID).ConfigureAwait(false);
|
||||
case "LOOT":
|
||||
|
||||
return await ResponseLoot(steamID).ConfigureAwait(false);
|
||||
case "PASSWORD":
|
||||
|
||||
return ResponsePassword(steamID);
|
||||
case "PAUSE":
|
||||
|
||||
return await ResponsePause(steamID, true).ConfigureAwait(false);
|
||||
case "PAUSE~":
|
||||
|
||||
return await ResponsePause(steamID, false).ConfigureAwait(false);
|
||||
case "RESUME":
|
||||
|
||||
return ResponseResume(steamID);
|
||||
case "RESTART":
|
||||
|
||||
return ResponseRestart(steamID);
|
||||
case "SA":
|
||||
|
||||
return await ResponseStatus(steamID, SharedInfo.ASF).ConfigureAwait(false);
|
||||
case "START":
|
||||
|
||||
return ResponseStart(steamID);
|
||||
case "STATS":
|
||||
|
||||
return ResponseStats(steamID);
|
||||
case "STATUS":
|
||||
|
||||
return ResponseStatus(steamID).Response;
|
||||
case "STOP":
|
||||
|
||||
return ResponseStop(steamID);
|
||||
case "UNPACK":
|
||||
|
||||
return await ResponseUnpackBoosters(steamID).ConfigureAwait(false);
|
||||
case "UPDATE":
|
||||
|
||||
return await ResponseUpdate(steamID).ConfigureAwait(false);
|
||||
case "VERSION":
|
||||
|
||||
return ResponseVersion(steamID);
|
||||
default:
|
||||
string pluginsResponse = await PluginsCore.OnBotCommand(Bot, steamID, message, args).ConfigureAwait(false);
|
||||
|
@ -175,191 +148,130 @@ namespace ArchiSteamFarm {
|
|||
return !string.IsNullOrEmpty(pluginsResponse) ? pluginsResponse : ResponseUnknown(steamID);
|
||||
}
|
||||
default:
|
||||
|
||||
switch (args[0].ToUpperInvariant()) {
|
||||
case "2FA":
|
||||
|
||||
return await Response2FA(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "2FANO":
|
||||
|
||||
return await Response2FAConfirm(steamID, Utilities.GetArgsAsText(args, 1, ","), false).ConfigureAwait(false);
|
||||
case "2FAOK":
|
||||
|
||||
return await Response2FAConfirm(steamID, Utilities.GetArgsAsText(args, 1, ","), true).ConfigureAwait(false);
|
||||
case "ADDLICENSE" when args.Length > 2:
|
||||
|
||||
return await ResponseAddLicense(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "ADDLICENSE":
|
||||
|
||||
return await ResponseAddLicense(steamID, args[1]).ConfigureAwait(false);
|
||||
case "BALANCE":
|
||||
|
||||
return await ResponseWalletBalance(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "BGR":
|
||||
|
||||
return await ResponseBackgroundGamesRedeemer(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "BL":
|
||||
|
||||
return await ResponseBlacklist(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "BLADD" when args.Length > 2:
|
||||
|
||||
return await ResponseBlacklistAdd(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "BLADD":
|
||||
|
||||
return await ResponseBlacklistAdd(steamID, args[1]).ConfigureAwait(false);
|
||||
case "BLRM" when args.Length > 2:
|
||||
|
||||
return await ResponseBlacklistRemove(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "BLRM":
|
||||
|
||||
return await ResponseBlacklistRemove(steamID, args[1]).ConfigureAwait(false);
|
||||
case "FARM":
|
||||
|
||||
return await ResponseFarm(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "INPUT" when args.Length > 3:
|
||||
|
||||
return await ResponseInput(steamID, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false);
|
||||
case "INPUT" when args.Length > 2:
|
||||
|
||||
return ResponseInput(steamID, args[1], args[2]);
|
||||
case "IB":
|
||||
|
||||
return await ResponseIdleBlacklist(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "IBADD" when args.Length > 2:
|
||||
|
||||
return await ResponseIdleBlacklistAdd(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "IBADD":
|
||||
|
||||
return await ResponseIdleBlacklistAdd(steamID, args[1]).ConfigureAwait(false);
|
||||
case "IBRM" when args.Length > 2:
|
||||
|
||||
return await ResponseIdleBlacklistRemove(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "IBRM":
|
||||
|
||||
return await ResponseIdleBlacklistRemove(steamID, args[1]).ConfigureAwait(false);
|
||||
case "IQ":
|
||||
|
||||
return await ResponseIdleQueue(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "IQADD" when args.Length > 2:
|
||||
|
||||
return await ResponseIdleQueueAdd(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "IQADD":
|
||||
|
||||
return await ResponseIdleQueueAdd(steamID, args[1]).ConfigureAwait(false);
|
||||
case "IQRM" when args.Length > 2:
|
||||
|
||||
return await ResponseIdleQueueRemove(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "IQRM":
|
||||
|
||||
return await ResponseIdleQueueRemove(steamID, args[1]).ConfigureAwait(false);
|
||||
case "LEVEL":
|
||||
|
||||
return await ResponseLevel(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "LOOT":
|
||||
|
||||
return await ResponseLoot(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "LOOT^" when args.Length > 3:
|
||||
|
||||
return await ResponseAdvancedLoot(steamID, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false);
|
||||
case "LOOT^" when args.Length > 2:
|
||||
|
||||
return await ResponseAdvancedLoot(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||
case "LOOT@" when args.Length > 2:
|
||||
|
||||
return await ResponseLootByRealAppIDs(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "LOOT@":
|
||||
|
||||
return await ResponseLootByRealAppIDs(steamID, args[1]).ConfigureAwait(false);
|
||||
case "NICKNAME" when args.Length > 2:
|
||||
|
||||
return await ResponseNickname(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
|
||||
case "NICKNAME":
|
||||
|
||||
return ResponseNickname(steamID, args[1]);
|
||||
case "OA":
|
||||
|
||||
return await ResponseOwns(steamID, SharedInfo.ASF, Utilities.GetArgsAsText(message, 1)).ConfigureAwait(false);
|
||||
case "OWNS" when args.Length > 2:
|
||||
|
||||
return await ResponseOwns(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
|
||||
case "OWNS":
|
||||
|
||||
return (await ResponseOwns(steamID, args[1]).ConfigureAwait(false)).Response;
|
||||
case "PASSWORD":
|
||||
|
||||
return await ResponsePassword(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "PAUSE":
|
||||
|
||||
return await ResponsePause(steamID, Utilities.GetArgsAsText(args, 1, ","), true).ConfigureAwait(false);
|
||||
case "PAUSE~":
|
||||
|
||||
return await ResponsePause(steamID, Utilities.GetArgsAsText(args, 1, ","), false).ConfigureAwait(false);
|
||||
case "PAUSE&" when args.Length > 2:
|
||||
|
||||
return await ResponsePause(steamID, args[1], true, Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
|
||||
case "PAUSE&":
|
||||
|
||||
return await ResponsePause(steamID, true, args[1]).ConfigureAwait(false);
|
||||
case "PLAY" when args.Length > 2:
|
||||
|
||||
return await ResponsePlay(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
|
||||
case "PLAY":
|
||||
|
||||
return await ResponsePlay(steamID, args[1]).ConfigureAwait(false);
|
||||
case "PRIVACY" when args.Length > 2:
|
||||
|
||||
return await ResponsePrivacy(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "PRIVACY":
|
||||
|
||||
return await ResponsePrivacy(steamID, args[1]).ConfigureAwait(false);
|
||||
case "R" when args.Length > 2:
|
||||
case "REDEEM" when args.Length > 2:
|
||||
|
||||
return await ResponseRedeem(steamID, args[1], Utilities.GetArgsAsText(args, 2, ",")).ConfigureAwait(false);
|
||||
case "R":
|
||||
case "REDEEM":
|
||||
|
||||
return await ResponseRedeem(steamID, args[1]).ConfigureAwait(false);
|
||||
case "R^" when args.Length > 3:
|
||||
case "REDEEM^" when args.Length > 3:
|
||||
|
||||
return await ResponseAdvancedRedeem(steamID, args[1], args[2], Utilities.GetArgsAsText(args, 3, ",")).ConfigureAwait(false);
|
||||
case "R^" when args.Length > 2:
|
||||
case "REDEEM^" when args.Length > 2:
|
||||
|
||||
return await ResponseAdvancedRedeem(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||
case "RESUME":
|
||||
|
||||
return await ResponseResume(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "START":
|
||||
|
||||
return await ResponseStart(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "STATUS":
|
||||
|
||||
return await ResponseStatus(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "STOP":
|
||||
|
||||
return await ResponseStop(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
case "TRANSFER" when args.Length > 2:
|
||||
|
||||
return await ResponseTransfer(steamID, args[1], Utilities.GetArgsAsText(message, 2)).ConfigureAwait(false);
|
||||
case "TRANSFER":
|
||||
|
||||
return await ResponseTransfer(steamID, args[1]).ConfigureAwait(false);
|
||||
case "TRANSFER^" when args.Length > 4:
|
||||
|
||||
return await ResponseAdvancedTransfer(steamID, args[1], args[2], args[3], Utilities.GetArgsAsText(message, 4)).ConfigureAwait(false);
|
||||
case "TRANSFER^" when args.Length > 3:
|
||||
|
||||
return await ResponseAdvancedTransfer(steamID, args[1], args[2], args[3]).ConfigureAwait(false);
|
||||
case "TRANSFER@" when args.Length > 3:
|
||||
|
||||
return await ResponseTransferByRealAppIDs(steamID, args[1], args[2], Utilities.GetArgsAsText(message, 3)).ConfigureAwait(false);
|
||||
case "TRANSFER@" when args.Length > 2:
|
||||
|
||||
return await ResponseTransferByRealAppIDs(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||
case "UNPACK":
|
||||
|
||||
return await ResponseUnpackBoosters(steamID, Utilities.GetArgsAsText(args, 1, ",")).ConfigureAwait(false);
|
||||
default:
|
||||
string pluginsResponse = await PluginsCore.OnBotCommand(Bot, steamID, message, args).ConfigureAwait(false);
|
||||
|
@ -381,7 +293,10 @@ namespace ArchiSteamFarm {
|
|||
string pluginsResponse = await PluginsCore.OnBotMessage(Bot, steamID, message).ConfigureAwait(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(pluginsResponse)) {
|
||||
await Bot.SendMessage(steamID, pluginsResponse).ConfigureAwait(false);
|
||||
if (!await Bot.SendMessage(steamID, pluginsResponse).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.Content, pluginsResponse));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -395,10 +310,14 @@ namespace ArchiSteamFarm {
|
|||
bool feedback = Bot.HasPermission(steamID, BotConfig.EPermission.FamilySharing);
|
||||
|
||||
if (feedback && !responseTask.IsCompleted) {
|
||||
await Bot.SendTypingMessage(steamID).ConfigureAwait(false);
|
||||
if (!await Bot.SendTypingMessage(steamID).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendTypingMessage)));
|
||||
}
|
||||
|
||||
while (!responseTask.IsCompleted && (await Task.WhenAny(responseTask, Task.Delay(SteamTypingStatusDelay)).ConfigureAwait(false) != responseTask)) {
|
||||
await Bot.SendTypingMessage(steamID).ConfigureAwait(false);
|
||||
if (!await Bot.SendTypingMessage(steamID).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendTypingMessage)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,7 +332,10 @@ namespace ArchiSteamFarm {
|
|||
response = FormatBotResponse(Strings.UnknownCommand);
|
||||
}
|
||||
|
||||
await Bot.SendMessage(steamID, response).ConfigureAwait(false);
|
||||
if (!await Bot.SendMessage(steamID, response).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.Content, response));
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task HandleMessage(ulong chatGroupID, ulong chatID, ulong steamID, string message) {
|
||||
|
@ -428,7 +350,10 @@ namespace ArchiSteamFarm {
|
|||
string pluginsResponse = await PluginsCore.OnBotMessage(Bot, steamID, message).ConfigureAwait(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(pluginsResponse)) {
|
||||
await Bot.SendMessage(chatGroupID, chatID, pluginsResponse).ConfigureAwait(false);
|
||||
if (!await Bot.SendMessage(chatGroupID, chatID, pluginsResponse).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.Content, pluginsResponse));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -444,10 +369,14 @@ namespace ArchiSteamFarm {
|
|||
if (feedback && !responseTask.IsCompleted) {
|
||||
string pleaseWaitMessage = FormatBotResponse(Strings.PleaseWait);
|
||||
|
||||
await Bot.SendMessage(chatGroupID, chatID, pleaseWaitMessage).ConfigureAwait(false);
|
||||
if (!await Bot.SendMessage(chatGroupID, chatID, pleaseWaitMessage).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
}
|
||||
|
||||
while (!responseTask.IsCompleted && (await Task.WhenAny(responseTask, Task.Delay(SteamTypingStatusDelay)).ConfigureAwait(false) != responseTask)) {
|
||||
await Bot.SendMessage(chatGroupID, chatID, pleaseWaitMessage).ConfigureAwait(false);
|
||||
if (!await Bot.SendMessage(chatGroupID, chatID, pleaseWaitMessage).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,7 +391,10 @@ namespace ArchiSteamFarm {
|
|||
response = FormatBotResponse(Strings.UnknownCommand);
|
||||
}
|
||||
|
||||
await Bot.SendMessage(chatGroupID, chatID, response).ConfigureAwait(false);
|
||||
if (!await Bot.SendMessage(chatGroupID, chatID, response).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.Content, response));
|
||||
}
|
||||
}
|
||||
|
||||
internal void OnNewLicenseList() {
|
||||
|
@ -759,7 +691,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, flag));
|
||||
}
|
||||
}
|
||||
|
@ -1981,12 +1912,13 @@ namespace ArchiSteamFarm {
|
|||
|
||||
// Child setting can't be less restrictive than its parent
|
||||
switch (index) {
|
||||
case 0: // Profile
|
||||
case 0:
|
||||
// Profile
|
||||
profile = privacySetting;
|
||||
|
||||
break;
|
||||
case 1: // OwnedGames, child of Profile
|
||||
|
||||
case 1:
|
||||
// OwnedGames, child of Profile
|
||||
if (profile < privacySetting) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(ownedGames)));
|
||||
}
|
||||
|
@ -1994,8 +1926,8 @@ namespace ArchiSteamFarm {
|
|||
ownedGames = privacySetting;
|
||||
|
||||
break;
|
||||
case 2: // Playtime, child of OwnedGames
|
||||
|
||||
case 2:
|
||||
// Playtime, child of OwnedGames
|
||||
if (ownedGames < privacySetting) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(playtime)));
|
||||
}
|
||||
|
@ -2003,8 +1935,8 @@ namespace ArchiSteamFarm {
|
|||
playtime = privacySetting;
|
||||
|
||||
break;
|
||||
case 3: // FriendsList, child of Profile
|
||||
|
||||
case 3:
|
||||
// FriendsList, child of Profile
|
||||
if (profile < privacySetting) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(ownedGames)));
|
||||
}
|
||||
|
@ -2012,8 +1944,8 @@ namespace ArchiSteamFarm {
|
|||
friendsList = privacySetting;
|
||||
|
||||
break;
|
||||
case 4: // Inventory, child of Profile
|
||||
|
||||
case 4:
|
||||
// Inventory, child of Profile
|
||||
if (profile < privacySetting) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inventory)));
|
||||
}
|
||||
|
@ -2021,8 +1953,8 @@ namespace ArchiSteamFarm {
|
|||
inventory = privacySetting;
|
||||
|
||||
break;
|
||||
case 5: // InventoryGifts, child of Inventory
|
||||
|
||||
case 5:
|
||||
// InventoryGifts, child of Inventory
|
||||
if (inventory < privacySetting) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(inventoryGifts)));
|
||||
}
|
||||
|
@ -2030,8 +1962,8 @@ namespace ArchiSteamFarm {
|
|||
inventoryGifts = privacySetting;
|
||||
|
||||
break;
|
||||
case 6: // Comments, child of Profile
|
||||
|
||||
case 6:
|
||||
// Comments, child of Profile
|
||||
if (profile < privacySetting) {
|
||||
return FormatBotResponse(string.Format(Strings.ErrorIsInvalid, nameof(comments)));
|
||||
}
|
||||
|
@ -2124,7 +2056,8 @@ namespace ArchiSteamFarm {
|
|||
StringBuilder response = new StringBuilder();
|
||||
|
||||
using (HashSet<string>.Enumerator keysEnumerator = pendingKeys.GetEnumerator()) {
|
||||
string key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Initial key
|
||||
// Initial key
|
||||
string key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
|
||||
while (!string.IsNullOrEmpty(key)) {
|
||||
string startingKey = key;
|
||||
|
@ -2134,19 +2067,24 @@ namespace ArchiSteamFarm {
|
|||
|
||||
while (!string.IsNullOrEmpty(key) && (currentBot != null)) {
|
||||
if (redeemFlags.HasFlag(ERedeemFlags.Validate) && !Utilities.IsValidCdKey(key)) {
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Next key
|
||||
// Next key
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
|
||||
continue; // Keep current bot
|
||||
// Keep current bot
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((currentBot == Bot) && (redeemFlags.HasFlag(ERedeemFlags.SkipInitial) || rateLimitedBots.Contains(currentBot))) {
|
||||
currentBot = null; // Either bot will be changed, or loop aborted
|
||||
// Either bot will be changed, or loop aborted
|
||||
currentBot = null;
|
||||
} else {
|
||||
ArchiHandler.PurchaseResponseCallback result = await currentBot.Actions.RedeemKey(key).ConfigureAwait(false);
|
||||
|
||||
if (result == null) {
|
||||
response.AppendLine(FormatBotResponse(string.Format(Strings.BotRedeem, key, EPurchaseResultDetail.Timeout), currentBot.BotName));
|
||||
currentBot = null; // Either bot will be changed, or loop aborted
|
||||
|
||||
// Either bot will be changed, or loop aborted
|
||||
currentBot = null;
|
||||
} else {
|
||||
if ((result.PurchaseResultDetail == EPurchaseResultDetail.CannotRedeemCodeFromClient) && (Bot.WalletCurrency != ECurrencyCode.Invalid)) {
|
||||
// If it's a wallet code, we try to redeem it first, then handle the inner result as our primary one
|
||||
|
@ -2154,7 +2092,9 @@ namespace ArchiSteamFarm {
|
|||
|
||||
if (walletResult != null) {
|
||||
result.Result = walletResult.Value.Result;
|
||||
result.PurchaseResultDetail = walletResult.Value.PurchaseResult.GetValueOrDefault(walletResult.Value.Result == EResult.OK ? EPurchaseResultDetail.NoDetail : EPurchaseResultDetail.BadActivationCode); // BadActivationCode is our smart guess in this case
|
||||
|
||||
// BadActivationCode is our smart guess in this case
|
||||
result.PurchaseResultDetail = walletResult.Value.PurchaseResult.GetValueOrDefault(walletResult.Value.Result == EResult.OK ? EPurchaseResultDetail.NoDetail : EPurchaseResultDetail.BadActivationCode);
|
||||
} else {
|
||||
result.Result = EResult.Timeout;
|
||||
result.PurchaseResultDetail = EPurchaseResultDetail.Timeout;
|
||||
|
@ -2167,7 +2107,6 @@ namespace ArchiSteamFarm {
|
|||
case EPurchaseResultDetail.DuplicateActivationCode:
|
||||
case EPurchaseResultDetail.NoDetail: // OK
|
||||
case EPurchaseResultDetail.Timeout:
|
||||
|
||||
if ((result.Items != null) && (result.Items.Count > 0)) {
|
||||
response.AppendLine(FormatBotResponse(string.Format(Strings.BotRedeemWithItems, key, result.Result + "/" + result.PurchaseResultDetail, string.Join(", ", result.Items)), currentBot.BotName));
|
||||
} else {
|
||||
|
@ -2178,18 +2117,20 @@ namespace ArchiSteamFarm {
|
|||
unusedKeys.Remove(key);
|
||||
}
|
||||
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Next key
|
||||
// Next key
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
|
||||
if (result.PurchaseResultDetail == EPurchaseResultDetail.NoDetail) {
|
||||
break; // Next bot (if needed)
|
||||
// Next bot (if needed)
|
||||
break;
|
||||
}
|
||||
|
||||
continue; // Keep current bot
|
||||
// Keep current bot
|
||||
continue;
|
||||
case EPurchaseResultDetail.AccountLocked:
|
||||
case EPurchaseResultDetail.AlreadyPurchased:
|
||||
case EPurchaseResultDetail.DoesNotOwnRequiredApp:
|
||||
case EPurchaseResultDetail.RestrictedCountry:
|
||||
|
||||
if ((result.Items != null) && (result.Items.Count > 0)) {
|
||||
response.AppendLine(FormatBotResponse(string.Format(Strings.BotRedeemWithItems, key, result.Result + "/" + result.PurchaseResultDetail, string.Join(", ", result.Items)), currentBot.BotName));
|
||||
} else {
|
||||
|
@ -2197,13 +2138,16 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
if (!forward || (keepMissingGames && (result.PurchaseResultDetail != EPurchaseResultDetail.AlreadyPurchased))) {
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Next key
|
||||
// Next key
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
|
||||
break; // Next bot (if needed)
|
||||
// Next bot (if needed)
|
||||
break;
|
||||
}
|
||||
|
||||
if (distribute) {
|
||||
break; // Next bot, without changing key
|
||||
// Next bot, without changing key
|
||||
break;
|
||||
}
|
||||
|
||||
Dictionary<uint, string> items = result.Items ?? new Dictionary<uint, string>();
|
||||
|
@ -2223,7 +2167,8 @@ namespace ArchiSteamFarm {
|
|||
case EPurchaseResultDetail.BadActivationCode:
|
||||
case EPurchaseResultDetail.DuplicateActivationCode:
|
||||
case EPurchaseResultDetail.NoDetail: // OK
|
||||
alreadyHandled = true; // This key is already handled, as we either redeemed it or we're sure it's dupe/invalid
|
||||
// This key is already handled, as we either redeemed it or we're sure it's dupe/invalid
|
||||
alreadyHandled = true;
|
||||
unusedKeys.Remove(key);
|
||||
|
||||
break;
|
||||
|
@ -2252,9 +2197,11 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Next key
|
||||
// Next key
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
|
||||
break; // Next bot (if needed)
|
||||
// Next bot (if needed)
|
||||
break;
|
||||
case EPurchaseResultDetail.RateLimited:
|
||||
rateLimitedBots.Add(currentBot);
|
||||
goto case EPurchaseResultDetail.AccountLocked;
|
||||
|
@ -2269,9 +2216,11 @@ namespace ArchiSteamFarm {
|
|||
|
||||
unusedKeys.Remove(key);
|
||||
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Next key
|
||||
// Next key
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
|
||||
break; // Next bot (if needed)
|
||||
// Next bot (if needed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2286,8 +2235,8 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
if (key == startingKey) {
|
||||
// We ran out of bots to try for this key, so change it to avoid infinite loop
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null; // Next key
|
||||
// We ran out of bots to try for this key, so change it to avoid infinite loop, next key
|
||||
key = keysEnumerator.MoveNext() ? keysEnumerator.Current : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2737,12 +2686,16 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
// It'd make sense here to actually check return code of ArchiWebHandler.UnpackBooster(), but it lies most of the time | https://github.com/JustArchi/ArchiSteamFarm/issues/704
|
||||
bool completeSuccess = true;
|
||||
|
||||
// It'd also make sense to run all of this in parallel, but it seems that Steam has a lot of problems with inventory-related parallel requests | https://steamcommunity.com/groups/ascfarm/discussions/1/3559414588264550284/
|
||||
foreach (Steam.Asset item in inventory) {
|
||||
await Bot.ArchiWebHandler.UnpackBooster(item.RealAppID, item.AssetID).ConfigureAwait(false);
|
||||
if (!await Bot.ArchiWebHandler.UnpackBooster(item.RealAppID, item.AssetID).ConfigureAwait(false)) {
|
||||
completeSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
return FormatBotResponse(Strings.Done);
|
||||
return FormatBotResponse(completeSuccess ? Strings.Success : Strings.Done);
|
||||
}
|
||||
|
||||
[ItemCanBeNull]
|
||||
|
|
|
@ -79,16 +79,14 @@ namespace ArchiSteamFarm.Helpers {
|
|||
if (!success) {
|
||||
switch (fallback) {
|
||||
case EFallback.DefaultForType:
|
||||
|
||||
return (false, default);
|
||||
case EFallback.FailedNow:
|
||||
|
||||
return (false, result);
|
||||
case EFallback.SuccessPreviously:
|
||||
|
||||
return (false, InitializedValue);
|
||||
default:
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(fallback), fallback));
|
||||
|
||||
goto case EFallback.DefaultForType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -515,7 +515,6 @@ namespace ArchiSteamFarm.Json {
|
|||
foreach (Tag tag in tags) {
|
||||
switch (tag.Identifier) {
|
||||
case "cardborder":
|
||||
|
||||
switch (tag.Value) {
|
||||
case "cardborder_0":
|
||||
type = Asset.EType.TradingCard;
|
||||
|
@ -533,7 +532,6 @@ namespace ArchiSteamFarm.Json {
|
|||
|
||||
break;
|
||||
case "droprate":
|
||||
|
||||
switch (tag.Value) {
|
||||
case "droprate_0":
|
||||
rarity = Asset.ERarity.Common;
|
||||
|
@ -555,7 +553,6 @@ namespace ArchiSteamFarm.Json {
|
|||
|
||||
break;
|
||||
case "Game":
|
||||
|
||||
if ((tag.Value.Length <= 4) || !tag.Value.StartsWith("app_", StringComparison.Ordinal)) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(tag.Value), tag.Value));
|
||||
|
||||
|
@ -574,12 +571,10 @@ namespace ArchiSteamFarm.Json {
|
|||
|
||||
break;
|
||||
case "item_class":
|
||||
|
||||
switch (tag.Value) {
|
||||
case "item_class_2":
|
||||
|
||||
// This is a fallback in case we'd have no cardborder available to interpret
|
||||
if (type == Asset.EType.Unknown) {
|
||||
// This is a fallback in case we'd have no cardborder available to interpret
|
||||
type = Asset.EType.TradingCard;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.Localization;
|
||||
using JetBrains.Annotations;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
|
@ -102,7 +103,9 @@ namespace ArchiSteamFarm.NLog {
|
|||
}
|
||||
}
|
||||
|
||||
await bot.SendMessage(ChatGroupID, SteamID, message).ConfigureAwait(false);
|
||||
if (!await bot.SendMessage(ChatGroupID, SteamID, message).ConfigureAwait(false)) {
|
||||
bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendPrivateMessage(string message, Bot bot = null) {
|
||||
|
@ -120,7 +123,9 @@ namespace ArchiSteamFarm.NLog {
|
|||
}
|
||||
}
|
||||
|
||||
await bot.SendMessage(SteamID, message).ConfigureAwait(false);
|
||||
if (!await bot.SendMessage(SteamID, message).ConfigureAwait(false)) {
|
||||
bot.ArchiLogger.LogGenericTrace(string.Format(Strings.WarningFailedWithError, nameof(Bot.SendMessage)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,11 +48,9 @@ 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;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace ArchiSteamFarm {
|
|||
internal static bool ShutdownSequenceInitialized { get; private set; }
|
||||
|
||||
// We need to keep this one assigned and not calculated on-demand
|
||||
private static readonly string ProcessFileName = Process.GetCurrentProcess().MainModule.FileName;
|
||||
private static readonly string ProcessFileName = Process.GetCurrentProcess().MainModule?.FileName ?? throw new ArgumentNullException(nameof(ProcessFileName));
|
||||
|
||||
private static readonly TaskCompletionSource<byte> ShutdownResetEvent = new TaskCompletionSource<byte>();
|
||||
private static bool SystemRequired;
|
||||
|
@ -430,7 +430,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (cryptKeyNext) {
|
||||
cryptKeyNext = false;
|
||||
HandleCryptKeyArgument(arg);
|
||||
|
@ -459,7 +458,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
break;
|
||||
default:
|
||||
|
||||
if (pathNext) {
|
||||
pathNext = false;
|
||||
HandlePathArgument(arg);
|
||||
|
|
|
@ -56,13 +56,14 @@ namespace ArchiSteamFarm {
|
|||
internal const string UpdateDirectory = "_old";
|
||||
internal const string WebsiteDirectory = "www";
|
||||
|
||||
internal static string HomeDirectory => Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
internal static Guid ModuleVersion => Assembly.GetEntryAssembly().ManifestModule.ModuleVersionId;
|
||||
internal static string HomeDirectory => Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location ?? throw new ArgumentNullException(nameof(HomeDirectory)));
|
||||
internal static Guid ModuleVersion => Assembly.GetEntryAssembly()?.ManifestModule.ModuleVersionId ?? throw new ArgumentNullException(nameof(ModuleVersion));
|
||||
|
||||
[NotNull]
|
||||
internal static string PublicIdentifier => AssemblyName + (BuildInfo.IsCustomBuild ? "-custom" : "");
|
||||
|
||||
internal static Version Version => Assembly.GetEntryAssembly().GetName().Version;
|
||||
[NotNull]
|
||||
internal static Version Version => Assembly.GetEntryAssembly()?.GetName().Version ?? throw new ArgumentNullException(nameof(Version));
|
||||
|
||||
[SuppressMessage("ReSharper", "ConvertToConstant.Global")]
|
||||
internal static class BuildInfo {
|
||||
|
|
|
@ -120,7 +120,11 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
internal async Task OnLoggedOn() => await Bot.ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).ConfigureAwait(false);
|
||||
internal async Task OnLoggedOn() {
|
||||
if (!await Bot.ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).ConfigureAwait(false)) {
|
||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningFailedWithError, nameof(ArchiWebHandler.JoinGroup)));
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task OnPersonaState(string nickname = null, string avatarHash = null) {
|
||||
if ((DateTime.UtcNow < LastAnnouncementCheck.AddHours(MinAnnouncementCheckTTL)) && (ShouldSendHeartBeats || (LastHeartBeat == DateTime.MinValue))) {
|
||||
|
|
|
@ -302,13 +302,11 @@ namespace ArchiSteamFarm {
|
|||
foreach ((ulong classID, uint amount) in tradableSet) {
|
||||
switch (amount) {
|
||||
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(amount), amount));
|
||||
|
||||
return false;
|
||||
case 1:
|
||||
|
||||
// Single tradable item, can be matchable or not depending on the rest of the inventory
|
||||
if (!fullSet.TryGetValue(classID, out uint fullAmount) || (fullAmount == 0) || (fullAmount < amount)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(fullAmount));
|
||||
|
@ -324,7 +322,6 @@ namespace ArchiSteamFarm {
|
|||
// A single exclusive tradable item is not matchable, continue
|
||||
continue;
|
||||
default:
|
||||
|
||||
// Any other combination of tradable items is always matchable
|
||||
return false;
|
||||
}
|
||||
|
@ -518,11 +515,9 @@ namespace ArchiSteamFarm {
|
|||
// Check if it's donation trade
|
||||
switch (tradeOffer.ItemsToGive.Count) {
|
||||
case 0 when tradeOffer.ItemsToReceive.Count == 0:
|
||||
|
||||
// If it's steam issue, try again later
|
||||
return ParseTradeResult.EResult.TryAgain;
|
||||
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);
|
||||
|
|
|
@ -137,7 +137,6 @@ namespace ArchiSteamFarm {
|
|||
|
||||
switch (ASF.GlobalConfig.OptimizationMode) {
|
||||
case GlobalConfig.EOptimizationMode.MinMemoryUsage:
|
||||
|
||||
foreach (Task task in tasks) {
|
||||
await task.ConfigureAwait(false);
|
||||
}
|
||||
|
@ -183,55 +182,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (text.Length % 2 != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ulong is 64-bits wide, each hexadecimal character is 4-bits wide, so we split each 16
|
||||
const byte split = 16;
|
||||
|
||||
string lastHex;
|
||||
|
||||
if (text.Length >= split) {
|
||||
StringBuilder hex = new StringBuilder(split, split);
|
||||
|
||||
foreach (char character in text) {
|
||||
hex.Append(character);
|
||||
|
||||
if (hex.Length < split) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ulong.TryParse(hex.ToString(), NumberStyles.HexNumber, null, out _)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hex.Clear();
|
||||
}
|
||||
|
||||
if (hex.Length == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
lastHex = hex.ToString();
|
||||
} else {
|
||||
lastHex = text;
|
||||
}
|
||||
|
||||
switch (lastHex.Length) {
|
||||
case 2:
|
||||
|
||||
return byte.TryParse(lastHex, NumberStyles.HexNumber, null, out _);
|
||||
case 4:
|
||||
|
||||
return ushort.TryParse(lastHex, NumberStyles.HexNumber, null, out _);
|
||||
case 8:
|
||||
|
||||
return uint.TryParse(lastHex, NumberStyles.HexNumber, null, out _);
|
||||
default:
|
||||
|
||||
return false;
|
||||
}
|
||||
return (text.Length % 2 == 0) && text.All(Uri.IsHexDigit);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
|
|
|
@ -591,14 +591,11 @@ 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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue