mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-18 15:30:30 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33df54365a | ||
|
|
4a6ae3064a | ||
|
|
84857e060b | ||
|
|
3311f2a703 | ||
|
|
5666ebf891 | ||
|
|
0ded4f3b80 | ||
|
|
4c9354308c | ||
|
|
0bcf2f35b7 | ||
|
|
b93d5187d6 | ||
|
|
1426922854 | ||
|
|
d8925f9409 | ||
|
|
4302029bee | ||
|
|
01a7800a44 | ||
|
|
ab3cf5b8d0 | ||
|
|
2ab9741fa8 | ||
|
|
f1c3339764 | ||
|
|
da01d4eab3 | ||
|
|
cd9bd5f0dd | ||
|
|
2602ac3623 | ||
|
|
2fe8db712e | ||
|
|
687b20bcb5 | ||
|
|
23d9dcffe7 | ||
|
|
42623ffb5a | ||
|
|
214003edbd | ||
|
|
c21333b6e9 | ||
|
|
630f1c008c |
10
.travis.yml
Normal file
10
.travis.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
sudo: false
|
||||
language: csharp
|
||||
solution: ArchiSteamFarm.sln
|
||||
|
||||
git:
|
||||
depth: 10
|
||||
|
||||
mono:
|
||||
- weekly
|
||||
- latest
|
||||
@@ -160,19 +160,19 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mkdir "$(SolutionDir)out" "$(SolutionDir)out\config"
|
||||
mkdir "$(SolutionDir)out\config"
|
||||
copy "$(TargetDir)config\ASF.json" "$(SolutionDir)out\config"
|
||||
copy "$(TargetDir)config\example.json" "$(SolutionDir)out\config"
|
||||
copy "$(TargetDir)config\minimal.json" "$(SolutionDir)out\config"
|
||||
"$(SolutionDir)tools\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
"$(SolutionDir)tools\ILRepack\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
del "$(SolutionDir)out\ASF.exe.config"
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mkdir -p "$(SolutionDir)out" "$(SolutionDir)out/config"
|
||||
mkdir -p "$(SolutionDir)out/config"
|
||||
cp "$(TargetDir)config/ASF.json" "$(SolutionDir)out/config"
|
||||
cp "$(TargetDir)config/example.json" "$(SolutionDir)out/config"
|
||||
cp "$(TargetDir)config/minimal.json" "$(SolutionDir)out/config"
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
rm "$(SolutionDir)out/ASF.exe.config"
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -255,14 +255,6 @@ namespace ArchiSteamFarm {
|
||||
Start().Forget();
|
||||
}
|
||||
|
||||
internal bool IsMaster(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return steamID == BotConfig.SteamMasterID || IsOwner(steamID);
|
||||
}
|
||||
|
||||
internal async Task AcceptConfirmations(Confirmation.ConfirmationType allowedConfirmationType = Confirmation.ConfirmationType.Unknown) {
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
return;
|
||||
@@ -308,7 +300,6 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
await Stop().ConfigureAwait(false);
|
||||
await Start().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -318,7 +309,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (BotConfig.ShutdownOnFarmingFinished) {
|
||||
await Shutdown().ConfigureAwait(false);
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,8 +334,12 @@ namespace ArchiSteamFarm {
|
||||
return ResponseExit(steamID);
|
||||
case "!farm":
|
||||
return ResponseFarm(steamID);
|
||||
case "!help":
|
||||
return ResponseHelp(steamID);
|
||||
case "!loot":
|
||||
return await ResponseSendTrade(steamID).ConfigureAwait(false);
|
||||
case "!pause":
|
||||
return await ResponsePause(steamID).ConfigureAwait(false);
|
||||
case "!rejoinchat":
|
||||
return ResponseRejoinChat(steamID);
|
||||
case "!restart":
|
||||
@@ -354,7 +349,7 @@ namespace ArchiSteamFarm {
|
||||
case "!statusall":
|
||||
return ResponseStatusAll(steamID);
|
||||
case "!stop":
|
||||
return await ResponseStop(steamID).ConfigureAwait(false);
|
||||
return ResponseStop(steamID);
|
||||
case "!update":
|
||||
return await ResponseUpdate(steamID).ConfigureAwait(false);
|
||||
default:
|
||||
@@ -377,6 +372,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
case "!farm":
|
||||
return ResponseFarm(steamID, args[1]);
|
||||
case "!help":
|
||||
return ResponseHelp(steamID, args[1]);
|
||||
case "!loot":
|
||||
return await ResponseSendTrade(steamID, args[1]).ConfigureAwait(false);
|
||||
case "!owns":
|
||||
@@ -385,6 +382,8 @@ namespace ArchiSteamFarm {
|
||||
} else {
|
||||
return await ResponseOwns(steamID, BotName, args[1]).ConfigureAwait(false);
|
||||
}
|
||||
case "!pause":
|
||||
return await ResponsePause(steamID, args[1]).ConfigureAwait(false);
|
||||
case "!play":
|
||||
if (args.Length > 2) {
|
||||
return await ResponsePlay(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||
@@ -402,7 +401,7 @@ namespace ArchiSteamFarm {
|
||||
case "!status":
|
||||
return ResponseStatus(steamID, args[1]);
|
||||
case "!stop":
|
||||
return await ResponseStop(steamID, args[1]).ConfigureAwait(false);
|
||||
return ResponseStop(steamID, args[1]);
|
||||
default:
|
||||
return ResponseUnknown(steamID);
|
||||
}
|
||||
@@ -410,48 +409,37 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task Start() {
|
||||
if (SteamClient.IsConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!KeepRunning) {
|
||||
KeepRunning = true;
|
||||
Task.Run(() => HandleCallbacks()).Forget();
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Starting...", BotName);
|
||||
|
||||
// 2FA tokens are expiring soon, use limiter only when we don't have any pending
|
||||
if (TwoFactorAuth == null) {
|
||||
await Program.LimitSteamRequestsAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Starting...", BotName);
|
||||
SteamClient.Connect();
|
||||
}
|
||||
|
||||
private async Task Stop() {
|
||||
if (!SteamClient.IsConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
private void Stop() {
|
||||
Logging.LogGenericInfo("Stopping...", BotName);
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && SteamClient.IsConnected; i++) {
|
||||
SteamClient.Disconnect();
|
||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
||||
}
|
||||
KeepRunning = false;
|
||||
|
||||
if (SteamClient.IsConnected) {
|
||||
Logging.LogGenericWarning("Could not stop this bot instance!", BotName);
|
||||
} else {
|
||||
Logging.LogGenericInfo("Stopped!", BotName);
|
||||
SteamClient.Disconnect();
|
||||
}
|
||||
|
||||
Program.OnBotShutdown();
|
||||
}
|
||||
|
||||
private async Task Shutdown() {
|
||||
KeepRunning = false;
|
||||
await Stop().ConfigureAwait(false);
|
||||
Program.OnBotShutdown();
|
||||
private bool IsMaster(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return steamID == BotConfig.SteamMasterID || IsOwner(steamID);
|
||||
}
|
||||
|
||||
private void ImportAuthenticator(string maFilePath) {
|
||||
@@ -485,7 +473,7 @@ namespace ArchiSteamFarm {
|
||||
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
||||
switch (loginResult) {
|
||||
case LoginResult.Need2FA:
|
||||
userLogin.TwoFactorCode = Program.GetUserInput(BotName, Program.EUserInputType.TwoFactorAuthentication);
|
||||
userLogin.TwoFactorCode = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
||||
@@ -503,19 +491,42 @@ namespace ArchiSteamFarm {
|
||||
BotDatabase.SteamGuardAccount.Session = userLogin.Session;
|
||||
|
||||
if (string.IsNullOrEmpty(BotDatabase.SteamGuardAccount.DeviceID)) {
|
||||
BotDatabase.SteamGuardAccount.DeviceID = Program.GetUserInput(BotName, Program.EUserInputType.DeviceID);
|
||||
BotDatabase.SteamGuardAccount.DeviceID = Program.GetUserInput(Program.EUserInputType.DeviceID, BotName);
|
||||
}
|
||||
|
||||
BotDatabase.Save();
|
||||
Logging.LogGenericInfo("Successfully finished importing mobile authenticator!", BotName);
|
||||
}
|
||||
|
||||
private string ResponseStatus(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
private async Task<string> ResponsePause(ulong steamID) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (CardsFarmer.ManualMode) {
|
||||
await CardsFarmer.SwitchToManualMode(false).ConfigureAwait(false);
|
||||
return "Automatic farming is enabled again!";
|
||||
} else {
|
||||
await CardsFarmer.SwitchToManualMode(true).ConfigureAwait(false);
|
||||
return "Automatic farming is now stopped!";
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<string> ResponsePause(ulong steamID, string botName) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(botName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bot bot;
|
||||
if (!Bots.TryGetValue(botName, out bot)) {
|
||||
return "Couldn't find any bot named " + botName + "!";
|
||||
}
|
||||
|
||||
return await bot.ResponsePause(steamID).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private string ResponseStatus(ulong steamID) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -567,11 +578,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> ResponseSendTrade(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -608,11 +615,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private string Response2FA(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -638,11 +641,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private string Response2FAOff(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -671,11 +670,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> Response2FAOK(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -714,11 +709,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private string ResponseFarm(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -743,12 +734,29 @@ namespace ArchiSteamFarm {
|
||||
return bot.ResponseFarm(steamID);
|
||||
}
|
||||
|
||||
private async Task<string> ResponseRedeem(ulong steamID, string message, bool validate) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(message)) {
|
||||
private string ResponseHelp(ulong steamID) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
return "https://github.com/" + Program.GithubRepo + "/wiki/Commands";
|
||||
}
|
||||
|
||||
private static string ResponseHelp(ulong steamID, string botName) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(botName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bot bot;
|
||||
if (!Bots.TryGetValue(botName, out bot)) {
|
||||
return "Couldn't find any bot named " + botName + "!";
|
||||
}
|
||||
|
||||
return bot.ResponseHelp(steamID);
|
||||
}
|
||||
|
||||
private async Task<string> ResponseRedeem(ulong steamID, string message, bool validate) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(message) || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -931,11 +939,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> ResponseAddLicense(ulong steamID, HashSet<uint> gameIDs) {
|
||||
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -984,11 +988,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> ResponseOwns(ulong steamID, string games) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(games)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(games) || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1040,20 +1040,19 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> ResponsePlay(ulong steamID, HashSet<uint> gameIDs) {
|
||||
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (gameIDs.Contains(0)) {
|
||||
if (await CardsFarmer.SwitchToManualMode(false).ConfigureAwait(false)) {
|
||||
if (CardsFarmer.ManualMode) {
|
||||
ResetGamesPlayed();
|
||||
await CardsFarmer.SwitchToManualMode(false).ConfigureAwait(false);
|
||||
}
|
||||
} else {
|
||||
await CardsFarmer.SwitchToManualMode(true).ConfigureAwait(false);
|
||||
if (!CardsFarmer.ManualMode) {
|
||||
await CardsFarmer.SwitchToManualMode(true).ConfigureAwait(false);
|
||||
}
|
||||
ArchiHandler.PlayGames(gameIDs);
|
||||
}
|
||||
|
||||
@@ -1089,11 +1088,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<string> ResponseStart(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1118,12 +1113,8 @@ namespace ArchiSteamFarm {
|
||||
return await bot.ResponseStart(steamID).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<string> ResponseStop(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
private string ResponseStop(ulong steamID) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1131,11 +1122,11 @@ namespace ArchiSteamFarm {
|
||||
return "That bot instance is already inactive!";
|
||||
}
|
||||
|
||||
await Shutdown().ConfigureAwait(false);
|
||||
Stop();
|
||||
return "Done!";
|
||||
}
|
||||
|
||||
private static async Task<string> ResponseStop(ulong steamID, string botName) {
|
||||
private static string ResponseStop(ulong steamID, string botName) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(botName)) {
|
||||
return null;
|
||||
}
|
||||
@@ -1145,15 +1136,11 @@ namespace ArchiSteamFarm {
|
||||
return "Couldn't find any bot named " + botName + "!";
|
||||
}
|
||||
|
||||
return await bot.ResponseStop(steamID).ConfigureAwait(false);
|
||||
return bot.ResponseStop(steamID);
|
||||
}
|
||||
|
||||
private string ResponseUnknown(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IsMaster(steamID)) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1214,7 +1201,7 @@ namespace ArchiSteamFarm {
|
||||
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
||||
switch (loginResult) {
|
||||
case LoginResult.NeedEmail:
|
||||
userLogin.EmailCode = Program.GetUserInput(BotName, Program.EUserInputType.SteamGuard);
|
||||
userLogin.EmailCode = Program.GetUserInput(Program.EUserInputType.SteamGuard, BotName);
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
||||
@@ -1228,7 +1215,7 @@ namespace ArchiSteamFarm {
|
||||
while ((linkResult = authenticatorLinker.AddAuthenticator()) != AuthenticatorLinker.LinkResult.AwaitingFinalization) {
|
||||
switch (linkResult) {
|
||||
case AuthenticatorLinker.LinkResult.MustProvidePhoneNumber:
|
||||
authenticatorLinker.PhoneNumber = Program.GetUserInput(BotName, Program.EUserInputType.PhoneNumber);
|
||||
authenticatorLinker.PhoneNumber = Program.GetUserInput(Program.EUserInputType.PhoneNumber, BotName);
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericError("Unhandled situation: " + linkResult, BotName);
|
||||
@@ -1238,7 +1225,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
BotDatabase.SteamGuardAccount = authenticatorLinker.LinkedAccount;
|
||||
|
||||
AuthenticatorLinker.FinalizeResult finalizeResult = authenticatorLinker.FinalizeAddAuthenticator(Program.GetUserInput(BotName, Program.EUserInputType.SMS));
|
||||
AuthenticatorLinker.FinalizeResult finalizeResult = authenticatorLinker.FinalizeAddAuthenticator(Program.GetUserInput(Program.EUserInputType.SMS, BotName));
|
||||
if (finalizeResult != AuthenticatorLinker.FinalizeResult.Success) {
|
||||
Logging.LogGenericError("Unhandled situation: " + finalizeResult, BotName);
|
||||
DelinkMobileAuthenticator();
|
||||
@@ -1246,7 +1233,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Successfully linked ASF as new mobile authenticator for this account!", BotName);
|
||||
Program.GetUserInput(BotName, Program.EUserInputType.RevocationCode, BotDatabase.SteamGuardAccount.RevocationCode);
|
||||
Program.GetUserInput(Program.EUserInputType.RevocationCode, BotName, BotDatabase.SteamGuardAccount.RevocationCode);
|
||||
}
|
||||
|
||||
private bool DelinkMobileAuthenticator() {
|
||||
@@ -1273,11 +1260,11 @@ namespace ArchiSteamFarm {
|
||||
|
||||
private void InitializeLoginAndPassword() {
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
BotConfig.SteamLogin = Program.GetUserInput(BotName, Program.EUserInputType.Login);
|
||||
BotConfig.SteamLogin = Program.GetUserInput(Program.EUserInputType.Login, BotName);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamPassword) && string.IsNullOrEmpty(BotDatabase.LoginKey)) {
|
||||
BotConfig.SteamPassword = Program.GetUserInput(BotName, Program.EUserInputType.Password);
|
||||
BotConfig.SteamPassword = Program.GetUserInput(Program.EUserInputType.Password, BotName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1347,17 +1334,17 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Disconnected from Steam!", BotName);
|
||||
await CardsFarmer.StopFarming().ConfigureAwait(false);
|
||||
|
||||
if (!KeepRunning) {
|
||||
return;
|
||||
}
|
||||
CardsFarmer.StopFarming().Forget();
|
||||
|
||||
// If we initiated disconnect, do not attempt to reconnect
|
||||
if (callback.UserInitiated) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!KeepRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InvalidPassword) {
|
||||
InvalidPassword = false;
|
||||
if (!string.IsNullOrEmpty(BotDatabase.LoginKey)) { // InvalidPassword means usually that login key has expired, if we used it
|
||||
@@ -1369,6 +1356,12 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
} else if (LoggedInElsewhere) {
|
||||
LoggedInElsewhere = false;
|
||||
|
||||
if (Program.GlobalConfig.AccountPlayingDelay == 0) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Account is being used elsewhere, ASF will try to resume farming in " + Program.GlobalConfig.AccountPlayingDelay + " minutes...", BotName);
|
||||
await Utilities.SleepAsync(Program.GlobalConfig.AccountPlayingDelay * 60 * 1000).ConfigureAwait(false);
|
||||
}
|
||||
@@ -1390,11 +1383,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private void OnChatInvite(SteamFriends.ChatInviteCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsMaster(callback.PatronID)) {
|
||||
if (callback == null || !IsMaster(callback.PatronID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1402,20 +1391,16 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async void OnChatMsg(SteamFriends.ChatMsgCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.ChatMsgType != EChatEntryType.ChatMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsMaster(callback.ChatterID)) {
|
||||
if (callback == null || callback.ChatMsgType != EChatEntryType.ChatMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (callback.Message) {
|
||||
case "!leave":
|
||||
if (!IsMaster(callback.ChatterID)) {
|
||||
break;
|
||||
}
|
||||
|
||||
SteamFriends.LeaveChat(callback.ChatRoomID);
|
||||
break;
|
||||
default:
|
||||
@@ -1442,6 +1427,7 @@ namespace ArchiSteamFarm {
|
||||
if (!IsMaster(friend.SteamID)) {
|
||||
break;
|
||||
}
|
||||
|
||||
SteamFriends.AddFriend(friend.SteamID);
|
||||
break;
|
||||
}
|
||||
@@ -1449,11 +1435,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async void OnFriendMsg(SteamFriends.FriendMsgCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.EntryType != EChatEntryType.ChatMsg) {
|
||||
if (callback == null || callback.EntryType != EChatEntryType.ChatMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1461,19 +1443,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async void OnFriendMsgHistory(SteamFriends.FriendMsgHistoryCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.Result != EResult.OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsMaster(callback.SteamID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.Messages.Count == 0) {
|
||||
if (callback == null || callback.Result != EResult.OK || callback.Messages.Count == 0 || !IsMaster(callback.SteamID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1527,11 +1497,11 @@ namespace ArchiSteamFarm {
|
||||
|
||||
switch (callback.Result) {
|
||||
case EResult.AccountLogonDenied:
|
||||
AuthCode = Program.GetUserInput(BotConfig.SteamLogin, Program.EUserInputType.SteamGuard);
|
||||
AuthCode = Program.GetUserInput(Program.EUserInputType.SteamGuard, BotName);
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
TwoFactorAuth = Program.GetUserInput(BotConfig.SteamLogin, Program.EUserInputType.TwoFactorAuthentication);
|
||||
TwoFactorAuth = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
} else {
|
||||
TwoFactorAuth = BotDatabase.SteamGuardAccount.GenerateSteamGuardCode();
|
||||
}
|
||||
@@ -1563,7 +1533,7 @@ namespace ArchiSteamFarm {
|
||||
ResetGamesPlayed();
|
||||
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamParentalPIN)) {
|
||||
BotConfig.SteamParentalPIN = Program.GetUserInput(BotName, Program.EUserInputType.SteamParentalPIN);
|
||||
BotConfig.SteamParentalPIN = Program.GetUserInput(Program.EUserInputType.SteamParentalPIN, BotName);
|
||||
}
|
||||
|
||||
if (!await ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN).ConfigureAwait(false)) {
|
||||
@@ -1601,7 +1571,7 @@ namespace ArchiSteamFarm {
|
||||
break;
|
||||
default: // Unexpected result, shutdown immediately
|
||||
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result, BotName);
|
||||
await Shutdown().ConfigureAwait(false);
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1671,7 +1641,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (checkTrades) {
|
||||
Trading.CheckTrades();
|
||||
Trading.CheckTrades().Forget();
|
||||
}
|
||||
|
||||
if (markInventory && BotConfig.DismissInventoryNotifications) {
|
||||
|
||||
@@ -42,7 +42,9 @@ namespace ArchiSteamFarm {
|
||||
private readonly Bot Bot;
|
||||
private readonly Timer Timer;
|
||||
|
||||
private volatile bool ManualMode, NowFarming;
|
||||
internal bool ManualMode { get; private set; }
|
||||
|
||||
private bool NowFarming;
|
||||
|
||||
internal CardsFarmer(Bot bot) {
|
||||
if (bot == null) {
|
||||
@@ -61,9 +63,9 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<bool> SwitchToManualMode(bool manualMode) {
|
||||
internal async Task SwitchToManualMode(bool manualMode) {
|
||||
if (ManualMode == manualMode) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
ManualMode = manualMode;
|
||||
@@ -75,8 +77,6 @@ namespace ArchiSteamFarm {
|
||||
Logging.LogGenericInfo("Now running in Automatic Farming mode", Bot.BotName);
|
||||
StartFarming().Forget();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal async Task StartFarming() {
|
||||
@@ -113,7 +113,6 @@ namespace ArchiSteamFarm {
|
||||
uint appID = gamesToFarmSolo.First();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
farmedSomething = true;
|
||||
Logging.LogGenericInfo("Done farming: " + appID, Bot.BotName);
|
||||
gamesToFarmSolo.Remove(appID);
|
||||
gamesToFarmSolo.TrimExcess();
|
||||
} else {
|
||||
@@ -122,7 +121,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (FarmMultiple(GamesToFarm)) {
|
||||
if (FarmMultiple()) {
|
||||
Logging.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Keys), Bot.BotName);
|
||||
} else {
|
||||
NowFarming = false;
|
||||
@@ -133,10 +132,9 @@ namespace ArchiSteamFarm {
|
||||
} else { // If we have unrestricted card drops, we use simple algorithm
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Simple", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
uint appID = GetAnyGameToFarm(GamesToFarm);
|
||||
uint appID = GamesToFarm.Keys.FirstOrDefault();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
farmedSomething = true;
|
||||
Logging.LogGenericInfo("Done farming: " + appID, Bot.BotName);
|
||||
} else {
|
||||
NowFarming = false;
|
||||
return;
|
||||
@@ -208,14 +206,6 @@ namespace ArchiSteamFarm {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static uint GetAnyGameToFarm(ConcurrentDictionary<uint, float> gamesToFarm) {
|
||||
if (gamesToFarm == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gamesToFarm.Keys.FirstOrDefault();
|
||||
}
|
||||
|
||||
private async Task<bool> IsAnythingToFarm() {
|
||||
if (NowFarming) {
|
||||
return true;
|
||||
@@ -302,13 +292,13 @@ namespace ArchiSteamFarm {
|
||||
HtmlNode timeNode = htmlNode.SelectSingleNode(".//div[@class='badge_title_stats_playtime']");
|
||||
if (timeNode == null) {
|
||||
Logging.LogNullError("timeNode", Bot.BotName);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
string hoursString = timeNode.InnerText;
|
||||
if (string.IsNullOrEmpty(hoursString)) {
|
||||
Logging.LogNullError("hoursString", Bot.BotName);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
hoursString = Regex.Match(hoursString, @"[0-9\.,]+").Value;
|
||||
@@ -364,24 +354,27 @@ namespace ArchiSteamFarm {
|
||||
return !htmlNode.InnerText.Contains("No card drops");
|
||||
}
|
||||
|
||||
private bool FarmMultiple(ConcurrentDictionary<uint, float> appIDs) {
|
||||
if (appIDs.Count == 0) {
|
||||
private bool FarmMultiple() {
|
||||
if (GamesToFarm.Count == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
float maxHour = 0;
|
||||
foreach (float hour in appIDs.Values) {
|
||||
if (hour > maxHour) {
|
||||
maxHour = hour;
|
||||
foreach (KeyValuePair<uint, float> game in GamesToFarm) {
|
||||
CurrentGamesFarming.Add(game.Key);
|
||||
if (game.Value > maxHour) {
|
||||
maxHour = game.Value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (uint appID in appIDs.Keys) {
|
||||
CurrentGamesFarming.Add(appID);
|
||||
if (maxHour >= 2) {
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Now farming: " + string.Join(", ", appIDs.Keys), Bot.BotName);
|
||||
if (FarmHours(maxHour, appIDs.Keys)) {
|
||||
Logging.LogGenericInfo("Now farming: " + string.Join(", ", CurrentGamesFarming), Bot.BotName);
|
||||
if (FarmHours(maxHour, CurrentGamesFarming)) {
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
return true;
|
||||
@@ -403,8 +396,11 @@ namespace ArchiSteamFarm {
|
||||
if (await Farm(appID).ConfigureAwait(false)) {
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
float ignored;
|
||||
GamesToFarm.TryRemove(appID, out ignored);
|
||||
float hours;
|
||||
if (GamesToFarm.TryRemove(appID, out hours)) {
|
||||
TimeSpan timeSpan = TimeSpan.FromHours(hours);
|
||||
Logging.LogGenericInfo("Done farming: " + appID + " after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!", Bot.BotName);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
CurrentGamesFarming.Clear();
|
||||
@@ -428,6 +424,11 @@ namespace ArchiSteamFarm {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't forget to update our GamesToFarm hours
|
||||
float timePlayed = Program.GlobalConfig.FarmingDelay / 60.0F;
|
||||
GamesToFarm[appID] += timePlayed;
|
||||
|
||||
keepFarming = await ShouldFarm(appID).ConfigureAwait(false);
|
||||
Logging.LogGenericInfo("Still farming: " + appID, Bot.BotName);
|
||||
}
|
||||
@@ -437,7 +438,7 @@ namespace ArchiSteamFarm {
|
||||
return success;
|
||||
}
|
||||
|
||||
private bool FarmHours(float maxHour, ICollection<uint> appIDs) {
|
||||
private bool FarmHours(float maxHour, HashSet<uint> appIDs) {
|
||||
if (maxHour < 0 || appIDs == null || appIDs.Count == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -450,7 +451,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
bool success = true;
|
||||
while (maxHour < 2) {
|
||||
Logging.LogGenericInfo("Still farming: " + string.Join(", ", appIDs), Bot.BotName);
|
||||
if (FarmResetEvent.WaitOne(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
|
||||
success = false;
|
||||
break;
|
||||
@@ -458,15 +458,12 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// Don't forget to update our GamesToFarm hours
|
||||
float timePlayed = Program.GlobalConfig.FarmingDelay / 60.0F;
|
||||
foreach (KeyValuePair<uint, float> gameToFarm in GamesToFarm) {
|
||||
if (!appIDs.Contains(gameToFarm.Key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GamesToFarm[gameToFarm.Key] = gameToFarm.Value + timePlayed;
|
||||
foreach (uint appID in appIDs) {
|
||||
GamesToFarm[appID] += timePlayed;
|
||||
}
|
||||
|
||||
maxHour += timePlayed;
|
||||
Logging.LogGenericInfo("Still farming: " + string.Join(", ", appIDs), Bot.BotName);
|
||||
}
|
||||
|
||||
Bot.ResetGamesPlayed();
|
||||
|
||||
@@ -36,6 +36,13 @@ namespace ArchiSteamFarm {
|
||||
Experimental
|
||||
}
|
||||
|
||||
private const byte DefaultMaxFarmingTime = 10;
|
||||
private const byte DefaultFarmingDelay = 5;
|
||||
private const byte DefaultHttpTimeout = 60;
|
||||
private const ushort DefaultWCFPort = 1242;
|
||||
|
||||
private static readonly ProtocolType DefaultSteamProtocol = ProtocolType.Tcp;
|
||||
|
||||
// This is hardcoded blacklist which should not be possible to change
|
||||
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 425280 };
|
||||
|
||||
@@ -49,19 +56,19 @@ namespace ArchiSteamFarm {
|
||||
internal EUpdateChannel UpdateChannel { get; private set; } = EUpdateChannel.Stable;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal ProtocolType SteamProtocol { get; private set; } = ProtocolType.Tcp;
|
||||
internal ProtocolType SteamProtocol { get; private set; } = DefaultSteamProtocol;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal ulong SteamOwnerID { get; private set; } = 0;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal byte MaxFarmingTime { get; private set; } = 10;
|
||||
internal byte MaxFarmingTime { get; private set; } = DefaultMaxFarmingTime;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal byte IdleFarmingPeriod { get; private set; } = 3;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal byte FarmingDelay { get; private set; } = 5;
|
||||
internal byte FarmingDelay { get; private set; } = DefaultFarmingDelay;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal byte AccountPlayingDelay { get; private set; } = 5;
|
||||
@@ -76,13 +83,13 @@ namespace ArchiSteamFarm {
|
||||
internal bool ForceHttp { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal byte HttpTimeout { get; private set; } = 60;
|
||||
internal byte HttpTimeout { get; private set; } = DefaultHttpTimeout;
|
||||
|
||||
[JsonProperty]
|
||||
internal string WCFHostname { get; set; } = "localhost";
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal string WCFHostname { get; private set; } = "localhost";
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal ushort WCFPort { get; private set; } = 1242;
|
||||
internal ushort WCFPort { get; private set; } = DefaultWCFPort;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool LogToFile { get; private set; } = true;
|
||||
@@ -112,17 +119,39 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
// SK2 supports only TCP and UDP steam protocols
|
||||
// Make sure that user can't screw this up
|
||||
// Ensure that user can't screw this up
|
||||
switch (globalConfig.SteamProtocol) {
|
||||
case ProtocolType.Tcp:
|
||||
case ProtocolType.Udp:
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ", default TCP protocol will be used instead");
|
||||
globalConfig.SteamProtocol = ProtocolType.Tcp;
|
||||
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ". Value of " + DefaultSteamProtocol + " will be used instead");
|
||||
globalConfig.SteamProtocol = DefaultSteamProtocol;
|
||||
break;
|
||||
}
|
||||
|
||||
// User might not know what he's doing
|
||||
// Ensure that he can't screw core ASF variables
|
||||
if (globalConfig.MaxFarmingTime == 0) {
|
||||
Logging.LogGenericWarning("Configured MaxFarmingTime is invalid: " + globalConfig.MaxFarmingTime + ". Value of " + DefaultMaxFarmingTime + " will be used instead");
|
||||
globalConfig.MaxFarmingTime = DefaultMaxFarmingTime;
|
||||
}
|
||||
|
||||
if (globalConfig.FarmingDelay == 0) {
|
||||
Logging.LogGenericWarning("Configured FarmingDelay is invalid: " + globalConfig.FarmingDelay + ". Value of " + DefaultFarmingDelay + " will be used instead");
|
||||
globalConfig.FarmingDelay = DefaultFarmingDelay;
|
||||
}
|
||||
|
||||
if (globalConfig.HttpTimeout == 0) {
|
||||
Logging.LogGenericWarning("Configured HttpTimeout is invalid: " + globalConfig.HttpTimeout + ". Value of " + DefaultHttpTimeout + " will be used instead");
|
||||
globalConfig.HttpTimeout = DefaultHttpTimeout;
|
||||
}
|
||||
|
||||
if (globalConfig.WCFPort == 0) {
|
||||
Logging.LogGenericWarning("Configured WCFPort is invalid: " + globalConfig.WCFPort + ". Value of " + DefaultWCFPort + " will be used instead");
|
||||
globalConfig.WCFPort = DefaultWCFPort;
|
||||
}
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace ArchiSteamFarm {
|
||||
SteamParentalPIN,
|
||||
RevocationCode,
|
||||
TwoFactorAuthentication,
|
||||
WCFHostname
|
||||
}
|
||||
|
||||
internal enum EMode : byte {
|
||||
@@ -58,10 +59,11 @@ namespace ArchiSteamFarm {
|
||||
internal const string ConfigDirectory = "config";
|
||||
internal const string DebugDirectory = "debug";
|
||||
internal const string LogFile = "log.txt";
|
||||
internal const string GithubRepo = "JustArchi/ArchiSteamFarm";
|
||||
internal const string GlobalConfigFile = ASF + ".json";
|
||||
internal const string GlobalDatabaseFile = ASF + ".db";
|
||||
|
||||
private const string GithubReleaseURL = "https://api.github.com/repos/JustArchi/ArchiSteamFarm/releases"; // GitHub API is HTTPS only
|
||||
private const string GithubReleaseURL = "https://api.github.com/repos/" + GithubRepo + "/releases"; // GitHub API is HTTPS only
|
||||
|
||||
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
|
||||
internal static readonly Version Version = Assembly.GetName().Version;
|
||||
@@ -262,7 +264,7 @@ namespace ArchiSteamFarm {
|
||||
}).Forget();
|
||||
}
|
||||
|
||||
internal static string GetUserInput(string botLogin, EUserInputType userInputType, string extraInformation = null) {
|
||||
internal static string GetUserInput(EUserInputType userInputType, string botName = null, string extraInformation = null) {
|
||||
if (userInputType == EUserInputType.Unknown) {
|
||||
return null;
|
||||
}
|
||||
@@ -272,36 +274,38 @@ namespace ArchiSteamFarm {
|
||||
ConsoleIsBusy = true;
|
||||
switch (userInputType) {
|
||||
case EUserInputType.DeviceID:
|
||||
Console.Write("<" + botLogin + "> Please enter your Device ID (including \"android:\"): ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your Device ID (including \"android:\"): ");
|
||||
break;
|
||||
case EUserInputType.Login:
|
||||
Console.Write("<" + botLogin + "> Please enter your login: ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your login: ");
|
||||
break;
|
||||
case EUserInputType.Password:
|
||||
Console.Write("<" + botLogin + "> Please enter your password: ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your password: ");
|
||||
break;
|
||||
case EUserInputType.PhoneNumber:
|
||||
Console.Write("<" + botLogin + "> Please enter your full phone number (e.g. +1234567890): ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your full phone number (e.g. +1234567890): ");
|
||||
break;
|
||||
case EUserInputType.SMS:
|
||||
Console.Write("<" + botLogin + "> Please enter SMS code sent on your mobile: ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter SMS code sent on your mobile: ");
|
||||
break;
|
||||
case EUserInputType.SteamGuard:
|
||||
Console.Write("<" + botLogin + "> Please enter the auth code sent to your email: ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter the auth code sent to your email: ");
|
||||
break;
|
||||
case EUserInputType.SteamParentalPIN:
|
||||
Console.Write("<" + botLogin + "> Please enter steam parental PIN: ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter steam parental PIN: ");
|
||||
break;
|
||||
case EUserInputType.RevocationCode:
|
||||
Console.WriteLine("<" + botLogin + "> PLEASE WRITE DOWN YOUR REVOCATION CODE: " + extraInformation);
|
||||
Console.WriteLine("<" + botLogin + "> THIS IS THE ONLY WAY TO NOT GET LOCKED OUT OF YOUR ACCOUNT!");
|
||||
Console.Write("<" + botLogin + "> Hit enter once ready...");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "PLEASE WRITE DOWN YOUR REVOCATION CODE: " + extraInformation);
|
||||
Console.Write("Hit enter once ready...");
|
||||
break;
|
||||
case EUserInputType.TwoFactorAuthentication:
|
||||
Console.Write("<" + botLogin + "> Please enter your 2 factor auth code from your authenticator app: ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your 2 factor auth code from your authenticator app: ");
|
||||
break;
|
||||
case EUserInputType.WCFHostname:
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your WCF hostname: ");
|
||||
break;
|
||||
default:
|
||||
Console.Write("<" + botLogin + "> Please enter not documented yet value of \"" + userInputType + "\": ");
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter not documented yet value of \"" + userInputType + "\": ");
|
||||
break;
|
||||
}
|
||||
result = Console.ReadLine();
|
||||
|
||||
@@ -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("2.0.1.7")]
|
||||
[assembly: AssemblyFileVersion("2.0.1.7")]
|
||||
[assembly: AssemblyVersion("2.0.2.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.0")]
|
||||
|
||||
@@ -35,9 +35,9 @@ namespace ArchiSteamFarm {
|
||||
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1);
|
||||
|
||||
private readonly Bot Bot;
|
||||
private readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1);
|
||||
private readonly SemaphoreSlim TradesSemaphore = new SemaphoreSlim(1);
|
||||
|
||||
private volatile byte ParsingTasks = 0;
|
||||
private byte ParsingTasks = 0;
|
||||
|
||||
internal static async Task LimitInventoryRequestsAsync() {
|
||||
await InventorySemaphore.WaitAsync().ConfigureAwait(false);
|
||||
@@ -55,18 +55,27 @@ namespace ArchiSteamFarm {
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
internal async void CheckTrades() {
|
||||
if (ParsingTasks >= 2) {
|
||||
internal async Task CheckTrades() {
|
||||
bool shouldRun = false;
|
||||
lock (TradesSemaphore) {
|
||||
if (ParsingTasks < 2) {
|
||||
ParsingTasks++;
|
||||
shouldRun = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
ParsingTasks++;
|
||||
await TradesSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
await Semaphore.WaitAsync().ConfigureAwait(false);
|
||||
await ParseActiveTrades().ConfigureAwait(false);
|
||||
Semaphore.Release();
|
||||
lock (TradesSemaphore) {
|
||||
ParsingTasks--;
|
||||
}
|
||||
|
||||
ParsingTasks--;
|
||||
TradesSemaphore.Release();
|
||||
}
|
||||
|
||||
private async Task ParseActiveTrades() {
|
||||
|
||||
@@ -42,6 +42,10 @@ namespace ArchiSteamFarm {
|
||||
private Client Client;
|
||||
|
||||
internal static void Init() {
|
||||
if (string.IsNullOrEmpty(Program.GlobalConfig.WCFHostname)) {
|
||||
Program.GlobalConfig.WCFHostname = Program.GetUserInput(Program.EUserInputType.WCFHostname);
|
||||
}
|
||||
|
||||
URL = "http://" + Program.GlobalConfig.WCFHostname + ":" + Program.GlobalConfig.WCFPort + "/ASF";
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +214,16 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
if (responseMessage == null || !responseMessage.IsSuccessStatusCode) {
|
||||
if (responseMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!responseMessage.IsSuccessStatusCode) {
|
||||
if (Program.GlobalConfig.Debug) {
|
||||
Logging.LogGenericError("Request: " + request + "failed!");
|
||||
Logging.LogGenericError("Status code: " + responseMessage.StatusCode);
|
||||
Logging.LogGenericError("Content: " + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ using System.IO;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
internal class ASFConfig {
|
||||
internal static List<ASFConfig> ASFConfigs = new List<ASFConfig>();
|
||||
internal static HashSet<ASFConfig> ASFConfigs = new HashSet<ASFConfig>();
|
||||
|
||||
internal string FilePath { get; set; }
|
||||
|
||||
@@ -37,9 +37,8 @@ namespace ConfigGenerator {
|
||||
ASFConfigs.Add(this);
|
||||
}
|
||||
|
||||
protected ASFConfig(string filePath) {
|
||||
protected ASFConfig(string filePath) : this() {
|
||||
FilePath = filePath;
|
||||
ASFConfigs.Add(this);
|
||||
}
|
||||
|
||||
internal virtual void Save() {
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
@@ -111,13 +110,11 @@
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mkdir "$(SolutionDir)out" "$(SolutionDir)out\config"
|
||||
"$(SolutionDir)tools\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
"$(SolutionDir)tools\ILRepack\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
del "$(SolutionDir)out\ASF-GUI.exe.config"
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mkdir -p "$(SolutionDir)out" "$(SolutionDir)out/config"
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
rm "$(SolutionDir)out/ASF-GUI.exe.config"
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
internal static class Debugging {
|
||||
#if DEBUG
|
||||
|
||||
@@ -27,6 +27,7 @@ using System.Windows.Forms;
|
||||
namespace ConfigGenerator {
|
||||
internal sealed class EnhancedPropertyGrid : PropertyGrid {
|
||||
private ASFConfig ASFConfig;
|
||||
|
||||
internal EnhancedPropertyGrid(ASFConfig config) : base() {
|
||||
if (config == null) {
|
||||
return;
|
||||
|
||||
@@ -36,6 +36,13 @@ namespace ConfigGenerator {
|
||||
Experimental
|
||||
}
|
||||
|
||||
private const byte DefaultMaxFarmingTime = 10;
|
||||
private const byte DefaultFarmingDelay = 5;
|
||||
private const byte DefaultHttpTimeout = 60;
|
||||
private const ushort DefaultWCFPort = 1242;
|
||||
|
||||
private static readonly ProtocolType DefaultSteamProtocol = ProtocolType.Tcp;
|
||||
|
||||
// This is hardcoded blacklist which should not be possible to change
|
||||
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 425280 };
|
||||
|
||||
@@ -49,19 +56,19 @@ namespace ConfigGenerator {
|
||||
public EUpdateChannel UpdateChannel { get; set; } = EUpdateChannel.Stable;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public ProtocolType SteamProtocol { get; set; } = ProtocolType.Tcp;
|
||||
public ProtocolType SteamProtocol { get; set; } = DefaultSteamProtocol;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public ulong SteamOwnerID { get; set; } = 0;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public byte MaxFarmingTime { get; set; } = 10;
|
||||
public byte MaxFarmingTime { get; set; } = DefaultMaxFarmingTime;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public byte IdleFarmingPeriod { get; set; } = 3;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public byte FarmingDelay { get; set; } = 5;
|
||||
public byte FarmingDelay { get; set; } = DefaultFarmingDelay;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public byte AccountPlayingDelay { get; set; } = 5;
|
||||
@@ -76,13 +83,13 @@ namespace ConfigGenerator {
|
||||
public bool ForceHttp { get; set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public byte HttpTimeout { get; set; } = 60;
|
||||
public byte HttpTimeout { get; set; } = DefaultHttpTimeout;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
[JsonProperty]
|
||||
public string WCFHostname { get; set; } = "localhost";
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public ushort WCFPort { get; set; } = 1242;
|
||||
public ushort WCFPort { get; set; } = DefaultWCFPort;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool LogToFile { get; set; } = true;
|
||||
@@ -117,17 +124,39 @@ namespace ConfigGenerator {
|
||||
globalConfig.FilePath = filePath;
|
||||
|
||||
// SK2 supports only TCP and UDP steam protocols
|
||||
// Make sure that user can't screw this up
|
||||
// Ensure that user can't screw this up
|
||||
switch (globalConfig.SteamProtocol) {
|
||||
case ProtocolType.Tcp:
|
||||
case ProtocolType.Udp:
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ", default TCP protocol will be used instead");
|
||||
globalConfig.SteamProtocol = ProtocolType.Tcp;
|
||||
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ". Value of " + DefaultSteamProtocol + " will be used instead");
|
||||
globalConfig.SteamProtocol = DefaultSteamProtocol;
|
||||
break;
|
||||
}
|
||||
|
||||
// User might not know what he's doing
|
||||
// Ensure that he can't screw core ASF variables
|
||||
if (globalConfig.MaxFarmingTime == 0) {
|
||||
Logging.LogGenericWarning("Configured MaxFarmingTime is invalid: " + globalConfig.MaxFarmingTime + ". Value of " + DefaultMaxFarmingTime + " will be used instead");
|
||||
globalConfig.MaxFarmingTime = DefaultMaxFarmingTime;
|
||||
}
|
||||
|
||||
if (globalConfig.FarmingDelay == 0) {
|
||||
Logging.LogGenericWarning("Configured FarmingDelay is invalid: " + globalConfig.FarmingDelay + ". Value of " + DefaultFarmingDelay + " will be used instead");
|
||||
globalConfig.FarmingDelay = DefaultFarmingDelay;
|
||||
}
|
||||
|
||||
if (globalConfig.HttpTimeout == 0) {
|
||||
Logging.LogGenericWarning("Configured HttpTimeout is invalid: " + globalConfig.HttpTimeout + ". Value of " + DefaultHttpTimeout + " will be used instead");
|
||||
globalConfig.HttpTimeout = DefaultHttpTimeout;
|
||||
}
|
||||
|
||||
if (globalConfig.WCFPort == 0) {
|
||||
Logging.LogGenericWarning("Configured WCFPort is invalid: " + globalConfig.WCFPort + ". Value of " + DefaultWCFPort + " will be used instead");
|
||||
globalConfig.WCFPort = DefaultWCFPort;
|
||||
}
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
|
||||
16
ConfigGenerator/MainForm.Designer.cs
generated
16
ConfigGenerator/MainForm.Designer.cs
generated
@@ -32,28 +32,30 @@
|
||||
this.MainTab.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.MainTab.Appearance = System.Windows.Forms.TabAppearance.Buttons;
|
||||
this.MainTab.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||
this.MainTab.HotTrack = true;
|
||||
this.MainTab.Location = new System.Drawing.Point(16, 13);
|
||||
this.MainTab.Location = new System.Drawing.Point(14, 14);
|
||||
this.MainTab.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
||||
this.MainTab.Multiline = true;
|
||||
this.MainTab.Name = "MainTab";
|
||||
this.MainTab.SelectedIndex = 0;
|
||||
this.MainTab.Size = new System.Drawing.Size(748, 529);
|
||||
this.MainTab.Size = new System.Drawing.Size(854, 745);
|
||||
this.MainTab.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
|
||||
this.MainTab.TabIndex = 1;
|
||||
this.MainTab.Selected += new System.Windows.Forms.TabControlEventHandler(this.MainTab_Selected);
|
||||
this.MainTab.Deselecting += new System.Windows.Forms.TabControlCancelEventHandler(this.MainTab_Deselecting);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 17F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.AutoScroll = true;
|
||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.ClientSize = new System.Drawing.Size(780, 557);
|
||||
this.ClientSize = new System.Drawing.Size(882, 774);
|
||||
this.Controls.Add(this.MainTab);
|
||||
this.Cursor = System.Windows.Forms.Cursors.Default;
|
||||
this.DoubleBuffered = true;
|
||||
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
|
||||
this.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||
this.HelpButton = true;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
ArchiSteamFarm
|
||||
===================
|
||||
|
||||
[](https://ci.appveyor.com/project/JustArchi/archisteamfarm) [](https://github.com/JustArchi/ArchiSteamFarm/releases/latest) [](https://github.com/JustArchi/ArchiSteamFarm/releases) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4) [](https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_)
|
||||
[](https://ci.appveyor.com/project/JustArchi/ArchiSteamFarm)
|
||||
[](https://travis-ci.org/JustArchi/ArchiSteamFarm)
|
||||
[](https://github.com/JustArchi/ArchiSteamFarm/releases/latest)
|
||||
[](https://github.com/JustArchi/ArchiSteamFarm/releases)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4)
|
||||
[](https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Binary file not shown.
BIN
tools/ILRepack/BamlParser.dll
Normal file
BIN
tools/ILRepack/BamlParser.dll
Normal file
Binary file not shown.
BIN
tools/ILRepack/Fasterflect.dll
Normal file
BIN
tools/ILRepack/Fasterflect.dll
Normal file
Binary file not shown.
BIN
tools/ILRepack/ILRepack.exe
Normal file
BIN
tools/ILRepack/ILRepack.exe
Normal file
Binary file not shown.
BIN
tools/ILRepack/Mono.Cecil.Mdb.dll
Normal file
BIN
tools/ILRepack/Mono.Cecil.Mdb.dll
Normal file
Binary file not shown.
BIN
tools/ILRepack/Mono.Cecil.Pdb.dll
Normal file
BIN
tools/ILRepack/Mono.Cecil.Pdb.dll
Normal file
Binary file not shown.
BIN
tools/ILRepack/Mono.Cecil.dll
Normal file
BIN
tools/ILRepack/Mono.Cecil.dll
Normal file
Binary file not shown.
BIN
tools/ILRepack/Mono.Posix.dll
Normal file
BIN
tools/ILRepack/Mono.Posix.dll
Normal file
Binary file not shown.
17
tools/NetHook2/README.md
Normal file
17
tools/NetHook2/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
NetHook2
|
||||
===================
|
||||
|
||||
This tool is used for reverse-engineering of Steam client. It's capable of hooking and recording network traffic sent/received by the client. If you're not trying to implement missing SK2 functionality in ASF, then please do not proceed.
|
||||
|
||||
1. Launch Steam client
|
||||
2. Execute ```hook.bat```
|
||||
3. Reproduce the functionality you're trying to add
|
||||
4. Execute ```unhook.bat```
|
||||
5. Use ```NetHookAnalyzer2.exe``` for analyzing recorded log (which can be found in your Steam directory)
|
||||
|
||||
- Source of the ```NetHook2.dll``` can be found **[here](https://github.com/SteamRE/SteamKit/tree/master/Resources/NetHook2)**
|
||||
- Source of the ```NetHookAnalyzer2.exe``` can be found **[here](https://github.com/SteamRE/SteamKit/tree/master/Resources/NetHookAnalyzer2)**
|
||||
|
||||
===================
|
||||
|
||||
There is absolutely no guarantee that this will even work for you, not to mention the consequences from hooking the external DLL into steam client. You're on your own.
|
||||
Reference in New Issue
Block a user