mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 15:14:41 +00:00
Closes #764
This commit is contained in:
parent
f3e12b714f
commit
66c80e618f
9 changed files with 138 additions and 54 deletions
|
@ -26,6 +26,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" Version="1.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.3.0-beta2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.3.0-beta2" />
|
||||
|
|
|
@ -155,7 +155,9 @@ namespace ArchiSteamFarm {
|
|||
Client.Send(request);
|
||||
|
||||
try {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
return await new AsyncJob<RedeemGuestPassResponseCallback>(Client, request.SourceJobID);
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
return null;
|
||||
|
@ -180,7 +182,9 @@ namespace ArchiSteamFarm {
|
|||
Client.Send(request);
|
||||
|
||||
try {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
return await new AsyncJob<PurchaseResponseCallback>(Client, request.SourceJobID);
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericException(e);
|
||||
return null;
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ConfigureAwaitChecker.Analyzer" Version="1.0.1" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.7.4" />
|
||||
<PackageReference Include="Humanizer" Version="2.2.0" />
|
||||
<PackageReference Include="ILLink.Tasks" Version="0.1.5-preview-1461378" />
|
||||
|
|
|
@ -53,6 +53,12 @@ namespace ArchiSteamFarm {
|
|||
|
||||
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
private static readonly Dictionary<string, SemaphoreSlim> WebLimitingSemaphores = new Dictionary<string, SemaphoreSlim>(3) {
|
||||
{ SteamCommunityURL, new SemaphoreSlim(1, 1) },
|
||||
{ SteamStoreURL, new SemaphoreSlim(1, 1) },
|
||||
{ WebAPI.DefaultBaseAddress.Host, new SemaphoreSlim(1, 1) }
|
||||
};
|
||||
|
||||
private readonly SemaphoreSlim ApiKeySemaphore = new SemaphoreSlim(1, 1);
|
||||
private readonly Bot Bot;
|
||||
private readonly SemaphoreSlim PublicInventorySemaphore = new SemaphoreSlim(1, 1);
|
||||
|
@ -148,11 +154,16 @@ namespace ArchiSteamFarm {
|
|||
iEconService.Timeout = WebBrowser.Timeout;
|
||||
|
||||
try {
|
||||
response = await iEconService.DeclineTradeOffer(
|
||||
tradeofferid: tradeID.ToString(),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
);
|
||||
response = await WebLimitRequest(WebAPI.DefaultBaseAddress.Host,
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await iEconService.DeclineTradeOffer(
|
||||
tradeofferid: tradeID.ToString(),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
)
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
} catch (Exception e) {
|
||||
|
@ -191,13 +202,18 @@ namespace ArchiSteamFarm {
|
|||
iEconService.Timeout = WebBrowser.Timeout;
|
||||
|
||||
try {
|
||||
response = await iEconService.GetTradeOffers(
|
||||
active_only: 1,
|
||||
get_descriptions: 1,
|
||||
get_received_offers: 1,
|
||||
secure: true,
|
||||
time_historical_cutoff: uint.MaxValue
|
||||
);
|
||||
response = await WebLimitRequest(WebAPI.DefaultBaseAddress.Host,
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await iEconService.GetTradeOffers(
|
||||
active_only: 1,
|
||||
get_descriptions: 1,
|
||||
get_received_offers: 1,
|
||||
secure: true,
|
||||
time_historical_cutoff: uint.MaxValue
|
||||
)
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
} catch (Exception e) {
|
||||
|
@ -537,11 +553,16 @@ namespace ArchiSteamFarm {
|
|||
iPlayerService.Timeout = WebBrowser.Timeout;
|
||||
|
||||
try {
|
||||
response = await iPlayerService.GetOwnedGames(
|
||||
steamid: steamID,
|
||||
include_appinfo: 1,
|
||||
secure: true
|
||||
);
|
||||
response = await WebLimitRequest(WebAPI.DefaultBaseAddress.Host,
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await iPlayerService.GetOwnedGames(
|
||||
steamid: steamID,
|
||||
include_appinfo: 1,
|
||||
secure: true
|
||||
)
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
} catch (Exception e) {
|
||||
|
@ -576,10 +597,15 @@ namespace ArchiSteamFarm {
|
|||
iTwoFactorService.Timeout = WebBrowser.Timeout;
|
||||
|
||||
try {
|
||||
response = await iTwoFactorService.QueryTime(
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
);
|
||||
response = await WebLimitRequest(WebAPI.DefaultBaseAddress.Host,
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await iTwoFactorService.QueryTime(
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
)
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
} catch (Exception e) {
|
||||
|
@ -671,11 +697,16 @@ namespace ArchiSteamFarm {
|
|||
iEconService.Timeout = WebBrowser.Timeout;
|
||||
|
||||
try {
|
||||
response = await iEconService.GetTradeHoldDurations(
|
||||
secure: true,
|
||||
steamid_target: steamID,
|
||||
trade_offer_access_token: tradeToken ?? "" // TODO: Change me once https://github.com/SteamRE/SteamKit/pull/522 is merged
|
||||
);
|
||||
response = await WebLimitRequest(WebAPI.DefaultBaseAddress.Host,
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await iEconService.GetTradeHoldDurations(
|
||||
secure: true,
|
||||
steamid_target: steamID,
|
||||
trade_offer_access_token: tradeToken ?? "" // TODO: Change me once https://github.com/SteamRE/SteamKit/pull/522 is merged
|
||||
)
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
} catch (Exception e) {
|
||||
|
@ -850,18 +881,23 @@ namespace ArchiSteamFarm {
|
|||
// Do the magic
|
||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.LoggingIn, ISteamUserAuth));
|
||||
|
||||
KeyValue authResult = null;
|
||||
KeyValue response = null;
|
||||
using (dynamic iSteamUserAuth = WebAPI.GetAsyncInterface(ISteamUserAuth)) {
|
||||
iSteamUserAuth.Timeout = WebBrowser.Timeout;
|
||||
|
||||
try {
|
||||
authResult = await iSteamUserAuth.AuthenticateUser(
|
||||
steamid: steamID,
|
||||
sessionkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedSessionKey, 0, cryptedSessionKey.Length)),
|
||||
encrypted_loginkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedLoginKey, 0, cryptedLoginKey.Length)),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
);
|
||||
response = await WebLimitRequest(WebAPI.DefaultBaseAddress.Host,
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
// ReSharper disable once AccessToDisposedClosure
|
||||
async () => await iSteamUserAuth.AuthenticateUser(
|
||||
steamid: steamID,
|
||||
sessionkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedSessionKey, 0, cryptedSessionKey.Length)),
|
||||
encrypted_loginkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedLoginKey, 0, cryptedLoginKey.Length)),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
)
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
).ConfigureAwait(false);
|
||||
} catch (TaskCanceledException e) {
|
||||
Bot.ArchiLogger.LogGenericDebuggingException(e);
|
||||
} catch (Exception e) {
|
||||
|
@ -869,17 +905,17 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
if (authResult == null) {
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string steamLogin = authResult["token"].Value;
|
||||
string steamLogin = response["token"].Value;
|
||||
if (string.IsNullOrEmpty(steamLogin)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(steamLogin));
|
||||
return false;
|
||||
}
|
||||
|
||||
string steamLoginSecure = authResult["tokensecure"].Value;
|
||||
string steamLoginSecure = response["tokensecure"].Value;
|
||||
if (string.IsNullOrEmpty(steamLoginSecure)) {
|
||||
Bot.ArchiLogger.LogNullError(nameof(steamLoginSecure));
|
||||
return false;
|
||||
|
@ -1411,7 +1447,7 @@ namespace ArchiSteamFarm {
|
|||
|
||||
Dictionary<string, string> data = new Dictionary<string, string>(1) { { "pin", parentalPin } };
|
||||
|
||||
WebBrowser.BasicResponse response = await WebBrowser.UrlPost(serviceURL + request, data, serviceURL).ConfigureAwait(false);
|
||||
WebBrowser.BasicResponse response = await WebLimitRequest(serviceURL, async () => await WebBrowser.UrlPost(serviceURL + request, data, serviceURL).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
return (response != null) && !IsSessionExpiredUri(response.FinalUri);
|
||||
}
|
||||
|
||||
|
@ -1441,7 +1477,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
WebBrowser.HtmlDocumentResponse response = await WebBrowser.UrlGetToHtmlDocument(host + request).ConfigureAwait(false);
|
||||
WebBrowser.HtmlDocumentResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToHtmlDocument(host + request).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1485,7 +1521,7 @@ namespace ArchiSteamFarm {
|
|||
return default;
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<T> response = await WebBrowser.UrlGetToJsonObject<T>(host + request).ConfigureAwait(false);
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToJsonObject<T>(host + request).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return default;
|
||||
}
|
||||
|
@ -1529,7 +1565,7 @@ namespace ArchiSteamFarm {
|
|||
return null;
|
||||
}
|
||||
|
||||
WebBrowser.XmlDocumentResponse response = await WebBrowser.UrlGetToXmlDocument(host + request).ConfigureAwait(false);
|
||||
WebBrowser.XmlDocumentResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlGetToXmlDocument(host + request).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1573,7 +1609,7 @@ namespace ArchiSteamFarm {
|
|||
return false;
|
||||
}
|
||||
|
||||
WebBrowser.BasicResponse response = await WebBrowser.UrlHead(host + request).ConfigureAwait(false);
|
||||
WebBrowser.BasicResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlHead(host + request).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1646,7 +1682,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
WebBrowser.HtmlDocumentResponse response = await WebBrowser.UrlPostToHtmlDocument(host + request, data, referer).ConfigureAwait(false);
|
||||
WebBrowser.HtmlDocumentResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToHtmlDocument(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1719,7 +1755,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<T> response = await WebBrowser.UrlPostToJsonObject<T>(host + request, data, referer).ConfigureAwait(false);
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject<T>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return default;
|
||||
}
|
||||
|
@ -1795,7 +1831,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<T> response = await WebBrowser.UrlPostToJsonObject<T>(host + request, data, referer).ConfigureAwait(false);
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject<T>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return default;
|
||||
}
|
||||
|
@ -1868,7 +1904,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
WebBrowser.BasicResponse response = await WebBrowser.UrlPost(host + request, data, referer).ConfigureAwait(false);
|
||||
WebBrowser.BasicResponse response = await WebLimitRequest(host, async () => await WebBrowser.UrlPost(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1886,6 +1922,33 @@ namespace ArchiSteamFarm {
|
|||
return await UrlPostWithSession(host, request, data, referer, session, --maxTries).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static async Task<T> WebLimitRequest<T>(string service, Func<Task<T>> function) {
|
||||
if (string.IsNullOrEmpty(service) || (function == null)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(service) + " || " + nameof(function));
|
||||
return default;
|
||||
}
|
||||
|
||||
if (Program.GlobalConfig.WebLimiterDelay == 0) {
|
||||
return await function().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!WebLimitingSemaphores.TryGetValue(service, out SemaphoreSlim semaphore)) {
|
||||
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(service), service));
|
||||
return default;
|
||||
}
|
||||
|
||||
await semaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
Task<T> task = function();
|
||||
|
||||
Utilities.InBackground(async () => {
|
||||
await Task.WhenAll(task, Task.Delay(Program.GlobalConfig.WebLimiterDelay)).ConfigureAwait(false);
|
||||
semaphore.Release();
|
||||
});
|
||||
|
||||
return await task.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private enum ESession : byte {
|
||||
None,
|
||||
Lowercase,
|
||||
|
|
|
@ -405,7 +405,9 @@ namespace ArchiSteamFarm {
|
|||
await PICSSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
productInfoResultSet = await SteamApps.PICSGetProductInfo(appID, null, false);
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
} finally {
|
||||
|
@ -575,7 +577,9 @@ namespace ArchiSteamFarm {
|
|||
await PICSSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
productInfoResultSet = await SteamApps.PICSGetProductInfo(Enumerable.Empty<uint>(), packageIDs);
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
} finally {
|
||||
|
@ -841,7 +845,9 @@ namespace ArchiSteamFarm {
|
|||
SteamUser.WebAPIUserNonceCallback callback;
|
||||
|
||||
try {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
callback = await SteamUser.RequestWebAPIUserNonce();
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
await Connect(true).ConfigureAwait(false);
|
||||
|
@ -1352,7 +1358,9 @@ namespace ArchiSteamFarm {
|
|||
|
||||
try {
|
||||
if (DateTime.UtcNow.Subtract(ArchiHandler.LastPacketReceived).TotalSeconds > MinHeartBeatTTL) {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
await SteamFriends.RequestProfileInfo(SteamClient.SteamID);
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
}
|
||||
|
||||
HeartBeatFailures = 0;
|
||||
|
@ -2573,7 +2581,9 @@ namespace ArchiSteamFarm {
|
|||
SteamApps.FreeLicenseCallback callback;
|
||||
|
||||
try {
|
||||
#pragma warning disable ConfigureAwaitChecker // CAC001
|
||||
callback = await SteamApps.RequestFreeLicense(gameID);
|
||||
#pragma warning restore ConfigureAwaitChecker // CAC001
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
response.Append(FormatBotResponse(string.Format(Strings.BotAddLicense, gameID, EResult.Timeout)));
|
||||
|
|
|
@ -108,6 +108,9 @@ namespace ArchiSteamFarm {
|
|||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal readonly byte UpdatePeriod = 24;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal readonly ushort WebLimiterDelay = 200;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal ulong SteamOwnerID { get; private set; }
|
||||
|
||||
|
|
|
@ -598,7 +598,7 @@ namespace ArchiSteamFarm {
|
|||
WebSocketReceiveResult result = await webSocketContext.WebSocket.ReceiveAsync(new byte[0], CancellationToken.None).ConfigureAwait(false);
|
||||
|
||||
if (result.MessageType != WebSocketMessageType.Close) {
|
||||
await webSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "You're not supposed to be sending any message but Close!", CancellationToken.None);
|
||||
await webSocketContext.WebSocket.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "You're not supposed to be sending any message but Close!", CancellationToken.None).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -381,10 +381,6 @@ namespace ArchiSteamFarm {
|
|||
return response;
|
||||
}
|
||||
|
||||
if (Debugging.IsUserDebugging) {
|
||||
ArchiLogger.LogGenericDebug(string.Format(Strings.Content, await response.Content.ReadAsStringAsync().ConfigureAwait(false)));
|
||||
}
|
||||
|
||||
// WARNING: We still have undisposed response by now, make sure to dispose it ASAP if we're not returning it!
|
||||
if ((response.StatusCode >= HttpStatusCode.Ambiguous) && (response.StatusCode < HttpStatusCode.BadRequest) && (maxRedirections > 0)) {
|
||||
Uri redirectUri = response.Headers.Location;
|
||||
|
@ -410,8 +406,13 @@ namespace ArchiSteamFarm {
|
|||
return await InternalRequest(redirectUri, httpMethod, data, referer, httpCompletionOption, --maxRedirections).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
response.Dispose();
|
||||
return null;
|
||||
using (response) {
|
||||
if (Debugging.IsUserDebugging) {
|
||||
ArchiLogger.LogGenericDebug(string.Format(Strings.Content, await response.Content.ReadAsStringAsync().ConfigureAwait(false)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<StringResponse> UrlGetToString(string request, string referer = null, byte maxTries = MaxTries) {
|
||||
|
|
|
@ -24,5 +24,6 @@
|
|||
"SteamOwnerID": 0,
|
||||
"SteamProtocols": 3,
|
||||
"UpdateChannel": 1,
|
||||
"UpdatePeriod": 24
|
||||
"UpdatePeriod": 24,
|
||||
"WebLimiterDelay": 200
|
||||
}
|
Loading…
Reference in a new issue