mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-22 09:18:37 +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>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
<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\ASF.json" "$(SolutionDir)out\config"
|
||||||
copy "$(TargetDir)config\example.json" "$(SolutionDir)out\config"
|
copy "$(TargetDir)config\example.json" "$(SolutionDir)out\config"
|
||||||
copy "$(TargetDir)config\minimal.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"
|
del "$(SolutionDir)out\ASF.exe.config"
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
<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/ASF.json" "$(SolutionDir)out/config"
|
||||||
cp "$(TargetDir)config/example.json" "$(SolutionDir)out/config"
|
cp "$(TargetDir)config/example.json" "$(SolutionDir)out/config"
|
||||||
cp "$(TargetDir)config/minimal.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"
|
rm "$(SolutionDir)out/ASF.exe.config"
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -255,14 +255,6 @@ namespace ArchiSteamFarm {
|
|||||||
Start().Forget();
|
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) {
|
internal async Task AcceptConfirmations(Confirmation.ConfirmationType allowedConfirmationType = Confirmation.ConfirmationType.Unknown) {
|
||||||
if (BotDatabase.SteamGuardAccount == null) {
|
if (BotDatabase.SteamGuardAccount == null) {
|
||||||
return;
|
return;
|
||||||
@@ -308,7 +300,6 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Stop().ConfigureAwait(false);
|
|
||||||
await Start().ConfigureAwait(false);
|
await Start().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +309,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (BotConfig.ShutdownOnFarmingFinished) {
|
if (BotConfig.ShutdownOnFarmingFinished) {
|
||||||
await Shutdown().ConfigureAwait(false);
|
Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,8 +334,12 @@ namespace ArchiSteamFarm {
|
|||||||
return ResponseExit(steamID);
|
return ResponseExit(steamID);
|
||||||
case "!farm":
|
case "!farm":
|
||||||
return ResponseFarm(steamID);
|
return ResponseFarm(steamID);
|
||||||
|
case "!help":
|
||||||
|
return ResponseHelp(steamID);
|
||||||
case "!loot":
|
case "!loot":
|
||||||
return await ResponseSendTrade(steamID).ConfigureAwait(false);
|
return await ResponseSendTrade(steamID).ConfigureAwait(false);
|
||||||
|
case "!pause":
|
||||||
|
return await ResponsePause(steamID).ConfigureAwait(false);
|
||||||
case "!rejoinchat":
|
case "!rejoinchat":
|
||||||
return ResponseRejoinChat(steamID);
|
return ResponseRejoinChat(steamID);
|
||||||
case "!restart":
|
case "!restart":
|
||||||
@@ -354,7 +349,7 @@ namespace ArchiSteamFarm {
|
|||||||
case "!statusall":
|
case "!statusall":
|
||||||
return ResponseStatusAll(steamID);
|
return ResponseStatusAll(steamID);
|
||||||
case "!stop":
|
case "!stop":
|
||||||
return await ResponseStop(steamID).ConfigureAwait(false);
|
return ResponseStop(steamID);
|
||||||
case "!update":
|
case "!update":
|
||||||
return await ResponseUpdate(steamID).ConfigureAwait(false);
|
return await ResponseUpdate(steamID).ConfigureAwait(false);
|
||||||
default:
|
default:
|
||||||
@@ -377,6 +372,8 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
case "!farm":
|
case "!farm":
|
||||||
return ResponseFarm(steamID, args[1]);
|
return ResponseFarm(steamID, args[1]);
|
||||||
|
case "!help":
|
||||||
|
return ResponseHelp(steamID, args[1]);
|
||||||
case "!loot":
|
case "!loot":
|
||||||
return await ResponseSendTrade(steamID, args[1]).ConfigureAwait(false);
|
return await ResponseSendTrade(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!owns":
|
case "!owns":
|
||||||
@@ -385,6 +382,8 @@ namespace ArchiSteamFarm {
|
|||||||
} else {
|
} else {
|
||||||
return await ResponseOwns(steamID, BotName, args[1]).ConfigureAwait(false);
|
return await ResponseOwns(steamID, BotName, args[1]).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
case "!pause":
|
||||||
|
return await ResponsePause(steamID, args[1]).ConfigureAwait(false);
|
||||||
case "!play":
|
case "!play":
|
||||||
if (args.Length > 2) {
|
if (args.Length > 2) {
|
||||||
return await ResponsePlay(steamID, args[1], args[2]).ConfigureAwait(false);
|
return await ResponsePlay(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||||
@@ -402,7 +401,7 @@ namespace ArchiSteamFarm {
|
|||||||
case "!status":
|
case "!status":
|
||||||
return ResponseStatus(steamID, args[1]);
|
return ResponseStatus(steamID, args[1]);
|
||||||
case "!stop":
|
case "!stop":
|
||||||
return await ResponseStop(steamID, args[1]).ConfigureAwait(false);
|
return ResponseStop(steamID, args[1]);
|
||||||
default:
|
default:
|
||||||
return ResponseUnknown(steamID);
|
return ResponseUnknown(steamID);
|
||||||
}
|
}
|
||||||
@@ -410,48 +409,37 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task Start() {
|
private async Task Start() {
|
||||||
if (SteamClient.IsConnected) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!KeepRunning) {
|
if (!KeepRunning) {
|
||||||
KeepRunning = true;
|
KeepRunning = true;
|
||||||
Task.Run(() => HandleCallbacks()).Forget();
|
Task.Run(() => HandleCallbacks()).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.LogGenericInfo("Starting...", BotName);
|
|
||||||
|
|
||||||
// 2FA tokens are expiring soon, use limiter only when we don't have any pending
|
// 2FA tokens are expiring soon, use limiter only when we don't have any pending
|
||||||
if (TwoFactorAuth == null) {
|
if (TwoFactorAuth == null) {
|
||||||
await Program.LimitSteamRequestsAsync().ConfigureAwait(false);
|
await Program.LimitSteamRequestsAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logging.LogGenericInfo("Starting...", BotName);
|
||||||
SteamClient.Connect();
|
SteamClient.Connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Stop() {
|
private void Stop() {
|
||||||
if (!SteamClient.IsConnected) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logging.LogGenericInfo("Stopping...", BotName);
|
Logging.LogGenericInfo("Stopping...", BotName);
|
||||||
|
KeepRunning = false;
|
||||||
for (byte i = 0; i < WebBrowser.MaxRetries && SteamClient.IsConnected; i++) {
|
|
||||||
SteamClient.Disconnect();
|
|
||||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SteamClient.IsConnected) {
|
if (SteamClient.IsConnected) {
|
||||||
Logging.LogGenericWarning("Could not stop this bot instance!", BotName);
|
SteamClient.Disconnect();
|
||||||
} else {
|
|
||||||
Logging.LogGenericInfo("Stopped!", BotName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Program.OnBotShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Shutdown() {
|
private bool IsMaster(ulong steamID) {
|
||||||
KeepRunning = false;
|
if (steamID == 0) {
|
||||||
await Stop().ConfigureAwait(false);
|
return false;
|
||||||
Program.OnBotShutdown();
|
}
|
||||||
|
|
||||||
|
return steamID == BotConfig.SteamMasterID || IsOwner(steamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImportAuthenticator(string maFilePath) {
|
private void ImportAuthenticator(string maFilePath) {
|
||||||
@@ -485,7 +473,7 @@ namespace ArchiSteamFarm {
|
|||||||
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
||||||
switch (loginResult) {
|
switch (loginResult) {
|
||||||
case LoginResult.Need2FA:
|
case LoginResult.Need2FA:
|
||||||
userLogin.TwoFactorCode = Program.GetUserInput(BotName, Program.EUserInputType.TwoFactorAuthentication);
|
userLogin.TwoFactorCode = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
||||||
@@ -503,19 +491,42 @@ namespace ArchiSteamFarm {
|
|||||||
BotDatabase.SteamGuardAccount.Session = userLogin.Session;
|
BotDatabase.SteamGuardAccount.Session = userLogin.Session;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(BotDatabase.SteamGuardAccount.DeviceID)) {
|
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();
|
BotDatabase.Save();
|
||||||
Logging.LogGenericInfo("Successfully finished importing mobile authenticator!", BotName);
|
Logging.LogGenericInfo("Successfully finished importing mobile authenticator!", BotName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseStatus(ulong steamID) {
|
private async Task<string> ResponsePause(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,11 +578,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponseSendTrade(ulong steamID) {
|
private async Task<string> ResponseSendTrade(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,11 +615,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string Response2FA(ulong steamID) {
|
private string Response2FA(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,11 +641,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string Response2FAOff(ulong steamID) {
|
private string Response2FAOff(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,11 +670,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Response2FAOK(ulong steamID) {
|
private async Task<string> Response2FAOK(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,11 +709,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseFarm(ulong steamID) {
|
private string ResponseFarm(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,12 +734,29 @@ namespace ArchiSteamFarm {
|
|||||||
return bot.ResponseFarm(steamID);
|
return bot.ResponseFarm(steamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponseRedeem(ulong steamID, string message, bool validate) {
|
private string ResponseHelp(ulong steamID) {
|
||||||
if (steamID == 0 || string.IsNullOrEmpty(message)) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -931,11 +939,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponseAddLicense(ulong steamID, HashSet<uint> gameIDs) {
|
private async Task<string> ResponseAddLicense(ulong steamID, HashSet<uint> gameIDs) {
|
||||||
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0) {
|
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -984,11 +988,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponseOwns(ulong steamID, string games) {
|
private async Task<string> ResponseOwns(ulong steamID, string games) {
|
||||||
if (steamID == 0 || string.IsNullOrEmpty(games)) {
|
if (steamID == 0 || string.IsNullOrEmpty(games) || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1040,20 +1040,19 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponsePlay(ulong steamID, HashSet<uint> gameIDs) {
|
private async Task<string> ResponsePlay(ulong steamID, HashSet<uint> gameIDs) {
|
||||||
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0) {
|
if (steamID == 0 || gameIDs == null || gameIDs.Count == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameIDs.Contains(0)) {
|
if (gameIDs.Contains(0)) {
|
||||||
if (await CardsFarmer.SwitchToManualMode(false).ConfigureAwait(false)) {
|
if (CardsFarmer.ManualMode) {
|
||||||
ResetGamesPlayed();
|
ResetGamesPlayed();
|
||||||
|
await CardsFarmer.SwitchToManualMode(false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await CardsFarmer.SwitchToManualMode(true).ConfigureAwait(false);
|
if (!CardsFarmer.ManualMode) {
|
||||||
|
await CardsFarmer.SwitchToManualMode(true).ConfigureAwait(false);
|
||||||
|
}
|
||||||
ArchiHandler.PlayGames(gameIDs);
|
ArchiHandler.PlayGames(gameIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1089,11 +1088,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponseStart(ulong steamID) {
|
private async Task<string> ResponseStart(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1118,12 +1113,8 @@ namespace ArchiSteamFarm {
|
|||||||
return await bot.ResponseStart(steamID).ConfigureAwait(false);
|
return await bot.ResponseStart(steamID).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> ResponseStop(ulong steamID) {
|
private string ResponseStop(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1131,11 +1122,11 @@ namespace ArchiSteamFarm {
|
|||||||
return "That bot instance is already inactive!";
|
return "That bot instance is already inactive!";
|
||||||
}
|
}
|
||||||
|
|
||||||
await Shutdown().ConfigureAwait(false);
|
Stop();
|
||||||
return "Done!";
|
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)) {
|
if (steamID == 0 || string.IsNullOrEmpty(botName)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1145,15 +1136,11 @@ namespace ArchiSteamFarm {
|
|||||||
return "Couldn't find any bot named " + botName + "!";
|
return "Couldn't find any bot named " + botName + "!";
|
||||||
}
|
}
|
||||||
|
|
||||||
return await bot.ResponseStop(steamID).ConfigureAwait(false);
|
return bot.ResponseStop(steamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ResponseUnknown(ulong steamID) {
|
private string ResponseUnknown(ulong steamID) {
|
||||||
if (steamID == 0) {
|
if (steamID == 0 || !IsMaster(steamID)) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(steamID)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1214,7 +1201,7 @@ namespace ArchiSteamFarm {
|
|||||||
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
while ((loginResult = userLogin.DoLogin()) != LoginResult.LoginOkay) {
|
||||||
switch (loginResult) {
|
switch (loginResult) {
|
||||||
case LoginResult.NeedEmail:
|
case LoginResult.NeedEmail:
|
||||||
userLogin.EmailCode = Program.GetUserInput(BotName, Program.EUserInputType.SteamGuard);
|
userLogin.EmailCode = Program.GetUserInput(Program.EUserInputType.SteamGuard, BotName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
||||||
@@ -1228,7 +1215,7 @@ namespace ArchiSteamFarm {
|
|||||||
while ((linkResult = authenticatorLinker.AddAuthenticator()) != AuthenticatorLinker.LinkResult.AwaitingFinalization) {
|
while ((linkResult = authenticatorLinker.AddAuthenticator()) != AuthenticatorLinker.LinkResult.AwaitingFinalization) {
|
||||||
switch (linkResult) {
|
switch (linkResult) {
|
||||||
case AuthenticatorLinker.LinkResult.MustProvidePhoneNumber:
|
case AuthenticatorLinker.LinkResult.MustProvidePhoneNumber:
|
||||||
authenticatorLinker.PhoneNumber = Program.GetUserInput(BotName, Program.EUserInputType.PhoneNumber);
|
authenticatorLinker.PhoneNumber = Program.GetUserInput(Program.EUserInputType.PhoneNumber, BotName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logging.LogGenericError("Unhandled situation: " + linkResult, BotName);
|
Logging.LogGenericError("Unhandled situation: " + linkResult, BotName);
|
||||||
@@ -1238,7 +1225,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
BotDatabase.SteamGuardAccount = authenticatorLinker.LinkedAccount;
|
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) {
|
if (finalizeResult != AuthenticatorLinker.FinalizeResult.Success) {
|
||||||
Logging.LogGenericError("Unhandled situation: " + finalizeResult, BotName);
|
Logging.LogGenericError("Unhandled situation: " + finalizeResult, BotName);
|
||||||
DelinkMobileAuthenticator();
|
DelinkMobileAuthenticator();
|
||||||
@@ -1246,7 +1233,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Logging.LogGenericInfo("Successfully linked ASF as new mobile authenticator for this account!", BotName);
|
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() {
|
private bool DelinkMobileAuthenticator() {
|
||||||
@@ -1273,11 +1260,11 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
private void InitializeLoginAndPassword() {
|
private void InitializeLoginAndPassword() {
|
||||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
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)) {
|
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);
|
Logging.LogGenericInfo("Disconnected from Steam!", BotName);
|
||||||
await CardsFarmer.StopFarming().ConfigureAwait(false);
|
CardsFarmer.StopFarming().Forget();
|
||||||
|
|
||||||
if (!KeepRunning) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we initiated disconnect, do not attempt to reconnect
|
// If we initiated disconnect, do not attempt to reconnect
|
||||||
if (callback.UserInitiated) {
|
if (callback.UserInitiated) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!KeepRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (InvalidPassword) {
|
if (InvalidPassword) {
|
||||||
InvalidPassword = false;
|
InvalidPassword = false;
|
||||||
if (!string.IsNullOrEmpty(BotDatabase.LoginKey)) { // InvalidPassword means usually that login key has expired, if we used it
|
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) {
|
} else if (LoggedInElsewhere) {
|
||||||
LoggedInElsewhere = false;
|
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);
|
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);
|
await Utilities.SleepAsync(Program.GlobalConfig.AccountPlayingDelay * 60 * 1000).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -1390,11 +1383,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void OnChatInvite(SteamFriends.ChatInviteCallback callback) {
|
private void OnChatInvite(SteamFriends.ChatInviteCallback callback) {
|
||||||
if (callback == null) {
|
if (callback == null || !IsMaster(callback.PatronID)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(callback.PatronID)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1402,20 +1391,16 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void OnChatMsg(SteamFriends.ChatMsgCallback callback) {
|
private async void OnChatMsg(SteamFriends.ChatMsgCallback callback) {
|
||||||
if (callback == null) {
|
if (callback == null || callback.ChatMsgType != EChatEntryType.ChatMsg) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback.ChatMsgType != EChatEntryType.ChatMsg) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(callback.ChatterID)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (callback.Message) {
|
switch (callback.Message) {
|
||||||
case "!leave":
|
case "!leave":
|
||||||
|
if (!IsMaster(callback.ChatterID)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
SteamFriends.LeaveChat(callback.ChatRoomID);
|
SteamFriends.LeaveChat(callback.ChatRoomID);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1442,6 +1427,7 @@ namespace ArchiSteamFarm {
|
|||||||
if (!IsMaster(friend.SteamID)) {
|
if (!IsMaster(friend.SteamID)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SteamFriends.AddFriend(friend.SteamID);
|
SteamFriends.AddFriend(friend.SteamID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1449,11 +1435,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void OnFriendMsg(SteamFriends.FriendMsgCallback callback) {
|
private async void OnFriendMsg(SteamFriends.FriendMsgCallback callback) {
|
||||||
if (callback == null) {
|
if (callback == null || callback.EntryType != EChatEntryType.ChatMsg) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback.EntryType != EChatEntryType.ChatMsg) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1461,19 +1443,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async void OnFriendMsgHistory(SteamFriends.FriendMsgHistoryCallback callback) {
|
private async void OnFriendMsgHistory(SteamFriends.FriendMsgHistoryCallback callback) {
|
||||||
if (callback == null) {
|
if (callback == null || callback.Result != EResult.OK || callback.Messages.Count == 0 || !IsMaster(callback.SteamID)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback.Result != EResult.OK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMaster(callback.SteamID)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback.Messages.Count == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1527,11 +1497,11 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
switch (callback.Result) {
|
switch (callback.Result) {
|
||||||
case EResult.AccountLogonDenied:
|
case EResult.AccountLogonDenied:
|
||||||
AuthCode = Program.GetUserInput(BotConfig.SteamLogin, Program.EUserInputType.SteamGuard);
|
AuthCode = Program.GetUserInput(Program.EUserInputType.SteamGuard, BotName);
|
||||||
break;
|
break;
|
||||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||||
if (BotDatabase.SteamGuardAccount == null) {
|
if (BotDatabase.SteamGuardAccount == null) {
|
||||||
TwoFactorAuth = Program.GetUserInput(BotConfig.SteamLogin, Program.EUserInputType.TwoFactorAuthentication);
|
TwoFactorAuth = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||||
} else {
|
} else {
|
||||||
TwoFactorAuth = BotDatabase.SteamGuardAccount.GenerateSteamGuardCode();
|
TwoFactorAuth = BotDatabase.SteamGuardAccount.GenerateSteamGuardCode();
|
||||||
}
|
}
|
||||||
@@ -1563,7 +1533,7 @@ namespace ArchiSteamFarm {
|
|||||||
ResetGamesPlayed();
|
ResetGamesPlayed();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(BotConfig.SteamParentalPIN)) {
|
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)) {
|
if (!await ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN).ConfigureAwait(false)) {
|
||||||
@@ -1601,7 +1571,7 @@ namespace ArchiSteamFarm {
|
|||||||
break;
|
break;
|
||||||
default: // Unexpected result, shutdown immediately
|
default: // Unexpected result, shutdown immediately
|
||||||
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result, BotName);
|
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result, BotName);
|
||||||
await Shutdown().ConfigureAwait(false);
|
Stop();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1671,7 +1641,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (checkTrades) {
|
if (checkTrades) {
|
||||||
Trading.CheckTrades();
|
Trading.CheckTrades().Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (markInventory && BotConfig.DismissInventoryNotifications) {
|
if (markInventory && BotConfig.DismissInventoryNotifications) {
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ namespace ArchiSteamFarm {
|
|||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
private readonly Timer Timer;
|
private readonly Timer Timer;
|
||||||
|
|
||||||
private volatile bool ManualMode, NowFarming;
|
internal bool ManualMode { get; private set; }
|
||||||
|
|
||||||
|
private bool NowFarming;
|
||||||
|
|
||||||
internal CardsFarmer(Bot bot) {
|
internal CardsFarmer(Bot bot) {
|
||||||
if (bot == null) {
|
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) {
|
if (ManualMode == manualMode) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ManualMode = manualMode;
|
ManualMode = manualMode;
|
||||||
@@ -75,8 +77,6 @@ namespace ArchiSteamFarm {
|
|||||||
Logging.LogGenericInfo("Now running in Automatic Farming mode", Bot.BotName);
|
Logging.LogGenericInfo("Now running in Automatic Farming mode", Bot.BotName);
|
||||||
StartFarming().Forget();
|
StartFarming().Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task StartFarming() {
|
internal async Task StartFarming() {
|
||||||
@@ -113,7 +113,6 @@ namespace ArchiSteamFarm {
|
|||||||
uint appID = gamesToFarmSolo.First();
|
uint appID = gamesToFarmSolo.First();
|
||||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||||
farmedSomething = true;
|
farmedSomething = true;
|
||||||
Logging.LogGenericInfo("Done farming: " + appID, Bot.BotName);
|
|
||||||
gamesToFarmSolo.Remove(appID);
|
gamesToFarmSolo.Remove(appID);
|
||||||
gamesToFarmSolo.TrimExcess();
|
gamesToFarmSolo.TrimExcess();
|
||||||
} else {
|
} else {
|
||||||
@@ -122,7 +121,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (FarmMultiple(GamesToFarm)) {
|
if (FarmMultiple()) {
|
||||||
Logging.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Keys), Bot.BotName);
|
Logging.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Keys), Bot.BotName);
|
||||||
} else {
|
} else {
|
||||||
NowFarming = false;
|
NowFarming = false;
|
||||||
@@ -133,10 +132,9 @@ namespace ArchiSteamFarm {
|
|||||||
} else { // If we have unrestricted card drops, we use simple algorithm
|
} else { // If we have unrestricted card drops, we use simple algorithm
|
||||||
Logging.LogGenericInfo("Chosen farming algorithm: Simple", Bot.BotName);
|
Logging.LogGenericInfo("Chosen farming algorithm: Simple", Bot.BotName);
|
||||||
while (GamesToFarm.Count > 0) {
|
while (GamesToFarm.Count > 0) {
|
||||||
uint appID = GetAnyGameToFarm(GamesToFarm);
|
uint appID = GamesToFarm.Keys.FirstOrDefault();
|
||||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||||
farmedSomething = true;
|
farmedSomething = true;
|
||||||
Logging.LogGenericInfo("Done farming: " + appID, Bot.BotName);
|
|
||||||
} else {
|
} else {
|
||||||
NowFarming = false;
|
NowFarming = false;
|
||||||
return;
|
return;
|
||||||
@@ -208,14 +206,6 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static uint GetAnyGameToFarm(ConcurrentDictionary<uint, float> gamesToFarm) {
|
|
||||||
if (gamesToFarm == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return gamesToFarm.Keys.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> IsAnythingToFarm() {
|
private async Task<bool> IsAnythingToFarm() {
|
||||||
if (NowFarming) {
|
if (NowFarming) {
|
||||||
return true;
|
return true;
|
||||||
@@ -302,13 +292,13 @@ namespace ArchiSteamFarm {
|
|||||||
HtmlNode timeNode = htmlNode.SelectSingleNode(".//div[@class='badge_title_stats_playtime']");
|
HtmlNode timeNode = htmlNode.SelectSingleNode(".//div[@class='badge_title_stats_playtime']");
|
||||||
if (timeNode == null) {
|
if (timeNode == null) {
|
||||||
Logging.LogNullError("timeNode", Bot.BotName);
|
Logging.LogNullError("timeNode", Bot.BotName);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
string hoursString = timeNode.InnerText;
|
string hoursString = timeNode.InnerText;
|
||||||
if (string.IsNullOrEmpty(hoursString)) {
|
if (string.IsNullOrEmpty(hoursString)) {
|
||||||
Logging.LogNullError("hoursString", Bot.BotName);
|
Logging.LogNullError("hoursString", Bot.BotName);
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
hoursString = Regex.Match(hoursString, @"[0-9\.,]+").Value;
|
hoursString = Regex.Match(hoursString, @"[0-9\.,]+").Value;
|
||||||
@@ -364,24 +354,27 @@ namespace ArchiSteamFarm {
|
|||||||
return !htmlNode.InnerText.Contains("No card drops");
|
return !htmlNode.InnerText.Contains("No card drops");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FarmMultiple(ConcurrentDictionary<uint, float> appIDs) {
|
private bool FarmMultiple() {
|
||||||
if (appIDs.Count == 0) {
|
if (GamesToFarm.Count == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float maxHour = 0;
|
float maxHour = 0;
|
||||||
foreach (float hour in appIDs.Values) {
|
foreach (KeyValuePair<uint, float> game in GamesToFarm) {
|
||||||
if (hour > maxHour) {
|
CurrentGamesFarming.Add(game.Key);
|
||||||
maxHour = hour;
|
if (game.Value > maxHour) {
|
||||||
|
maxHour = game.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (uint appID in appIDs.Keys) {
|
if (maxHour >= 2) {
|
||||||
CurrentGamesFarming.Add(appID);
|
CurrentGamesFarming.Clear();
|
||||||
|
CurrentGamesFarming.TrimExcess();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logging.LogGenericInfo("Now farming: " + string.Join(", ", appIDs.Keys), Bot.BotName);
|
Logging.LogGenericInfo("Now farming: " + string.Join(", ", CurrentGamesFarming), Bot.BotName);
|
||||||
if (FarmHours(maxHour, appIDs.Keys)) {
|
if (FarmHours(maxHour, CurrentGamesFarming)) {
|
||||||
CurrentGamesFarming.Clear();
|
CurrentGamesFarming.Clear();
|
||||||
CurrentGamesFarming.TrimExcess();
|
CurrentGamesFarming.TrimExcess();
|
||||||
return true;
|
return true;
|
||||||
@@ -403,8 +396,11 @@ namespace ArchiSteamFarm {
|
|||||||
if (await Farm(appID).ConfigureAwait(false)) {
|
if (await Farm(appID).ConfigureAwait(false)) {
|
||||||
CurrentGamesFarming.Clear();
|
CurrentGamesFarming.Clear();
|
||||||
CurrentGamesFarming.TrimExcess();
|
CurrentGamesFarming.TrimExcess();
|
||||||
float ignored;
|
float hours;
|
||||||
GamesToFarm.TryRemove(appID, out ignored);
|
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;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
CurrentGamesFarming.Clear();
|
CurrentGamesFarming.Clear();
|
||||||
@@ -428,6 +424,11 @@ namespace ArchiSteamFarm {
|
|||||||
success = false;
|
success = false;
|
||||||
break;
|
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);
|
keepFarming = await ShouldFarm(appID).ConfigureAwait(false);
|
||||||
Logging.LogGenericInfo("Still farming: " + appID, Bot.BotName);
|
Logging.LogGenericInfo("Still farming: " + appID, Bot.BotName);
|
||||||
}
|
}
|
||||||
@@ -437,7 +438,7 @@ namespace ArchiSteamFarm {
|
|||||||
return success;
|
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) {
|
if (maxHour < 0 || appIDs == null || appIDs.Count == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -450,7 +451,6 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
while (maxHour < 2) {
|
while (maxHour < 2) {
|
||||||
Logging.LogGenericInfo("Still farming: " + string.Join(", ", appIDs), Bot.BotName);
|
|
||||||
if (FarmResetEvent.WaitOne(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
|
if (FarmResetEvent.WaitOne(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
@@ -458,15 +458,12 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
// Don't forget to update our GamesToFarm hours
|
// Don't forget to update our GamesToFarm hours
|
||||||
float timePlayed = Program.GlobalConfig.FarmingDelay / 60.0F;
|
float timePlayed = Program.GlobalConfig.FarmingDelay / 60.0F;
|
||||||
foreach (KeyValuePair<uint, float> gameToFarm in GamesToFarm) {
|
foreach (uint appID in appIDs) {
|
||||||
if (!appIDs.Contains(gameToFarm.Key)) {
|
GamesToFarm[appID] += timePlayed;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GamesToFarm[gameToFarm.Key] = gameToFarm.Value + timePlayed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maxHour += timePlayed;
|
maxHour += timePlayed;
|
||||||
|
Logging.LogGenericInfo("Still farming: " + string.Join(", ", appIDs), Bot.BotName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot.ResetGamesPlayed();
|
Bot.ResetGamesPlayed();
|
||||||
|
|||||||
@@ -36,6 +36,13 @@ namespace ArchiSteamFarm {
|
|||||||
Experimental
|
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
|
// 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 };
|
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;
|
internal EUpdateChannel UpdateChannel { get; private set; } = EUpdateChannel.Stable;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal ProtocolType SteamProtocol { get; private set; } = ProtocolType.Tcp;
|
internal ProtocolType SteamProtocol { get; private set; } = DefaultSteamProtocol;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal ulong SteamOwnerID { get; private set; } = 0;
|
internal ulong SteamOwnerID { get; private set; } = 0;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal byte MaxFarmingTime { get; private set; } = 10;
|
internal byte MaxFarmingTime { get; private set; } = DefaultMaxFarmingTime;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal byte IdleFarmingPeriod { get; private set; } = 3;
|
internal byte IdleFarmingPeriod { get; private set; } = 3;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal byte FarmingDelay { get; private set; } = 5;
|
internal byte FarmingDelay { get; private set; } = DefaultFarmingDelay;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal byte AccountPlayingDelay { get; private set; } = 5;
|
internal byte AccountPlayingDelay { get; private set; } = 5;
|
||||||
@@ -76,13 +83,13 @@ namespace ArchiSteamFarm {
|
|||||||
internal bool ForceHttp { get; private set; } = false;
|
internal bool ForceHttp { get; private set; } = false;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[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)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal string WCFHostname { get; private set; } = "localhost";
|
internal ushort WCFPort { get; private set; } = DefaultWCFPort;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
|
||||||
internal ushort WCFPort { get; private set; } = 1242;
|
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal bool LogToFile { get; private set; } = true;
|
internal bool LogToFile { get; private set; } = true;
|
||||||
@@ -112,17 +119,39 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SK2 supports only TCP and UDP steam protocols
|
// 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) {
|
switch (globalConfig.SteamProtocol) {
|
||||||
case ProtocolType.Tcp:
|
case ProtocolType.Tcp:
|
||||||
case ProtocolType.Udp:
|
case ProtocolType.Udp:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ", default TCP protocol will be used instead");
|
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ". Value of " + DefaultSteamProtocol + " will be used instead");
|
||||||
globalConfig.SteamProtocol = ProtocolType.Tcp;
|
globalConfig.SteamProtocol = DefaultSteamProtocol;
|
||||||
break;
|
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;
|
return globalConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace ArchiSteamFarm {
|
|||||||
SteamParentalPIN,
|
SteamParentalPIN,
|
||||||
RevocationCode,
|
RevocationCode,
|
||||||
TwoFactorAuthentication,
|
TwoFactorAuthentication,
|
||||||
|
WCFHostname
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum EMode : byte {
|
internal enum EMode : byte {
|
||||||
@@ -58,10 +59,11 @@ namespace ArchiSteamFarm {
|
|||||||
internal const string ConfigDirectory = "config";
|
internal const string ConfigDirectory = "config";
|
||||||
internal const string DebugDirectory = "debug";
|
internal const string DebugDirectory = "debug";
|
||||||
internal const string LogFile = "log.txt";
|
internal const string LogFile = "log.txt";
|
||||||
|
internal const string GithubRepo = "JustArchi/ArchiSteamFarm";
|
||||||
internal const string GlobalConfigFile = ASF + ".json";
|
internal const string GlobalConfigFile = ASF + ".json";
|
||||||
internal const string GlobalDatabaseFile = ASF + ".db";
|
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();
|
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
|
||||||
internal static readonly Version Version = Assembly.GetName().Version;
|
internal static readonly Version Version = Assembly.GetName().Version;
|
||||||
@@ -262,7 +264,7 @@ namespace ArchiSteamFarm {
|
|||||||
}).Forget();
|
}).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) {
|
if (userInputType == EUserInputType.Unknown) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -272,36 +274,38 @@ namespace ArchiSteamFarm {
|
|||||||
ConsoleIsBusy = true;
|
ConsoleIsBusy = true;
|
||||||
switch (userInputType) {
|
switch (userInputType) {
|
||||||
case EUserInputType.DeviceID:
|
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;
|
break;
|
||||||
case EUserInputType.Login:
|
case EUserInputType.Login:
|
||||||
Console.Write("<" + botLogin + "> Please enter your login: ");
|
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your login: ");
|
||||||
break;
|
break;
|
||||||
case EUserInputType.Password:
|
case EUserInputType.Password:
|
||||||
Console.Write("<" + botLogin + "> Please enter your password: ");
|
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter your password: ");
|
||||||
break;
|
break;
|
||||||
case EUserInputType.PhoneNumber:
|
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;
|
break;
|
||||||
case EUserInputType.SMS:
|
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;
|
break;
|
||||||
case EUserInputType.SteamGuard:
|
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;
|
break;
|
||||||
case EUserInputType.SteamParentalPIN:
|
case EUserInputType.SteamParentalPIN:
|
||||||
Console.Write("<" + botLogin + "> Please enter steam parental PIN: ");
|
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter steam parental PIN: ");
|
||||||
break;
|
break;
|
||||||
case EUserInputType.RevocationCode:
|
case EUserInputType.RevocationCode:
|
||||||
Console.WriteLine("<" + botLogin + "> PLEASE WRITE DOWN YOUR REVOCATION CODE: " + extraInformation);
|
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "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("Hit enter once ready...");
|
||||||
Console.Write("<" + botLogin + "> Hit enter once ready...");
|
|
||||||
break;
|
break;
|
||||||
case EUserInputType.TwoFactorAuthentication:
|
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;
|
break;
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
result = Console.ReadLine();
|
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
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("2.0.1.7")]
|
[assembly: AssemblyVersion("2.0.2.0")]
|
||||||
[assembly: AssemblyFileVersion("2.0.1.7")]
|
[assembly: AssemblyFileVersion("2.0.2.0")]
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ namespace ArchiSteamFarm {
|
|||||||
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1);
|
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1);
|
||||||
|
|
||||||
private readonly Bot Bot;
|
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() {
|
internal static async Task LimitInventoryRequestsAsync() {
|
||||||
await InventorySemaphore.WaitAsync().ConfigureAwait(false);
|
await InventorySemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
@@ -55,18 +55,27 @@ namespace ArchiSteamFarm {
|
|||||||
Bot = bot;
|
Bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async void CheckTrades() {
|
internal async Task CheckTrades() {
|
||||||
if (ParsingTasks >= 2) {
|
bool shouldRun = false;
|
||||||
|
lock (TradesSemaphore) {
|
||||||
|
if (ParsingTasks < 2) {
|
||||||
|
ParsingTasks++;
|
||||||
|
shouldRun = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shouldRun) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsingTasks++;
|
await TradesSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
await Semaphore.WaitAsync().ConfigureAwait(false);
|
|
||||||
await ParseActiveTrades().ConfigureAwait(false);
|
await ParseActiveTrades().ConfigureAwait(false);
|
||||||
Semaphore.Release();
|
lock (TradesSemaphore) {
|
||||||
|
ParsingTasks--;
|
||||||
|
}
|
||||||
|
|
||||||
ParsingTasks--;
|
TradesSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ParseActiveTrades() {
|
private async Task ParseActiveTrades() {
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ namespace ArchiSteamFarm {
|
|||||||
private Client Client;
|
private Client Client;
|
||||||
|
|
||||||
internal static void Init() {
|
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";
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ using System.IO;
|
|||||||
|
|
||||||
namespace ConfigGenerator {
|
namespace ConfigGenerator {
|
||||||
internal class ASFConfig {
|
internal class ASFConfig {
|
||||||
internal static List<ASFConfig> ASFConfigs = new List<ASFConfig>();
|
internal static HashSet<ASFConfig> ASFConfigs = new HashSet<ASFConfig>();
|
||||||
|
|
||||||
internal string FilePath { get; set; }
|
internal string FilePath { get; set; }
|
||||||
|
|
||||||
@@ -37,9 +37,8 @@ namespace ConfigGenerator {
|
|||||||
ASFConfigs.Add(this);
|
ASFConfigs.Add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ASFConfig(string filePath) {
|
protected ASFConfig(string filePath) : this() {
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
ASFConfigs.Add(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual void Save() {
|
internal virtual void Save() {
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Deployment" />
|
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
@@ -111,13 +110,11 @@
|
|||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||||
mkdir "$(SolutionDir)out" "$(SolutionDir)out\config"
|
"$(SolutionDir)tools\ILRepack\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||||
"$(SolutionDir)tools\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"
|
del "$(SolutionDir)out\ASF-GUI.exe.config"
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||||
mkdir -p "$(SolutionDir)out" "$(SolutionDir)out/config"
|
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"
|
||||||
mono -O=all "$(SolutionDir)tools/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"
|
rm "$(SolutionDir)out/ASF-GUI.exe.config"
|
||||||
</PostBuildEvent>
|
</PostBuildEvent>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -22,9 +22,6 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace ConfigGenerator {
|
namespace ConfigGenerator {
|
||||||
internal static class Debugging {
|
internal static class Debugging {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ using System.Windows.Forms;
|
|||||||
namespace ConfigGenerator {
|
namespace ConfigGenerator {
|
||||||
internal sealed class EnhancedPropertyGrid : PropertyGrid {
|
internal sealed class EnhancedPropertyGrid : PropertyGrid {
|
||||||
private ASFConfig ASFConfig;
|
private ASFConfig ASFConfig;
|
||||||
|
|
||||||
internal EnhancedPropertyGrid(ASFConfig config) : base() {
|
internal EnhancedPropertyGrid(ASFConfig config) : base() {
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -36,6 +36,13 @@ namespace ConfigGenerator {
|
|||||||
Experimental
|
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
|
// 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 };
|
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;
|
public EUpdateChannel UpdateChannel { get; set; } = EUpdateChannel.Stable;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public ProtocolType SteamProtocol { get; set; } = ProtocolType.Tcp;
|
public ProtocolType SteamProtocol { get; set; } = DefaultSteamProtocol;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public ulong SteamOwnerID { get; set; } = 0;
|
public ulong SteamOwnerID { get; set; } = 0;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public byte MaxFarmingTime { get; set; } = 10;
|
public byte MaxFarmingTime { get; set; } = DefaultMaxFarmingTime;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public byte IdleFarmingPeriod { get; set; } = 3;
|
public byte IdleFarmingPeriod { get; set; } = 3;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public byte FarmingDelay { get; set; } = 5;
|
public byte FarmingDelay { get; set; } = DefaultFarmingDelay;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public byte AccountPlayingDelay { get; set; } = 5;
|
public byte AccountPlayingDelay { get; set; } = 5;
|
||||||
@@ -76,13 +83,13 @@ namespace ConfigGenerator {
|
|||||||
public bool ForceHttp { get; set; } = false;
|
public bool ForceHttp { get; set; } = false;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[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";
|
public string WCFHostname { get; set; } = "localhost";
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public ushort WCFPort { get; set; } = 1242;
|
public ushort WCFPort { get; set; } = DefaultWCFPort;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
public bool LogToFile { get; set; } = true;
|
public bool LogToFile { get; set; } = true;
|
||||||
@@ -117,17 +124,39 @@ namespace ConfigGenerator {
|
|||||||
globalConfig.FilePath = filePath;
|
globalConfig.FilePath = filePath;
|
||||||
|
|
||||||
// SK2 supports only TCP and UDP steam protocols
|
// 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) {
|
switch (globalConfig.SteamProtocol) {
|
||||||
case ProtocolType.Tcp:
|
case ProtocolType.Tcp:
|
||||||
case ProtocolType.Udp:
|
case ProtocolType.Udp:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ", default TCP protocol will be used instead");
|
Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ". Value of " + DefaultSteamProtocol + " will be used instead");
|
||||||
globalConfig.SteamProtocol = ProtocolType.Tcp;
|
globalConfig.SteamProtocol = DefaultSteamProtocol;
|
||||||
break;
|
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;
|
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)
|
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.Left)
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
| 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.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.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
||||||
this.MainTab.Multiline = true;
|
this.MainTab.Multiline = true;
|
||||||
this.MainTab.Name = "MainTab";
|
this.MainTab.Name = "MainTab";
|
||||||
this.MainTab.SelectedIndex = 0;
|
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.TabIndex = 1;
|
||||||
this.MainTab.Selected += new System.Windows.Forms.TabControlEventHandler(this.MainTab_Selected);
|
this.MainTab.Selected += new System.Windows.Forms.TabControlEventHandler(this.MainTab_Selected);
|
||||||
this.MainTab.Deselecting += new System.Windows.Forms.TabControlCancelEventHandler(this.MainTab_Deselecting);
|
this.MainTab.Deselecting += new System.Windows.Forms.TabControlCancelEventHandler(this.MainTab_Deselecting);
|
||||||
//
|
//
|
||||||
// MainForm
|
// 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.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.AutoScroll = true;
|
this.AutoScroll = true;
|
||||||
this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
this.ClientSize = new System.Drawing.Size(882, 774);
|
||||||
this.ClientSize = new System.Drawing.Size(780, 557);
|
|
||||||
this.Controls.Add(this.MainTab);
|
this.Controls.Add(this.MainTab);
|
||||||
|
this.Cursor = System.Windows.Forms.Cursors.Default;
|
||||||
this.DoubleBuffered = true;
|
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.Font = new System.Drawing.Font("Segoe UI", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
|
|
||||||
this.HelpButton = true;
|
this.HelpButton = true;
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||||
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
ArchiSteamFarm
|
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