Work work

This commit is contained in:
JustArchi
2015-11-01 02:04:44 +01:00
parent 337c397505
commit 164240641b
8 changed files with 233 additions and 85 deletions

View File

@@ -113,6 +113,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="cirno.ico" /> <Content Include="cirno.ico" />
<Content Include="config\example.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
@@ -129,6 +132,14 @@ if $(ConfigurationName) == Release (
<PreBuildEvent> <PreBuildEvent>
</PreBuildEvent> </PreBuildEvent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<PostBuildEvent>if $(ConfigurationName) == Release (
mkdir "$(TargetDir)out" "$(TargetDir)out\config"
copy "$(TargetDir)config\example.xml" "$(TargetDir)out\config"
"$(SolutionDir)tools\ILMerge.exe" /out:"$(TargetDir)out\ASF.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
del "$(TargetDir)out\ASF.pdb"
)</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@@ -27,7 +27,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
@@ -35,7 +34,7 @@ namespace ArchiSteamFarm {
internal class Bot { internal class Bot {
private const ushort CallbackSleep = 500; // In miliseconds private const ushort CallbackSleep = 500; // In miliseconds
private static readonly HashSet<Bot> Bots = new HashSet<Bot>(); private static readonly Dictionary<string, Bot> Bots = new Dictionary<string, Bot>();
private readonly string ConfigFile; private readonly string ConfigFile;
private readonly string SentryFile; private readonly string SentryFile;
@@ -78,7 +77,7 @@ namespace ArchiSteamFarm {
internal static async Task ShutdownAllBots() { internal static async Task ShutdownAllBots() {
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
lock (Bots) { lock (Bots) {
foreach (Bot bot in Bots) { foreach (Bot bot in Bots.Values) {
tasks.Add(Task.Run(async () => await bot.Shutdown().ConfigureAwait(false))); tasks.Add(Task.Run(async () => await bot.Shutdown().ConfigureAwait(false)));
} }
} }
@@ -86,19 +85,25 @@ namespace ArchiSteamFarm {
} }
internal Bot(string botName) { internal Bot(string botName) {
if (Bots.ContainsKey(botName)) {
return;
}
BotName = botName; BotName = botName;
ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml"); ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml");
SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin"); SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin");
ReadConfig(); if (!ReadConfig()) {
return;
}
if (!Enabled) { if (!Enabled) {
return; return;
} }
lock (Bots) { lock (Bots) {
Bots.Add(this); Bots.Add(BotName, this);
} }
// Initialize // Initialize
@@ -133,7 +138,11 @@ namespace ArchiSteamFarm {
Start(); Start();
} }
private void ReadConfig() { private bool ReadConfig() {
if (!File.Exists(ConfigFile)) {
return false;
}
using (XmlReader reader = XmlReader.Create(ConfigFile)) { using (XmlReader reader = XmlReader.Create(ConfigFile)) {
while (reader.Read()) { while (reader.Read()) {
if (reader.NodeType != XmlNodeType.Element) { if (reader.NodeType != XmlNodeType.Element) {
@@ -192,6 +201,8 @@ namespace ArchiSteamFarm {
} }
} }
} }
return true;
} }
internal void Start() { internal void Start() {
@@ -215,12 +226,23 @@ namespace ArchiSteamFarm {
IsRunning = false; IsRunning = false;
} }
internal async Task Shutdown() { private async Task<bool> Shutdown(string botNameToShutdown) {
await Stop().ConfigureAwait(false); Bot botToShutdown;
lock (Bots) { if (!Bots.TryGetValue(botNameToShutdown, out botToShutdown)) {
Bots.Remove(this); return false;
} }
Program.OnBotShutdown(this);
await botToShutdown.Stop().ConfigureAwait(false);
lock (Bots) {
Bots.Remove(botNameToShutdown);
}
Program.OnBotShutdown(botToShutdown);
return true;
}
internal async Task<bool> Shutdown() {
return await Shutdown(BotName).ConfigureAwait(false);
} }
internal async Task OnFarmingFinished() { internal async Task OnFarmingFinished() {
@@ -240,6 +262,63 @@ namespace ArchiSteamFarm {
} }
} }
private void SendMessageToUser(ulong steamID, string message) {
if (steamID == 0 || string.IsNullOrEmpty(message)) {
return;
}
SteamFriends.SendChatMessage(steamID, EChatEntryType.ChatMsg, message);
}
private void ResponseStatus(ulong steamID) {
if (steamID == 0) {
return;
}
SendMessageToUser(steamID, "Currently " + Bots.Count + " bots are running");
}
private void ResponseStart(ulong steamID, string botNameToStart) {
if (steamID == 0 || string.IsNullOrEmpty(botNameToStart)) {
return;
}
if (Bots.ContainsKey(botNameToStart)) {
SendMessageToUser(steamID, "That bot instance is already running!");
return;
}
new Bot(botNameToStart);
if (Bots.ContainsKey(botNameToStart)) {
SendMessageToUser(steamID, "Done!");
} else {
SendMessageToUser(steamID, "That bot instance failed to start, make sure that " + botNameToStart + ".xml config exists and bot is active!");
}
}
private async Task ResponseStop(ulong steamID, string botNameToShutdown) {
if (steamID == 0 || string.IsNullOrEmpty(botNameToShutdown)) {
return;
}
if (!Bots.ContainsKey(botNameToShutdown)) {
SendMessageToUser(steamID, "That bot instance is already inactive!");
return;
}
if (await Shutdown(botNameToShutdown).ConfigureAwait(false)) {
SendMessageToUser(steamID, "Done!");
} else {
SendMessageToUser(steamID, "That bot instance failed to shutdown!");
}
}
private void OnConnected(SteamClient.ConnectedCallback callback) { private void OnConnected(SteamClient.ConnectedCallback callback) {
if (callback == null) { if (callback == null) {
return; return;
@@ -275,17 +354,21 @@ namespace ArchiSteamFarm {
}); });
} }
private void OnDisconnected(SteamClient.DisconnectedCallback callback) { private async void OnDisconnected(SteamClient.DisconnectedCallback callback) {
if (callback == null) { if (callback == null) {
return; return;
} }
if (callback.UserInitiated) {
return;
}
if (SteamClient == null) { if (SteamClient == null) {
return; return;
} }
Logging.LogGenericWarning(BotName, "Disconnected from Steam, reconnecting..."); Logging.LogGenericWarning(BotName, "Disconnected from Steam, reconnecting...");
Thread.Sleep(TimeSpan.FromMilliseconds(CallbackSleep)); await Utilities.SleepAsync(CallbackSleep).ConfigureAwait(false);
SteamClient.Connect(); SteamClient.Connect();
} }
@@ -336,16 +419,43 @@ namespace ArchiSteamFarm {
if (message.Length == 17 && message[5] == '-' && message[11] == '-') { if (message.Length == 17 && message[5] == '-' && message[11] == '-') {
ArchiHandler.RedeemKey(message); ArchiHandler.RedeemKey(message);
return;
} }
if (!message.StartsWith("!")) {
return;
}
if (!message.Contains(" ")) {
switch (message) { switch (message) {
case "!exit":
await ShutdownAllBots().ConfigureAwait(false);
break;
case "!farm": case "!farm":
await CardsFarmer.StartFarming().ConfigureAwait(false); await CardsFarmer.StartFarming().ConfigureAwait(false);
SendMessageToUser(steamID, "Done!");
break; break;
case "!exit": case "!restart":
await Program.Restart().ConfigureAwait(false);
break;
case "!status":
ResponseStatus(steamID);
break;
case "!stop":
await Shutdown().ConfigureAwait(false); await Shutdown().ConfigureAwait(false);
break; break;
} }
} else {
string[] args = message.Split(' ');
switch (args[0]) {
case "!start":
ResponseStart(steamID, args[1]);
break;
case "!stop":
await ResponseStop(steamID, args[1]).ConfigureAwait(false);
break;
}
}
} }
private void OnPersonaState(SteamFriends.PersonaStateCallback callback) { private void OnPersonaState(SteamFriends.PersonaStateCallback callback) {
@@ -418,7 +528,7 @@ namespace ArchiSteamFarm {
case EResult.TryAnotherCM: case EResult.TryAnotherCM:
Logging.LogGenericWarning(BotName, "Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult + ", retrying..."); Logging.LogGenericWarning(BotName, "Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult + ", retrying...");
await Stop().ConfigureAwait(false); await Stop().ConfigureAwait(false);
Thread.Sleep(5000); await Utilities.SleepAsync(CallbackSleep).ConfigureAwait(false);
Start(); Start();
break; break;
default: default:
@@ -484,7 +594,7 @@ namespace ArchiSteamFarm {
} }
var purchaseResult = callback.PurchaseResult; var purchaseResult = callback.PurchaseResult;
SteamFriends.SendChatMessage(SteamMasterID, EChatEntryType.ChatMsg, "Status: " + purchaseResult); SendMessageToUser(SteamMasterID, "Status: " + purchaseResult);
if (purchaseResult == ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK) { if (purchaseResult == ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK) {
await CardsFarmer.StartFarming().ConfigureAwait(false); await CardsFarmer.StartFarming().ConfigureAwait(false);

View File

@@ -132,7 +132,7 @@ namespace ArchiSteamFarm {
FarmResetEvent.Set(); FarmResetEvent.Set();
while (NowFarming) { while (NowFarming) {
Logging.LogGenericInfo(Bot.BotName, "Waiting for reaction..."); Logging.LogGenericInfo(Bot.BotName, "Waiting for reaction...");
Thread.Sleep(1000); await Utilities.SleepAsync(1000).ConfigureAwait(false);
} }
FarmResetEvent.Reset(); FarmResetEvent.Reset();
Logging.LogGenericInfo(Bot.BotName, "Farming stopped!"); Logging.LogGenericInfo(Bot.BotName, "Farming stopped!");

View File

@@ -26,7 +26,8 @@ using System.Diagnostics;
namespace ArchiSteamFarm { namespace ArchiSteamFarm {
internal static class Debugging { internal static class Debugging {
internal static bool IsReleaseBuild { get; private set; } = true; internal static bool IsDebugBuild { get; private set; } = false;
internal static bool IsReleaseBuild { get; private set; } = !IsDebugBuild;
static Debugging() { static Debugging() {
MarkIfDebug(); MarkIfDebug();
@@ -34,7 +35,8 @@ namespace ArchiSteamFarm {
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void MarkIfDebug() { private static void MarkIfDebug() {
IsReleaseBuild = false; IsDebugBuild = true;
IsReleaseBuild = !IsDebugBuild;
} }
} }
} }

View File

@@ -45,7 +45,9 @@ namespace ArchiSteamFarm {
internal static readonly object ConsoleLock = new object(); internal static readonly object ConsoleLock = new object();
private static readonly ManualResetEvent ShutdownResetEvent = new ManualResetEvent(false); private static readonly ManualResetEvent ShutdownResetEvent = new ManualResetEvent(false);
private static readonly AssemblyName AssemblyName = Assembly.GetExecutingAssembly().GetName(); private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
private static readonly string ExecutablePath = Assembly.Location;
private static readonly AssemblyName AssemblyName = Assembly.GetName();
private static readonly string ExeName = AssemblyName.Name + ".exe"; private static readonly string ExeName = AssemblyName.Name + ".exe";
private static readonly string Version = AssemblyName.Version.ToString(); private static readonly string Version = AssemblyName.Version.ToString();
@@ -69,7 +71,7 @@ namespace ArchiSteamFarm {
if (localVersion.CompareTo(remoteVersion) < 0) { if (localVersion.CompareTo(remoteVersion) < 0) {
Logging.LogGenericNotice("", "New version is available!"); Logging.LogGenericNotice("", "New version is available!");
Logging.LogGenericNotice("", "Consider updating yourself!"); Logging.LogGenericNotice("", "Consider updating yourself!");
Thread.Sleep(5000); await Utilities.SleepAsync(5000).ConfigureAwait(false);
} else if (localVersion.CompareTo(remoteVersion) > 0) { } else if (localVersion.CompareTo(remoteVersion) > 0) {
Logging.LogGenericNotice("", "You're currently using pre-release version!"); Logging.LogGenericNotice("", "You're currently using pre-release version!");
Logging.LogGenericNotice("", "Be careful!"); Logging.LogGenericNotice("", "Be careful!");
@@ -81,6 +83,12 @@ namespace ArchiSteamFarm {
Environment.Exit(exitCode); Environment.Exit(exitCode);
} }
internal static async Task Restart() {
await Bot.ShutdownAllBots().ConfigureAwait(false);
System.Diagnostics.Process.Start(ExecutablePath);
Environment.Exit(0);
}
internal static string GetUserInput(string botLogin, EUserInputType userInputType) { internal static string GetUserInput(string botLogin, EUserInputType userInputType) {
string result; string result;
lock (ConsoleLock) { lock (ConsoleLock) {
@@ -107,10 +115,10 @@ namespace ArchiSteamFarm {
return result; return result;
} }
internal static void OnBotShutdown(Bot bot) { internal static async void OnBotShutdown(Bot bot) {
if (Bot.GetRunningBotsCount() == 0) { if (Bot.GetRunningBotsCount() == 0) {
Logging.LogGenericInfo("Main", "No bots are running, exiting"); Logging.LogGenericInfo("Main", "No bots are running, exiting");
Thread.Sleep(5000); // This might be the only message user gets, consider giving him some time await Utilities.SleepAsync(5000).ConfigureAwait(false); // This might be the only message user gets, consider giving him some time
ShutdownResetEvent.Set(); ShutdownResetEvent.Set();
} }
} }
@@ -120,6 +128,16 @@ namespace ArchiSteamFarm {
Task.Run(async () => await CheckForUpdate().ConfigureAwait(false)).Wait(); Task.Run(async () => await CheckForUpdate().ConfigureAwait(false)).Wait();
// Allow loading configs from source tree if it's a debug build
if (Debugging.IsDebugBuild) {
for (var i = 0; i < 4; i++) {
Directory.SetCurrentDirectory("..");
if (Directory.Exists(ConfigDirectoryPath)) {
break;
}
}
}
if (!Directory.Exists(ConfigDirectoryPath)) { if (!Directory.Exists(ConfigDirectoryPath)) {
Logging.LogGenericError("Main", "Config directory doesn't exist!"); Logging.LogGenericError("Main", "Config directory doesn't exist!");
Console.ReadLine(); Console.ReadLine();

View File

@@ -36,35 +36,34 @@ namespace ArchiSteamFarm {
Bot = bot; Bot = bot;
} }
internal void CheckTrades() { internal async void CheckTrades() {
if (ParsingTasks < 2) { if (ParsingTasks < 2) {
ParsingTasks++; ParsingTasks++;
Task.Run(() => ParseActiveTrades());
await Semaphore.WaitAsync().ConfigureAwait(false);
await ParseActiveTrades().ConfigureAwait(false);
Semaphore.Release();
ParsingTasks--;
} }
} }
private async Task ParseActiveTrades() { private async Task ParseActiveTrades() {
await Semaphore.WaitAsync().ConfigureAwait(false);
List<SteamTradeOffer> tradeOffers = Bot.ArchiWebHandler.GetTradeOffers(); List<SteamTradeOffer> tradeOffers = Bot.ArchiWebHandler.GetTradeOffers();
if (tradeOffers != null) { if (tradeOffers == null) {
return;
}
List<Task> tasks = new List<Task>(); List<Task> tasks = new List<Task>();
foreach (SteamTradeOffer tradeOffer in tradeOffers) { foreach (SteamTradeOffer tradeOffer in tradeOffers) {
if (tradeOffer.trade_offer_state == SteamTradeOffer.ETradeOfferState.Active) { if (tradeOffer.trade_offer_state == SteamTradeOffer.ETradeOfferState.Active) {
Task task = Task.Run(async () => { tasks.Add(Task.Run(async () => await ParseTrade(tradeOffer).ConfigureAwait(false)));
await ParseTrade(tradeOffer).ConfigureAwait(false);
});
tasks.Add(task);
} }
} }
await Task.WhenAll(tasks).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false);
} }
ParsingTasks--;
Semaphore.Release();
}
private async Task ParseTrade(SteamTradeOffer tradeOffer) { private async Task ParseTrade(SteamTradeOffer tradeOffer) {
if (tradeOffer == null) { if (tradeOffer == null) {
return; return;

View File

@@ -35,6 +35,10 @@ using System.Threading.Tasks;
namespace ArchiSteamFarm { namespace ArchiSteamFarm {
internal static class Utilities { internal static class Utilities {
internal static async Task SleepAsync(int miliseconds) {
await Task.Delay(miliseconds).ConfigureAwait(false);
}
internal static ulong OnlyNumbers(string inputString) { internal static ulong OnlyNumbers(string inputString) {
if (string.IsNullOrEmpty(inputString)) { if (string.IsNullOrEmpty(inputString)) {
return 0; return 0;

View File

@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<!-- Every bot should have it's own unique .xml configuration file, this is example on which you can base on --> <!-- Every bot should have it's own unique .xml configuration file, this is example on which you can base on -->
<!-- Notice, if you use special characters reserved for XML, you should escape them -->
<!-- Escape table: [& - &amp;] | [" - &quot;] | [' - &apos;] | [< - &lt;] | [> - &gt;] -->
<!-- So e.g. if your SteamPassword is "foo&" you should write value="foo&amp;" -->
<!-- Master switch to turn account on and off, set to "true" after you're done --> <!-- Master switch to turn account on and off, set to "true" after you're done -->
<!-- TIP: This bot instance won't run unless below switch is set to "true" --> <!-- TIP: This bot instance won't run unless below switch is set to "true" -->
<Enabled type="bool" value="false"/> <Enabled type="bool" value="false"/>