From 5e974aceb4a60899a70c30fad35de96ac1d51f75 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sun, 4 Dec 2016 02:49:56 +0100 Subject: [PATCH] Further optimizations and bugfixes --- ArchiSteamFarm/Bot.cs | 3 ++ ArchiSteamFarm/Statistics.cs | 84 +++++++++++++++++++++++++----------- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 6f94d06fb..654a395a3 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -1180,6 +1180,9 @@ namespace ArchiSteamFarm { Program.GlobalDatabase.CellID = callback.CellID; } + // Sometimes Steam won't send us our own PersonaStateCallback, so request it explicitly + SteamFriends.RequestFriendInfo(callback.ClientSteamID, EClientPersonaStateFlag.Presence); + if (BotDatabase.MobileAuthenticator == null) { // Support and convert SDA files string maFilePath = Path.Combine(SharedInfo.ConfigDirectory, callback.ClientSteamID.ConvertToUInt64() + ".maFile"); diff --git a/ArchiSteamFarm/Statistics.cs b/ArchiSteamFarm/Statistics.cs index 981e23f84..8627ffd67 100644 --- a/ArchiSteamFarm/Statistics.cs +++ b/ArchiSteamFarm/Statistics.cs @@ -24,15 +24,18 @@ using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using SteamKit2; namespace ArchiSteamFarm { - internal sealed class Statistics { + internal sealed class Statistics : IDisposable { private const byte MinHeartBeatTTL = 5; // Minimum amount of minutes we must wait before sending next HeartBeat private readonly Bot Bot; + private readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1); + private string LastAvatarHash; private DateTime LastHeartBeat = DateTime.MinValue; internal Statistics(Bot bot) { @@ -43,35 +46,53 @@ namespace ArchiSteamFarm { Bot = bot; } + public void Dispose() => Semaphore.Dispose(); + internal async Task OnHeartBeat() { if (DateTime.Now < LastHeartBeat.AddMinutes(MinHeartBeatTTL)) { return; } - const string request = SharedInfo.StatisticsServer + "/api/HeartBeat"; - Dictionary data = new Dictionary(1) { - { "SteamID", Bot.SteamID.ToString() } - }; + await Semaphore.WaitAsync().ConfigureAwait(false); - // We don't need retry logic here - if (await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false)) { - LastHeartBeat = DateTime.Now; + try { + if (DateTime.Now < LastHeartBeat.AddMinutes(MinHeartBeatTTL)) { + return; + } + + const string request = SharedInfo.StatisticsServer + "/api/HeartBeat"; + Dictionary data = new Dictionary(1) { + { "SteamID", Bot.SteamID.ToString() } + }; + + // We don't need retry logic here + if (await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false)) { + LastHeartBeat = DateTime.Now; + } + } finally { + Semaphore.Release(); } } internal async Task OnLoggedOn() { 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" } - }; + await Semaphore.WaitAsync().ConfigureAwait(false); - // We don't need retry logic here - await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); + try { + 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); + } finally { + Semaphore.Release(); + } } internal async Task OnPersonaState(SteamFriends.PersonaStateCallback callback) { @@ -81,15 +102,30 @@ namespace ArchiSteamFarm { } string avatarHash = BitConverter.ToString(callback.AvatarHash).Replace("-", "").ToLowerInvariant(); + if (!string.IsNullOrEmpty(LastAvatarHash) && avatarHash.Equals(LastAvatarHash)) { + return; + } - const string request = SharedInfo.StatisticsServer + "/api/PersonaState"; - Dictionary data = new Dictionary(2) { - { "SteamID", Bot.SteamID.ToString() }, - { "AvatarHash", avatarHash } - }; + await Semaphore.WaitAsync().ConfigureAwait(false); - // We don't need retry logic here - await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false); + try { + if (!string.IsNullOrEmpty(LastAvatarHash) && avatarHash.Equals(LastAvatarHash)) { + return; + } + + 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 + if (await Program.WebBrowser.UrlPost(request, data).ConfigureAwait(false)) { + LastAvatarHash = avatarHash; + } + } finally { + Semaphore.Release(); + } } } } \ No newline at end of file