ASF-specific WebBrowser enhancements, closes #192

This commit is contained in:
JustArchi
2016-04-12 16:58:45 +02:00
parent c8fb715558
commit 790e6baf46
3 changed files with 73 additions and 68 deletions

View File

@@ -45,7 +45,7 @@ namespace ArchiSteamFarm {
private readonly Bot Bot;
private readonly SemaphoreSlim SessionSemaphore = new SemaphoreSlim(1);
private readonly CookieContainer CookieContainer = new CookieContainer();
private readonly WebBrowser WebBrowser;
private DateTime LastSessionRefreshCheck = DateTime.MinValue;
@@ -60,6 +60,8 @@ namespace ArchiSteamFarm {
}
Bot = bot;
WebBrowser = new WebBrowser(bot.BotName);
}
internal bool Init(SteamClient steamClient, string webAPIUserNonce, string parentalPin) {
@@ -114,13 +116,13 @@ namespace ArchiSteamFarm {
Logging.LogGenericInfo("Success!", Bot.BotName);
CookieContainer.Add(new Cookie("sessionid", sessionID, "/", "." + SteamCommunity));
WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", "." + SteamCommunity));
string steamLogin = authResult["token"].Value;
CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", "." + SteamCommunity));
WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", "." + SteamCommunity));
string steamLoginSecure = authResult["tokensecure"].Value;
CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", "." + SteamCommunity));
WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", "." + SteamCommunity));
if (!UnlockParentalAccount(parentalPin).Result) {
return false;
@@ -133,7 +135,7 @@ namespace ArchiSteamFarm {
internal async Task<bool?> IsLoggedIn() {
HtmlDocument htmlDocument = null;
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/profile", CookieContainer).ConfigureAwait(false);
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/profile").ConfigureAwait(false);
}
if (htmlDocument == null) {
@@ -184,7 +186,7 @@ namespace ArchiSteamFarm {
XmlDocument response = null;
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
response = await WebBrowser.UrlGetToXML(request, CookieContainer).ConfigureAwait(false);
response = await WebBrowser.UrlGetToXML(request).ConfigureAwait(false);
}
if (response == null) {
@@ -289,7 +291,7 @@ namespace ArchiSteamFarm {
return false;
}
string sessionID = CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
if (string.IsNullOrEmpty(sessionID)) {
Logging.LogNullError("sessionID");
return false;
@@ -304,7 +306,7 @@ namespace ArchiSteamFarm {
bool result = false;
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
result = await WebBrowser.UrlPost(request, data, CookieContainer).ConfigureAwait(false);
result = await WebBrowser.UrlPost(request, data).ConfigureAwait(false);
}
if (!result) {
@@ -324,7 +326,7 @@ namespace ArchiSteamFarm {
return false;
}
string sessionID = CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
if (string.IsNullOrEmpty(sessionID)) {
Logging.LogNullError("sessionID");
return false;
@@ -341,7 +343,7 @@ namespace ArchiSteamFarm {
bool result = false;
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
result = await WebBrowser.UrlPost(request, data, CookieContainer, referer).ConfigureAwait(false);
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
}
if (!result) {
@@ -359,7 +361,7 @@ namespace ArchiSteamFarm {
JObject jObject = null;
for (byte i = 0; i < WebBrowser.MaxRetries && jObject == null; i++) {
jObject = await WebBrowser.UrlGetToJObject(SteamCommunityURL + "/my/inventory/json/753/6?trading=1", CookieContainer).ConfigureAwait(false);
jObject = await WebBrowser.UrlGetToJObject(SteamCommunityURL + "/my/inventory/json/753/6?trading=1").ConfigureAwait(false);
}
if (jObject == null) {
@@ -394,7 +396,7 @@ namespace ArchiSteamFarm {
return false;
}
string sessionID = CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
if (string.IsNullOrEmpty(sessionID)) {
Logging.LogNullError("sessionID");
return false;
@@ -437,7 +439,7 @@ namespace ArchiSteamFarm {
bool result = false;
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
result = await WebBrowser.UrlPost(request, data, CookieContainer, referer).ConfigureAwait(false);
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
}
if (!result) {
@@ -460,7 +462,7 @@ namespace ArchiSteamFarm {
HtmlDocument htmlDocument = null;
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/badges?p=" + page, CookieContainer).ConfigureAwait(false);
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/badges?p=" + page).ConfigureAwait(false);
}
if (htmlDocument == null) {
@@ -482,7 +484,7 @@ namespace ArchiSteamFarm {
HtmlDocument htmlDocument = null;
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/gamecards/" + appID, CookieContainer).ConfigureAwait(false);
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/gamecards/" + appID).ConfigureAwait(false);
}
if (htmlDocument == null) {
@@ -500,7 +502,7 @@ namespace ArchiSteamFarm {
bool result = false;
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
result = await WebBrowser.UrlGet(SteamCommunityURL + "/my/inventory", CookieContainer).ConfigureAwait(false);
result = await WebBrowser.UrlGet(SteamCommunityURL + "/my/inventory").ConfigureAwait(false);
}
if (!result) {
@@ -520,7 +522,7 @@ namespace ArchiSteamFarm {
return false;
}
string sessionID = CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
if (string.IsNullOrEmpty(sessionID)) {
Logging.LogNullError("sessionID");
return false;
@@ -533,7 +535,7 @@ namespace ArchiSteamFarm {
bool result = false;
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
result = await WebBrowser.UrlPost(request, data, CookieContainer).ConfigureAwait(false);
result = await WebBrowser.UrlPost(request, data).ConfigureAwait(false);
}
if (!result) {
@@ -559,7 +561,7 @@ namespace ArchiSteamFarm {
HttpResponseMessage response = null;
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
response = await WebBrowser.UrlPostToResponse(request, data, CookieContainer, referer).ConfigureAwait(false);
response = await WebBrowser.UrlPostToResponse(request, data, referer).ConfigureAwait(false);
}
if (response == null) {
@@ -589,7 +591,7 @@ namespace ArchiSteamFarm {
}
Logging.LogGenericInfo("Success!", Bot.BotName);
CookieContainer.Add(new Cookie("steamparental", setCookie, "/", "." + SteamCommunity));
WebBrowser.CookieContainer.Add(new Cookie("steamparental", setCookie, "/", "." + SteamCommunity));
return true;
}

View File

@@ -82,6 +82,7 @@ namespace ArchiSteamFarm {
private static Timer AutoUpdatesTimer;
private static EMode Mode = EMode.Normal;
private static WebBrowser WebBrowser;
internal static async Task CheckForUpdate() {
string oldExeFile = ExecutableFile + ".old";
@@ -369,6 +370,8 @@ namespace ArchiSteamFarm {
ArchiWebHandler.Init();
WebBrowser.Init();
WCF.Init();
WebBrowser = new WebBrowser("Main");
}
private static void ParseArgs(string[] args) {

View File

@@ -34,31 +34,20 @@ using System.Threading.Tasks;
using System.Xml;
namespace ArchiSteamFarm {
internal static class WebBrowser {
internal sealed class WebBrowser {
internal const byte MaxRetries = 5; // Defines maximum number of retries, UrlRequest() does not handle retry by itself (it's app responsibility)
private const byte MaxConnections = 10; // Defines maximum number of connections per ServicePoint. Be careful, as it also defines maximum number of sockets in CLOSE_WAIT state
private const byte MaxIdleTime = 15; // In seconds, how long socket is allowed to stay in CLOSE_WAIT state after there are no connections to it
internal static readonly CookieContainer CookieContainer = new CookieContainer();
private static readonly string DefaultUserAgent = "ArchiSteamFarm/" + Program.Version;
private static readonly HttpClientHandler HttpClientHandler = new HttpClientHandler {
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
CookieContainer = CookieContainer
};
private static readonly HttpClient HttpClient = new HttpClient(HttpClientHandler) {
Timeout = TimeSpan.FromSeconds(GlobalConfig.DefaultHttpTimeout)
};
internal readonly CookieContainer CookieContainer = new CookieContainer();
private readonly HttpClient HttpClient;
private readonly string Identifier;
internal static void Init() {
HttpClient.Timeout = TimeSpan.FromSeconds(Program.GlobalConfig.HttpTimeout);
// Most web services expect that UserAgent is set, so we declare it globally
// Any request can override that on as-needed basis (see: RequestOptions.FakeUserAgent)
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(DefaultUserAgent);
// Set max connection limit from default of 2 to desired value
ServicePointManager.DefaultConnectionLimit = MaxConnections;
@@ -74,12 +63,32 @@ namespace ArchiSteamFarm {
#endif
}
internal static async Task<bool> UrlGet(string request, CookieContainer cookieContainer = null, string referer = null) {
internal WebBrowser(string identifier) {
if (string.IsNullOrEmpty(identifier)) {
return;
}
Identifier = identifier;
HttpClientHandler httpClientHandler = new HttpClientHandler {
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
CookieContainer = CookieContainer
};
HttpClient = new HttpClient(httpClientHandler) {
Timeout = TimeSpan.FromSeconds(Program.GlobalConfig.HttpTimeout)
};
// Most web services expect that UserAgent is set, so we declare it globally
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(DefaultUserAgent);
}
internal async Task<bool> UrlGet(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return false;
}
HttpResponseMessage response = await UrlGetToResponse(request, cookieContainer, referer).ConfigureAwait(false);
HttpResponseMessage response = await UrlGetToResponse(request, referer).ConfigureAwait(false);
if (response == null) {
return false;
}
@@ -88,12 +97,12 @@ namespace ArchiSteamFarm {
return true;
}
internal static async Task<bool> UrlPost(string request, Dictionary<string, string> data = null, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<bool> UrlPost(string request, Dictionary<string, string> data = null, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return false;
}
HttpResponseMessage response = await UrlPostToResponse(request, data, cookieContainer, referer).ConfigureAwait(false);
HttpResponseMessage response = await UrlPostToResponse(request, data, referer).ConfigureAwait(false);
if (response == null) {
return false;
}
@@ -102,28 +111,28 @@ namespace ArchiSteamFarm {
return true;
}
internal static async Task<HttpResponseMessage> UrlGetToResponse(string request, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<HttpResponseMessage> UrlGetToResponse(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
return await UrlRequest(request, HttpMethod.Get, null, cookieContainer, referer).ConfigureAwait(false);
return await UrlRequest(request, HttpMethod.Get, null, referer).ConfigureAwait(false);
}
internal static async Task<HttpResponseMessage> UrlPostToResponse(string request, Dictionary<string, string> data = null, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<HttpResponseMessage> UrlPostToResponse(string request, Dictionary<string, string> data = null, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
return await UrlRequest(request, HttpMethod.Post, data, cookieContainer, referer).ConfigureAwait(false);
return await UrlRequest(request, HttpMethod.Post, data, referer).ConfigureAwait(false);
}
internal static async Task<string> UrlGetToContent(string request, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<string> UrlGetToContent(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
HttpResponseMessage httpResponse = await UrlGetToResponse(request, cookieContainer, referer).ConfigureAwait(false);
HttpResponseMessage httpResponse = await UrlGetToResponse(request, referer).ConfigureAwait(false);
if (httpResponse == null) {
return null;
}
@@ -134,12 +143,12 @@ namespace ArchiSteamFarm {
return result;
}
internal static async Task<Stream> UrlGetToStream(string request, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<Stream> UrlGetToStream(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
HttpResponseMessage httpResponse = await UrlGetToResponse(request, cookieContainer, referer).ConfigureAwait(false);
HttpResponseMessage httpResponse = await UrlGetToResponse(request, referer).ConfigureAwait(false);
if (httpResponse == null) {
return null;
}
@@ -150,12 +159,12 @@ namespace ArchiSteamFarm {
return result;
}
internal static async Task<HtmlDocument> UrlGetToHtmlDocument(string request, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<HtmlDocument> UrlGetToHtmlDocument(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
string content = await UrlGetToContent(request, cookieContainer, referer).ConfigureAwait(false);
string content = await UrlGetToContent(request, referer).ConfigureAwait(false);
if (string.IsNullOrEmpty(content)) {
return null;
}
@@ -167,12 +176,12 @@ namespace ArchiSteamFarm {
return htmlDocument;
}
internal static async Task<JObject> UrlGetToJObject(string request, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<JObject> UrlGetToJObject(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
string content = await UrlGetToContent(request, cookieContainer, referer).ConfigureAwait(false);
string content = await UrlGetToContent(request, referer).ConfigureAwait(false);
if (string.IsNullOrEmpty(content)) {
return null;
}
@@ -189,12 +198,12 @@ namespace ArchiSteamFarm {
return jObject;
}
internal static async Task<XmlDocument> UrlGetToXML(string request, CookieContainer cookieContainer = null, string referer = null) {
internal async Task<XmlDocument> UrlGetToXML(string request, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
string content = await UrlGetToContent(request, cookieContainer, referer).ConfigureAwait(false);
string content = await UrlGetToContent(request, referer).ConfigureAwait(false);
if (string.IsNullOrEmpty(content)) {
return null;
}
@@ -211,7 +220,7 @@ namespace ArchiSteamFarm {
return xmlDocument;
}
private static async Task<HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary<string, string> data = null, CookieContainer cookieContainer = null, string referer = null) {
private async Task<HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary<string, string> data = null, string referer = null) {
if (string.IsNullOrEmpty(request) || httpMethod == null) {
return null;
}
@@ -236,16 +245,7 @@ namespace ArchiSteamFarm {
}
try {
if (cookieContainer == null) {
responseMessage = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
} else {
using (HttpClientHandler httpClientHandler = new HttpClientHandler {
AutomaticDecompression = HttpClientHandler.AutomaticDecompression,
CookieContainer = cookieContainer
}) using (HttpClient httpClient = new HttpClient(httpClientHandler)) {
responseMessage = await httpClient.SendAsync(requestMessage).ConfigureAwait(false);
}
}
responseMessage = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
} catch { // Request failed, we don't need to know the exact reason, swallow exception
return null;
}
@@ -253,10 +253,10 @@ namespace ArchiSteamFarm {
if (responseMessage == null || !responseMessage.IsSuccessStatusCode) {
if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug) {
Logging.LogGenericError("Request: " + request + " failed!");
Logging.LogGenericError("Request: " + request + " failed!", Identifier);
if (responseMessage != null) {
Logging.LogGenericError("Status code: " + responseMessage.StatusCode);
Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false));
Logging.LogGenericError("Status code: " + responseMessage.StatusCode, Identifier);
Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false), Identifier);
}
}
return null;