Improve statistics reporting

Skip reporting when user has private or empty inventory
This commit is contained in:
JustArchi
2017-02-08 14:35:01 +01:00
parent 92b9aeae31
commit 89a36beeae
2 changed files with 77 additions and 18 deletions

View File

@@ -58,14 +58,16 @@ namespace ArchiSteamFarm {
private static int Timeout = GlobalConfig.DefaultConnectionTimeout * 1000; // This must be int type
private readonly Bot Bot;
private readonly SemaphoreSlim PublicInventorySemaphore = new SemaphoreSlim(1);
private readonly SemaphoreSlim SessionSemaphore = new SemaphoreSlim(1);
private readonly SemaphoreSlim SteamApiKeySemaphore = new SemaphoreSlim(1);
private readonly WebBrowser WebBrowser;
internal bool Ready { get; private set; }
private bool? CachedPublicInventory;
private string CachedSteamApiKey;
private DateTime LastSessionRefreshCheck = DateTime.MinValue;
private string SteamApiKey;
private ulong SteamID;
internal ArchiWebHandler(Bot bot) {
@@ -79,6 +81,7 @@ namespace ArchiSteamFarm {
}
public void Dispose() {
PublicInventorySemaphore.Dispose();
SessionSemaphore.Dispose();
SteamApiKeySemaphore.Dispose();
}
@@ -172,7 +175,7 @@ namespace ArchiSteamFarm {
}
string steamApiKey = await GetApiKey().ConfigureAwait(false);
if (string.IsNullOrEmpty(SteamApiKey)) {
if (string.IsNullOrEmpty(steamApiKey)) {
return;
}
@@ -223,7 +226,7 @@ namespace ArchiSteamFarm {
internal async Task<HashSet<Steam.TradeOffer>> GetActiveTradeOffers() {
string steamApiKey = await GetApiKey().ConfigureAwait(false);
if (string.IsNullOrEmpty(SteamApiKey)) {
if (string.IsNullOrEmpty(steamApiKey)) {
return null;
}
@@ -611,7 +614,7 @@ namespace ArchiSteamFarm {
}
string steamApiKey = await GetApiKey().ConfigureAwait(false);
if (string.IsNullOrEmpty(SteamApiKey)) {
if (string.IsNullOrEmpty(steamApiKey)) {
return null;
}
@@ -784,6 +787,31 @@ namespace ArchiSteamFarm {
return response?.Success;
}
internal async Task<bool> HasPublicInventory() {
if (CachedPublicInventory.HasValue) {
return CachedPublicInventory.Value;
}
// We didn't fetch API key yet
await PublicInventorySemaphore.WaitAsync().ConfigureAwait(false);
try {
if (CachedPublicInventory.HasValue) {
return CachedPublicInventory.Value;
}
bool? isInventoryPublic = await IsInventoryPublic().ConfigureAwait(false);
if (!isInventoryPublic.HasValue) {
return false;
}
CachedPublicInventory = isInventoryPublic.Value;
return isInventoryPublic.Value;
} finally {
PublicInventorySemaphore.Release();
}
}
internal async Task<bool> HasValidApiKey() => !string.IsNullOrEmpty(await GetApiKey().ConfigureAwait(false));
internal static void Init() => Timeout = Program.GlobalConfig.ConnectionTimeout * 1000;
@@ -984,18 +1012,18 @@ namespace ArchiSteamFarm {
}
private async Task<string> GetApiKey(bool allowRegister = true) {
if (SteamApiKey != null) {
if (CachedSteamApiKey != null) {
// We fetched API key already, and either got valid one, or permanent AccessDenied
// In any case, this is our final result
return SteamApiKey;
return CachedSteamApiKey;
}
// We didn't fetch API key yet
await SteamApiKeySemaphore.WaitAsync().ConfigureAwait(false);
try {
if (SteamApiKey != null) {
return SteamApiKey;
if (CachedSteamApiKey != null) {
return CachedSteamApiKey;
}
Tuple<ESteamApiKeyState, string> result = await GetApiKeyState().ConfigureAwait(false);
@@ -1008,8 +1036,8 @@ namespace ArchiSteamFarm {
case ESteamApiKeyState.Registered:
// We succeeded in fetching API key, and it resulted in registered key
// Cache the result and return it
SteamApiKey = result.Item2;
return SteamApiKey;
CachedSteamApiKey = result.Item2;
return CachedSteamApiKey;
case ESteamApiKeyState.NotRegisteredYet:
// We succeeded in fetching API key, and it resulted in no key registered yet
if (!allowRegister) {
@@ -1034,7 +1062,7 @@ namespace ArchiSteamFarm {
case ESteamApiKeyState.AccessDenied:
// We succeeded in fetching API key, but it resulted in access denied
// Cache the result as empty, and return null
SteamApiKey = "";
CachedSteamApiKey = "";
return null;
default:
// We got some kind of error, maybe it's temporary, maybe it's permanent
@@ -1183,6 +1211,25 @@ namespace ArchiSteamFarm {
}
}
private async Task<bool?> IsInventoryPublic() {
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
return null;
}
const string request = SteamCommunityURL + "/my/edit/settings?l=english";
HtmlDocument htmlDocument = await WebBrowser.UrlGetToHtmlDocumentRetry(request).ConfigureAwait(false);
HtmlNode htmlNode = htmlDocument?.DocumentNode.SelectSingleNode("//input[@id='inventoryPrivacySetting_public']");
if (htmlNode == null) {
return null;
}
// Notice: checked doesn't have a value - null is lack of attribute, "" is attribute existing
string state = htmlNode.GetAttributeValue("checked", null);
return state != null;
}
private async Task<bool?> IsLoggedIn() {
// It would make sense to use /my/profile here, but it dismisses notifications related to profile comments
// So instead, we'll use some less intrusive link, such as /my/videos

View File

@@ -24,9 +24,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.JSON;
using SteamKit2;
namespace ArchiSteamFarm {
@@ -85,6 +87,7 @@ namespace ArchiSteamFarm {
internal async Task OnLoggedOn() => await Bot.ArchiWebHandler.JoinGroup(SharedInfo.ASFGroupSteamID).ConfigureAwait(false);
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
internal async Task OnPersonaState(SteamFriends.PersonaStateCallback callback) {
if (callback == null) {
ASF.ArchiLogger.LogNullError(nameof(callback));
@@ -92,17 +95,17 @@ namespace ArchiSteamFarm {
}
// Don't announce if we don't meet conditions
if (!Bot.HasMobileAuthenticator || !Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher) || !await Bot.ArchiWebHandler.HasValidApiKey().ConfigureAwait(false)) {
if (!Bot.HasMobileAuthenticator || !Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher) || !await Bot.ArchiWebHandler.HasValidApiKey().ConfigureAwait(false) || !await Bot.ArchiWebHandler.HasPublicInventory().ConfigureAwait(false)) {
ShouldSendHeartBeats = false;
return;
}
string nickname = callback.Name ?? "";
string avatarHash = "";
string avatarHash = "";
if ((callback.AvatarHash != null) && (callback.AvatarHash.Length > 0) && callback.AvatarHash.Any(singleByte => singleByte != 0)) {
avatarHash = BitConverter.ToString(callback.AvatarHash).Replace("-", "").ToLowerInvariant();
if (avatarHash.Equals("0000000000000000000000000000000000000000")) {
if (avatarHash.All(singleChar => singleChar == '0')) {
avatarHash = "";
}
}
@@ -110,7 +113,7 @@ namespace ArchiSteamFarm {
bool matchEverything = Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything);
// Skip announcing if we already announced this bot with the same data
if (!string.IsNullOrEmpty(LastNickname) && nickname.Equals(LastNickname) && !string.IsNullOrEmpty(LastAvatarHash) && avatarHash.Equals(LastAvatarHash) && LastMatchEverything.HasValue && (matchEverything == LastMatchEverything.Value)) {
if ((LastNickname != null) && nickname.Equals(LastNickname) && (LastAvatarHash != null) && avatarHash.Equals(LastAvatarHash) && LastMatchEverything.HasValue && (matchEverything == LastMatchEverything.Value)) {
return;
}
@@ -118,7 +121,15 @@ namespace ArchiSteamFarm {
try {
// Skip announcing if we already announced this bot with the same data
if (!string.IsNullOrEmpty(LastNickname) && nickname.Equals(LastNickname) && !string.IsNullOrEmpty(LastAvatarHash) && avatarHash.Equals(LastAvatarHash) && LastMatchEverything.HasValue && (matchEverything == LastMatchEverything.Value)) {
if ((LastNickname != null) && nickname.Equals(LastNickname) && (LastAvatarHash != null) && avatarHash.Equals(LastAvatarHash) && LastMatchEverything.HasValue && (matchEverything == LastMatchEverything.Value)) {
return;
}
await Trading.LimitInventoryRequestsAsync().ConfigureAwait(false);
HashSet<Steam.Item> inventory = await Bot.ArchiWebHandler.GetMySteamInventory(true, new HashSet<Steam.Item.EType> { Steam.Item.EType.TradingCard }).ConfigureAwait(false);
if ((inventory == null) || (inventory.Count == 0)) {
// Don't announce, we have empty inventory
return;
}
@@ -126,12 +137,13 @@ namespace ArchiSteamFarm {
ShouldSendHeartBeats = true;
string request = await GetURL().ConfigureAwait(false) + "/api/Announce";
Dictionary<string, string> data = new Dictionary<string, string>(5) {
Dictionary<string, string> data = new Dictionary<string, string>(6) {
{ "SteamID", Bot.SteamID.ToString() },
{ "Guid", Program.GlobalDatabase.Guid.ToString("N") },
{ "Nickname", nickname },
{ "AvatarHash", avatarHash },
{ "MatchEverything", matchEverything ? "1" : "0" }
{ "MatchEverything", matchEverything ? "1" : "0" },
{ "CardsCount", inventory.Count.ToString() }
};
// We don't need retry logic here