mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-01 06:00:46 +00:00
ASF: Big revolution #131
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -4,8 +4,8 @@
|
||||
|
||||
# Ignore all config files, apart from ones we want to include
|
||||
ArchiSteamFarm/config/*
|
||||
!ArchiSteamFarm/config/example.xml
|
||||
!ArchiSteamFarm/config/minimal.xml
|
||||
!ArchiSteamFarm/config/example.json
|
||||
!ArchiSteamFarm/config/minimal.json
|
||||
|
||||
# Ignore local debugging log file
|
||||
ArchiSteamFarm/log.txt
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -101,6 +101,8 @@
|
||||
<Compile Include="ArchiHandler.cs" />
|
||||
<Compile Include="ArchiWebHandler.cs" />
|
||||
<Compile Include="Bot.cs" />
|
||||
<Compile Include="BotConfig.cs" />
|
||||
<Compile Include="BotDatabase.cs" />
|
||||
<Compile Include="CardsFarmer.cs" />
|
||||
<Compile Include="CMsgClientClanInviteAction.cs" />
|
||||
<Compile Include="Debugging.cs" />
|
||||
@@ -134,12 +136,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="cirno.ico" />
|
||||
<Content Include="config\example.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="config\minimal.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SteamAuth\SteamAuth.csproj">
|
||||
@@ -147,6 +143,9 @@
|
||||
<Name>SteamAuth</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="config\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
@@ -155,15 +154,15 @@
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mkdir "$(TargetDir)out" "$(TargetDir)out\config"
|
||||
copy "$(TargetDir)config\example.xml" "$(TargetDir)out\config"
|
||||
copy "$(TargetDir)config\minimal.xml" "$(TargetDir)out\config"
|
||||
copy "$(TargetDir)config\example.json" "$(TargetDir)out\config"
|
||||
copy "$(TargetDir)config\minimal.json" "$(TargetDir)out\config"
|
||||
"$(SolutionDir)tools\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(TargetDir)out\ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
del "$(TargetDir)out\ASF.exe.config"
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mkdir -p "$(TargetDir)out" "$(TargetDir)out/config"
|
||||
cp "$(TargetDir)config/example.xml" "$(TargetDir)out/config"
|
||||
cp "$(TargetDir)config/minimal.xml" "$(TargetDir)out/config"
|
||||
cp "$(TargetDir)config/example.json" "$(TargetDir)out/config"
|
||||
cp "$(TargetDir)config/minimal.json" "$(TargetDir)out/config"
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(TargetDir)out/ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
rm "$(TargetDir)out/ASF.exe.config"
|
||||
</PostBuildEvent>
|
||||
|
||||
@@ -37,17 +37,12 @@ namespace ArchiSteamFarm {
|
||||
private const int Timeout = 1000 * WebBrowser.HttpTimeout; // In miliseconds
|
||||
|
||||
private readonly Bot Bot;
|
||||
private readonly string ApiKey;
|
||||
private readonly Dictionary<string, string> Cookie = new Dictionary<string, string>(4);
|
||||
|
||||
private ulong SteamID;
|
||||
|
||||
internal ArchiWebHandler(Bot bot, string apiKey) {
|
||||
internal ArchiWebHandler(Bot bot) {
|
||||
Bot = bot;
|
||||
|
||||
if (!string.IsNullOrEmpty(apiKey) && !apiKey.Equals("null")) {
|
||||
ApiKey = apiKey;
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<bool> Init(SteamClient steamClient, string webAPIUserNonce, string parentalPin) {
|
||||
@@ -147,12 +142,12 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal List<SteamTradeOffer> GetTradeOffers() {
|
||||
if (ApiKey == null) {
|
||||
if (string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyValue response = null;
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService", ApiKey)) {
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService", Bot.BotConfig.SteamApiKey)) {
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
@@ -269,12 +264,12 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal bool DeclineTradeOffer(ulong tradeID) {
|
||||
if (tradeID == 0 || ApiKey == null) {
|
||||
if (tradeID == 0 || string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyValue response = null;
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService", ApiKey)) {
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService", Bot.BotConfig.SteamApiKey)) {
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
|
||||
@@ -33,7 +33,6 @@ using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Text;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
@@ -42,16 +41,17 @@ namespace ArchiSteamFarm {
|
||||
private const ushort CallbackSleep = 500; // In miliseconds
|
||||
|
||||
internal static readonly ConcurrentDictionary<string, Bot> Bots = new ConcurrentDictionary<string, Bot>();
|
||||
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 303700, 335590, 368020, 425280 };
|
||||
|
||||
private static readonly uint LoginID = MsgClientLogon.ObfuscationMask; // This must be the same for all ASF bots and all ASF processes
|
||||
|
||||
private readonly string ConfigFile, LoginKeyFile, MobileAuthenticatorFile, SentryFile;
|
||||
private readonly string SentryFile;
|
||||
private readonly Timer SendItemsTimer;
|
||||
|
||||
internal readonly string BotName;
|
||||
internal readonly ArchiHandler ArchiHandler;
|
||||
internal readonly ArchiWebHandler ArchiWebHandler;
|
||||
internal readonly BotConfig BotConfig;
|
||||
internal readonly BotDatabase BotDatabase;
|
||||
internal readonly SteamClient SteamClient;
|
||||
|
||||
private readonly CallbackManager CallbackManager;
|
||||
@@ -62,35 +62,10 @@ namespace ArchiSteamFarm {
|
||||
private readonly Trading Trading;
|
||||
|
||||
internal bool KeepRunning { get; private set; } = false;
|
||||
internal SteamGuardAccount SteamGuardAccount { get; private set; }
|
||||
|
||||
// Config variables
|
||||
internal bool Enabled { get; private set; } = false;
|
||||
internal string SteamLogin { get; private set; } = "null";
|
||||
internal string SteamPassword { get; private set; } = "null";
|
||||
internal string SteamNickname { get; private set; } = "null";
|
||||
internal string SteamApiKey { get; private set; } = "null";
|
||||
internal string SteamParentalPIN { get; private set; } = "0";
|
||||
internal ulong SteamMasterID { get; private set; } = 0;
|
||||
internal ulong SteamMasterClanID { get; private set; } = 0;
|
||||
internal bool StartOnLaunch { get; private set; } = true;
|
||||
internal bool CardDropsRestricted { get; private set; } = false;
|
||||
internal bool FarmOffline { get; private set; } = false;
|
||||
internal bool HandleOfflineMessages { get; private set; } = false;
|
||||
internal bool ForwardKeysToOtherBots { get; private set; } = false;
|
||||
internal bool DistributeKeys { get; private set; } = false;
|
||||
internal bool UseAsfAsMobileAuthenticator { get; private set; } = false;
|
||||
internal bool ShutdownOnFarmingFinished { get; private set; } = false;
|
||||
internal bool SendOnFarmingFinished { get; private set; } = false;
|
||||
internal string SteamTradeToken { get; private set; } = "null";
|
||||
internal byte SendTradePeriod { get; private set; } = 0;
|
||||
internal HashSet<uint> Blacklist { get; } = new HashSet<uint>();
|
||||
internal HashSet<uint> GamesPlayedWhileIdle { get; } = new HashSet<uint>() { 0 };
|
||||
internal bool Statistics { get; private set; } = true;
|
||||
|
||||
private bool InvalidPassword = false;
|
||||
private bool LoggedInElsewhere = false;
|
||||
private string AuthCode, LoginKey, TwoFactorAuth;
|
||||
private string AuthCode, TwoFactorAuth;
|
||||
|
||||
internal static string GetAnyBotName() {
|
||||
foreach (string botName in Bots.Keys) {
|
||||
@@ -136,22 +111,6 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
BotName = botName;
|
||||
|
||||
string botPath = Path.Combine(Program.ConfigDirectory, botName);
|
||||
ConfigFile = botPath + ".xml";
|
||||
LoginKeyFile = botPath + ".key";
|
||||
MobileAuthenticatorFile = botPath + ".auth";
|
||||
SentryFile = botPath + ".bin";
|
||||
|
||||
if (!ReadConfig()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool alreadyExists;
|
||||
lock (Bots) {
|
||||
alreadyExists = Bots.ContainsKey(botName);
|
||||
@@ -164,6 +123,62 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
BotName = botName;
|
||||
|
||||
string botPath = Path.Combine(Program.ConfigDirectory, botName);
|
||||
|
||||
// CONVERSION START
|
||||
if (File.Exists(botPath + ".xml")) {
|
||||
BotConfig = BotConfig.LoadOldFormat(botPath + ".xml");
|
||||
if (BotConfig == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BotConfig.Convert(botPath + ".json")) {
|
||||
try {
|
||||
File.Delete(botPath + ".xml");
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, botName);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// CONVERSION END
|
||||
|
||||
BotConfig = BotConfig.Load(botPath + ".json");
|
||||
if (BotConfig == null) {
|
||||
Logging.LogGenericError("Your config for this bot instance is invalid, it won't run!", botName);
|
||||
return;
|
||||
}
|
||||
|
||||
// CONVERSION START
|
||||
if (File.Exists(botPath + ".key")) {
|
||||
BotDatabase = BotDatabase.Load(botPath + ".db");
|
||||
try {
|
||||
BotDatabase.LoginKey = File.ReadAllText(botPath + ".key");
|
||||
File.Delete(botPath + ".key");
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
}
|
||||
if (File.Exists(botPath + ".auth")) {
|
||||
BotDatabase = BotDatabase.Load(botPath + ".db");
|
||||
try {
|
||||
BotDatabase.SteamGuardAccount = JsonConvert.DeserializeObject<SteamGuardAccount>(File.ReadAllText(botPath + ".auth"));
|
||||
File.Delete(botPath + ".auth");
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
}
|
||||
// CONVERSION END
|
||||
|
||||
if (!BotConfig.Enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
BotDatabase = BotDatabase.Load(botPath + ".db");
|
||||
SentryFile = botPath + ".bin";
|
||||
|
||||
// Initialize
|
||||
SteamClient = new SteamClient();
|
||||
|
||||
@@ -184,14 +199,6 @@ namespace ArchiSteamFarm {
|
||||
CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
|
||||
CallbackManager.Subscribe<SteamFriends.FriendMsgHistoryCallback>(OnFriendMsgHistory);
|
||||
|
||||
if (UseAsfAsMobileAuthenticator && File.Exists(MobileAuthenticatorFile)) {
|
||||
try {
|
||||
SteamGuardAccount = JsonConvert.DeserializeObject<SteamGuardAccount>(File.ReadAllText(MobileAuthenticatorFile));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, botName);
|
||||
}
|
||||
}
|
||||
|
||||
SteamUser = SteamClient.GetHandler<SteamUser>();
|
||||
CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
|
||||
CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
|
||||
@@ -203,20 +210,20 @@ namespace ArchiSteamFarm {
|
||||
CallbackManager.Subscribe<ArchiHandler.OfflineMessageCallback>(OnOfflineMessage);
|
||||
CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);
|
||||
|
||||
ArchiWebHandler = new ArchiWebHandler(this, SteamApiKey);
|
||||
ArchiWebHandler = new ArchiWebHandler(this);
|
||||
CardsFarmer = new CardsFarmer(this);
|
||||
Trading = new Trading(this);
|
||||
|
||||
if (SendTradePeriod > 0 && SendItemsTimer == null) {
|
||||
if (BotConfig.SendTradePeriod > 0 && SendItemsTimer == null) {
|
||||
SendItemsTimer = new Timer(
|
||||
async e => await ResponseSendTrade().ConfigureAwait(false),
|
||||
null,
|
||||
TimeSpan.FromHours(SendTradePeriod), // Delay
|
||||
TimeSpan.FromHours(SendTradePeriod) // Period
|
||||
TimeSpan.FromHours(BotConfig.SendTradePeriod), // Delay
|
||||
TimeSpan.FromHours(BotConfig.SendTradePeriod) // Period
|
||||
);
|
||||
}
|
||||
|
||||
if (!StartOnLaunch) {
|
||||
if (!BotConfig.StartOnLaunch) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,15 +232,15 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task AcceptAllConfirmations() {
|
||||
if (SteamGuardAccount == null) {
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await SteamGuardAccount.RefreshSessionAsync().ConfigureAwait(false);
|
||||
await BotDatabase.SteamGuardAccount.RefreshSessionAsync().ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
foreach (Confirmation confirmation in await SteamGuardAccount.FetchConfirmationsAsync().ConfigureAwait(false)) {
|
||||
if (SteamGuardAccount.AcceptConfirmation(confirmation)) {
|
||||
foreach (Confirmation confirmation in await BotDatabase.SteamGuardAccount.FetchConfirmationsAsync().ConfigureAwait(false)) {
|
||||
if (BotDatabase.SteamGuardAccount.AcceptConfirmation(confirmation)) {
|
||||
Logging.LogGenericInfo("Accepting confirmation: Success!", BotName);
|
||||
} else {
|
||||
Logging.LogGenericWarning("Accepting confirmation: Failed!", BotName);
|
||||
@@ -247,10 +254,10 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal void ResetGamesPlayed() {
|
||||
if (GamesPlayedWhileIdle.Contains(0)) {
|
||||
if (BotConfig.GamesPlayedWhileIdle.Contains(0)) {
|
||||
ArchiHandler.PlayGames(0);
|
||||
} else {
|
||||
ArchiHandler.PlayGames(GamesPlayedWhileIdle);
|
||||
ArchiHandler.PlayGames(BotConfig.GamesPlayedWhileIdle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,10 +268,10 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task OnFarmingFinished(bool farmedSomething) {
|
||||
if (farmedSomething && SendOnFarmingFinished) {
|
||||
if (farmedSomething && BotConfig.SendOnFarmingFinished) {
|
||||
await ResponseSendTrade().ConfigureAwait(false);
|
||||
}
|
||||
if (ShutdownOnFarmingFinished) {
|
||||
if (BotConfig.ShutdownOnFarmingFinished) {
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
@@ -417,13 +424,13 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> ResponseSendTrade() {
|
||||
if (SteamMasterID == 0) {
|
||||
if (BotConfig.SteamMasterID == 0) {
|
||||
return "Trade couldn't be send because SteamMasterID is not defined!";
|
||||
}
|
||||
|
||||
string token = null;
|
||||
if (!string.IsNullOrEmpty(SteamTradeToken) && !SteamTradeToken.Equals("null")) {
|
||||
token = SteamTradeToken;
|
||||
if (!string.IsNullOrEmpty(BotConfig.SteamTradeToken) && !BotConfig.SteamTradeToken.Equals("null")) {
|
||||
token = BotConfig.SteamTradeToken;
|
||||
}
|
||||
|
||||
await Trading.LimitInventoryRequestsAsync().ConfigureAwait(false);
|
||||
@@ -433,7 +440,7 @@ namespace ArchiSteamFarm {
|
||||
return "Nothing to send, inventory seems empty!";
|
||||
}
|
||||
|
||||
if (await ArchiWebHandler.SendTradeOffer(inventory, SteamMasterID, token).ConfigureAwait(false)) {
|
||||
if (await ArchiWebHandler.SendTradeOffer(inventory, BotConfig.SteamMasterID, token).ConfigureAwait(false)) {
|
||||
await AcceptAllConfirmations().ConfigureAwait(false);
|
||||
return "Trade offer sent successfully!";
|
||||
} else {
|
||||
@@ -455,12 +462,12 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private string Response2FA() {
|
||||
if (SteamGuardAccount == null) {
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
return "That bot doesn't have ASF 2FA enabled!";
|
||||
}
|
||||
|
||||
long timeLeft = 30 - TimeAligner.GetSteamTime() % 30;
|
||||
return "2FA Token: " + SteamGuardAccount.GenerateSteamGuardCode() + " (expires in " + timeLeft + " seconds)";
|
||||
return "2FA Token: " + BotDatabase.SteamGuardAccount.GenerateSteamGuardCode() + " (expires in " + timeLeft + " seconds)";
|
||||
}
|
||||
|
||||
private static string Response2FA(string botName) {
|
||||
@@ -477,7 +484,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private string Response2FAOff() {
|
||||
if (SteamGuardAccount == null) {
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
return "That bot doesn't have ASF 2FA enabled!";
|
||||
}
|
||||
|
||||
@@ -542,7 +549,7 @@ namespace ArchiSteamFarm {
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OnCooldown:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.RegionLocked:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + purchaseResult + " | Items: " + string.Join("", items));
|
||||
if (DistributeKeys) {
|
||||
if (BotConfig.DistributeKeys) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
@@ -551,13 +558,13 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
} while (currentBot == this);
|
||||
|
||||
if (!ForwardKeysToOtherBots) {
|
||||
if (!BotConfig.ForwardKeysToOtherBots) {
|
||||
key = reader.ReadLine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ForwardKeysToOtherBots) {
|
||||
if (!BotConfig.ForwardKeysToOtherBots) {
|
||||
key = reader.ReadLine();
|
||||
break;
|
||||
}
|
||||
@@ -606,7 +613,7 @@ namespace ArchiSteamFarm {
|
||||
break;
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + purchaseResult + " | Items: " + string.Join("", items));
|
||||
if (DistributeKeys) {
|
||||
if (BotConfig.DistributeKeys) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
@@ -620,7 +627,7 @@ namespace ArchiSteamFarm {
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.DuplicatedKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.InvalidKey:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + purchaseResult + " | Items: " + string.Join("", items));
|
||||
if (DistributeKeys && !ForwardKeysToOtherBots) {
|
||||
if (BotConfig.DistributeKeys && !BotConfig.ForwardKeysToOtherBots) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
@@ -830,12 +837,12 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private bool LinkMobileAuthenticator() {
|
||||
if (SteamGuardAccount != null) {
|
||||
if (BotDatabase.SteamGuardAccount != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Linking new ASF MobileAuthenticator...", BotName);
|
||||
UserLogin userLogin = new UserLogin(SteamLogin, SteamPassword);
|
||||
UserLogin userLogin = new UserLogin(BotConfig.SteamLogin, BotConfig.SteamPassword);
|
||||
LoginResult loginResult;
|
||||
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
||||
switch (loginResult) {
|
||||
@@ -862,14 +869,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
SteamGuardAccount = authenticatorLinker.LinkedAccount;
|
||||
|
||||
try {
|
||||
File.WriteAllText(MobileAuthenticatorFile, JsonConvert.SerializeObject(SteamGuardAccount));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
return false;
|
||||
}
|
||||
BotDatabase.SteamGuardAccount = authenticatorLinker.LinkedAccount;
|
||||
|
||||
AuthenticatorLinker.FinalizeResult finalizeResult = authenticatorLinker.FinalizeAddAuthenticator(Program.GetUserInput(BotName, Program.EUserInputType.SMS));
|
||||
if (finalizeResult != AuthenticatorLinker.FinalizeResult.Success) {
|
||||
@@ -879,33 +879,30 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Successfully linked ASF as new mobile authenticator for this account!", BotName);
|
||||
Program.GetUserInput(BotName, Program.EUserInputType.RevocationCode, SteamGuardAccount.RevocationCode);
|
||||
Program.GetUserInput(BotName, Program.EUserInputType.RevocationCode, BotDatabase.SteamGuardAccount.RevocationCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool DelinkMobileAuthenticator() {
|
||||
if (SteamGuardAccount == null) {
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = SteamGuardAccount.DeactivateAuthenticator();
|
||||
SteamGuardAccount = null;
|
||||
bool result = BotDatabase.SteamGuardAccount.DeactivateAuthenticator();
|
||||
|
||||
try {
|
||||
File.Delete(MobileAuthenticatorFile);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
if (result) {
|
||||
BotDatabase.SteamGuardAccount = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void JoinMasterChat() {
|
||||
if (SteamMasterClanID == 0) {
|
||||
if (BotConfig.SteamMasterClanID == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamFriends.JoinChat(SteamMasterClanID);
|
||||
SteamFriends.JoinChat(BotConfig.SteamMasterClanID);
|
||||
}
|
||||
|
||||
private void OnConnected(SteamClient.ConnectedCallback callback) {
|
||||
@@ -926,14 +923,6 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.Exists(LoginKeyFile)) {
|
||||
try {
|
||||
LoginKey = File.ReadAllText(LoginKeyFile);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
}
|
||||
|
||||
byte[] sentryHash = null;
|
||||
if (File.Exists(SentryFile)) {
|
||||
try {
|
||||
@@ -944,20 +933,20 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
if (SteamLogin.Equals("null")) {
|
||||
SteamLogin = Program.GetUserInput(BotName, Program.EUserInputType.Login);
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
BotConfig.SteamLogin = Program.GetUserInput(BotName, Program.EUserInputType.Login);
|
||||
}
|
||||
|
||||
if (SteamPassword.Equals("null") && string.IsNullOrEmpty(LoginKey)) {
|
||||
SteamPassword = Program.GetUserInput(BotName, Program.EUserInputType.Password);
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamPassword) && string.IsNullOrEmpty(BotDatabase.LoginKey)) {
|
||||
BotConfig.SteamPassword = Program.GetUserInput(BotName, Program.EUserInputType.Password);
|
||||
}
|
||||
|
||||
SteamUser.LogOn(new SteamUser.LogOnDetails {
|
||||
Username = SteamLogin,
|
||||
Password = SteamPassword,
|
||||
Username = BotConfig.SteamLogin,
|
||||
Password = BotConfig.SteamPassword,
|
||||
AuthCode = AuthCode,
|
||||
LoginID = LoginID,
|
||||
LoginKey = LoginKey,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorAuth,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
@@ -983,15 +972,8 @@ namespace ArchiSteamFarm {
|
||||
|
||||
if (InvalidPassword) {
|
||||
InvalidPassword = false;
|
||||
if (!string.IsNullOrEmpty(LoginKey)) { // InvalidPassword means usually that login key has expired, if we used it
|
||||
LoginKey = null;
|
||||
|
||||
try {
|
||||
File.Delete(LoginKeyFile);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(BotDatabase.LoginKey)) { // InvalidPassword means usually that login key has expired, if we used it
|
||||
BotDatabase.LoginKey = null;
|
||||
Logging.LogGenericInfo("Removed expired login key", BotName);
|
||||
} else { // If we didn't use login key, InvalidPassword usually means we got captcha or other network-based throttling
|
||||
Logging.LogGenericInfo("Will retry after 25 minutes...", BotName);
|
||||
@@ -1024,7 +1006,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.PatronID != SteamMasterID) {
|
||||
if (callback.PatronID != BotConfig.SteamMasterID) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1040,7 +1022,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.ChatterID != SteamMasterID) {
|
||||
if (callback.ChatterID != BotConfig.SteamMasterID) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1069,7 +1051,7 @@ namespace ArchiSteamFarm {
|
||||
// TODO: Accept clan invites from master?
|
||||
break;
|
||||
default:
|
||||
if (friend.SteamID == SteamMasterID) {
|
||||
if (friend.SteamID == BotConfig.SteamMasterID) {
|
||||
SteamFriends.AddFriend(friend.SteamID);
|
||||
}
|
||||
break;
|
||||
@@ -1086,7 +1068,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.Sender != SteamMasterID) {
|
||||
if (callback.Sender != BotConfig.SteamMasterID) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1102,7 +1084,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.SteamID != SteamMasterID) {
|
||||
if (callback.SteamID != BotConfig.SteamMasterID) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1132,7 +1114,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FarmOffline) {
|
||||
if (!BotConfig.FarmOffline) {
|
||||
SteamFriends.SetPersonaState(EPersonaState.Online);
|
||||
}
|
||||
}
|
||||
@@ -1160,13 +1142,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
switch (callback.Result) {
|
||||
case EResult.AccountLogonDenied:
|
||||
AuthCode = Program.GetUserInput(SteamLogin, Program.EUserInputType.SteamGuard);
|
||||
AuthCode = Program.GetUserInput(BotConfig.SteamLogin, Program.EUserInputType.SteamGuard);
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
if (SteamGuardAccount == null) {
|
||||
TwoFactorAuth = Program.GetUserInput(SteamLogin, Program.EUserInputType.TwoFactorAuthentication);
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
TwoFactorAuth = Program.GetUserInput(BotConfig.SteamLogin, Program.EUserInputType.TwoFactorAuthentication);
|
||||
} else {
|
||||
TwoFactorAuth = SteamGuardAccount.GenerateSteamGuardCode();
|
||||
TwoFactorAuth = BotDatabase.SteamGuardAccount.GenerateSteamGuardCode();
|
||||
}
|
||||
break;
|
||||
case EResult.InvalidPassword:
|
||||
@@ -1176,7 +1158,7 @@ namespace ArchiSteamFarm {
|
||||
case EResult.OK:
|
||||
Logging.LogGenericInfo("Successfully logged on!", BotName);
|
||||
|
||||
if (UseAsfAsMobileAuthenticator && TwoFactorAuth == null && SteamGuardAccount == null) {
|
||||
if (BotConfig.UseAsfAsMobileAuthenticator && TwoFactorAuth == null && BotDatabase.SteamGuardAccount == null) {
|
||||
LinkMobileAuthenticator();
|
||||
}
|
||||
|
||||
@@ -1184,27 +1166,23 @@ namespace ArchiSteamFarm {
|
||||
AuthCode = null;
|
||||
TwoFactorAuth = null;
|
||||
|
||||
if (!SteamNickname.Equals("null")) {
|
||||
await SteamFriends.SetPersonaName(SteamNickname);
|
||||
}
|
||||
|
||||
ResetGamesPlayed();
|
||||
|
||||
if (SteamParentalPIN.Equals("null")) {
|
||||
SteamParentalPIN = Program.GetUserInput(BotName, Program.EUserInputType.SteamParentalPIN);
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamParentalPIN)) {
|
||||
BotConfig.SteamParentalPIN = Program.GetUserInput(BotName, Program.EUserInputType.SteamParentalPIN);
|
||||
}
|
||||
|
||||
if (!await ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, SteamParentalPIN).ConfigureAwait(false)) {
|
||||
if (!await ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN).ConfigureAwait(false)) {
|
||||
await Restart().ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SteamMasterClanID != 0) {
|
||||
await ArchiWebHandler.JoinClan(SteamMasterClanID).ConfigureAwait(false);
|
||||
if (BotConfig.SteamMasterClanID != 0) {
|
||||
await ArchiWebHandler.JoinClan(BotConfig.SteamMasterClanID).ConfigureAwait(false);
|
||||
JoinMasterChat();
|
||||
}
|
||||
|
||||
if (Statistics) {
|
||||
if (BotConfig.Statistics) {
|
||||
await ArchiWebHandler.JoinClan(ArchiSCFarmGroup).ConfigureAwait(false);
|
||||
SteamFriends.JoinChat(ArchiSCFarmGroup);
|
||||
}
|
||||
@@ -1231,12 +1209,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
File.WriteAllText(LoginKeyFile, callback.LoginKey);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
|
||||
BotDatabase.LoginKey = callback.LoginKey;
|
||||
SteamUser.AcceptNewLoginKey(callback);
|
||||
}
|
||||
|
||||
@@ -1309,7 +1282,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HandleOfflineMessages) {
|
||||
if (!BotConfig.HandleOfflineMessages) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1326,115 +1299,5 @@ namespace ArchiSteamFarm {
|
||||
await CardsFarmer.RestartFarming().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadConfig() {
|
||||
if (!File.Exists(ConfigFile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
using (XmlReader reader = XmlReader.Create(ConfigFile)) {
|
||||
while (reader.Read()) {
|
||||
if (reader.NodeType != XmlNodeType.Element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string key = reader.Name;
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = reader.GetAttribute("value");
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case "Enabled":
|
||||
Enabled = bool.Parse(value);
|
||||
break;
|
||||
case "SteamLogin":
|
||||
SteamLogin = value;
|
||||
break;
|
||||
case "SteamPassword":
|
||||
SteamPassword = value;
|
||||
break;
|
||||
case "SteamNickname":
|
||||
SteamNickname = value;
|
||||
break;
|
||||
case "SteamApiKey":
|
||||
SteamApiKey = value;
|
||||
break;
|
||||
case "SteamTradeToken":
|
||||
SteamTradeToken = value;
|
||||
break;
|
||||
case "SteamParentalPIN":
|
||||
SteamParentalPIN = value;
|
||||
break;
|
||||
case "SteamMasterID":
|
||||
SteamMasterID = ulong.Parse(value);
|
||||
break;
|
||||
case "SteamMasterClanID":
|
||||
SteamMasterClanID = ulong.Parse(value);
|
||||
break;
|
||||
case "StartOnLaunch":
|
||||
StartOnLaunch = bool.Parse(value);
|
||||
break;
|
||||
case "UseAsfAsMobileAuthenticator":
|
||||
UseAsfAsMobileAuthenticator = bool.Parse(value);
|
||||
break;
|
||||
case "CardDropsRestricted":
|
||||
CardDropsRestricted = bool.Parse(value);
|
||||
break;
|
||||
case "FarmOffline":
|
||||
FarmOffline = bool.Parse(value);
|
||||
break;
|
||||
case "HandleOfflineMessages":
|
||||
HandleOfflineMessages = bool.Parse(value);
|
||||
break;
|
||||
case "ForwardKeysToOtherBots":
|
||||
ForwardKeysToOtherBots = bool.Parse(value);
|
||||
break;
|
||||
case "DistributeKeys":
|
||||
DistributeKeys = bool.Parse(value);
|
||||
break;
|
||||
case "ShutdownOnFarmingFinished":
|
||||
ShutdownOnFarmingFinished = bool.Parse(value);
|
||||
break;
|
||||
case "SendOnFarmingFinished":
|
||||
SendOnFarmingFinished = bool.Parse(value);
|
||||
break;
|
||||
case "SendTradePeriod":
|
||||
SendTradePeriod = byte.Parse(value);
|
||||
break;
|
||||
case "Blacklist":
|
||||
Blacklist.Clear();
|
||||
foreach (string appID in value.Split(',')) {
|
||||
Blacklist.Add(uint.Parse(appID));
|
||||
}
|
||||
break;
|
||||
case "GamesPlayedWhileIdle":
|
||||
GamesPlayedWhileIdle.Clear();
|
||||
foreach (string appID in value.Split(',')) {
|
||||
GamesPlayedWhileIdle.Add(uint.Parse(appID));
|
||||
}
|
||||
break;
|
||||
case "Statistics":
|
||||
Statistics = bool.Parse(value);
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericWarning("Unrecognized config value: " + key + "=" + value, BotName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
Logging.LogGenericError("Your config for this bot instance is invalid, it won't run!", BotName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
252
ArchiSteamFarm/BotConfig.cs
Normal file
252
ArchiSteamFarm/BotConfig.cs
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
|
||||
Contact: JustArchi@JustArchi.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class BotConfig {
|
||||
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 303700, 335590, 368020, 425280 };
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool Enabled { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool StartOnLaunch { get; private set; } = true;
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamLogin { get; set; } = null;
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamPassword { get; set; } = null;
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamParentalPIN { get; set; } = "0";
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamApiKey { get; private set; } = null;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal ulong SteamMasterID { get; private set; } = 0;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal ulong SteamMasterClanID { get; private set; } = 0;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool CardDropsRestricted { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool FarmOffline { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool HandleOfflineMessages { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool ForwardKeysToOtherBots { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool DistributeKeys { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool UseAsfAsMobileAuthenticator { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool ShutdownOnFarmingFinished { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool SendOnFarmingFinished { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal string SteamTradeToken { get; private set; } = null;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal byte SendTradePeriod { get; private set; } = 0;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal HashSet<uint> GamesPlayedWhileIdle { get; private set; } = new HashSet<uint>() { 0 };
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool Statistics { get; private set; } = true;
|
||||
|
||||
|
||||
internal static BotConfig Load(string path) {
|
||||
if (!File.Exists(path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BotConfig botConfig;
|
||||
try {
|
||||
botConfig = JsonConvert.DeserializeObject<BotConfig>(File.ReadAllText(path));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
return botConfig;
|
||||
}
|
||||
|
||||
// TODO: This should be removed soon
|
||||
internal static BotConfig LoadOldFormat(string path) {
|
||||
if (!File.Exists(path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BotConfig botConfig = new BotConfig();
|
||||
|
||||
try {
|
||||
using (XmlReader reader = XmlReader.Create(path)) {
|
||||
while (reader.Read()) {
|
||||
if (reader.NodeType != XmlNodeType.Element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string key = reader.Name;
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = reader.GetAttribute("value");
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case "Enabled":
|
||||
botConfig.Enabled = bool.Parse(value);
|
||||
break;
|
||||
case "SteamLogin":
|
||||
botConfig.SteamLogin = value;
|
||||
break;
|
||||
case "SteamPassword":
|
||||
botConfig.SteamPassword = value;
|
||||
break;
|
||||
case "SteamApiKey":
|
||||
botConfig.SteamApiKey = value;
|
||||
break;
|
||||
case "SteamTradeToken":
|
||||
botConfig.SteamTradeToken = value;
|
||||
break;
|
||||
case "SteamParentalPIN":
|
||||
botConfig.SteamParentalPIN = value;
|
||||
break;
|
||||
case "SteamMasterID":
|
||||
botConfig.SteamMasterID = ulong.Parse(value);
|
||||
break;
|
||||
case "SteamMasterClanID":
|
||||
botConfig.SteamMasterClanID = ulong.Parse(value);
|
||||
break;
|
||||
case "StartOnLaunch":
|
||||
botConfig.StartOnLaunch = bool.Parse(value);
|
||||
break;
|
||||
case "UseAsfAsMobileAuthenticator":
|
||||
botConfig.UseAsfAsMobileAuthenticator = bool.Parse(value);
|
||||
break;
|
||||
case "CardDropsRestricted":
|
||||
botConfig.CardDropsRestricted = bool.Parse(value);
|
||||
break;
|
||||
case "FarmOffline":
|
||||
botConfig.FarmOffline = bool.Parse(value);
|
||||
break;
|
||||
case "HandleOfflineMessages":
|
||||
botConfig.HandleOfflineMessages = bool.Parse(value);
|
||||
break;
|
||||
case "ForwardKeysToOtherBots":
|
||||
botConfig.ForwardKeysToOtherBots = bool.Parse(value);
|
||||
break;
|
||||
case "DistributeKeys":
|
||||
botConfig.DistributeKeys = bool.Parse(value);
|
||||
break;
|
||||
case "ShutdownOnFarmingFinished":
|
||||
botConfig.ShutdownOnFarmingFinished = bool.Parse(value);
|
||||
break;
|
||||
case "SendOnFarmingFinished":
|
||||
botConfig.SendOnFarmingFinished = bool.Parse(value);
|
||||
break;
|
||||
case "SendTradePeriod":
|
||||
botConfig.SendTradePeriod = byte.Parse(value);
|
||||
break;
|
||||
case "GamesPlayedWhileIdle":
|
||||
botConfig.GamesPlayedWhileIdle.Clear();
|
||||
foreach (string appID in value.Split(',')) {
|
||||
botConfig.GamesPlayedWhileIdle.Add(uint.Parse(appID));
|
||||
}
|
||||
break;
|
||||
case "Statistics":
|
||||
botConfig.Statistics = bool.Parse(value);
|
||||
break;
|
||||
case "Blacklist":
|
||||
case "SteamNickname":
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericWarning("Unrecognized config value: " + key + "=" + value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
Logging.LogGenericError("Your config for this bot instance is invalid, it won't run!");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Fixups for new format
|
||||
if (botConfig.SteamLogin != null && botConfig.SteamLogin.Equals("null")) {
|
||||
botConfig.SteamLogin = null;
|
||||
}
|
||||
|
||||
if (botConfig.SteamPassword != null && botConfig.SteamPassword.Equals("null")) {
|
||||
botConfig.SteamPassword = null;
|
||||
}
|
||||
|
||||
if (botConfig.SteamApiKey != null && botConfig.SteamApiKey.Equals("null")) {
|
||||
botConfig.SteamApiKey = null;
|
||||
}
|
||||
|
||||
if (botConfig.SteamParentalPIN != null && botConfig.SteamParentalPIN.Equals("null")) {
|
||||
botConfig.SteamParentalPIN = null;
|
||||
}
|
||||
|
||||
return botConfig;
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
private BotConfig() { }
|
||||
|
||||
// TODO: This should be removed soon
|
||||
internal bool Convert(string path) {
|
||||
try {
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.LogGenericWarning("Your config was converted to new ASF V2.0 format");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
96
ArchiSteamFarm/BotDatabase.cs
Normal file
96
ArchiSteamFarm/BotDatabase.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
|
||||
Contact: JustArchi@JustArchi.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using SteamAuth;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class BotDatabase {
|
||||
internal string LoginKey {
|
||||
get {
|
||||
return _LoginKey;
|
||||
}
|
||||
set {
|
||||
_LoginKey = value;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
internal SteamGuardAccount SteamGuardAccount {
|
||||
get {
|
||||
return _SteamGuardAccount;
|
||||
}
|
||||
set {
|
||||
_SteamGuardAccount = value;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty(Required = Required.AllowNull)]
|
||||
private string _LoginKey;
|
||||
|
||||
[JsonProperty(Required = Required.AllowNull)]
|
||||
private SteamGuardAccount _SteamGuardAccount;
|
||||
|
||||
private string FilePath;
|
||||
|
||||
internal static BotDatabase Load(string filePath) {
|
||||
if (!File.Exists(filePath)) {
|
||||
return new BotDatabase(filePath);
|
||||
}
|
||||
|
||||
BotDatabase botDatabase;
|
||||
try {
|
||||
botDatabase = JsonConvert.DeserializeObject<BotDatabase>(File.ReadAllText(filePath));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
botDatabase.FilePath = filePath;
|
||||
return botDatabase;
|
||||
}
|
||||
|
||||
// This constructor is used when creating new database
|
||||
private BotDatabase(string filePath) {
|
||||
FilePath = filePath;
|
||||
Save();
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
private BotDatabase() { }
|
||||
|
||||
private void Save() {
|
||||
lock (FilePath) {
|
||||
try {
|
||||
File.WriteAllText(FilePath, JsonConvert.SerializeObject(this));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +178,7 @@ namespace ArchiSteamFarm {
|
||||
bool farmedSomething = false;
|
||||
|
||||
// Now the algorithm used for farming depends on whether account is restricted or not
|
||||
if (Bot.CardDropsRestricted) { // If we have restricted card drops, we use complex algorithm
|
||||
if (Bot.BotConfig.CardDropsRestricted) { // If we have restricted card drops, we use complex algorithm
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Complex", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
List<uint> gamesToFarmSolo = GetGamesToFarmSolo(GamesToFarm);
|
||||
@@ -294,7 +294,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
// If we have restricted card drops, actually do check hours of all games that are left to farm
|
||||
if (Bot.CardDropsRestricted) {
|
||||
if (Bot.BotConfig.CardDropsRestricted) {
|
||||
tasks = new List<Task>(GamesToFarm.Keys.Count);
|
||||
Logging.LogGenericInfo("Checking hours...", Bot.BotName);
|
||||
foreach (uint appID in GamesToFarm.Keys) {
|
||||
@@ -327,7 +327,7 @@ namespace ArchiSteamFarm {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Bot.GlobalBlacklist.Contains(appID) || Bot.Blacklist.Contains(appID)) {
|
||||
if (BotConfig.GlobalBlacklist.Contains(appID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,14 +267,25 @@ namespace ArchiSteamFarm {
|
||||
// Before attempting to connect, initialize our list of CMs
|
||||
Bot.RefreshCMs().Wait();
|
||||
|
||||
foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.xml")) {
|
||||
foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.json")) {
|
||||
string botName = Path.GetFileNameWithoutExtension(configFile);
|
||||
Bot bot = new Bot(botName);
|
||||
if (!bot.Enabled) {
|
||||
if (!bot.BotConfig.Enabled) {
|
||||
Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
|
||||
}
|
||||
}
|
||||
|
||||
// CONVERSION START
|
||||
foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.xml")) {
|
||||
string botName = Path.GetFileNameWithoutExtension(configFile);
|
||||
Logging.LogGenericWarning("Found legacy " + botName + ".xml config file, it will now be converted to new ASF V2.0 format!");
|
||||
Bot bot = new Bot(botName);
|
||||
if (!bot.BotConfig.Enabled) {
|
||||
Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);
|
||||
}
|
||||
}
|
||||
// CONVERSION END
|
||||
|
||||
// Check if we got any bots running
|
||||
OnBotShutdown();
|
||||
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.7.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.7.0.0")]
|
||||
[assembly: AssemblyVersion("2.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0.0")]
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tradeOffer.items_to_give.Count == 0 || tradeOffer.OtherSteamID64 == Bot.SteamMasterID) {
|
||||
if (tradeOffer.items_to_give.Count == 0 || tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID) {
|
||||
Logging.LogGenericInfo("Accepting trade: " + tradeID, Bot.BotName);
|
||||
await Bot.ArchiWebHandler.AcceptTradeOffer(tradeID).ConfigureAwait(false);
|
||||
} else {
|
||||
|
||||
24
ArchiSteamFarm/config/example.json
Normal file
24
ArchiSteamFarm/config/example.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"Enabled": false,
|
||||
"StartOnLaunch": true,
|
||||
"SteamLogin": null,
|
||||
"SteamPassword": null,
|
||||
"SteamParentalPIN": "0",
|
||||
"SteamApiKey": null,
|
||||
"SteamMasterID": 0,
|
||||
"SteamMasterClanID": 0,
|
||||
"CardDropsRestricted": false,
|
||||
"FarmOffline": false,
|
||||
"HandleOfflineMessages": false,
|
||||
"ForwardKeysToOtherBots": false,
|
||||
"DistributeKeys": false,
|
||||
"UseAsfAsMobileAuthenticator": false,
|
||||
"ShutdownOnFarmingFinished": false,
|
||||
"SendOnFarmingFinished": false,
|
||||
"SteamTradeToken": "null",
|
||||
"SendTradePeriod": 0,
|
||||
"GamesPlayedWhileIdle": [
|
||||
0
|
||||
],
|
||||
"Statistics": true
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<!-- This is full-fledged example config, you may be also interested in minimal.xml for bare minimum one -->
|
||||
|
||||
<!-- This config includes all user-switchable properties that you may want to change on per-bot basis -->
|
||||
<!-- Default values used in config match default ASF values when given config property is not found -->
|
||||
<!-- In other words, if given property is not defined, ASF will assume default pre-programmed value -->
|
||||
|
||||
<!-- Notice, if you use special characters reserved for XML, you should escape them -->
|
||||
<!-- Escape table: [& - &] | [" - "] | [' - '] | [< - <] | [> - >] -->
|
||||
<!-- So e.g. if your SteamPassword is "foo&" you should write value="foo&" -->
|
||||
|
||||
<!-- Type of the property is a tip for you that defines what values you can use -->
|
||||
<!-- bool - Boolean value that can be only "true" or "false" -->
|
||||
<!-- string - Any sequence of characters, unless stated otherwise (keep in mind escape table above), with special treatment of "null" value -->
|
||||
<!-- byte - 8-bit unsigned integer, used mostly for small numbers (0-255) -->
|
||||
<!-- uint - 32-bit unsigned integer, used mostly for steam appID -->
|
||||
<!-- ulong - 64-bit unsigned (long) integer, used mostly for representing steamID64 -->
|
||||
<!-- HashSet(uint) - Comma-separated list of unique 32-bit unsigned integers -->
|
||||
|
||||
<!-- Master switch to turn account on and off, set to "true" after you're done -->
|
||||
<!-- This bot instance won't run unless below switch is set to "true" -->
|
||||
<Enabled type="bool" value="false"/>
|
||||
|
||||
<!-- This is your steam login, the one you use for logging in to steam -->
|
||||
<!-- You can use "null" if you wish to enter login on every startup -->
|
||||
<SteamLogin type="string" value="null"/>
|
||||
|
||||
<!-- This is your steam password, the one you use for logging in to steam -->
|
||||
<!-- You can use "null" if you wish to enter password on every startup -->
|
||||
<SteamPassword type="string" value="null"/>
|
||||
|
||||
<!-- This is steam nickname, the one you want to use for bot. Can be anything up to 32 characters -->
|
||||
<!-- You can use "null" if you wish to preserve your actual nickname, and this is what you want most likely -->
|
||||
<SteamNickname type="string" value="null"/>
|
||||
|
||||
<!-- This is your bot's API key, get one at https://steamcommunity.com/dev/apikey while logged in as a bot, domain doesn't matter -->
|
||||
<!-- Remember that each account should have unique API key generated through above link, wrong API key will make all API-based functionalities to fail -->
|
||||
<!-- API key is useless for primary accounts, as they're not using trading feature, you can leave it at "null" if you're configuring a primary account -->
|
||||
<!-- When at "null", it will disable all ASF API-based functionalities such as trading -->
|
||||
<SteamApiKey type="string" value="null"/>
|
||||
|
||||
<!-- This is your parental PIN if you use steam parental functionality -->
|
||||
<!-- Most likely you don't want to change it. You can use "null" if you wish to enter PIN on every startup, 0 means there is no PIN, and this is probably what you want -->
|
||||
<SteamParentalPIN type="string" value="0"/>
|
||||
|
||||
<!-- This is steamID64 of the bot-master - you, for example "76561198006963719" -->
|
||||
<!-- You can get one e.g. by logging in to http://steamrep.com/ -->
|
||||
<!-- If you're configuring primary account, you can safely leave it at "0", as you're master yourself -->
|
||||
<!-- When at "0", bot won't accept any commands, including steam cd-keys or trades" -->
|
||||
<SteamMasterID type="ulong" value="0"/>
|
||||
|
||||
<!-- This is steamID64 of the master clan (group). If defined, bot will join the group and the chat automatically after logging in -->
|
||||
<!-- The easiest way to get one is to check groups on your profile: http://steamcommunity.com/my/profile" -->
|
||||
<!-- Then copying the URL of "Leave group" link, it will look like this: javascript:leaveGroupPrompt('103582791440160998','Archi\'s SC Farm') -->
|
||||
<!-- The steamID64 we're looking for is there, in above example: "103582791440160998" -->
|
||||
<!-- Remember that joining a group and the chat requires having non-restricted access to steam community, which is not always the case with alts -->
|
||||
<!-- If you don't have your own farming group, most likely you don't want to change it, 0 means there is no master group defined -->
|
||||
<SteamMasterClanID type="ulong" value="0"/>
|
||||
|
||||
<!-- This switch defines if bot should automatically start when ASF process is launched -->
|
||||
<!-- Some people might want to avoid that, as they may prefer to issue "!start" command themselves -->
|
||||
<!-- Most likely you want to keep this switch enabled, unless you have a reason -->
|
||||
<StartOnLaunch type="bool" value="true"/>
|
||||
|
||||
<!-- This switch defines if you want to use built-in ASF two-factor-authentication (ASF 2FA) for this account -->
|
||||
<!-- The one and only purpose for this function is automating steam logins and steam trades, so you won't need to enter 2FA codes all the time -->
|
||||
<!-- This however defeats the whole purpose of two-factor-auth, and should be used on alt accounts ONLY -->
|
||||
<!-- You should read full documentation, along with explanation here: https://github.com/JustArchi/ArchiSteamFarm/wiki/Escrow -->
|
||||
<!-- Personally I suggest switching this to "true" ONLY for alts -->
|
||||
<!-- WARNING, this option can potentially LOCK OUT YOUR ACCOUNT! If you don't fully understand this feature, DON'T USE IT! -->
|
||||
<UseAsfAsMobileAuthenticator type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines if the account has card drops restricted -->
|
||||
<!-- Restricted card drops means that the account doesn't receive any steam cards until it plays the game for at least 2 hours -->
|
||||
<!-- There is no magical way to detect it by ASF, I made this option config-based switch -->
|
||||
<!-- Based on our observations, it looks like most accounts that never issued a refund have non-restricted card drops, and this is what default value assumes -->
|
||||
<!-- However, if you noticed that your cards never drop until you hit 2 hours played mark, consider setting it as "true" -->
|
||||
<!-- Guessing "wrong" won't have any real consequences, ASF will just work in non-optimal way, and everybody wants to drop cards fast, right? -->
|
||||
<!-- Based on this parameter, ASF will try to choose the most optimal cards farming algorithm for this account -->
|
||||
<CardDropsRestricted type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines if the account should stay as "Offline" after logging in to Steam. This has several advantages and disadvantages -->
|
||||
<!-- Personally I find it extremely useful for primary accounts, as your status will remain "Online" and not "In-Game" when ASF is farming -->
|
||||
<!-- Thanks to that, your friends will never ask you again if you're playing or farming the game. Your status will now nicely reflect that -->
|
||||
<!-- However, it's less useful for alt accounts, as you won't be able to interact with bots and check what they're doing - they'll appear as "Offline" -->
|
||||
<!-- Personally I suggest switching this to "true" for primary accounts, and leaving it at "false" for alt accounts -->
|
||||
<!-- Bot won't be able to receive and answer to your commands, unless you set "HandleOfflineMessages" below to "true" as well -->
|
||||
<FarmOffline type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines if bot should handle offline messages when it sees them -->
|
||||
<!-- Basically it should be used only when "FarmOffline" property above is true, so bot can handle offline messages -->
|
||||
<!-- Reading offline messages will also mark them as received, therefore it should not be used if you want to keep them for later -->
|
||||
<!-- Personally I suggest keeping this on "false" for primary accounts, and considering switching to "true" for alts, if "FarmOffline" above is set to true as well -->
|
||||
<HandleOfflineMessages type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines if bot should try to forward key to the other bot in case of failing to redeem on his own account -->
|
||||
<!-- This can be useful if you want to send key to your farm and you don't care which account redeems it -->
|
||||
<!-- When "true", bot will try redeeming "AlreadyOwned", "BaseGameRequired", "OnCooldown" and "RegionLocked" keys on other available accounts -->
|
||||
<!-- By default this option is disabled, as not everyone might want to redeem keys on other configured accounts -->
|
||||
<!-- WARNING: Remember that Steam issues temporary ban on too many failed key activations (OnCooldown status) -->
|
||||
<!-- Therefore, be careful when it comes to multiple keys activations, this option is supposed to help you, not make you lazy -->
|
||||
<ForwardKeysToOtherBots type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines bot's behaviour on getting multiple keys -->
|
||||
<!-- When "false", bot will try to redeem all keys on it's own account, when "true", keys will be distributed on "one bot, one key" basis -->
|
||||
<!-- Keep in mind that "ForwardKeysToOtherBots" property defined above affects this switch as well -->
|
||||
<!-- When "ForwardKeysToOtherBots" is "true", bot will try redeeming "AlreadyOwned", "BaseGameRequired", "OnCooldown" and "RegionLocked" keys on other available accounts -->
|
||||
<!-- If "ForwardKeysToOtherBots" is set to "false", bot will keep unused keys for itself -->
|
||||
<!-- By default this option is disabled, as not everyone might want to alter the multiple keys redeeming behaviour -->
|
||||
<!-- Switch this to "true" only if you prefer to use "one bot, one key" behaviour, instead of default one, which is to redeem all keys only on one account -->
|
||||
<DistributeKeys type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines if bot should disconnect once farming is finished -->
|
||||
<!-- Keep in mind that when no bots are active, ASF will shutdown as well -->
|
||||
<!-- You may want to disconnect the bot after he's done, if that's the case, set below to "true" -->
|
||||
<!-- However, you may instead want to keep it online for the whole time, in this case, leave it at "false" -->
|
||||
<!-- Even when bot is not farming anything, he'll keep checking badges from time to time, if there is anything new to farm -->
|
||||
<!-- Personally I suggest leaving it at "false", unless you have a reason to close the process after all bots finished farming -->
|
||||
<ShutdownOnFarmingFinished type="bool" value="false"/>
|
||||
|
||||
<!-- This switch defines if bot should send you all the items it farmed after farming is finished -->
|
||||
<!-- Remember that in order to use this feature, SteamMasterID must be defined above -->
|
||||
<!-- If SteamMasterID is not a friend of this bot, SteamTradeToken will also be needed to set below -->
|
||||
<SendOnFarmingFinished type="bool" value="false"/>
|
||||
|
||||
<!-- This is a SteamTradeToken of SteamMasterID, which is required if bot doesn't have SteamMasterID on friend list -->
|
||||
<!-- You can get the token here: http://steamcommunity.com/id/me/tradeoffers/privacy while being logged in as SteamMasterID -->
|
||||
<!-- The token has 8 characters and is written in the last part of trade URL link, starting after "&token=" -->
|
||||
<SteamTradeToken type="string" value="null"/>
|
||||
|
||||
<!-- This switch defines if bot should send you trade offer with all farmed cards on regular basis -->
|
||||
<!-- This can become useful if you have lots of games to farm and you don't want to wait for all of them to be farmed -->
|
||||
<!-- However, if you have many bots running, it may become a bit spammy/intrusive, so it's not enabled by default -->
|
||||
<!-- Remember that there is also "SendOnFarmingFinished" switch above, which is far less intrusive and can be used instead -->
|
||||
<!-- This property defines how often bot should send you a trade offer, in hours -->
|
||||
<!-- For example, setting this to "24" will result in a trade offer being sent once per day (24 hours) -->
|
||||
<!-- Default value of "0" disables that feature -->
|
||||
<SendTradePeriod type="byte" value="0"/>
|
||||
|
||||
<!-- This is comma-separated list of IDs that should not be considered for farming -->
|
||||
<!-- Default value includes appIDs that are wrongly appearing on the profile, e.g. Summer Sale, Winter Sale or Monster Summer Game -->
|
||||
<!-- In addition to blacklist defined here, ASF also has global blacklist, which is being updated on as-needed basis, so you don't need to update this entry -->
|
||||
<!-- You probably don't want to change anything here -->
|
||||
<Blacklist type="HashSet(uint)" value="303700,335590,368020,425280"/>
|
||||
|
||||
<!-- This is comma-separated list of IDs that should be played when ASF is idle -->
|
||||
<!-- Idle ASF means that ASF is currently not doing anything - account has nothing to farm, it's only periodically checked for new cards available for dropping -->
|
||||
<!-- If you want from ASF to be "playing" specific game(s) instead, you can specify them here. Remember that given account should already own specified appIDs -->
|
||||
<!-- By default ASF is not playing any games when in idle state. You can change it below, remember to remove "0" appID from the collection -->
|
||||
<GamesPlayedWhileIdle type="HashSet(uint)" value="0"/>
|
||||
|
||||
<!-- This switch enables statistics for me - bot will join Archi's SC Farm group and chat on steam -->
|
||||
<!-- Consider leaving it at "true", this way I can check how many running bots are active -->
|
||||
<!-- Such information directly affects my willings to work on the project, as I can see how many users are actually using it -->
|
||||
<!-- So if you want to see new versions coming up, bugs being fixed, and new features getting implemented, consider leaving it at "true" -->
|
||||
<!-- You can find the group, along with all the statistics here: http://steamcommunity.com/groups/ascfarm -->
|
||||
<Statistics type="bool" value="true"/>
|
||||
</configuration>
|
||||
24
ArchiSteamFarm/config/minimal.json
Normal file
24
ArchiSteamFarm/config/minimal.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"Enabled": false,
|
||||
"StartOnLaunch": true,
|
||||
"SteamLogin": null,
|
||||
"SteamPassword": null,
|
||||
"SteamParentalPIN": "0",
|
||||
"SteamApiKey": null,
|
||||
"SteamMasterID": 0,
|
||||
"SteamMasterClanID": 0,
|
||||
"CardDropsRestricted": false,
|
||||
"FarmOffline": false,
|
||||
"HandleOfflineMessages": false,
|
||||
"ForwardKeysToOtherBots": false,
|
||||
"DistributeKeys": false,
|
||||
"UseAsfAsMobileAuthenticator": false,
|
||||
"ShutdownOnFarmingFinished": false,
|
||||
"SendOnFarmingFinished": false,
|
||||
"SteamTradeToken": null,
|
||||
"SendTradePeriod": 0,
|
||||
"GamesPlayedWhileIdle": [
|
||||
0
|
||||
],
|
||||
"Statistics": true
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<!-- This is minimalistic config "just to make ASF work". For full-fledged config, please take a look at example.xml -->
|
||||
<!-- Full-fledged config includes some neat features such as offline farming or cards farming algorithm selection -->
|
||||
<!-- ASF will use default values for missing properties, check example.xml to see all of them -->
|
||||
<Enabled type="bool" value="false"/>
|
||||
<SteamLogin type="string" value="null"/>
|
||||
<SteamPassword type="string" value="null"/>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user