mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-01 06:00:46 +00:00
Improve statistics reporting
Skip reporting when user has private or empty inventory
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user