mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-09-20 22:42:06 +00:00
Rewrite #414 in a way that makes me happy
This commit is contained in:
parent
d188065490
commit
de897aaa92
7 changed files with 252 additions and 199 deletions
|
@ -64,19 +64,9 @@ namespace ArchiSteamFarm {
|
|||
internal bool Ready { get; private set; }
|
||||
|
||||
private DateTime LastSessionRefreshCheck = DateTime.MinValue;
|
||||
private string SteamApiKey;
|
||||
private ulong SteamID;
|
||||
|
||||
private string _SteamApiKey;
|
||||
internal string SteamApiKey => ObtainApiKey().Result;
|
||||
private enum ESteamApiKeyState : byte {
|
||||
Unknown = 0,
|
||||
Invalid = 1,
|
||||
Registered = 2,
|
||||
NotRegistered = 3,
|
||||
AccessDenied = 4,
|
||||
}
|
||||
private ESteamApiKeyState SteamApiKeyState;
|
||||
|
||||
internal ArchiWebHandler(Bot bot) {
|
||||
if (bot == null) {
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
|
@ -95,7 +85,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -123,7 +113,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -151,7 +141,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -171,15 +161,20 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
*/
|
||||
|
||||
internal void DeclineTradeOffer(ulong tradeID) {
|
||||
if ((tradeID == 0) || string.IsNullOrEmpty(SteamApiKey)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(tradeID) + " || " + nameof(SteamApiKey));
|
||||
internal async Task DeclineTradeOffer(ulong tradeID) {
|
||||
if (tradeID == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(tradeID));
|
||||
return;
|
||||
}
|
||||
|
||||
string steamApiKey = await GetApiKey().ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(SteamApiKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KeyValue response = null;
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
||||
using (dynamic iEconService = WebAPI.GetInterface(IEconService, SteamApiKey)) {
|
||||
using (dynamic iEconService = WebAPI.GetInterface(IEconService, steamApiKey)) {
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
try {
|
||||
|
@ -201,7 +196,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
/*
|
||||
internal async Task<HashSet<uint>> GenerateNewDiscoveryQueue() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -222,15 +217,15 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
*/
|
||||
|
||||
internal HashSet<Steam.TradeOffer> GetActiveTradeOffers() {
|
||||
internal async Task<HashSet<Steam.TradeOffer>> GetActiveTradeOffers() {
|
||||
string steamApiKey = await GetApiKey().ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(SteamApiKey)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(SteamApiKey));
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyValue response = null;
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
||||
using (dynamic iEconService = WebAPI.GetInterface(IEconService, SteamApiKey)) {
|
||||
using (dynamic iEconService = WebAPI.GetInterface(IEconService, steamApiKey)) {
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
try {
|
||||
|
@ -332,114 +327,13 @@ namespace ArchiSteamFarm {
|
|||
return result;
|
||||
}
|
||||
|
||||
private async Task<ESteamApiKeyState> UpdateApiKey() {
|
||||
if ( !await RefreshSessionIfNeeded().ConfigureAwait(false) ) {
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
|
||||
string request = SteamCommunityURL + "/dev/apikey?l=english";
|
||||
|
||||
HtmlDocument htmlDocument = await WebBrowser.UrlGetToHtmlDocumentRetry(request).ConfigureAwait(false);
|
||||
|
||||
HtmlNode titleNode = htmlDocument?.DocumentNode.SelectSingleNode("//div[@id='mainContents']/h2");
|
||||
|
||||
if (titleNode == null) {
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
|
||||
string title = titleNode.InnerText;
|
||||
|
||||
if (title.IndexOf("Access Denied") == 0) {
|
||||
return ESteamApiKeyState.AccessDenied;
|
||||
}
|
||||
|
||||
HtmlNode htmlNode = htmlDocument?.DocumentNode.SelectSingleNode("//div[@id='bodyContents_ex']/p");
|
||||
if (htmlNode == null) {
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
|
||||
string text = htmlNode.InnerText;
|
||||
|
||||
if (string.IsNullOrEmpty(text)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
|
||||
int hintIndex = text.IndexOf("Registering for a Steam Web API Key", StringComparison.Ordinal);
|
||||
if (hintIndex == 0) {
|
||||
return ESteamApiKeyState.NotRegistered;
|
||||
}
|
||||
|
||||
int keyIndex = text.IndexOf("Key: ", StringComparison.Ordinal);
|
||||
if ( keyIndex < 0 ) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(keyIndex));
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
|
||||
keyIndex += 5;
|
||||
text = text.Substring(keyIndex);
|
||||
|
||||
if ( text.Length != 32 ) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
|
||||
string allowedChars = "0123456789ABCDEF";
|
||||
foreach (char c in text) {
|
||||
if (!allowedChars.Contains(c.ToString()) ) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return ESteamApiKeyState.Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
this._SteamApiKey = text;
|
||||
|
||||
return ESteamApiKeyState.Registered;
|
||||
}
|
||||
|
||||
private async Task<bool> RegisterApiKey() {
|
||||
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
|
||||
if ( string.IsNullOrEmpty(sessionID) ) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(sessionID));
|
||||
return false;
|
||||
}
|
||||
|
||||
string request = SteamCommunityURL + "/dev/registerkey";
|
||||
Dictionary<string, string> data = new Dictionary<string, string>(4) {
|
||||
{"domain", "localhost" },
|
||||
{"agreeToTerms", "agreed"},
|
||||
{"sessionid", sessionID},
|
||||
{"Submit", "Register"}
|
||||
};
|
||||
|
||||
return await WebBrowser.UrlPostRetry( request, data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<string> ObtainApiKey() {
|
||||
switch (SteamApiKeyState) {
|
||||
case ESteamApiKeyState.Unknown:
|
||||
SteamApiKeyState = await UpdateApiKey().ConfigureAwait(false);
|
||||
return await ObtainApiKey().ConfigureAwait(false);
|
||||
case ESteamApiKeyState.NotRegistered:
|
||||
await RegisterApiKey().ConfigureAwait(false);
|
||||
SteamApiKeyState = ESteamApiKeyState.Unknown;
|
||||
return await ObtainApiKey().ConfigureAwait(false);
|
||||
case ESteamApiKeyState.Registered:
|
||||
return _SteamApiKey;
|
||||
case ESteamApiKeyState.AccessDenied:
|
||||
return string.Empty;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task<HtmlDocument> GetBadgePage(byte page) {
|
||||
if (page == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(page));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -453,7 +347,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -474,7 +368,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -484,7 +378,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
/*
|
||||
internal async Task<HtmlDocument> GetDiscoveryQueuePage() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -494,7 +388,7 @@ namespace ArchiSteamFarm {
|
|||
*/
|
||||
|
||||
internal async Task<HashSet<ulong>> GetFamilySharingSteamIDs() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -533,7 +427,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -541,13 +435,53 @@ namespace ArchiSteamFarm {
|
|||
return await WebBrowser.UrlGetToHtmlDocumentRetry(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal async Task<Dictionary<uint, string>> GetMyOwnedGames() {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const string request = SteamCommunityURL + "/my/games/?xml=1";
|
||||
|
||||
XmlDocument response = await WebBrowser.UrlGetToXMLRetry(request).ConfigureAwait(false);
|
||||
|
||||
XmlNodeList xmlNodeList = response?.SelectNodes("gamesList/games/game");
|
||||
if ((xmlNodeList == null) || (xmlNodeList.Count == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<uint, string> result = new Dictionary<uint, string>(xmlNodeList.Count);
|
||||
foreach (XmlNode xmlNode in xmlNodeList) {
|
||||
XmlNode appNode = xmlNode.SelectSingleNode("appID");
|
||||
if (appNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appNode));
|
||||
return null;
|
||||
}
|
||||
|
||||
uint appID;
|
||||
if (!uint.TryParse(appNode.InnerText, out appID)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID));
|
||||
return null;
|
||||
}
|
||||
|
||||
XmlNode nameNode = xmlNode.SelectSingleNode("name");
|
||||
if (nameNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(nameNode));
|
||||
return null;
|
||||
}
|
||||
|
||||
result[appID] = nameNode.InnerText;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<HashSet<Steam.Item>> GetMySteamInventory(bool tradable, HashSet<Steam.Item.EType> wantedTypes) {
|
||||
if ((wantedTypes == null) || (wantedTypes.Count == 0)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(wantedTypes));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -666,55 +600,20 @@ namespace ArchiSteamFarm {
|
|||
return result;
|
||||
}
|
||||
|
||||
internal async Task<Dictionary<uint, string>> GetOwnedGames() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
internal async Task<Dictionary<uint, string>> GetOwnedGames(ulong steamID) {
|
||||
if (steamID == 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(steamID));
|
||||
return null;
|
||||
}
|
||||
|
||||
const string request = SteamCommunityURL + "/my/games/?xml=1";
|
||||
|
||||
XmlDocument response = await WebBrowser.UrlGetToXMLRetry(request).ConfigureAwait(false);
|
||||
|
||||
XmlNodeList xmlNodeList = response?.SelectNodes("gamesList/games/game");
|
||||
if ((xmlNodeList == null) || (xmlNodeList.Count == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Dictionary<uint, string> result = new Dictionary<uint, string>(xmlNodeList.Count);
|
||||
foreach (XmlNode xmlNode in xmlNodeList) {
|
||||
XmlNode appNode = xmlNode.SelectSingleNode("appID");
|
||||
if (appNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appNode));
|
||||
return null;
|
||||
}
|
||||
|
||||
uint appID;
|
||||
if (!uint.TryParse(appNode.InnerText, out appID)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(appID));
|
||||
return null;
|
||||
}
|
||||
|
||||
XmlNode nameNode = xmlNode.SelectSingleNode("name");
|
||||
if (nameNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(nameNode));
|
||||
return null;
|
||||
}
|
||||
|
||||
result[appID] = nameNode.InnerText;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Dictionary<uint, string> GetOwnedGames(ulong steamID) {
|
||||
if ((steamID == 0) || string.IsNullOrEmpty(SteamApiKey)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(SteamApiKey));
|
||||
string steamApiKey = await GetApiKey().ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(SteamApiKey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyValue response = null;
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
||||
using (dynamic iPlayerService = WebAPI.GetInterface(IPlayerService, SteamApiKey)) {
|
||||
using (dynamic iPlayerService = WebAPI.GetInterface(IPlayerService, steamApiKey)) {
|
||||
iPlayerService.Timeout = Timeout;
|
||||
|
||||
try {
|
||||
|
@ -775,7 +674,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
/*
|
||||
internal async Task<HtmlDocument> GetSteamAwardsPage() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -790,7 +689,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -841,7 +740,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -857,7 +756,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -881,6 +780,8 @@ namespace ArchiSteamFarm {
|
|||
return response?.Success;
|
||||
}
|
||||
|
||||
internal async Task<bool> HasValidApiKey() => !string.IsNullOrEmpty(await GetApiKey().ConfigureAwait(false));
|
||||
|
||||
internal static void Init() => Timeout = Program.GlobalConfig.HttpTimeout * 1000;
|
||||
|
||||
internal async Task<bool> Init(ulong steamID, EUniverse universe, string webAPIUserNonce, string parentalPin) {
|
||||
|
@ -976,7 +877,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -996,7 +897,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
internal async Task<bool> MarkInventory() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1012,7 +913,7 @@ namespace ArchiSteamFarm {
|
|||
return ArchiHandler.PurchaseResponseCallback.EPurchaseResult.Unknown;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return ArchiHandler.PurchaseResponseCallback.EPurchaseResult.Timeout;
|
||||
}
|
||||
|
||||
|
@ -1031,7 +932,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1078,6 +979,122 @@ namespace ArchiSteamFarm {
|
|||
return true;
|
||||
}
|
||||
|
||||
private async Task<string> GetApiKey(bool allowRegister = true) {
|
||||
switch (SteamApiKey) {
|
||||
case null:
|
||||
// We didn't fetch API key yet
|
||||
Tuple<ESteamApiKeyState, string> result = await GetApiKeyState().ConfigureAwait(false);
|
||||
if (result == null) {
|
||||
// Request timed out, bad luck, we'll try again later
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (result.Item1) {
|
||||
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;
|
||||
case ESteamApiKeyState.NotRegisteredYet:
|
||||
// We succeeded in fetching API key, and it resulted in no key registered yet
|
||||
if (!allowRegister) {
|
||||
// But this call doesn't allow us to register it, so return null
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we're allowed to register the key, let's do so
|
||||
if (!await RegisterApiKey().ConfigureAwait(false)) {
|
||||
// Request timed out, bad luck, we'll try again later
|
||||
return null;
|
||||
}
|
||||
|
||||
// We should have key ready, to let's call GetApiKey() recursively, but don't allow further recursion
|
||||
return await GetApiKey(false).ConfigureAwait(false);
|
||||
case ESteamApiKeyState.AccessDenied:
|
||||
// We succeeded in fetching API key, but it resulted in access denied
|
||||
// Cache the result as empty, and return null
|
||||
SteamApiKey = "";
|
||||
return null;
|
||||
default:
|
||||
// We got some kind of error, maybe it's temporary, maybe it's permanent
|
||||
// Don't cache anything, we'll try again later
|
||||
return null;
|
||||
}
|
||||
case "":
|
||||
// API key is permanently unavailable via AccessDenied
|
||||
return null;
|
||||
default:
|
||||
// We have key already fetched and cached, return it
|
||||
return SteamApiKey;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Tuple<ESteamApiKeyState, string>> GetApiKeyState() {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const string request = SteamCommunityURL + "/dev/apikey?l=english";
|
||||
HtmlDocument htmlDocument = await WebBrowser.UrlGetToHtmlDocumentRetry(request).ConfigureAwait(false);
|
||||
|
||||
HtmlNode titleNode = htmlDocument?.DocumentNode.SelectSingleNode("//div[@id='mainContents']/h2");
|
||||
if (titleNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string title = titleNode.InnerText;
|
||||
if (string.IsNullOrEmpty(title)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(title));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
if (title.Contains("Access Denied")) {
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.AccessDenied, null);
|
||||
}
|
||||
|
||||
HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//div[@id='bodyContents_ex']/p");
|
||||
if (htmlNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(htmlNode));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
string text = htmlNode.InnerText;
|
||||
if (string.IsNullOrEmpty(text)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
if (text.Contains("Registering for a Steam Web API Key")) {
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.NotRegisteredYet, null);
|
||||
}
|
||||
|
||||
int keyIndex = text.IndexOf("Key: ", StringComparison.Ordinal);
|
||||
if (keyIndex < 0) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(keyIndex));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
keyIndex += 5;
|
||||
|
||||
if (text.Length <= keyIndex) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
text = text.Substring(keyIndex);
|
||||
if (text.Length != 32) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
if (Utilities.IsValidHexadecimalString(text)) {
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Registered, text);
|
||||
}
|
||||
|
||||
Bot.ArchiLogger.LogNullError(nameof(text));
|
||||
return new Tuple<ESteamApiKeyState, string>(ESteamApiKeyState.Error, null);
|
||||
}
|
||||
|
||||
/*
|
||||
internal async Task<bool> SteamAwardsVote(byte voteID, uint appID) {
|
||||
if ((voteID == 0) || (appID == 0)) {
|
||||
|
@ -1085,7 +1102,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1230,6 +1247,28 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<bool> RegisterApiKey() {
|
||||
if (!Ready || !await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
|
||||
if (string.IsNullOrEmpty(sessionID)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(sessionID));
|
||||
return false;
|
||||
}
|
||||
|
||||
const string request = SteamCommunityURL + "/dev/registerkey";
|
||||
Dictionary<string, string> data = new Dictionary<string, string>(4) {
|
||||
{ "domain", "localhost" },
|
||||
{ "agreeToTerms", "agreed" },
|
||||
{ "sessionid", sessionID },
|
||||
{ "Submit", "Register" }
|
||||
};
|
||||
|
||||
return await WebBrowser.UrlPostRetry(request, data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<bool> UnlockParentalAccount(string parentalPin) {
|
||||
if (string.IsNullOrEmpty(parentalPin)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(parentalPin));
|
||||
|
@ -1252,5 +1291,12 @@ namespace ArchiSteamFarm {
|
|||
Bot.ArchiLogger.LogGenericInfo(Strings.Success);
|
||||
return true;
|
||||
}
|
||||
|
||||
private enum ESteamApiKeyState : byte {
|
||||
Error,
|
||||
Registered,
|
||||
NotRegisteredYet,
|
||||
AccessDenied
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,7 +60,6 @@ namespace ArchiSteamFarm {
|
|||
internal readonly string BotName;
|
||||
|
||||
internal bool HasMobileAuthenticator => BotDatabase?.MobileAuthenticator != null;
|
||||
internal bool HasValidApiKey => !string.IsNullOrEmpty(ArchiWebHandler.SteamApiKey);
|
||||
internal bool IsConnectedAndLoggedOn => (SteamClient?.IsConnected == true) && (SteamClient.SteamID != null);
|
||||
internal bool IsPlayingPossible => !PlayingBlocked && (LibraryLockedBySteamID == 0);
|
||||
|
||||
|
@ -1832,10 +1831,10 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
Dictionary<uint, string> ownedGames;
|
||||
if (HasValidApiKey) {
|
||||
ownedGames = ArchiWebHandler.GetOwnedGames(SteamClient.SteamID);
|
||||
if (await ArchiWebHandler.HasValidApiKey().ConfigureAwait(false)) {
|
||||
ownedGames = await ArchiWebHandler.GetOwnedGames(SteamClient.SteamID).ConfigureAwait(false);
|
||||
} else {
|
||||
ownedGames = await ArchiWebHandler.GetOwnedGames().ConfigureAwait(false);
|
||||
ownedGames = await ArchiWebHandler.GetMyOwnedGames().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if ((ownedGames == null) || (ownedGames.Count == 0)) {
|
||||
|
|
|
@ -40,9 +40,6 @@ namespace ArchiSteamFarm {
|
|||
private readonly Bot Bot;
|
||||
private readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1);
|
||||
|
||||
private bool HasAutomatedTrading => Bot.HasMobileAuthenticator && Bot.HasValidApiKey;
|
||||
private bool SteamTradeMatcher => Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher);
|
||||
|
||||
private string LastAvatarHash;
|
||||
private DateTime LastHeartBeat = DateTime.MinValue;
|
||||
private bool? LastMatchEverything;
|
||||
|
@ -95,7 +92,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
// Don't announce if we don't meet conditions
|
||||
if (!HasAutomatedTrading || !SteamTradeMatcher) {
|
||||
if (!Bot.HasMobileAuthenticator || !Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher) || !await Bot.ArchiWebHandler.HasValidApiKey().ConfigureAwait(false)) {
|
||||
ShouldSendHeartBeats = false;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -91,11 +91,7 @@ namespace ArchiSteamFarm {
|
|||
internal void OnDisconnected() => IgnoredTrades.ClearAndTrim();
|
||||
|
||||
private async Task ParseActiveTrades() {
|
||||
if (!Bot.HasValidApiKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<Steam.TradeOffer> tradeOffers = Bot.ArchiWebHandler.GetActiveTradeOffers();
|
||||
HashSet<Steam.TradeOffer> tradeOffers = await Bot.ArchiWebHandler.GetActiveTradeOffers().ConfigureAwait(false);
|
||||
if ((tradeOffers == null) || (tradeOffers.Count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
@ -150,7 +146,7 @@ namespace ArchiSteamFarm {
|
|||
if (result.Result == ParseTradeResult.EResult.RejectedPermanently) {
|
||||
if (Bot.BotConfig.IsBotAccount) {
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.RejectingTrade, tradeOffer.TradeOfferID));
|
||||
Bot.ArchiWebHandler.DeclineTradeOffer(tradeOffer.TradeOfferID);
|
||||
await Bot.ArchiWebHandler.DeclineTradeOffer(tradeOffer.TradeOfferID).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
@ -76,6 +77,25 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
*/
|
||||
|
||||
internal static bool IsValidHexadecimalString(string text) {
|
||||
if (string.IsNullOrEmpty(text)) {
|
||||
Program.ArchiLogger.LogNullError(nameof(text));
|
||||
return false;
|
||||
}
|
||||
|
||||
const byte split = 16;
|
||||
for (byte i = 0; i < text.Length; i += split) {
|
||||
string textPart = string.Join("", text.Skip(i).Take(split));
|
||||
|
||||
ulong ignored;
|
||||
if (!ulong.TryParse(textPart, NumberStyles.HexNumber, null, out ignored)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static string ToHumanReadable(this TimeSpan timeSpan) {
|
||||
// It's really dirty, I'd appreciate a lot if C# offered nice TimeSpan formatting by default
|
||||
// Normally I'd use third-party library like Humanizer, but using it only for this bit is not worth it
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
"SendOnFarmingFinished": false,
|
||||
"SendTradePeriod": 0,
|
||||
"ShutdownOnFarmingFinished": false,
|
||||
"SteamApiKey": null,
|
||||
"SteamLogin": null,
|
||||
"SteamMasterClanID": 0,
|
||||
"SteamMasterID": 0,
|
||||
|
|
|
@ -108,10 +108,6 @@ namespace ConfigGenerator {
|
|||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool ShutdownOnFarmingFinished { get; set; } = false;
|
||||
|
||||
[LocalizedCategory("Access")]
|
||||
[JsonProperty]
|
||||
public string SteamApiKey { get; set; } = null;
|
||||
|
||||
[LocalizedCategory("Core")]
|
||||
[JsonProperty]
|
||||
public string SteamLogin { get; set; } = null;
|
||||
|
|
Loading…
Reference in a new issue