Compare commits

..

51 Commits

Author SHA1 Message Date
JustArchi
5a2caab7fc Use MD5 for single instance path 2020-05-22 00:04:04 +02:00
JustArchi
8db90b6c2f Use hexadecimal strings for OS-wide resources
base64 slash character can cause problems with filepaths, besides, it's best to use ASCII only there due to various OS limitations
2020-05-21 23:42:32 +02:00
JustArchi
1c18fab68e Also chmod the directory for CrossProcessFileBasedSemaphore 2020-05-21 23:31:07 +02:00
JustArchi
42b59cd066 Update CrossProcessFileBasedSemaphore.cs 2020-05-21 23:09:53 +02:00
JustArchi
a47b85ff85 Allow CrossProcessFileBasedSemaphore to sleep asynchronously 2020-05-21 23:08:02 +02:00
JustArchi
0f1b3f05f9 Implement CrossProcessFileBasedSemaphore in place of CrossProcessMutexBasedSemaphore
Hopefully this one works better
2020-05-21 23:02:04 +02:00
JustArchi
01482e8dd0 Misc 2020-05-21 22:47:23 +02:00
JustArchi
771d8b3391 Do not attempt to join chat if the account is limited
It won't work anyway
2020-05-21 11:03:29 +02:00
JustArchi
9d17c5d791 Bump 2020-05-21 11:00:12 +02:00
JustArchi
0fe0e1a84d Disable cross-process semaphore on Linux for now 2020-05-21 10:51:57 +02:00
JustArchi
5d542fbf5e Merge branch 'master' of https://github.com/JustArchiNET/ArchiSteamFarm 2020-05-21 10:51:29 +02:00
dependabot-preview[bot]
72979ee309 Bump wiki from 297f6b9 to 9892a76
Bumps [wiki](https://github.com/JustArchiNET/ArchiSteamFarm.wiki) from `297f6b9` to `9892a76`.
- [Release notes](https://github.com/JustArchiNET/ArchiSteamFarm.wiki/releases)
- [Commits](297f6b9d8f...9892a76ff0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-21 01:22:09 +00:00
JustArchi
9054f03556 CI: Misc 2020-05-20 23:44:54 +02:00
JustArchi
6db61d164f Bump 2020-05-20 23:40:05 +02:00
JustArchi
9c7b9a6c7a Translations update 2020-05-20 23:36:32 +02:00
JustArchi
2b16198f22 Add LoginLimiter to cross-process semaphores 2020-05-20 23:09:27 +02:00
JustArchi
88bb631eea Update CrossProcessMutexBasedSemaphore.cs 2020-05-20 22:04:01 +02:00
JustArchi
6c22724835 Implement OS-wide, cross-process semaphores for ASF instances
Distinction is preserved on webproxy basis (even for LoginLimiter which shouldn't work like that)

Addresses crucial part of #1798
2020-05-20 22:01:29 +02:00
JustArchi
ab57163695 Update Logging.cs 2020-05-20 20:43:13 +02:00
dependabot-preview[bot]
e31b0403cd Bump ASF-ui from 4006f45 to dc5f0b1
Bumps [ASF-ui](https://github.com/JustArchiNET/ASF-ui) from `4006f45` to `dc5f0b1`.
- [Release notes](https://github.com/JustArchiNET/ASF-ui/releases)
- [Commits](4006f452f6...dc5f0b139f)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-20 08:11:37 +00:00
dependabot-preview[bot]
2642268383 Bump ASF-WebConfigGenerator from f8508ae to 296f453
Bumps [ASF-WebConfigGenerator](https://github.com/JustArchiNET/ASF-WebConfigGenerator) from `f8508ae` to `296f453`.
- [Release notes](https://github.com/JustArchiNET/ASF-WebConfigGenerator/releases)
- [Commits](f8508ae8d7...296f453fd3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-20 07:58:02 +00:00
dependabot-preview[bot]
690dca0bd7 Bump ASF-ui from e66d641 to 4006f45
Bumps [ASF-ui](https://github.com/JustArchiNET/ASF-ui) from `e66d641` to `4006f45`.
- [Release notes](https://github.com/JustArchiNET/ASF-ui/releases)
- [Commits](e66d6412e2...4006f452f6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-19 01:21:29 +00:00
dependabot-preview[bot]
28ba310b67 Bump NLog from 4.7.1 to 4.7.2
Bumps [NLog](https://github.com/NLog/NLog) from 4.7.1 to 4.7.2.
- [Release notes](https://github.com/NLog/NLog/releases)
- [Changelog](https://github.com/NLog/NLog/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/NLog/NLog/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-18 21:05:44 +00:00
JustArchi
a58b1bd4a3 Bump 2020-05-16 01:23:13 +02:00
JustArchi
9259043e6d Load NLog.config when not in AppContext.BaseDirectory instead
This is needed as custom NLog.config no longer gets loaded in single-file scenario, where NLog probes the directory of the unpacked files instead.

For non-single-publishes this doesn't change anything, as home directory is equal to base directory if not using custom path.
2020-05-16 00:54:28 +02:00
JustArchi
2d5b736e74 Bump 2020-05-15 23:26:09 +02:00
JustArchi
9fbbfe618b Translations update 2020-05-15 23:19:40 +02:00
JustArchi
3ace90432f Closes #1544 2020-05-15 17:43:09 +02:00
dependabot-preview[bot]
acd80a724d Bump NLog from 4.7.0 to 4.7.1
Bumps [NLog](https://github.com/NLog/NLog) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/NLog/NLog/releases)
- [Changelog](https://github.com/NLog/NLog/blob/v4.7.1/CHANGELOG.md)
- [Commits](https://github.com/NLog/NLog/compare/v4.7...v4.7.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-15 15:07:51 +00:00
Łukasz Domeradzki
57edf48d13 CI enhancements (#1789)
* Artifacts enhancements tests

* Update ci.yml

* More tests

* Update .travis.yml

* Update .travis.yml
2020-05-14 21:25:53 +02:00
dependabot-preview[bot]
eac5d2029f Bump ASF-WebConfigGenerator from 2e3c2e3 to 5492983
Bumps [ASF-WebConfigGenerator](https://github.com/JustArchiNET/ASF-WebConfigGenerator) from `2e3c2e3` to `5492983`.
- [Release notes](https://github.com/JustArchiNET/ASF-WebConfigGenerator/releases)
- [Commits](2e3c2e3582...5492983196)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 01:27:22 +00:00
dependabot-preview[bot]
bfc9d8f66a Bump ASF-ui from ce521ec to 44824ea
Bumps [ASF-ui](https://github.com/JustArchiNET/ASF-ui) from `ce521ec` to `44824ea`.
- [Release notes](https://github.com/JustArchiNET/ASF-ui/releases)
- [Commits](ce521ecc5a...44824eaf3a)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-14 01:23:54 +00:00
JustArchi
c01f588541 Revert "Use 2-part SDK channel for GitHub CI"
This reverts commit cda211a3d6.
2020-05-13 23:08:49 +02:00
JustArchi
cda211a3d6 Use 2-part SDK channel for GitHub CI
This should work now, I guess?
2020-05-13 23:06:30 +02:00
JustArchi
b527ee56b7 Update ci.yml 2020-05-13 23:02:12 +02:00
JustArchi
a3145251de Allow GitHub CI artifacts upload to fail
We might run into 429 rate limited when a lot of jobs are running at the same time, artifacts upload is not mandatory for verifying the build
2020-05-13 22:48:38 +02:00
dependabot-preview[bot]
5c2f0edadc Bump Microsoft.Extensions.Logging.Configuration from 3.1.3 to 3.1.4
Bumps [Microsoft.Extensions.Logging.Configuration](https://github.com/aspnet/Extensions) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/aspnet/Extensions/releases)
- [Commits](https://github.com/aspnet/Extensions/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-13 11:24:04 +00:00
dependabot-preview[bot]
af22b5158a Bump Microsoft.Extensions.Configuration.Json from 3.1.3 to 3.1.4
Bumps [Microsoft.Extensions.Configuration.Json](https://github.com/aspnet/Extensions) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/aspnet/Extensions/releases)
- [Commits](https://github.com/aspnet/Extensions/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-13 10:23:21 +00:00
dependabot-preview[bot]
80d4f377b0 Bump System.Collections.Immutable from 1.7.0 to 1.7.1
Bumps [System.Collections.Immutable](https://github.com/dotnet/corefx) from 1.7.0 to 1.7.1.
- [Release notes](https://github.com/dotnet/corefx/releases)
- [Commits](https://github.com/dotnet/corefx/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-12 17:30:15 +00:00
dependabot-preview[bot]
c611d1dee8 Bump Microsoft.AspNetCore.Mvc.NewtonsoftJson from 3.1.3 to 3.1.4
Bumps [Microsoft.AspNetCore.Mvc.NewtonsoftJson](https://github.com/aspnet/AspNetCore) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/aspnet/AspNetCore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/master/docs/CrossRepoBreakingChanges.md)
- [Commits](https://github.com/aspnet/AspNetCore/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-12 17:07:52 +00:00
dependabot-preview[bot]
56d430046a Bump System.Composition from 1.4.0 to 1.4.1
Bumps [System.Composition](https://github.com/dotnet/corefx) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/dotnet/corefx/releases)
- [Commits](https://github.com/dotnet/corefx/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-12 17:07:04 +00:00
dependabot-preview[bot]
30e9f36889 Bump ASF-ui from c6df93f to ce521ec
Bumps [ASF-ui](https://github.com/JustArchiNET/ASF-ui) from `c6df93f` to `ce521ec`.
- [Release notes](https://github.com/JustArchiNET/ASF-ui/releases)
- [Commits](c6df93f63c...ce521ecc5a)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-12 07:59:50 +00:00
dependabot-preview[bot]
11ceb1098f Bump ASF-WebConfigGenerator from b74c577 to 2e3c2e3
Bumps [ASF-WebConfigGenerator](https://github.com/JustArchiNET/ASF-WebConfigGenerator) from `b74c577` to `2e3c2e3`.
- [Release notes](https://github.com/JustArchiNET/ASF-WebConfigGenerator/releases)
- [Commits](b74c5774cd...2e3c2e3582)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-11 01:27:30 +00:00
dependabot-preview[bot]
031208f096 Bump wiki from 5c75fad to d95525c
Bumps [wiki](https://github.com/JustArchiNET/ArchiSteamFarm.wiki) from `5c75fad` to `d95525c`.
- [Release notes](https://github.com/JustArchiNET/ArchiSteamFarm.wiki/releases)
- [Commits](5c75fad9a6...d95525cd09)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-05-11 01:22:57 +00:00
JustArchi
ba37ab445d Correct volume entries
Docker documentation being outright wrong again
2020-05-10 19:10:06 +02:00
JustArchi
7edbe4a82f Misc 2020-05-10 18:53:10 +02:00
JustArchi
4d0bdf6789 Skip translation progress for invariant languages as well
Fixes annoying notice in docker containers
2020-05-10 18:46:55 +02:00
JustArchi
e98fe07c02 Add VOLUME directive to ASF dockerfiles 2020-05-10 18:28:17 +02:00
JustArchi
2e4142c93e Slightly optimize docker build process 2020-05-10 01:13:54 +02:00
JustArchi
38c9848509 Misc CI enhancements 2020-05-10 01:04:25 +02:00
JustArchi
8960478939 Bump 2020-05-09 20:00:34 +02:00
28 changed files with 604 additions and 171 deletions

View File

@@ -5,7 +5,7 @@ on: [push, pull_request]
env:
CONFIGURATION: Release
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SDK_VERSION: 3.1.201
DOTNET_SDK_VERSION: 3.1.300
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
GITHUB_JOBS: 2 # 2-core CPU, without HT: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources
NET_CORE_VERSION: netcoreapp3.1
@@ -56,13 +56,19 @@ jobs:
run: npm run-script build:ci --no-progress --prefix ASF-ui
- name: Build ArchiSteamFarm
run: dotnet build ArchiSteamFarm -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" --nologo
run: dotnet build ArchiSteamFarm -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" -p:UseAppHost=false --nologo
- name: Build ArchiSteamFarm.CustomPlugins.ExamplePlugin
run: dotnet build ArchiSteamFarm.CustomPlugins.ExamplePlugin -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" --nologo
run: dotnet build ArchiSteamFarm.CustomPlugins.ExamplePlugin -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" -p:UseAppHost=false --nologo
- name: Run ArchiSteamFarm.Tests
run: dotnet test ArchiSteamFarm.Tests -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" --nologo
run: dotnet test ArchiSteamFarm.Tests -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" -p:UseAppHost=false --nologo
- name: Perform cleanup in preparation for publishing
run: dotnet clean ArchiSteamFarm -c "${{ env.CONFIGURATION }}" -f "${{ env.NET_CORE_VERSION }}" -p:UseAppHost=false --nologo
- name: Restore packages in preparation for publishing
run: dotnet restore ArchiSteamFarm
- name: Publish ArchiSteamFarm on Unix
if: startsWith(matrix.os, 'macos-') || startsWith(matrix.os, 'ubuntu-')
@@ -76,7 +82,7 @@ jobs:
if [ "$1" = 'generic' ]; then
local variantArgs="-p:UseAppHost=false"
else
local variantArgs="-p:PublishTrimmed=true -r $1"
local variantArgs="-p:PublishSingleFile=true -p:PublishTrimmed=true -r $1"
fi
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o "out/${1}" "-p:ASFVariant=$1" --no-restore --nologo $variantArgs
@@ -88,10 +94,19 @@ jobs:
# Include .ico file for all platforms, since only Windows script can bundle it inside the exe
cp "resources/ASF.ico" "out/${1}/ArchiSteamFarm.ico"
}
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" --nologo
dotnet restore ArchiSteamFarm
if command -v 7z >/dev/null; then
7z a -bd -slp -tzip -mm=Deflate -mx=1 "out/ASF-${1}.zip" "${GITHUB_WORKSPACE}/out/${1}/*"
elif command -v zip >/dev/null; then
(
cd "${GITHUB_WORKSPACE}/out/${1}"
zip -1 -q -r "../ASF-${1}.zip" .
)
else
echo "ERROR: No supported zip tool!"
return 1
fi
}
jobs=""
@@ -132,7 +147,7 @@ jobs:
if ($variant -like 'generic*') {
$variantArgs = '-p:UseAppHost=false'
} else {
$variantArgs = '-p:PublishTrimmed=true', '-r', "$variant"
$variantArgs = '-p:PublishSingleFile=true', '-p:PublishTrimmed=true', '-r', "$variant"
}
dotnet publish ArchiSteamFarm -c "$env:CONFIGURATION" -f "$targetFramework" -o "out\$variant" "-p:ASFVariant=$variant" --no-restore --nologo $variantArgs
@@ -152,18 +167,12 @@ jobs:
Copy-Item 'resources\ASF.ico' "out\$variant\ArchiSteamFarm.ico"
}
}
}
dotnet clean ArchiSteamFarm -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" --nologo
7z a -bd -slp -tzip -mm=Deflate -mx=1 "out\ASF-$variant.zip" "$env:GITHUB_WORKSPACE\out\$variant\*"
if ($LastExitCode -ne 0) {
throw "Last command failed."
}
dotnet restore ArchiSteamFarm
if ($LastExitCode -ne 0) {
throw "Last command failed."
if ($LastExitCode -ne 0) {
throw "Last command failed."
}
}
foreach ($variant in $env:VARIANTS.Split([char[]] $null, [System.StringSplitOptions]::RemoveEmptyEntries)) {
@@ -173,44 +182,51 @@ jobs:
Get-Job | Receive-Job -Wait -AutoRemoveJob
- name: Upload ASF-generic
uses: actions/upload-artifact@v1
continue-on-error: true
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-generic
path: out/generic
path: out/ASF-generic.zip
- name: Upload ASF-generic-netf
continue-on-error: true
if: startsWith(matrix.os, 'windows-')
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-generic-netf
path: out/generic-netf
path: out/ASF-generic-netf.zip
- name: Upload ASF-linux-arm
uses: actions/upload-artifact@v1
continue-on-error: true
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-linux-arm
path: out/linux-arm
path: out/ASF-linux-arm.zip
- name: Upload ASF-linux-arm64
uses: actions/upload-artifact@v1
continue-on-error: true
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-linux-arm64
path: out/linux-arm64
path: out/ASF-linux-arm64.zip
- name: Upload ASF-linux-x64
uses: actions/upload-artifact@v1
continue-on-error: true
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-linux-x64
path: out/linux-x64
path: out/ASF-linux-x64.zip
- name: Upload ASF-osx-x64
uses: actions/upload-artifact@v1
continue-on-error: true
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-osx-x64
path: out/osx-x64
path: out/ASF-osx-x64.zip
- name: Upload ASF-win-x64
uses: actions/upload-artifact@v1
continue-on-error: true
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}_ASF-win-x64
path: out/win-x64
path: out/ASF-win-x64.zip

View File

@@ -17,6 +17,9 @@ env:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
- NET_CORE_VERSION: netcoreapp3.1
- VARIANTS="generic linux-arm linux-arm64 linux-x64 osx-x64 win-x64" # NOTE: When modifying variants, don't forget to update ASF_VARIANT definitions in SharedInfo.cs!
addons:
homebrew:
packages: p7zip
before_script:
- |
set -eu
@@ -31,15 +34,18 @@ script:
npm ci --no-progress --prefix ASF-ui
npm run-script deploy --no-progress --prefix ASF-ui
dotnet build ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" --nologo
dotnet build ArchiSteamFarm.CustomPlugins.ExamplePlugin -c "$CONFIGURATION" -f "$NET_CORE_VERSION" --nologo
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" --nologo
dotnet build ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:UseAppHost=false --nologo
dotnet build ArchiSteamFarm.CustomPlugins.ExamplePlugin -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:UseAppHost=false --nologo
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:UseAppHost=false --nologo
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:UseAppHost=false --nologo
dotnet restore ArchiSteamFarm
publish() {
if [ "$1" = 'generic' ]; then
local variantArgs="-p:UseAppHost=false"
else
local variantArgs="-p:PublishTrimmed=true -r $1"
local variantArgs="-p:PublishSingleFile=true -p:PublishTrimmed=true -r $1"
fi
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o "out/${1}" "-p:ASFVariant=$1" --no-restore --nologo $variantArgs
@@ -48,10 +54,22 @@ script:
if [ -d "ArchiSteamFarm/overlay/${1}" ]; then
cp "ArchiSteamFarm/overlay/${1}/"* "out/${1}"
fi
}
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" --nologo
dotnet restore ArchiSteamFarm
# Include .ico file for all platforms, since only Windows script can bundle it inside the exe
cp "resources/ASF.ico" "out/${1}/ArchiSteamFarm.ico"
if command -v 7z >/dev/null; then
7z a -bd -slp -tzip -mm=Deflate -mx=1 "out/ASF-${1}.zip" "${TRAVIS_BUILD_DIR}/out/${1}/*"
elif command -v zip >/dev/null; then
(
cd "${TRAVIS_BUILD_DIR}/out/${1}"
zip -1 -q -r "../ASF-${1}.zip" .
)
else
echo "ERROR: No supported zip tool!"
return 1
fi
}
jobs=""
@@ -76,5 +94,5 @@ matrix:
dist: bionic
- os: osx
# Ref: https://docs.travis-ci.com/user/reference/osx
dotnet: 3.1.201 # For OSX, we need absolute dotnet version until https://github.com/dotnet/core-setup/issues/4187 is resolved
osx_image: xcode11.3
dotnet: 3.1.300 # For OSX, we need absolute dotnet version until https://github.com/dotnet/core-setup/issues/4187 is resolved
osx_image: xcode11.4

2
ASF-ui

Submodule ASF-ui updated: c6df93f63c...dc5f0b139f

View File

@@ -92,7 +92,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceWhileStatementBraces/@EntryIndexedValue">WARNING</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FunctionComplexityOverflow/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=FunctionComplexityOverflow/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue">HINT</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=ImplicitlyCapturedClosure/@EntryIndexedValue">SUGGESTION</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=IncorrectBlankLinesNearBraces/@EntryIndexedValue">WARNING</s:String>

View File

@@ -22,11 +22,14 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ArchiSteamFarm.Helpers;
using ArchiSteamFarm.IPC;
using ArchiSteamFarm.Localization;
using ArchiSteamFarm.NLog;
@@ -55,6 +58,13 @@ namespace ArchiSteamFarm {
[PublicAPI]
public static WebBrowser WebBrowser { get; internal set; }
internal static ICrossProcessSemaphore ConfirmationsSemaphore { get; private set; }
internal static ICrossProcessSemaphore GiftsSemaphore { get; private set; }
internal static ICrossProcessSemaphore InventorySemaphore { get; private set; }
internal static ICrossProcessSemaphore LoginRateLimitingSemaphore { get; private set; }
internal static ICrossProcessSemaphore LoginSemaphore { get; private set; }
internal static ImmutableDictionary<string, (ICrossProcessSemaphore RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore)> WebLimitingSemaphores { get; private set; }
private static readonly SemaphoreSlim UpdateSemaphore = new SemaphoreSlim(1, 1);
private static Timer AutoUpdatesTimer;
@@ -131,6 +141,22 @@ namespace ArchiSteamFarm {
}
GlobalConfig = globalConfig;
string webProxyText = !string.IsNullOrEmpty(globalConfig.WebProxyText) ? "-" + BitConverter.ToString(Encoding.UTF8.GetBytes(globalConfig.WebProxyText)).Replace("-", "") : "";
ConfirmationsSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(ConfirmationsSemaphore) + webProxyText);
GiftsSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(GiftsSemaphore) + webProxyText);
InventorySemaphore ??= OS.CreateCrossProcessSemaphore(nameof(InventorySemaphore) + webProxyText);
LoginRateLimitingSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(LoginRateLimitingSemaphore) + webProxyText);
LoginSemaphore ??= OS.CreateCrossProcessSemaphore(nameof(LoginSemaphore) + webProxyText);
WebLimitingSemaphores ??= new Dictionary<string, (ICrossProcessSemaphore RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore)>(4, StringComparer.OrdinalIgnoreCase) {
{ nameof(ArchiWebHandler), (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ ArchiWebHandler.SteamCommunityURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(ArchiWebHandler.SteamCommunityURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ ArchiWebHandler.SteamHelpURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(ArchiWebHandler.SteamHelpURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ ArchiWebHandler.SteamStoreURL, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(ArchiWebHandler.SteamStoreURL)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ WebAPI.DefaultBaseAddress.Host, (OS.CreateCrossProcessSemaphore(nameof(ArchiWebHandler) + webProxyText + "-" + nameof(WebAPI)), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }
}.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase);
}
internal static void InitGlobalDatabase(GlobalDatabase globalDatabase) {
@@ -279,7 +305,7 @@ namespace ArchiSteamFarm {
string executable = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.AssemblyName);
if (File.Exists(executable)) {
OS.UnixSetFileAccessExecutable(executable);
OS.UnixSetFileAccess(executable, OS.EUnixPermission.Combined755);
}
}
@@ -657,8 +683,10 @@ namespace ArchiSteamFarm {
try {
await SteamDirectory.LoadAsync(steamConfiguration).ConfigureAwait(false);
ArchiLogger.LogGenericInfo(Strings.Success);
} catch {
} catch (Exception e) {
ArchiLogger.LogGenericWarningException(e);
ArchiLogger.LogGenericWarning(Strings.BotSteamDirectoryInitializationFailed);
await Task.Delay(5000).ConfigureAwait(false);
}
}
@@ -751,8 +779,8 @@ namespace ArchiSteamFarm {
case "":
// No directory, root folder
switch (fileName) {
case Logging.NLogConfigurationFile:
case SharedInfo.LogFile:
case "NLog.config":
// Files with those names in root directory we want to keep
continue;
}

View File

@@ -21,7 +21,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Threading;
@@ -36,7 +35,6 @@ using SteamKit2;
namespace ArchiSteamFarm {
public sealed class Actions : IAsyncDisposable {
private static readonly SemaphoreSlim GiftCardsSemaphore = new SemaphoreSlim(1, 1);
private static readonly SemaphoreSlim GiftsSemaphore = new SemaphoreSlim(1, 1);
private readonly Bot Bot;
private readonly ConcurrentHashSet<ulong> HandledGifts = new ConcurrentHashSet<ulong>();
@@ -46,7 +44,7 @@ namespace ArchiSteamFarm {
private bool ProcessingGiftsScheduled;
private bool TradingScheduled;
internal Actions([JetBrains.Annotations.NotNull] Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
internal Actions([NotNull] Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
public async ValueTask DisposeAsync() {
// Those are objects that are always being created if constructor doesn't throw exception
@@ -236,7 +234,6 @@ namespace ArchiSteamFarm {
}
[PublicAPI]
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
public async Task<(bool Success, string Message)> SendInventory(uint appID = Steam.Asset.SteamAppID, ulong contextID = Steam.Asset.SteamCommunityContextID, ulong targetSteamID = 0, string tradeToken = null, Func<Steam.Asset, bool> filterFunction = null) {
if ((appID == 0) || (contextID == 0)) {
Bot.ArchiLogger.LogNullError(nameof(appID) + " || " + nameof(contextID));
@@ -440,16 +437,22 @@ namespace ArchiSteamFarm {
private ulong GetFirstSteamMasterID() => Bot.BotConfig.SteamUserPermissions.Where(kv => (kv.Key != 0) && (kv.Value == BotConfig.EPermission.Master)).Select(kv => kv.Key).OrderByDescending(steamID => steamID != Bot.SteamID).ThenBy(steamID => steamID).FirstOrDefault();
private static async Task LimitGiftsRequestsAsync() {
if (ASF.GiftsSemaphore == null) {
ASF.ArchiLogger.LogNullError(nameof(ASF.GiftsSemaphore));
return;
}
if (ASF.GlobalConfig.GiftsLimiterDelay == 0) {
return;
}
await GiftsSemaphore.WaitAsync().ConfigureAwait(false);
await ASF.GiftsSemaphore.WaitAsync().ConfigureAwait(false);
Utilities.InBackground(
async () => {
await Task.Delay(ASF.GlobalConfig.GiftsLimiterDelay * 1000).ConfigureAwait(false);
GiftsSemaphore.Release();
ASF.GiftsSemaphore.Release();
}
);
}

View File

@@ -2,14 +2,14 @@
<PropertyGroup>
<ApplicationIcon>../resources/ASF.ico</ApplicationIcon>
<AssemblyVersion>4.2.0.7</AssemblyVersion>
<AssemblyVersion>4.2.1.2</AssemblyVersion>
<Authors>JustArchi</Authors>
<Company>JustArchi</Company>
<Copyright>Copyright © ArchiSteamFarm 2015-2020</Copyright>
<DefaultItemExcludes>$(DefaultItemExcludes);config/**;debug/**;out/**;overlay/**</DefaultItemExcludes>
<Description>ASF is a C# application with primary purpose of idling Steam cards from multiple accounts simultaneously.</Description>
<ErrorReport>none</ErrorReport>
<FileVersion>4.2.0.7</FileVersion>
<FileVersion>4.2.1.2</FileVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>8.0</LangVersion>
<NoWarn>1591</NoWarn>
@@ -62,18 +62,19 @@
<PackageReference Include="Markdig.Signed" Version="0.20.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.0.0" />
<PackageReference Include="NLog" Version="4.7.0" />
<PackageReference Include="NLog" Version="4.7.2" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.2" />
<PackageReference Include="SteamKit2" Version="2.3.0-Beta.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.4.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="5.4.1" />
<PackageReference Include="System.Composition" Version="1.4.0" />
<PackageReference Include="System.Composition" Version="1.4.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.7.0" />
<PackageReference Include="System.Linq.Async" Version="4.1.1" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
</ItemGroup>
@@ -86,9 +87,9 @@
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="3.1.3" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="3.1.4" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.1" />
<Reference Include="System.Net.Http">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Net.Http.dll</HintPath>
</Reference>

View File

@@ -22,7 +22,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -62,16 +61,6 @@ namespace ArchiSteamFarm {
private const string SteamHelpHost = "help.steampowered.com";
private const string SteamStoreHost = "store.steampowered.com";
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1, 1);
private static readonly ImmutableDictionary<string, (SemaphoreSlim RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore)> WebLimitingSemaphores = new Dictionary<string, (SemaphoreSlim RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore)>(4, StringComparer.Ordinal) {
{ nameof(ArchiWebHandler), (new SemaphoreSlim(1, 1), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ SteamCommunityURL, (new SemaphoreSlim(1, 1), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ SteamHelpURL, (new SemaphoreSlim(1, 1), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ SteamStoreURL, (new SemaphoreSlim(1, 1), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) },
{ WebAPI.DefaultBaseAddress.Host, (new SemaphoreSlim(1, 1), new SemaphoreSlim(WebBrowser.MaxConnections, WebBrowser.MaxConnections)) }
}.ToImmutableDictionary(StringComparer.Ordinal);
[PublicAPI]
public readonly ArchiCacheable<string> CachedApiKey;
@@ -88,7 +77,7 @@ namespace ArchiSteamFarm {
private bool MarkingInventoryScheduled;
private string VanityURL;
internal ArchiWebHandler([JetBrains.Annotations.NotNull] Bot bot) {
internal ArchiWebHandler([NotNull] Bot bot) {
Bot = bot ?? throw new ArgumentNullException(nameof(bot));
CachedApiKey = new ArchiCacheable<string>(ResolveApiKey);
@@ -121,14 +110,17 @@ namespace ArchiSteamFarm {
return string.IsNullOrEmpty(VanityURL) ? "/profiles/" + Bot.SteamID : "/id/" + VanityURL;
}
[JetBrains.Annotations.NotNull]
[NotNull]
[PublicAPI]
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
public async IAsyncEnumerable<Steam.Asset> GetInventoryAsync(ulong steamID = 0, uint appID = Steam.Asset.SteamAppID, ulong contextID = Steam.Asset.SteamCommunityContextID) {
if ((appID == 0) || (contextID == 0)) {
throw new ArgumentException(string.Format(Strings.ErrorObjectIsNull, nameof(appID) + " || " + nameof(contextID)));
}
if (ASF.InventorySemaphore == null) {
throw new ArgumentNullException(nameof(ASF.InventorySemaphore));
}
if (steamID == 0) {
if (!Initialized) {
for (byte i = 0; (i < ASF.GlobalConfig.ConnectionTimeout) && !Initialized && Bot.IsConnectedAndLoggedOn; i++) {
@@ -152,7 +144,7 @@ namespace ArchiSteamFarm {
HashSet<ulong> assetIDs = new HashSet<ulong>();
while (true) {
await InventorySemaphore.WaitAsync().ConfigureAwait(false);
await ASF.InventorySemaphore.WaitAsync().ConfigureAwait(false);
try {
Steam.InventoryResponse response = await UrlGetToJsonObjectWithSession<Steam.InventoryResponse>(SteamCommunityURL, request + (startAssetID > 0 ? "&start_assetid=" + startAssetID : "")).ConfigureAwait(false);
@@ -222,12 +214,12 @@ namespace ArchiSteamFarm {
startAssetID = response.LastAssetID;
} finally {
if (ASF.GlobalConfig.InventoryLimiterDelay == 0) {
InventorySemaphore.Release();
ASF.InventorySemaphore.Release();
} else {
Utilities.InBackground(
async () => {
await Task.Delay(ASF.GlobalConfig.InventoryLimiterDelay * 1000).ConfigureAwait(false);
InventorySemaphore.Release();
ASF.InventorySemaphore.Release();
}
);
}
@@ -1183,14 +1175,20 @@ namespace ArchiSteamFarm {
return default;
}
if (ASF.WebLimitingSemaphores == null) {
ASF.ArchiLogger.LogNullError(nameof(ASF.WebLimitingSemaphores));
return default;
}
if (ASF.GlobalConfig.WebLimiterDelay == 0) {
return await function().ConfigureAwait(false);
}
if (!WebLimitingSemaphores.TryGetValue(service, out (SemaphoreSlim RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore) limiters)) {
if (!ASF.WebLimitingSemaphores.TryGetValue(service, out (ICrossProcessSemaphore RateLimitingSemaphore, SemaphoreSlim OpenConnectionsSemaphore) limiters)) {
ASF.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(service), service));
if (!WebLimitingSemaphores.TryGetValue(nameof(ArchiWebHandler), out limiters)) {
if (!ASF.WebLimitingSemaphores.TryGetValue(nameof(ArchiWebHandler), out limiters)) {
ASF.ArchiLogger.LogNullError(nameof(limiters));
return await function().ConfigureAwait(false);
@@ -1381,7 +1379,7 @@ namespace ArchiSteamFarm {
return true;
}
[JetBrains.Annotations.NotNull]
[NotNull]
internal HttpClient GenerateDisposableHttpClient() => WebBrowser.GenerateDisposableHttpClient();
[ItemCanBeNull]
@@ -2155,9 +2153,15 @@ namespace ArchiSteamFarm {
}
internal async Task MarkInventory() {
if (ASF.InventorySemaphore == null) {
Bot.ArchiLogger.LogNullError(nameof(ASF.InventorySemaphore));
return;
}
// We aim to have a maximum of 2 tasks, one already working, and one waiting in the queue
// This way we can call this function as many times as needed e.g. because of Steam events
lock (InventorySemaphore) {
lock (ASF.InventorySemaphore) {
if (MarkingInventoryScheduled) {
return;
}
@@ -2165,10 +2169,10 @@ namespace ArchiSteamFarm {
MarkingInventoryScheduled = true;
}
await InventorySemaphore.WaitAsync().ConfigureAwait(false);
await ASF.InventorySemaphore.WaitAsync().ConfigureAwait(false);
try {
lock (InventorySemaphore) {
lock (ASF.InventorySemaphore) {
MarkingInventoryScheduled = false;
}
@@ -2176,12 +2180,12 @@ namespace ArchiSteamFarm {
await UrlHeadWithSession(SteamCommunityURL, request, false).ConfigureAwait(false);
} finally {
if (ASF.GlobalConfig.InventoryLimiterDelay == 0) {
InventorySemaphore.Release();
ASF.InventorySemaphore.Release();
} else {
Utilities.InBackground(
async () => {
await Task.Delay(ASF.GlobalConfig.InventoryLimiterDelay * 1000).ConfigureAwait(false);
InventorySemaphore.Release();
ASF.InventorySemaphore.Release();
}
);
}

View File

@@ -24,7 +24,6 @@ using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
@@ -62,8 +61,6 @@ namespace ArchiSteamFarm {
internal static EOSType OSType { get; private set; } = EOSType.Unknown;
private static readonly SemaphoreSlim BotsSemaphore = new SemaphoreSlim(1, 1);
private static readonly SemaphoreSlim LoginRateLimitingSemaphore = new SemaphoreSlim(1, 1);
private static readonly SemaphoreSlim LoginSemaphore = new SemaphoreSlim(1, 1);
[JsonIgnore]
[PublicAPI]
@@ -151,7 +148,7 @@ namespace ArchiSteamFarm {
#pragma warning disable IDE0051
[JsonProperty(PropertyName = SharedInfo.UlongCompatibilityStringPrefix + nameof(SteamID))]
[JetBrains.Annotations.NotNull]
[NotNull]
private string SSteamID => SteamID.ToString();
#pragma warning restore IDE0051
@@ -203,7 +200,7 @@ namespace ArchiSteamFarm {
private string TwoFactorCode;
private byte TwoFactorCodeFailures;
private Bot([JetBrains.Annotations.NotNull] string botName, [JetBrains.Annotations.NotNull] BotConfig botConfig, [JetBrains.Annotations.NotNull] BotDatabase botDatabase) {
private Bot([NotNull] string botName, [NotNull] BotConfig botConfig, [NotNull] BotDatabase botDatabase) {
if (string.IsNullOrEmpty(botName) || (botConfig == null) || (botDatabase == null)) {
throw new ArgumentNullException(nameof(botName) + " || " + nameof(botConfig) + " || " + nameof(botDatabase));
}
@@ -1913,7 +1910,7 @@ namespace ArchiSteamFarm {
}
private async Task JoinMasterChatGroupID() {
if (BotConfig.SteamMasterClanID == 0) {
if ((BotConfig.SteamMasterClanID == 0) || IsAccountLimited) {
return;
}
@@ -1939,23 +1936,29 @@ namespace ArchiSteamFarm {
}
private static async Task LimitLoginRequestsAsync() {
if (ASF.GlobalConfig.LoginLimiterDelay == 0) {
await LoginRateLimitingSemaphore.WaitAsync().ConfigureAwait(false);
LoginRateLimitingSemaphore.Release();
if ((ASF.LoginSemaphore == null) || (ASF.LoginRateLimitingSemaphore == null)) {
ASF.ArchiLogger.LogNullError(nameof(ASF.LoginSemaphore) + " || " + nameof(ASF.LoginRateLimitingSemaphore));
return;
}
await LoginSemaphore.WaitAsync().ConfigureAwait(false);
if (ASF.GlobalConfig.LoginLimiterDelay == 0) {
await ASF.LoginRateLimitingSemaphore.WaitAsync().ConfigureAwait(false);
ASF.LoginRateLimitingSemaphore.Release();
return;
}
await ASF.LoginSemaphore.WaitAsync().ConfigureAwait(false);
try {
await LoginRateLimitingSemaphore.WaitAsync().ConfigureAwait(false);
LoginRateLimitingSemaphore.Release();
await ASF.LoginRateLimitingSemaphore.WaitAsync().ConfigureAwait(false);
ASF.LoginRateLimitingSemaphore.Release();
} finally {
Utilities.InBackground(
async () => {
await Task.Delay(ASF.GlobalConfig.LoginLimiterDelay * 1000).ConfigureAwait(false);
LoginSemaphore.Release();
ASF.LoginSemaphore.Release();
}
);
}
@@ -2074,6 +2077,12 @@ namespace ArchiSteamFarm {
return;
}
if (ASF.LoginRateLimitingSemaphore == null) {
ASF.ArchiLogger.LogNullError(nameof(ASF.LoginRateLimitingSemaphore));
return;
}
EResult lastLogOnResult = LastLogOnResult;
LastLogOnResult = EResult.Invalid;
HeartBeatFailures = 0;
@@ -2120,14 +2129,14 @@ namespace ArchiSteamFarm {
case EResult.RateLimitExceeded:
ArchiLogger.LogGenericInfo(string.Format(Strings.BotRateLimitExceeded, TimeSpan.FromMinutes(LoginCooldownInMinutes).ToHumanReadable()));
if (!await LoginRateLimitingSemaphore.WaitAsync(1000 * WebBrowser.MaxTries).ConfigureAwait(false)) {
if (!await ASF.LoginRateLimitingSemaphore.WaitAsync(1000 * WebBrowser.MaxTries).ConfigureAwait(false)) {
break;
}
try {
await Task.Delay(LoginCooldownInMinutes * 60 * 1000).ConfigureAwait(false);
} finally {
LoginRateLimitingSemaphore.Release();
ASF.LoginRateLimitingSemaphore.Release();
}
break;
@@ -2820,7 +2829,6 @@ namespace ArchiSteamFarm {
WalletCurrency = callback.Currency;
}
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
private async Task RedeemGamesInBackground() {
if (!await GamesRedeemerInBackgroundSemaphore.WaitAsync(0).ConfigureAwait(false)) {
return;

View File

@@ -23,7 +23,6 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Net;
@@ -98,7 +97,7 @@ namespace ArchiSteamFarm {
private bool PermanentlyPaused;
private bool ShouldResumeFarming = true;
internal CardsFarmer([JetBrains.Annotations.NotNull] Bot bot) {
internal CardsFarmer([NotNull] Bot bot) {
Bot = bot ?? throw new ArgumentNullException(nameof(bot));
if (ASF.GlobalConfig.IdleFarmingPeriod > 0) {
@@ -373,7 +372,6 @@ namespace ArchiSteamFarm {
await StartFarming().ConfigureAwait(false);
}
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
private async Task CheckPage(IDocument htmlDocument, ISet<uint> parsedAppIDs) {
if ((htmlDocument == null) || (parsedAppIDs == null)) {
Bot.ArchiLogger.LogNullError(nameof(htmlDocument) + " || " + nameof(parsedAppIDs));
@@ -1243,7 +1241,7 @@ namespace ArchiSteamFarm {
internal uint PlayableAppID { get; set; }
internal Game(uint appID, [JetBrains.Annotations.NotNull] string gameName, float hoursPlayed, ushort cardsRemaining, byte badgeLevel) {
internal Game(uint appID, [NotNull] string gameName, float hoursPlayed, ushort cardsRemaining, byte badgeLevel) {
if ((appID == 0) || string.IsNullOrEmpty(gameName) || (hoursPlayed < 0) || (cardsRemaining == 0)) {
throw new ArgumentOutOfRangeException(nameof(appID) + " || " + nameof(gameName) + " || " + nameof(hoursPlayed) + " || " + nameof(cardsRemaining));
}

View File

@@ -21,7 +21,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Text;
@@ -40,7 +39,7 @@ namespace ArchiSteamFarm {
private readonly Bot Bot;
private readonly Dictionary<uint, string> CachedGamesOwned = new Dictionary<uint, string>();
internal Commands([JetBrains.Annotations.NotNull] Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
internal Commands([NotNull] Bot bot) => Bot = bot ?? throw new ArgumentNullException(nameof(bot));
[PublicAPI]
public static string FormatBotResponse(string response, string botName) {
@@ -1635,7 +1634,6 @@ namespace ArchiSteamFarm {
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
}
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
private async Task<(string Response, Dictionary<string, string> OwnedGames)> ResponseOwns(ulong steamID, string query) {
if ((steamID == 0) || string.IsNullOrEmpty(query)) {
Bot.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(query));
@@ -2154,7 +2152,6 @@ namespace ArchiSteamFarm {
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null;
}
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
private async Task<string> ResponseRedeem(ulong steamID, string keysText, ERedeemFlags redeemFlags = ERedeemFlags.None) {
if ((steamID == 0) || string.IsNullOrEmpty(keysText)) {
Bot.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(keysText));

View File

@@ -0,0 +1,199 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2020 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Diagnostics;
using System.IO;
using System.Security.AccessControl;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace ArchiSteamFarm.Helpers {
internal sealed class CrossProcessFileBasedSemaphore : ICrossProcessSemaphore {
private const ushort SpinLockDelay = 1000; // In milliseconds
private readonly string FilePath;
private readonly SemaphoreSlim LocalSemaphore = new SemaphoreSlim(1, 1);
private FileStream FileLock;
internal CrossProcessFileBasedSemaphore([NotNull] string name) {
if (string.IsNullOrEmpty(name)) {
throw new ArgumentNullException(nameof(name));
}
FilePath = Path.Combine(Path.GetTempPath(), SharedInfo.ASF, name);
EnsureFileExists();
}
public void Dispose() {
LocalSemaphore.Dispose();
FileLock?.Dispose();
}
void ICrossProcessSemaphore.Release() {
lock (LocalSemaphore) {
if (FileLock == null) {
throw new ArgumentNullException(nameof(FileLock));
}
FileLock.Dispose();
FileLock = null;
}
LocalSemaphore.Release();
}
async Task ICrossProcessSemaphore.WaitAsync() {
await LocalSemaphore.WaitAsync().ConfigureAwait(false);
bool success = false;
try {
while (true) {
try {
lock (LocalSemaphore) {
if (FileLock != null) {
throw new ArgumentNullException(nameof(FileLock));
}
EnsureFileExists();
FileLock = new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
success = true;
return;
}
} catch (IOException) {
await Task.Delay(SpinLockDelay).ConfigureAwait(false);
}
}
} finally {
if (!success) {
LocalSemaphore.Release();
}
}
}
async Task<bool> ICrossProcessSemaphore.WaitAsync(int millisecondsTimeout) {
Stopwatch stopwatch = Stopwatch.StartNew();
if (!await LocalSemaphore.WaitAsync(millisecondsTimeout).ConfigureAwait(false)) {
stopwatch.Stop();
return false;
}
stopwatch.Stop();
bool success = false;
try {
millisecondsTimeout -= (int) stopwatch.ElapsedMilliseconds;
if (millisecondsTimeout <= 0) {
return false;
}
try {
while (true) {
try {
lock (LocalSemaphore) {
if (FileLock != null) {
throw new ArgumentNullException(nameof(FileLock));
}
EnsureFileExists();
FileLock = new FileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
success = true;
return true;
}
} catch (IOException) {
if (millisecondsTimeout <= SpinLockDelay) {
return false;
}
await Task.Delay(SpinLockDelay).ConfigureAwait(false);
millisecondsTimeout -= SpinLockDelay;
}
}
} finally {
if (!success) {
LocalSemaphore.Release();
}
}
} finally {
if (!success) {
LocalSemaphore.Release();
}
}
}
private void EnsureFileExists() {
FileInfo fileInfo = new FileInfo(FilePath);
if (fileInfo.Exists) {
return;
}
string directoryPath = Path.GetDirectoryName(FilePath);
if (string.IsNullOrEmpty(directoryPath)) {
ASF.ArchiLogger.LogNullError(nameof(directoryPath));
return;
}
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
if (!directoryInfo.Exists) {
Directory.CreateDirectory(directoryPath);
if (OS.IsUnix) {
OS.UnixSetFileAccess(directoryPath, OS.EUnixPermission.Combined777);
} else {
DirectorySecurity directorySecurity = new DirectorySecurity(FilePath, AccessControlSections.All);
directoryInfo.SetAccessControl(directorySecurity);
}
}
try {
using (new FileStream(FilePath, FileMode.CreateNew)) { }
if (OS.IsUnix) {
OS.UnixSetFileAccess(FilePath, OS.EUnixPermission.Combined777);
} else {
FileSecurity fileSecurity = new FileSecurity(FilePath, AccessControlSections.All);
fileInfo.SetAccessControl(fileSecurity);
}
} catch (IOException) {
// Ignored, if the file was already created in the meantime by another instance, this is fine
}
}
}
}

View File

@@ -0,0 +1,53 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2020 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace ArchiSteamFarm.Helpers {
internal sealed class CrossProcessSemaphore : ICrossProcessSemaphore {
private readonly Semaphore GlobalSemaphore;
internal CrossProcessSemaphore([NotNull] string name) {
if (string.IsNullOrEmpty(name)) {
throw new ArgumentNullException(nameof(name));
}
GlobalSemaphore = new Semaphore(1, 1, name);
}
public void Dispose() => GlobalSemaphore.Dispose();
void ICrossProcessSemaphore.Release() => GlobalSemaphore.Release();
[NotNull]
Task ICrossProcessSemaphore.WaitAsync() {
GlobalSemaphore.WaitOne();
return Task.CompletedTask;
}
[NotNull]
Task<bool> ICrossProcessSemaphore.WaitAsync(int millisecondsTimeout) => Task.FromResult(GlobalSemaphore.WaitOne(millisecondsTimeout));
}
}

View File

@@ -0,0 +1,31 @@
// _ _ _ ____ _ _____
// / \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
// / _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
// / ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
// /_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
// |
// Copyright 2015-2020 Łukasz "JustArchi" Domeradzki
// Contact: JustArchi@JustArchi.net
// |
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// |
// http://www.apache.org/licenses/LICENSE-2.0
// |
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Threading.Tasks;
namespace ArchiSteamFarm.Helpers {
internal interface ICrossProcessSemaphore : IDisposable {
internal void Release();
internal Task WaitAsync();
internal Task<bool> WaitAsync(int millisecondsTimeout);
}
}

View File

@@ -40,7 +40,6 @@ namespace ArchiSteamFarm {
private const byte SteamTimeTTL = 24; // For how many hours we can assume that SteamTimeDifference is correct
private static readonly char[] CodeCharacters = { '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y' };
private static readonly SemaphoreSlim ConfirmationsSemaphore = new SemaphoreSlim(1, 1);
private static readonly SemaphoreSlim TimeSemaphore = new SemaphoreSlim(1, 1);
private static DateTime LastSteamTimeCheck;
@@ -439,16 +438,22 @@ namespace ArchiSteamFarm {
}
private static async Task LimitConfirmationsRequestsAsync() {
if (ASF.ConfirmationsSemaphore == null) {
ASF.ArchiLogger.LogNullError(nameof(ASF.ConfirmationsSemaphore));
return;
}
if (ASF.GlobalConfig.ConfirmationsLimiterDelay == 0) {
return;
}
await ConfirmationsSemaphore.WaitAsync().ConfigureAwait(false);
await ASF.ConfirmationsSemaphore.WaitAsync().ConfigureAwait(false);
Utilities.InBackground(
async () => {
await Task.Delay(ASF.GlobalConfig.ConfirmationsLimiterDelay * 1000).ConfigureAwait(false);
ConfirmationsSemaphore.Release();
ASF.ConfirmationsSemaphore.Release();
}
);
}

View File

@@ -35,7 +35,9 @@ using NLog.Targets;
namespace ArchiSteamFarm.NLog {
internal static class Logging {
private const byte ConsoleResponsivenessDelay = 250; // In miliseconds
internal const string NLogConfigurationFile = "NLog.config";
private const byte ConsoleResponsivenessDelay = 250; // In milliseconds
private const string GeneralLayout = @"${date:format=yyyy-MM-dd HH\:mm\:ss}|${processname}-${processid}|${level:uppercase=true}|" + LayoutMessage;
private const string LayoutMessage = @"${logger}|${message}${onexception:inner= ${exception:format=toString,Data}}";
@@ -142,8 +144,8 @@ namespace ArchiSteamFarm.NLog {
internal static void InitCoreLoggers(bool uniqueInstance) {
try {
if ((Directory.GetCurrentDirectory() != SharedInfo.HomeDirectory) && File.Exists("NLog.config")) {
LogManager.Configuration = new XmlLoggingConfiguration("NLog.config");
if ((Directory.GetCurrentDirectory() != AppContext.BaseDirectory) && File.Exists(NLogConfigurationFile)) {
LogManager.Configuration = new XmlLoggingConfiguration(NLogConfigurationFile);
}
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);

View File

@@ -23,9 +23,11 @@ using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using ArchiSteamFarm.Helpers;
using ArchiSteamFarm.Localization;
using JetBrains.Annotations;
@@ -60,6 +62,25 @@ namespace ArchiSteamFarm {
}
}
internal static ICrossProcessSemaphore CreateCrossProcessSemaphore(string objectName) {
if (string.IsNullOrEmpty(objectName)) {
ASF.ArchiLogger.LogNullError(nameof(objectName));
return null;
}
string resourceName = GetOsResourceName(objectName);
try {
return new CrossProcessSemaphore(resourceName);
} catch (PlatformNotSupportedException e) {
// CrossProcessSemaphore is currently available only for Windows platforms, we use alternative synchronization for other OSes
ASF.ArchiLogger.LogGenericDebuggingException(e);
return new CrossProcessFileBasedSemaphore(resourceName);
}
}
internal static void Init(bool systemRequired, GlobalConfig.EOptimizationMode optimizationMode) {
if (!Enum.IsDefined(typeof(GlobalConfig.EOptimizationMode), optimizationMode)) {
ASF.ArchiLogger.LogNullError(nameof(optimizationMode));
@@ -94,7 +115,14 @@ namespace ArchiSteamFarm {
return false;
}
string uniqueName = "Global\\" + SharedInfo.AssemblyName + "-" + Convert.ToBase64String(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()));
string uniqueName;
// The only purpose of using hashingAlgorithm here is to cut on a potential size of the resource name - paths can be really long, and we almost certainly have some upper limit on the resource name we can allocate
// At the same time it'd be the best if we avoided all special characters, such as '/' found e.g. in base64, as we can't be sure that it's not a prohibited character in regards to native OS implementation
// Because of that, MD5 is sufficient for our case, as it generates alphanumeric characters only, and is barely 128-bit long. We don't need any kind of complex cryptography or collision detection here, any hashing algorithm will do, and the shorter the better
using (MD5 hashingAlgorithm = MD5.Create()) {
uniqueName = "Global\\" + GetOsResourceName(nameof(SingleInstance)) + "-" + BitConverter.ToString(hashingAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(Directory.GetCurrentDirectory()))).Replace("-", "");
}
Mutex singleInstance = new Mutex(true, uniqueName, out bool result);
@@ -109,7 +137,7 @@ namespace ArchiSteamFarm {
return true;
}
internal static void UnixSetFileAccessExecutable(string path) {
internal static void UnixSetFileAccess(string path, EUnixPermission permission) {
if (string.IsNullOrEmpty(path) || !File.Exists(path)) {
ASF.ArchiLogger.LogNullError(nameof(path));
@@ -121,7 +149,7 @@ namespace ArchiSteamFarm {
}
// Chmod() returns 0 on success, -1 on failure
if (NativeMethods.Chmod(path, (int) NativeMethods.UnixExecutePermission) != 0) {
if (NativeMethods.Chmod(path, (int) permission) != 0) {
ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningFailedWithError, Marshal.GetLastWin32Error()));
}
}
@@ -137,6 +165,16 @@ namespace ArchiSteamFarm {
SingleInstance = null;
}
private static string GetOsResourceName(string objectName) {
if (string.IsNullOrEmpty(objectName)) {
ASF.ArchiLogger.LogNullError(nameof(objectName));
return null;
}
return SharedInfo.AssemblyName + "-" + objectName;
}
private static void WindowsDisableQuickEditMode() {
if (!IsWindows) {
return;
@@ -173,11 +211,25 @@ namespace ArchiSteamFarm {
}
}
[Flags]
internal enum EUnixPermission : ushort {
OtherExecute = 0x1,
OtherWrite = 0x2,
OtherRead = 0x4,
GroupExecute = 0x8,
GroupWrite = 0x10,
GroupRead = 0x20,
UserExecute = 0x40,
UserWrite = 0x80,
UserRead = 0x100,
Combined755 = UserRead | UserWrite | UserExecute | GroupRead | GroupExecute | OtherRead | OtherExecute,
Combined777 = UserRead | UserWrite | UserExecute | GroupRead | GroupWrite | GroupExecute | OtherRead | OtherWrite | OtherExecute
}
private static class NativeMethods {
internal const EExecutionState AwakeExecutionState = EExecutionState.SystemRequired | EExecutionState.AwayModeRequired | EExecutionState.Continuous;
internal const uint EnableQuickEditMode = 0x0040;
internal const sbyte StandardInputHandle = -10;
internal const EUnixPermission UnixExecutePermission = EUnixPermission.UserRead | EUnixPermission.UserWrite | EUnixPermission.UserExecute | EUnixPermission.GroupRead | EUnixPermission.GroupExecute | EUnixPermission.OtherRead | EUnixPermission.OtherExecute;
[DllImport("libc", EntryPoint = "chmod", SetLastError = true)]
internal static extern int Chmod(string path, int mode);
@@ -201,22 +253,6 @@ namespace ArchiSteamFarm {
AwayModeRequired = 0x00000040,
Continuous = 0x80000000
}
[Flags]
internal enum EUnixPermission : ushort {
OtherExecute = 0x1,
OtherRead = 0x4,
GroupExecute = 0x8,
GroupRead = 0x20,
UserExecute = 0x40,
UserWrite = 0x80,
UserRead = 0x100
/*
OtherWrite = 0x2
GroupWrite = 0x10
*/
}
}
}
}

View File

@@ -217,13 +217,18 @@ namespace ArchiSteamFarm {
// GetCultureInfo() would be better but we can't use it for specifying neutral cultures such as "en"
CultureInfo culture = CultureInfo.CreateSpecificCulture(ASF.GlobalConfig.CurrentCulture);
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.DefaultThreadCurrentUICulture = culture;
} catch (Exception) {
} catch (Exception e) {
ASF.ArchiLogger.LogGenericWarningException(e);
ASF.ArchiLogger.LogGenericError(Strings.ErrorInvalidCurrentCulture);
}
}
if (CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("en")) {
return;
// Skip translation progress for English and invariant (such as "C") cultures
switch (CultureInfo.CurrentUICulture.TwoLetterISOLanguageName) {
case "en":
case "iv":
return;
}
// We can't dispose this resource set, as we can't be sure if it isn't used somewhere else, rely on GC in this case

View File

@@ -352,7 +352,6 @@ namespace ArchiSteamFarm {
}
}
[SuppressMessage("ReSharper", "FunctionComplexityOverflow")]
private async Task<bool> MatchActivelyRound(IReadOnlyCollection<Steam.Asset.EType> acceptedMatchableTypes, IDictionary<ulong, (byte Tries, ISet<ulong> GivenAssetIDs, ISet<ulong> ReceivedAssetIDs)> triedSteamIDs) {
if ((acceptedMatchableTypes == null) || (acceptedMatchableTypes.Count == 0) || (triedSteamIDs == null)) {
Bot.ArchiLogger.LogNullError(nameof(acceptedMatchableTypes) + " || " + nameof(triedSteamIDs));

View File

@@ -8,6 +8,8 @@ RUN echo "node: $(node --version)" && \
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
ENV NET_CORE_VERSION netcoreapp3.1
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -21,14 +23,17 @@ RUN dotnet --info && \
dotnet build ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm --nologo && \
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm --nologo && \
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm --nologo && \
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=linux-arm -p:PublishTrimmed=true -r linux-arm --nologo && \
cp "ArchiSteamFarm/overlay/linux-arm/ArchiSteamFarm-Service.sh" "out/ArchiSteamFarm-Service.sh"
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=linux-arm -p:PublishSingleFile=true -p:PublishTrimmed=true -r linux-arm --nologo && \
if [ -d "ArchiSteamFarm/overlay/linux-arm" ]; then cp "ArchiSteamFarm/overlay/linux-arm/"* "out"; fi
FROM mcr.microsoft.com/dotnet/core/runtime-deps:3.1-buster-slim-arm32v7 AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
LABEL maintainer="JustArchi <JustArchi@JustArchi.net>"
EXPOSE 1242
WORKDIR /app
COPY --from=build-dotnet /app/out .
VOLUME ["/app/config", "/app/logs", "/app/plugins"]
HEALTHCHECK CMD ["pidof", "-q", "ArchiSteamFarm"]
ENTRYPOINT ["./ArchiSteamFarm-Service.sh", "--no-restart", "--process-required", "--system-required"]

View File

@@ -8,6 +8,8 @@ RUN echo "node: $(node --version)" && \
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
ENV NET_CORE_VERSION netcoreapp3.1
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -21,14 +23,17 @@ RUN dotnet --info && \
dotnet build ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm64 --nologo && \
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm64 --nologo && \
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm64 --nologo && \
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=linux-arm64 -p:PublishTrimmed=true -r linux-arm64 --nologo && \
cp "ArchiSteamFarm/overlay/linux-arm64/ArchiSteamFarm-Service.sh" "out/ArchiSteamFarm-Service.sh"
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=linux-arm64 -p:PublishSingleFile=true -p:PublishTrimmed=true -r linux-arm64 --nologo && \
if [ -d "ArchiSteamFarm/overlay/linux-arm64" ]; then cp "ArchiSteamFarm/overlay/linux-arm64/"* "out"; fi
FROM mcr.microsoft.com/dotnet/core/runtime-deps:3.1-buster-slim-arm64v8 AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
LABEL maintainer="JustArchi <JustArchi@JustArchi.net>"
EXPOSE 1242
WORKDIR /app
COPY --from=build-dotnet /app/out .
VOLUME ["/app/config", "/app/logs", "/app/plugins"]
HEALTHCHECK CMD ["pidof", "-q", "ArchiSteamFarm"]
ENTRYPOINT ["./ArchiSteamFarm-Service.sh", "--no-restart", "--process-required", "--system-required"]

View File

@@ -8,6 +8,8 @@ RUN echo "node: $(node --version)" && \
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
ENV NET_CORE_VERSION netcoreapp3.1
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -21,14 +23,17 @@ RUN dotnet --info && \
dotnet build ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-x64 --nologo && \
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-x64 --nologo && \
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-x64 --nologo && \
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=linux-x64 -p:PublishTrimmed=true -r linux-x64 --nologo && \
cp "ArchiSteamFarm/overlay/linux-x64/ArchiSteamFarm-Service.sh" "out/ArchiSteamFarm-Service.sh"
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=linux-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true -r linux-x64 --nologo && \
if [ -d "ArchiSteamFarm/overlay/linux-x64" ]; then cp "ArchiSteamFarm/overlay/linux-x64/"* "out"; fi
FROM mcr.microsoft.com/dotnet/core/runtime-deps:3.1-buster-slim AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
LABEL maintainer="JustArchi <JustArchi@JustArchi.net>"
EXPOSE 1242
WORKDIR /app
COPY --from=build-dotnet /app/out .
VOLUME ["/app/config", "/app/logs", "/app/plugins"]
HEALTHCHECK CMD ["pidof", "-q", "ArchiSteamFarm"]
ENTRYPOINT ["./ArchiSteamFarm-Service.sh", "--no-restart", "--process-required", "--system-required"]

View File

@@ -8,6 +8,8 @@ RUN echo "node: $(node --version)" && \
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
ENV NET_CORE_VERSION netcoreapp3.1
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -22,13 +24,16 @@ RUN dotnet --info && \
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm --nologo && \
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm --nologo && \
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=docker -p:SelfContained=false -p:UseAppHost=false -r linux-arm --nologo && \
cp "ArchiSteamFarm/overlay/generic/ArchiSteamFarm.sh" "out/ArchiSteamFarm.sh"
if [ -d "ArchiSteamFarm/overlay/generic" ]; then cp "ArchiSteamFarm/overlay/generic/"* "out"; fi
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim-arm32v7 AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
LABEL maintainer="JustArchi <JustArchi@JustArchi.net>"
EXPOSE 1242
WORKDIR /app
COPY --from=build-dotnet /app/out .
VOLUME ["/app/config", "/app/logs", "/app/plugins"]
HEALTHCHECK CMD ["pidof", "-q", "dotnet"]
ENTRYPOINT ["./ArchiSteamFarm.sh", "--no-restart", "--process-required", "--system-required"]

View File

@@ -8,6 +8,8 @@ RUN echo "node: $(node --version)" && \
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
ENV NET_CORE_VERSION netcoreapp3.1
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -22,13 +24,16 @@ RUN dotnet --info && \
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm64 --nologo && \
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-arm64 --nologo && \
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=docker -p:SelfContained=false -p:UseAppHost=false -r linux-arm64 --nologo && \
cp "ArchiSteamFarm/overlay/generic/ArchiSteamFarm.sh" "out/ArchiSteamFarm.sh"
if [ -d "ArchiSteamFarm/overlay/generic" ]; then cp "ArchiSteamFarm/overlay/generic/"* "out"; fi
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim-arm64v8 AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
LABEL maintainer="JustArchi <JustArchi@JustArchi.net>"
EXPOSE 1242
WORKDIR /app
COPY --from=build-dotnet /app/out .
VOLUME ["/app/config", "/app/logs", "/app/plugins"]
HEALTHCHECK CMD ["pidof", "-q", "dotnet"]
ENTRYPOINT ["./ArchiSteamFarm.sh", "--no-restart", "--process-required", "--system-required"]

View File

@@ -8,6 +8,8 @@ RUN echo "node: $(node --version)" && \
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-dotnet
ENV CONFIGURATION Release
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
ENV NET_CORE_VERSION netcoreapp3.1
WORKDIR /app
COPY --from=build-node /app/dist ASF-ui/dist
@@ -22,13 +24,16 @@ RUN dotnet --info && \
dotnet test ArchiSteamFarm.Tests -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-x64 --nologo && \
dotnet clean ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -p:SelfContained=false -p:UseAppHost=false -r linux-x64 --nologo && \
dotnet publish ArchiSteamFarm -c "$CONFIGURATION" -f "$NET_CORE_VERSION" -o out -p:ASFVariant=docker -p:SelfContained=false -p:UseAppHost=false -r linux-x64 --nologo && \
cp "ArchiSteamFarm/overlay/generic/ArchiSteamFarm.sh" "out/ArchiSteamFarm.sh"
if [ -d "ArchiSteamFarm/overlay/generic" ]; then cp "ArchiSteamFarm/overlay/generic/"* "out"; fi
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS runtime
ENV ASPNETCORE_URLS=
ENV DOTNET_CLI_TELEMETRY_OPTOUT 1
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE 1
LABEL maintainer="JustArchi <JustArchi@JustArchi.net>"
EXPOSE 1242
WORKDIR /app
COPY --from=build-dotnet /app/out .
VOLUME ["/app/config", "/app/logs", "/app/plugins"]
HEALTHCHECK CMD ["pidof", "-q", "dotnet"]
ENTRYPOINT ["./ArchiSteamFarm.sh", "--no-restart", "--process-required", "--system-required"]

View File

@@ -98,7 +98,7 @@ build_script:
}
dotnet build ArchiSteamFarm -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" --nologo
dotnet build ArchiSteamFarm -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" -p:UseAppHost=false --nologo
if ($LastExitCode -ne 0) {
@@ -106,7 +106,7 @@ build_script:
}
dotnet build ArchiSteamFarm.CustomPlugins.ExamplePlugin -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" --nologo
dotnet build ArchiSteamFarm.CustomPlugins.ExamplePlugin -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" -p:UseAppHost=false --nologo
if ($LastExitCode -ne 0) {
@@ -121,7 +121,7 @@ test_script:
$ProgressPreference = 'SilentlyContinue'
dotnet test ArchiSteamFarm.Tests -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" --nologo
dotnet test ArchiSteamFarm.Tests -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" -p:UseAppHost=false --nologo
if ($LastExitCode -ne 0) {
@@ -136,6 +136,22 @@ after_test:
$ProgressPreference = 'SilentlyContinue'
dotnet clean ArchiSteamFarm -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" -p:UseAppHost=false --nologo
if ($LastExitCode -ne 0) {
throw "Last command failed."
}
dotnet restore ArchiSteamFarm
if ($LastExitCode -ne 0) {
throw "Last command failed."
}
$PublishBlock = {
param($variant)
@@ -154,7 +170,7 @@ after_test:
if ($variant -like 'generic*') {
$variantArgs = '-p:UseAppHost=false'
} else {
$variantArgs = '-p:PublishTrimmed=true', '-r', "$variant"
$variantArgs = '-p:PublishSingleFile=true', '-p:PublishTrimmed=true', '-r', "$variant"
}
dotnet publish ArchiSteamFarm -c "$env:CONFIGURATION" -f "$targetFramework" -o "out\$variant" "-p:ASFVariant=$variant" --no-restore --nologo $variantArgs
@@ -202,22 +218,6 @@ after_test:
}
dotnet clean ArchiSteamFarm -c "$env:CONFIGURATION" -f "$env:NET_CORE_VERSION" --nologo
if ($LastExitCode -ne 0) {
throw "Last command failed."
}
dotnet restore ArchiSteamFarm
if ($LastExitCode -ne 0) {
throw "Last command failed."
}
foreach ($variant in $env:VARIANTS.Split([char[]] $null, [System.StringSplitOptions]::RemoveEmptyEntries)) {
Start-Job -Name "$variant" $PublishBlock -ArgumentList "$variant"
}

2
wiki

Submodule wiki updated: 5c75fad9a6...9892a76ff0