mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-25 10:46:48 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f69ee6364d | ||
|
|
a468f9301d | ||
|
|
efa541d68d | ||
|
|
068ad1b06a | ||
|
|
f3bec05e1f | ||
|
|
a84dc1b01e | ||
|
|
ca4a3ee972 | ||
|
|
1c817426b8 | ||
|
|
5ec9bc14a9 | ||
|
|
67f451069a | ||
|
|
4eb73af250 | ||
|
|
ef60e23a53 | ||
|
|
2b57d0a9e6 | ||
|
|
ae183ae3ad | ||
|
|
725a3a5106 | ||
|
|
289f573b00 | ||
|
|
a8a6e658e2 | ||
|
|
797bb6fc98 | ||
|
|
41f61503fb | ||
|
|
764c979560 | ||
|
|
a0531ff1f3 | ||
|
|
30d5a4cdc2 | ||
|
|
750ff1a09a | ||
|
|
c5cc247e2d | ||
|
|
813bac5e52 | ||
|
|
267cf1597e | ||
|
|
4716312c3f | ||
|
|
31b735c3d3 | ||
|
|
e9baae4d03 | ||
|
|
f97142200f | ||
|
|
34bc25b023 | ||
|
|
ede24b9fd5 | ||
|
|
c656b61ce2 | ||
|
|
3fb804fbd1 | ||
|
|
eb5f126c76 | ||
|
|
815d0732c3 | ||
|
|
a517cf216d | ||
|
|
e5a6eede24 | ||
|
|
7a3c28f3f6 | ||
|
|
49381cea84 |
2
.github/workflows/crowdin-ci.yml
vendored
2
.github/workflows/crowdin-ci.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Upload latest strings for translation on Crowdin
|
||||
uses: crowdin/github-action@0749939f635900a2521aa6aac7a3766642b2dc71 # v2.11.0
|
||||
uses: crowdin/github-action@08713f00a50548bfe39b37e8f44afb53e7a802d4 # v2.12.0
|
||||
with:
|
||||
crowdin_branch_name: main
|
||||
config: '.github/crowdin.yml'
|
||||
|
||||
4
.github/workflows/docker-publish-latest.yml
vendored
4
.github/workflows/docker-publish-latest.yml
vendored
@@ -27,14 +27,14 @@ jobs:
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
6
.github/workflows/docker-publish-main.yml
vendored
6
.github/workflows/docker-publish-main.yml
vendored
@@ -28,14 +28,14 @@ jobs:
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
push: true
|
||||
|
||||
- name: Update DockerHub repository description
|
||||
uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4.0.2
|
||||
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
@@ -28,14 +28,14 @@ jobs:
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
|
||||
|
||||
- name: Login to ghcr.io
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
2
.github/workflows/publish.yml
vendored
2
.github/workflows/publish.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Node.js with npm
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
|
||||
with:
|
||||
check-latest: true
|
||||
node-version: ${{ env.NODE_JS_VERSION }}
|
||||
|
||||
2
.github/workflows/translations.yml
vendored
2
.github/workflows/translations.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
git reset --hard origin/master
|
||||
|
||||
- name: Download latest translations from Crowdin
|
||||
uses: crowdin/github-action@0749939f635900a2521aa6aac7a3766642b2dc71 # v2.11.0
|
||||
uses: crowdin/github-action@08713f00a50548bfe39b37e8f44afb53e7a802d4 # v2.12.0
|
||||
with:
|
||||
upload_sources: false
|
||||
download_translations: true
|
||||
|
||||
2
ASF-ui
2
ASF-ui
Submodule ASF-ui updated: d3b89fc7c3...a46fdc376d
@@ -526,7 +526,7 @@ internal sealed class Bot {
|
||||
ArgumentNullException.ThrowIfNull(itemsToSend);
|
||||
|
||||
Dictionary<(uint RealAppID, ulong ContextID, ulong ClassID), long> realResult = itemsToSend.GroupBy(static asset => (asset.RealAppID, asset.ContextID, asset.ClassID)).ToDictionary(static group => group.Key, static group => group.Sum(static asset => asset.Amount));
|
||||
Assert.AreEqual(expectedResult.Count, realResult.Count);
|
||||
Assert.HasCount(expectedResult.Count, realResult);
|
||||
Assert.IsTrue(expectedResult.All(expectation => realResult.TryGetValue(expectation.Key, out long reality) && (expectation.Value == reality)));
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,11 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
|
||||
try {
|
||||
while (true) {
|
||||
if (!await EnsureFileExists().ConfigureAwait(false)) {
|
||||
throw new IOException(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
|
||||
|
||||
await Task.Delay(SpinLockDelay * 25, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -128,7 +132,7 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
|
||||
try {
|
||||
stopwatch.Stop();
|
||||
|
||||
if (stopwatch.ElapsedMilliseconds >= millisecondsTimeout) {
|
||||
if (stopwatch.ElapsedMilliseconds > millisecondsTimeout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -136,7 +140,18 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
|
||||
|
||||
while (true) {
|
||||
if (!await EnsureFileExists().ConfigureAwait(false)) {
|
||||
throw new IOException(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
|
||||
ASF.ArchiLogger.LogGenericError(Strings.FormatWarningFailedWithError(nameof(EnsureFileExists)));
|
||||
|
||||
if (millisecondsTimeout <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int sleep = Math.Min(millisecondsTimeout, SpinLockDelay * 25);
|
||||
|
||||
await Task.Delay(sleep, cancellationToken).ConfigureAwait(false);
|
||||
millisecondsTimeout -= sleep;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -154,12 +169,14 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
|
||||
} catch (FileNotFoundException) {
|
||||
throw;
|
||||
} catch (IOException) {
|
||||
if (millisecondsTimeout <= SpinLockDelay) {
|
||||
if (millisecondsTimeout <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await Task.Delay(SpinLockDelay, cancellationToken).ConfigureAwait(false);
|
||||
millisecondsTimeout -= SpinLockDelay;
|
||||
int sleep = Math.Min(millisecondsTimeout, SpinLockDelay);
|
||||
|
||||
await Task.Delay(sleep, cancellationToken).ConfigureAwait(false);
|
||||
millisecondsTimeout -= sleep;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -184,20 +201,26 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directoryPath)) {
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
DirectoryInfo directoryInfo = Directory.CreateDirectory(directoryPath);
|
||||
try {
|
||||
if (OperatingSystem.IsWindows()) {
|
||||
DirectoryInfo directoryInfo = Directory.CreateDirectory(directoryPath);
|
||||
|
||||
try {
|
||||
DirectorySecurity directorySecurity = new(directoryPath, AccessControlSections.All);
|
||||
try {
|
||||
DirectorySecurity directorySecurity = new(directoryPath, AccessControlSections.All);
|
||||
|
||||
directoryInfo.SetAccessControl(directorySecurity);
|
||||
} catch (PrivilegeNotHeldException e) {
|
||||
// Non-critical, user might have no rights to manage the resource
|
||||
ASF.ArchiLogger.LogGenericDebuggingException(e);
|
||||
directoryInfo.SetAccessControl(directorySecurity);
|
||||
} catch (PrivilegeNotHeldException e) {
|
||||
// Non-critical, user might have no rights to manage the resource
|
||||
ASF.ArchiLogger.LogGenericDebuggingException(e);
|
||||
}
|
||||
} else if (OperatingSystem.IsFreeBSD() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) {
|
||||
// We require global access from all users, as other ASFs might need to put additional files in there
|
||||
Directory.CreateDirectory(directoryPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
|
||||
}
|
||||
} else if (OperatingSystem.IsFreeBSD() || OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) {
|
||||
// We require global access from all users, as other ASFs might need to put additional files in there
|
||||
Directory.CreateDirectory(directoryPath, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute | UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute | UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute);
|
||||
} catch (IOException e) {
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,11 +251,21 @@ internal sealed class CrossProcessFileBasedSemaphore : IAsyncDisposable, ICrossP
|
||||
await new FileStream(FilePath, fileStreamOptions).DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignored, if the file was already created in the meantime by another instance, this is fine
|
||||
ASF.ArchiLogger.LogGenericDebuggingException(e);
|
||||
if (i == 0) {
|
||||
// Ignored, if the file was already created in the meantime by another instance, this is fine
|
||||
ASF.ArchiLogger.LogGenericDebuggingException(e);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// It's not fine if the same issue happened again
|
||||
ASF.ArchiLogger.LogGenericException(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
// It's also not fine if we failed to create the file twice in a row
|
||||
return File.Exists(FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ public sealed class ASFResponse {
|
||||
internal ASFResponse(string buildVariant, bool canUpdate, GlobalConfig globalConfig, uint memoryUsage, DateTime processStartTime, Version version) {
|
||||
ArgumentException.ThrowIfNullOrEmpty(buildVariant);
|
||||
ArgumentNullException.ThrowIfNull(globalConfig);
|
||||
ArgumentOutOfRangeException.ThrowIfZero(memoryUsage);
|
||||
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(processStartTime, DateTime.UnixEpoch);
|
||||
ArgumentNullException.ThrowIfNull(version);
|
||||
|
||||
|
||||
@@ -584,7 +584,10 @@
|
||||
<value>Рівень бота {0}.</value>
|
||||
<comment>{0} will be replaced by bot's level</comment>
|
||||
</data>
|
||||
|
||||
<data name="BotInventory" xml:space="preserve">
|
||||
<value>{0}/{1} ({2}/{3}): {4} активів</value>
|
||||
<comment>{0} will be replaced by appID (number), {1} will be replaced by contextID (number), {2} will be replaced by app's name (string), {3} will be replaced by name of the context (string), {4} will be replaced by number of assets in the specified inventory (number).</comment>
|
||||
</data>
|
||||
<data name="ActivelyMatchingItems" xml:space="preserve">
|
||||
<value>Підбір предметів Steam, раунд #{0}...</value>
|
||||
<comment>{0} will be replaced by round number</comment>
|
||||
|
||||
@@ -2323,6 +2323,7 @@ public sealed class Bot : IAsyncDisposable, IDisposable {
|
||||
case EResult.Busy: // No clue, might be some internal gateway timeout, just try again
|
||||
case EResult.DuplicateRequest: // This will happen if user reacts to popup and tries to use the code afterwards, we have the code saved in ASF, we just need to try again
|
||||
case EResult.Expired: // Usually means refresh token is no longer authorized to use, otherwise just try again
|
||||
case EResult.Fail: // Usually some internal issue during authorization, just try again
|
||||
case EResult.FileNotFound: // User denied approval despite telling us that they accepted it, just try again
|
||||
case EResult.InvalidPassword: // Usually means refresh token is no longer authorized to use, otherwise just try again
|
||||
case EResult.NoConnection: // Usually network issues
|
||||
|
||||
@@ -1031,7 +1031,8 @@ public sealed class CardsFarmer : IAsyncDisposable, IDisposable {
|
||||
IElement? nameNode = htmlDocument.QuerySelectorAll("span[class='profile_small_header_location']").LastOrDefault();
|
||||
|
||||
if (nameNode == null) {
|
||||
Bot.ArchiLogger.LogNullError(nameNode);
|
||||
// Normally we should log null error here, but here's why we don't: https://www.youtube.com/watch?v=nSKp2StlS6s&t=40s
|
||||
Bot.ArchiLogger.LogGenericWarning(Strings.FormatErrorIsInvalid(nameof(nameNode)));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,13 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json.Serialization;
|
||||
using ArchiSteamFarm.Helpers.Json;
|
||||
|
||||
namespace ArchiSteamFarm.Steam.Data;
|
||||
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
public sealed class InventoryAppData {
|
||||
[JsonInclude]
|
||||
[JsonPropertyName("appid")]
|
||||
@@ -88,4 +90,7 @@ public sealed class InventoryAppData {
|
||||
[JsonPropertyName("trade_permissions")]
|
||||
[JsonRequired]
|
||||
public string TradePermissions { get; private init; } = "";
|
||||
|
||||
[JsonConstructor]
|
||||
private InventoryAppData() { }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>6.2.2.3</Version>
|
||||
<Version>6.2.3.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="AngleSharp" Version="1.3.0" />
|
||||
<PackageVersion Include="CryptSharpStandard" Version="1.0.0" />
|
||||
<PackageVersion Include="Humanizer" Version="3.0.0-beta.96" />
|
||||
<PackageVersion Include="Humanizer" Version="3.0.0-rc.6" />
|
||||
<PackageVersion Include="JetBrains.Annotations.Sources" Version="2025.2.2" />
|
||||
<PackageVersion Include="Markdig.Signed" Version="0.42.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.9" />
|
||||
<PackageVersion Include="Markdig.Signed" Version="0.43.0" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.ResxSourceGenerator" Version="5.0.0-1.25277.114" />
|
||||
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.14.0" />
|
||||
<PackageVersion Include="MSTest" Version="3.10.4" />
|
||||
<PackageVersion Include="MSTest" Version="4.0.1" />
|
||||
<PackageVersion Include="Nito.AsyncEx.Coordination" Version="5.1.2" />
|
||||
<PackageVersion Include="NLog.Web.AspNetCore" Version="6.0.4" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.12.0-beta.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.12.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.12.0" />
|
||||
<PackageVersion Include="Scalar.AspNetCore" Version="2.8.7" />
|
||||
<PackageVersion Include="NLog.Web.AspNetCore" Version="6.0.5" />
|
||||
<PackageVersion Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.13.1-beta.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.13.1" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.13.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="1.13.0" />
|
||||
<PackageVersion Include="OpenTelemetry.Instrumentation.Runtime" Version="1.13.0" />
|
||||
<PackageVersion Include="Scalar.AspNetCore" Version="2.9.0" />
|
||||
<PackageVersion Include="SteamKit2" Version="3.3.1" />
|
||||
<PackageVersion Include="System.Composition" Version="9.0.9" />
|
||||
<PackageVersion Include="System.Composition.AttributedModel" Version="9.0.9" />
|
||||
<PackageVersion Include="System.Composition" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Composition.AttributedModel" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Linq.Async" Version="6.0.3" />
|
||||
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="9.0.9" />
|
||||
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="9.0.10" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
2
wiki
2
wiki
Submodule wiki updated: 51924d6ec1...6cf74f5de9
Reference in New Issue
Block a user