diff --git a/ArchiSteamFarm/ArchiSteamFarm.csproj b/ArchiSteamFarm/ArchiSteamFarm.csproj index 007ec6914..3060a18ce 100644 --- a/ArchiSteamFarm/ArchiSteamFarm.csproj +++ b/ArchiSteamFarm/ArchiSteamFarm.csproj @@ -136,6 +136,7 @@ + diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index ebc26ab2d..0bcadbfeb 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -665,6 +665,9 @@ namespace ArchiSteamFarm { try { await SteamApps.PICSGetProductInfo(0, null); + if (Program.GlobalConfig.Statistics) { + Statistics.OnHeartBeat(this).Forget(); + } } catch { if (!IsConnectedAndLoggedOn || (HeartBeatFailures == byte.MaxValue)) { return; @@ -1210,7 +1213,7 @@ namespace ArchiSteamFarm { } if (Program.GlobalConfig.Statistics) { - ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).Forget(); + Statistics.OnLoggedOn(this).Forget(); } Trading.CheckTrades().Forget(); @@ -1320,7 +1323,10 @@ namespace ArchiSteamFarm { } if (callback.FriendID == SteamClient.SteamID) { - Events.OnStateUpdated(this, callback); + Events.OnPersonaState(this, callback); + if (Program.GlobalConfig.Statistics) { + Statistics.OnPersonaState(this, callback).Forget(); + } } else if ((callback.FriendID == LibraryLockedBySteamID) && (callback.GameID == 0)) { LibraryLockedBySteamID = 0; CheckOccupationStatus(); diff --git a/ArchiSteamFarm/Events.cs b/ArchiSteamFarm/Events.cs index 085220e26..0966611b1 100644 --- a/ArchiSteamFarm/Events.cs +++ b/ArchiSteamFarm/Events.cs @@ -38,6 +38,6 @@ namespace ArchiSteamFarm { Program.Shutdown(); } - internal static void OnStateUpdated(Bot bot, SteamFriends.PersonaStateCallback callback) { } + internal static void OnPersonaState(Bot bot, SteamFriends.PersonaStateCallback callback) { } } } \ No newline at end of file diff --git a/ArchiSteamFarm/SharedInfo.cs b/ArchiSteamFarm/SharedInfo.cs index 5fc5e450e..b476f2df0 100644 --- a/ArchiSteamFarm/SharedInfo.cs +++ b/ArchiSteamFarm/SharedInfo.cs @@ -43,6 +43,7 @@ namespace ArchiSteamFarm { internal const string LogFile = "log.txt"; internal const string ServiceDescription = "ASF is an application that allows you to farm steam cards using multiple steam accounts simultaneously."; internal const string ServiceName = "ArchiSteamFarm"; + internal const string StatisticsServer = "https://asf.justarchi.net"; internal const string VersionNumber = "2.1.7.0"; internal static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version; diff --git a/ArchiSteamFarm/Statistics.cs b/ArchiSteamFarm/Statistics.cs new file mode 100644 index 000000000..1ac98c435 --- /dev/null +++ b/ArchiSteamFarm/Statistics.cs @@ -0,0 +1,85 @@ +/* + _ _ _ ____ _ _____ + / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___ + / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \ + / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | | +/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_| + + Copyright 2015-2016 Łukasz "JustArchi" Domeradzki + Contact: JustArchi@JustArchi.net + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using SteamKit2; + +namespace ArchiSteamFarm { + internal static class Statistics { + internal static async Task OnHeartBeat(Bot bot) { + if (bot == null) { + ASF.ArchiLogger.LogNullError(nameof(bot)); + return; + } + + const string request = SharedInfo.StatisticsServer + "/api/HeartBeat"; + Dictionary data = new Dictionary(1) { + { "SteamID", bot.SteamID.ToString() } + }; + + // We don't need retry logic here + await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); + } + + internal static async Task OnLoggedOn(Bot bot) { + if (bot == null) { + ASF.ArchiLogger.LogNullError(nameof(bot)); + return; + } + + await bot.ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).ConfigureAwait(false); + + const string request = SharedInfo.StatisticsServer + "/api/LoggedOn"; + Dictionary data = new Dictionary(4) { + { "SteamID", bot.SteamID.ToString() }, + { "HasMobileAuthenticator", bot.HasMobileAuthenticator ? "1" : "0" }, + { "SteamTradeMatcher", bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher) ? "1" : "0" }, + { "MatchEverything", bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything) ? "1" : "0" } + }; + + // We don't need retry logic here + await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); + } + + internal static async Task OnPersonaState(Bot bot, SteamFriends.PersonaStateCallback callback) { + if ((bot == null) || (callback == null)) { + ASF.ArchiLogger.LogNullError(nameof(bot) + " || " + nameof(callback)); + return; + } + + string avatarHash = BitConverter.ToString(callback.AvatarHash).Replace("-", "").ToLowerInvariant(); + + const string request = SharedInfo.StatisticsServer + "/api/PersonaState"; + Dictionary data = new Dictionary(2) { + { "SteamID", bot.SteamID.ToString() }, + { "AvatarHash", avatarHash } + }; + + // We don't need retry logic here + await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); + } + } +} \ No newline at end of file diff --git a/ArchiSteamFarm/WebBrowser.cs b/ArchiSteamFarm/WebBrowser.cs index b0516a4c9..e902f85b5 100644 --- a/ArchiSteamFarm/WebBrowser.cs +++ b/ArchiSteamFarm/WebBrowser.cs @@ -219,6 +219,17 @@ namespace ArchiSteamFarm { return null; } + internal async Task UrlPost(string request, IEnumerable> data = null, string referer = null) { + if (string.IsNullOrEmpty(request)) { + ArchiLogger.LogNullError(nameof(request)); + return false; + } + + using (HttpResponseMessage response = await UrlPostToResponse(request, data, referer).ConfigureAwait(false)) { + return response != null; + } + } + internal async Task UrlPostRetry(string request, ICollection> data = null, string referer = null) { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); @@ -428,17 +439,6 @@ namespace ArchiSteamFarm { } } - private async Task UrlPost(string request, IEnumerable> data = null, string referer = null) { - if (string.IsNullOrEmpty(request)) { - ArchiLogger.LogNullError(nameof(request)); - return false; - } - - using (HttpResponseMessage response = await UrlPostToResponse(request, data, referer).ConfigureAwait(false)) { - return response != null; - } - } - private async Task UrlPostToContent(string request, IEnumerable> data = null, string referer = null) { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); diff --git a/GUI/Events.cs b/GUI/Events.cs index f0b691e12..b040b7c50 100644 --- a/GUI/Events.cs +++ b/GUI/Events.cs @@ -31,7 +31,7 @@ namespace ArchiSteamFarm { internal static class Events { internal static void OnBotShutdown() { } - internal static void OnStateUpdated(Bot bot, SteamFriends.PersonaStateCallback callback) { + internal static void OnPersonaState(Bot bot, SteamFriends.PersonaStateCallback callback) { if (bot == null) { ASF.ArchiLogger.LogNullError(nameof(bot)); return; diff --git a/GUI/GUI.csproj b/GUI/GUI.csproj index f6ae2af71..199ca51d4 100644 --- a/GUI/GUI.csproj +++ b/GUI/GUI.csproj @@ -145,6 +145,9 @@ SharedInfo.cs + + Statistics.cs + Trading.cs diff --git a/resources/Statistics.mwb b/resources/Statistics.mwb new file mode 100644 index 000000000..22149cc3d Binary files /dev/null and b/resources/Statistics.mwb differ