mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-28 12:10:47 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e325d58944 | ||
|
|
185dde9d34 | ||
|
|
04afb5b891 | ||
|
|
a7442e61b1 | ||
|
|
2a35de0afd | ||
|
|
5351e61687 | ||
|
|
e83c468fba | ||
|
|
70cf69d9db | ||
|
|
a84d16a1dd | ||
|
|
ea3347b36d | ||
|
|
2865259a6a | ||
|
|
cb6c5e2de2 | ||
|
|
a6a8dfb78b |
2
ASF-ui
2
ASF-ui
Submodule ASF-ui updated: 1dd2f3797c...810095a335
@@ -8,8 +8,8 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -913,7 +913,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject<T>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject<T, Dictionary<string, string>>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
|
||||
if (response == null) {
|
||||
return null;
|
||||
@@ -1028,7 +1028,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject<T>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
WebBrowser.ObjectResponse<T> response = await WebLimitRequest(host, async () => await WebBrowser.UrlPostToJsonObject<T, List<KeyValuePair<string, string>>>(host + request, data, referer).ConfigureAwait(false)).ConfigureAwait(false);
|
||||
|
||||
if (response == null) {
|
||||
return null;
|
||||
|
||||
@@ -86,10 +86,18 @@ namespace ArchiSteamFarm {
|
||||
[PublicAPI]
|
||||
public readonly Commands Commands;
|
||||
|
||||
[JsonIgnore]
|
||||
[PublicAPI]
|
||||
public readonly SteamApps SteamApps;
|
||||
|
||||
[JsonIgnore]
|
||||
[PublicAPI]
|
||||
public readonly SteamConfiguration SteamConfiguration;
|
||||
|
||||
[JsonIgnore]
|
||||
[PublicAPI]
|
||||
public readonly SteamFriends SteamFriends;
|
||||
|
||||
[JsonProperty]
|
||||
[PublicAPI]
|
||||
public uint GamesToRedeemInBackgroundCount => BotDatabase?.GamesToRedeemInBackgroundCount ?? 0;
|
||||
@@ -110,8 +118,6 @@ namespace ArchiSteamFarm {
|
||||
internal readonly BotDatabase BotDatabase;
|
||||
|
||||
internal readonly ConcurrentDictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated, ulong AccessToken)> OwnedPackageIDs = new ConcurrentDictionary<uint, (EPaymentMethod PaymentMethod, DateTime TimeCreated, ulong AccessToken)>();
|
||||
internal readonly SteamApps SteamApps;
|
||||
internal readonly SteamFriends SteamFriends;
|
||||
|
||||
internal bool CanReceiveSteamCards => !IsAccountLimited && !IsAccountLocked;
|
||||
internal bool IsAccountLimited => AccountFlags.HasFlag(EAccountFlags.LimitedUser) || AccountFlags.HasFlag(EAccountFlags.LimitedUserForce);
|
||||
@@ -234,7 +240,7 @@ namespace ArchiSteamFarm {
|
||||
// Initialize
|
||||
SteamClient = new SteamClient(SteamConfiguration, botName);
|
||||
|
||||
if (Debugging.IsUserDebugging && Directory.Exists(SharedInfo.DebugDirectory)) {
|
||||
if (Debugging.IsDebugConfigured && Directory.Exists(SharedInfo.DebugDirectory)) {
|
||||
string debugListenerPath = Path.Combine(SharedInfo.DebugDirectory, botName);
|
||||
|
||||
try {
|
||||
@@ -2363,7 +2369,7 @@ namespace ArchiSteamFarm {
|
||||
foreach (SteamApps.LicenseListCallback.License license in callback.LicenseList.Where(license => license.PackageID != 0)) {
|
||||
OwnedPackageIDs[license.PackageID] = (license.PaymentMethod, license.TimeCreated, license.AccessToken);
|
||||
|
||||
if (!ASF.GlobalDatabase.PackagesData.TryGetValue(license.PackageID, out (uint ChangeNumber, HashSet<uint> AppIDs) packageData) || (packageData.ChangeNumber < license.LastChangeNumber) || (packageData.AppIDs == null)) {
|
||||
if (!ASF.GlobalDatabase.PackagesDataReadOnly.TryGetValue(license.PackageID, out (uint ChangeNumber, HashSet<uint> AppIDs) packageData) || (packageData.ChangeNumber < license.LastChangeNumber) || (packageData.AppIDs == null)) {
|
||||
packagesToRefresh[license.PackageID] = (uint) license.LastChangeNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +84,10 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "_LoginKey")]
|
||||
[JsonProperty(PropertyName = "_" + nameof(LoginKey))]
|
||||
private string BackingLoginKey;
|
||||
|
||||
[JsonProperty(PropertyName = "_MobileAuthenticator")]
|
||||
[JsonProperty(PropertyName = "_" + nameof(MobileAuthenticator))]
|
||||
private MobileAuthenticator BackingMobileAuthenticator;
|
||||
|
||||
private BotDatabase([NotNull] string filePath) {
|
||||
|
||||
@@ -35,14 +35,19 @@ using Newtonsoft.Json;
|
||||
namespace ArchiSteamFarm {
|
||||
public sealed class GlobalDatabase : SerializableFile {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
[PublicAPI]
|
||||
public readonly Guid Guid = Guid.NewGuid();
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal readonly ConcurrentDictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)> PackagesData = new ConcurrentDictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)>();
|
||||
[JsonIgnore]
|
||||
[PublicAPI]
|
||||
public IReadOnlyDictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)> PackagesDataReadOnly => PackagesData;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal readonly InMemoryServerListProvider ServerListProvider = new InMemoryServerListProvider();
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
private readonly ConcurrentDictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)> PackagesData = new ConcurrentDictionary<uint, (uint ChangeNumber, HashSet<uint> AppIDs)>();
|
||||
|
||||
private readonly SemaphoreSlim PackagesRefreshSemaphore = new SemaphoreSlim(1, 1);
|
||||
|
||||
internal uint CellID {
|
||||
@@ -58,7 +63,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "_CellID", Required = Required.DisallowNull)]
|
||||
[JsonProperty(PropertyName = "_" + nameof(CellID), Required = Required.DisallowNull)]
|
||||
private uint BackingCellID;
|
||||
|
||||
private GlobalDatabase([NotNull] string filePath) : this() {
|
||||
|
||||
@@ -324,15 +324,17 @@ namespace ArchiSteamFarm {
|
||||
|
||||
Logging.EnableTraceLogging();
|
||||
|
||||
DebugLog.AddListener(new Debugging.DebugListener());
|
||||
DebugLog.Enabled = true;
|
||||
if (Debugging.IsDebugConfigured) {
|
||||
DebugLog.AddListener(new Debugging.DebugListener());
|
||||
DebugLog.Enabled = true;
|
||||
|
||||
if (Directory.Exists(SharedInfo.DebugDirectory)) {
|
||||
try {
|
||||
Directory.Delete(SharedInfo.DebugDirectory, true);
|
||||
await Task.Delay(1000).ConfigureAwait(false); // Dirty workaround giving Windows some time to sync
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
if (Directory.Exists(SharedInfo.DebugDirectory)) {
|
||||
try {
|
||||
Directory.Delete(SharedInfo.DebugDirectory, true);
|
||||
await Task.Delay(1000).ConfigureAwait(false); // Dirty workaround giving Windows some time to sync
|
||||
} catch (Exception e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using AngleSharp;
|
||||
@@ -284,7 +285,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
[ItemCanBeNull]
|
||||
[PublicAPI]
|
||||
public async Task<BasicResponse> UrlPost(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) {
|
||||
public async Task<BasicResponse> UrlPost<T>(string request, T data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
@@ -321,7 +322,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
[ItemCanBeNull]
|
||||
[PublicAPI]
|
||||
public async Task<HtmlDocumentResponse> UrlPostToHtmlDocument(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) {
|
||||
public async Task<HtmlDocumentResponse> UrlPostToHtmlDocument<T>(string request, T data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
@@ -366,21 +367,21 @@ namespace ArchiSteamFarm {
|
||||
|
||||
[ItemCanBeNull]
|
||||
[PublicAPI]
|
||||
public async Task<ObjectResponse<T>> UrlPostToJsonObject<T>(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class {
|
||||
public async Task<ObjectResponse<TResult>> UrlPostToJsonObject<TResult, TData>(string request, TData data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where TResult : class where TData : class {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
ObjectResponse<T> result = null;
|
||||
ObjectResponse<TResult> result = null;
|
||||
|
||||
for (byte i = 0; i < maxTries; i++) {
|
||||
await using StreamResponse response = await UrlPostToStream(request, data, referer, requestOptions | ERequestOptions.ReturnClientErrors, 1).ConfigureAwait(false);
|
||||
|
||||
if (response?.StatusCode.IsClientErrorCode() == true) {
|
||||
if (requestOptions.HasFlag(ERequestOptions.ReturnClientErrors)) {
|
||||
result = new ObjectResponse<T>(response);
|
||||
result = new ObjectResponse<TResult>(response);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -390,21 +391,21 @@ namespace ArchiSteamFarm {
|
||||
continue;
|
||||
}
|
||||
|
||||
T obj;
|
||||
TResult obj;
|
||||
|
||||
try {
|
||||
using StreamReader steamReader = new StreamReader(response.Content);
|
||||
using JsonReader jsonReader = new JsonTextReader(steamReader);
|
||||
JsonSerializer serializer = new JsonSerializer();
|
||||
|
||||
obj = serializer.Deserialize<T>(jsonReader);
|
||||
obj = serializer.Deserialize<TResult>(jsonReader);
|
||||
} catch (Exception e) {
|
||||
ArchiLogger.LogGenericWarningException(e);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return new ObjectResponse<T>(response, obj);
|
||||
return new ObjectResponse<TResult>(response, obj);
|
||||
}
|
||||
|
||||
if (maxTries > 1) {
|
||||
@@ -567,7 +568,7 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await InternalRequest(new Uri(request), HttpMethod.Get, null, referer, httpCompletionOption).ConfigureAwait(false);
|
||||
return await InternalRequest<object>(new Uri(request), HttpMethod.Get, null, referer, httpCompletionOption).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> InternalHead(string request, string referer = null) {
|
||||
@@ -577,10 +578,10 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await InternalRequest(new Uri(request), HttpMethod.Head, null, referer).ConfigureAwait(false);
|
||||
return await InternalRequest<object>(new Uri(request), HttpMethod.Head, null, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> InternalPost(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) {
|
||||
private async Task<HttpResponseMessage> InternalPost<T>(string request, T data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead) where T : class {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
ArchiLogger.LogNullError(nameof(request));
|
||||
|
||||
@@ -590,7 +591,7 @@ namespace ArchiSteamFarm {
|
||||
return await InternalRequest(new Uri(request), HttpMethod.Post, data, referer, httpCompletionOption).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> InternalRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) {
|
||||
private async Task<HttpResponseMessage> InternalRequest<T>(Uri requestUri, HttpMethod httpMethod, T data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) where T : class {
|
||||
if ((requestUri == null) || (httpMethod == null)) {
|
||||
ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod));
|
||||
|
||||
@@ -605,10 +606,27 @@ namespace ArchiSteamFarm {
|
||||
#endif
|
||||
|
||||
if (data != null) {
|
||||
try {
|
||||
request.Content = new FormUrlEncodedContent(data);
|
||||
} catch (UriFormatException) {
|
||||
request.Content = new StringContent(string.Join("&", data.Select(kv => WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value))), null, "application/x-www-form-urlencoded");
|
||||
switch (data) {
|
||||
case HttpContent content:
|
||||
request.Content = content;
|
||||
|
||||
break;
|
||||
case IReadOnlyCollection<KeyValuePair<string, string>> dictionary:
|
||||
try {
|
||||
request.Content = new FormUrlEncodedContent(dictionary);
|
||||
} catch (UriFormatException) {
|
||||
request.Content = new StringContent(string.Join("&", dictionary.Select(kv => WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value))), null, "application/x-www-form-urlencoded");
|
||||
}
|
||||
|
||||
break;
|
||||
case string text:
|
||||
request.Content = new StringContent(text);
|
||||
|
||||
break;
|
||||
default:
|
||||
request.Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,7 +750,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
[ItemCanBeNull]
|
||||
private async Task<StreamResponse> UrlPostToStream(string request, IReadOnlyCollection<KeyValuePair<string, string>> data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) {
|
||||
private async Task<StreamResponse> UrlPostToStream<T>(string request, T data = null, string referer = null, ERequestOptions requestOptions = ERequestOptions.None, byte maxTries = MaxTries) where T : class {
|
||||
if (string.IsNullOrEmpty(request) || (maxTries == 0)) {
|
||||
ArchiLogger.LogNullError(nameof(request) + " || " + nameof(maxTries));
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ if [ -n "${DOTNET_RUNNING_IN_CONTAINER-}" ] && [ "$DOTNET_RUNNING_IN_CONTAINER"
|
||||
while [ "$loops" -gt 0 ]; do
|
||||
sleep 10
|
||||
|
||||
if [ -d "/var/tmp/.net/ArchiSteamFarm" ]; then
|
||||
find "/var/tmp/.net/ArchiSteamFarm" -mindepth 2 -maxdepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
|
||||
if [ -d "/var/tmp/.net" ]; then
|
||||
find "/var/tmp/.net" -mindepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
|
||||
fixed_path="$(echo "$broken_path" | sed 's/\\/\//g')"
|
||||
|
||||
mkdir -p "$(dirname "$fixed_path")"
|
||||
|
||||
@@ -70,8 +70,8 @@ if [ -n "${DOTNET_RUNNING_IN_CONTAINER-}" ] && [ "$DOTNET_RUNNING_IN_CONTAINER"
|
||||
while [ "$loops" -gt 0 ]; do
|
||||
sleep 10
|
||||
|
||||
if [ -d "/var/tmp/.net/ArchiSteamFarm" ]; then
|
||||
find "/var/tmp/.net/ArchiSteamFarm" -mindepth 2 -maxdepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
|
||||
if [ -d "/var/tmp/.net" ]; then
|
||||
find "/var/tmp/.net" -mindepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
|
||||
fixed_path="$(echo "$broken_path" | sed 's/\\/\//g')"
|
||||
|
||||
mkdir -p "$(dirname "$fixed_path")"
|
||||
|
||||
@@ -70,8 +70,8 @@ if [ -n "${DOTNET_RUNNING_IN_CONTAINER-}" ] && [ "$DOTNET_RUNNING_IN_CONTAINER"
|
||||
while [ "$loops" -gt 0 ]; do
|
||||
sleep 10
|
||||
|
||||
if [ -d "/var/tmp/.net/ArchiSteamFarm" ]; then
|
||||
find "/var/tmp/.net/ArchiSteamFarm" -mindepth 2 -maxdepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
|
||||
if [ -d "/var/tmp/.net" ]; then
|
||||
find "/var/tmp/.net" -mindepth 2 -name '*\\*' | while IFS="" read -r broken_path; do
|
||||
fixed_path="$(echo "$broken_path" | sed 's/\\/\//g')"
|
||||
|
||||
mkdir -p "$(dirname "$fixed_path")"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>4.2.2.0</Version>
|
||||
<Version>4.2.2.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
2
wiki
2
wiki
Submodule wiki updated: bc6f295df5...508359a397
Reference in New Issue
Block a user