mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-20 00:08:38 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4187e194e | ||
|
|
32b2ea9fb7 | ||
|
|
6e87ee3718 | ||
|
|
a718d1cefe | ||
|
|
019f347be4 | ||
|
|
5b2b00a9f0 | ||
|
|
e6e1b6f061 | ||
|
|
88a7d2e7e9 | ||
|
|
b223fc2d97 | ||
|
|
589f4f5746 | ||
|
|
c4e7bbbf0c | ||
|
|
bbb43600e5 | ||
|
|
c602654800 | ||
|
|
7a49dc5188 | ||
|
|
f1b84e57e4 |
14
.travis.yml
14
.travis.yml
@@ -17,6 +17,8 @@ mono: none
|
|||||||
|
|
||||||
# ASF requires .NET Core 2.0+
|
# ASF requires .NET Core 2.0+
|
||||||
# TODO: We should target stable 2.0.0 once it's released
|
# TODO: We should target stable 2.0.0 once it's released
|
||||||
|
# TODO: Update at least to preview2 once https://github.com/travis-ci/travis-ci/issues/8037 is fixed
|
||||||
|
# TODO: Add --no-restore to dotnet test when we get preview2+
|
||||||
dotnet: 2.0.0-preview1-005977
|
dotnet: 2.0.0-preview1-005977
|
||||||
|
|
||||||
env:
|
env:
|
||||||
@@ -28,6 +30,7 @@ script:
|
|||||||
- set -e
|
- set -e
|
||||||
- dotnet restore
|
- dotnet restore
|
||||||
- dotnet build -c Release
|
- dotnet build -c Release
|
||||||
|
- dotnet test -c Release --no-build ArchiSteamFarm.Tests
|
||||||
- dotnet publish -c Release -o out/generic
|
- dotnet publish -c Release -o out/generic
|
||||||
- echo "generic" > "ArchiSteamFarm/out/generic/ArchiSteamFarm.version"
|
- echo "generic" > "ArchiSteamFarm/out/generic/ArchiSteamFarm.version"
|
||||||
- dotnet publish -c Release -r win-x64 -o out/win-x64
|
- dotnet publish -c Release -r win-x64 -o out/win-x64
|
||||||
@@ -39,16 +42,17 @@ script:
|
|||||||
- dotnet publish -c Release -r osx-x64 -o out/osx-x64
|
- dotnet publish -c Release -r osx-x64 -o out/osx-x64
|
||||||
- echo "osx-x64" > "ArchiSteamFarm/out/osx-x64/ArchiSteamFarm.version"
|
- echo "osx-x64" > "ArchiSteamFarm/out/osx-x64/ArchiSteamFarm.version"
|
||||||
|
|
||||||
# This is our main build matrix
|
|
||||||
matrix:
|
matrix:
|
||||||
# We can use fast finish, as we don't need to wait for all builds to mark it as failed/passed
|
# We can use fast finish, as we don't need to wait for allow_failures builds to mark build as success
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
allow_failures:
|
allow_failures:
|
||||||
# We allow OS X to fail until https://github.com/travis-ci/travis-ci/issues/7757 is fixed
|
# TODO: We allow OS X to fail until https://github.com/travis-ci/travis-ci/issues/7757 is fixed
|
||||||
- os: osx
|
- os: osx
|
||||||
include:
|
include:
|
||||||
# We're building ASF with dotnet on latest versions of Linux and OS X
|
# We're building ASF with dotnet on latest versions of Linux and OS X
|
||||||
# Ref: https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments
|
# Ref: https://docs.travis-ci.com/user/ci-environment/#Virtualization-environments
|
||||||
|
# Ref: https://docs.travis-ci.com/user/trusty-ci-environment/
|
||||||
|
# Ref: https://docs.travis-ci.com/user/osx-ci-environment/
|
||||||
- os: linux
|
- os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|||||||
30
ArchiSteamFarm.Tests/ArchiSteamFarm.Tests.csproj
Normal file
30
ArchiSteamFarm.Tests/ArchiSteamFarm.Tests.csproj
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ErrorReport>none</ErrorReport>
|
||||||
|
<RuntimeIdentifiers>win-x64;linux-x64;linux-arm;osx-x64</RuntimeIdentifiers>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<DebugSymbols>false</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
|
||||||
|
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0-beta" />
|
||||||
|
<PackageReference Include="MSTest.TestFramework" Version="1.2.0-beta" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ArchiSteamFarm\ArchiSteamFarm.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
175
ArchiSteamFarm.Tests/Trading.cs
Normal file
175
ArchiSteamFarm.Tests/Trading.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
_ _ _ ____ _ _____
|
||||||
|
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||||
|
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||||
|
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||||
|
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||||
|
|
||||||
|
Copyright 2015-2017 Ł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.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using ArchiSteamFarm.JSON;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
|
||||||
|
namespace ArchiSteamFarm.Tests {
|
||||||
|
[TestClass]
|
||||||
|
public sealed class Trading {
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingMultiGameBadReject() {
|
||||||
|
Steam.Item item1Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1Game1X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 9, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
Steam.Item item1Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 1, 730, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 4, 1, 730, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1Game1X9, item1Game2, item2Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1Game1, item1Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2Game1, item2Game2 };
|
||||||
|
|
||||||
|
Assert.IsFalse(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingMultiGameMultiTypeBadReject() {
|
||||||
|
Steam.Item item1Type1Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1Type1Game1X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 9, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Type1Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
Steam.Item item3Type2Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 1, 730, Steam.Item.EType.Emoticon);
|
||||||
|
Steam.Item item3Type2Game2X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 9, 730, Steam.Item.EType.Emoticon);
|
||||||
|
Steam.Item item4Type2Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 4, 1, 730, Steam.Item.EType.Emoticon);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1Type1Game1X9, item3Type2Game2X9, item4Type2Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1Type1Game1, item4Type2Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2Type1Game1, item3Type2Game2 };
|
||||||
|
|
||||||
|
Assert.IsFalse(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingMultiGameMultiTypeNeutralAccept() {
|
||||||
|
Steam.Item item1Type1Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1Type1Game1X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 9, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Type1Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
Steam.Item item3Type2Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 1, 730, Steam.Item.EType.Emoticon);
|
||||||
|
Steam.Item item4Type2Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 4, 1, 730, Steam.Item.EType.Emoticon);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1Type1Game1X9, item3Type2Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1Type1Game1, item3Type2Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2Type1Game1, item4Type2Game2 };
|
||||||
|
|
||||||
|
Assert.IsTrue(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingMultiGameNeutralAccept() {
|
||||||
|
Steam.Item item1Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1Game1X2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 2, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Game1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
Steam.Item item1Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 730, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Game2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 730, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1Game1X2, item1Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1Game1, item1Game2 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2Game1, item2Game2 };
|
||||||
|
|
||||||
|
Assert.IsTrue(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingSingleGameBadReject() {
|
||||||
|
Steam.Item item1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1, item2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2 };
|
||||||
|
|
||||||
|
Assert.IsFalse(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingSingleGameGoodAccept() {
|
||||||
|
Steam.Item item1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1X2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 2, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1X2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2 };
|
||||||
|
|
||||||
|
Assert.IsTrue(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingSingleGameMultiTypeBadReject() {
|
||||||
|
Steam.Item item1Type1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1Type1X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 9, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Type1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
Steam.Item item3Type2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 1, 570, Steam.Item.EType.Emoticon);
|
||||||
|
Steam.Item item3Type2X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 9, 570, Steam.Item.EType.Emoticon);
|
||||||
|
Steam.Item item4Type2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 4, 1, 570, Steam.Item.EType.Emoticon);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1Type1X9, item3Type2X9, item4Type2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1Type1, item4Type2 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2Type1, item3Type2 };
|
||||||
|
|
||||||
|
Assert.IsFalse(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingSingleGameMultiTypeNeutralAccept() {
|
||||||
|
Steam.Item item1Type1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item1Type1X9 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 9, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2Type1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
Steam.Item item3Type2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 3, 1, 570, Steam.Item.EType.Emoticon);
|
||||||
|
Steam.Item item4Type2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 4, 1, 570, Steam.Item.EType.Emoticon);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1Type1X9, item3Type2 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1Type1, item3Type2 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2Type1, item4Type2 };
|
||||||
|
|
||||||
|
Assert.IsTrue(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TradingSingleGameNeutralAccept() {
|
||||||
|
Steam.Item item1 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 1, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
Steam.Item item2 = new Steam.Item(Steam.Item.SteamAppID, Steam.Item.SteamCommunityContextID, 2, 1, 570, Steam.Item.EType.TradingCard);
|
||||||
|
|
||||||
|
HashSet<Steam.Item> inventory = new HashSet<Steam.Item> { item1 };
|
||||||
|
HashSet<Steam.Item> itemsToGive = new HashSet<Steam.Item> { item1 };
|
||||||
|
HashSet<Steam.Item> itemsToReceive = new HashSet<Steam.Item> { item2 };
|
||||||
|
|
||||||
|
Assert.IsTrue(AcceptsTrade(inventory, itemsToGive, itemsToReceive));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AcceptsTrade(HashSet<Steam.Item> inventory, HashSet<Steam.Item> itemsToGive, HashSet<Steam.Item> itemsToReceive) {
|
||||||
|
Type trading = typeof(ArchiSteamFarm.Trading);
|
||||||
|
MethodInfo method = trading.GetMethod("IsTradeNeutralOrBetter", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
|
||||||
|
return (bool) method.Invoke(null, new object[] { inventory, itemsToGive, itemsToReceive });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26608.5
|
VisualStudioVersion = 15.0.26621.2
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchiSteamFarm", "ArchiSteamFarm\ArchiSteamFarm.csproj", "{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ArchiSteamFarm", "ArchiSteamFarm\ArchiSteamFarm.csproj", "{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchiSteamFarm.Tests", "ArchiSteamFarm.Tests\ArchiSteamFarm.Tests.csproj", "{91DC4C4F-3C23-4716-8CB2-BC7EAB65D759}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -15,8 +17,15 @@ Global
|
|||||||
{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
{CF84911C-2C4C-4195-8AF3-ABBB6D3DE9AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{91DC4C4F-3C23-4716-8CB2-BC7EAB65D759}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{91DC4C4F-3C23-4716-8CB2-BC7EAB65D759}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{91DC4C4F-3C23-4716-8CB2-BC7EAB65D759}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{91DC4C4F-3C23-4716-8CB2-BC7EAB65D759}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {D7D54143-C857-4B76-A219-0E98C5BC4895}
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -117,7 +117,7 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue">False</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue">False</s:Boolean>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue">END_OF_LINE</s:String>
|
||||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AFTER_CONTROL_TRANSFER_STATEMENTS/@EntryValue">1</s:Int64>
|
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AFTER_CONTROL_TRANSFER_STATEMENTS/@EntryValue">1</s:Int64>
|
||||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_FIELD/@EntryValue">0</s:Int64>
|
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AROUND_FIELD/@EntryValue">1</s:Int64>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">END_OF_LINE</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/CASE_BLOCK_BRACES/@EntryValue">END_OF_LINE</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER_SAME_LINE</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/EMPTY_BLOCK_STYLE/@EntryValue">TOGETHER_SAME_LINE</s:String>
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_STYLE/@EntryValue">Tab</s:String>
|
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/INDENT_STYLE/@EntryValue">Tab</s:String>
|
||||||
@@ -384,4 +384,5 @@
|
|||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EXml_002ECodeStyle_002EFormatSettingsUpgrade_002EXmlMoveToCommonFormatterSettingsUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Int64 x:Key="/Default/Environment/UnitTesting/ParallelProcessesCount/@EntryValue">8</s:Int64></wpf:ResourceDictionary>
|
||||||
@@ -76,7 +76,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
version = version.TrimEnd();
|
version = version.TrimEnd();
|
||||||
if (string.IsNullOrEmpty(version) || !IsVersionValid(version)) {
|
if (string.IsNullOrEmpty(version) || !IsValidVersion(version)) {
|
||||||
ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, SharedInfo.VersionFile));
|
ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, SharedInfo.VersionFile));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup from previous update - old non-runtime in-use files
|
// Cleanup from previous update - old non-runtime in-use files
|
||||||
foreach (string file in Directory.GetFiles(targetDirectory, "*.old", SearchOption.AllDirectories)) {
|
foreach (string file in Directory.EnumerateFiles(targetDirectory, "*.old", SearchOption.AllDirectories)) {
|
||||||
try {
|
try {
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -217,14 +217,7 @@ namespace ArchiSteamFarm {
|
|||||||
// Before attempting to connect, initialize our list of CMs
|
// Before attempting to connect, initialize our list of CMs
|
||||||
await Bot.InitializeCMs(Program.GlobalDatabase.CellID, Program.GlobalDatabase.ServerListProvider).ConfigureAwait(false);
|
await Bot.InitializeCMs(Program.GlobalDatabase.CellID, Program.GlobalDatabase.ServerListProvider).ConfigureAwait(false);
|
||||||
|
|
||||||
foreach (string botName in Directory.EnumerateFiles(SharedInfo.ConfigDirectory, "*.json").Select(Path.GetFileNameWithoutExtension).Where(botName => !string.IsNullOrEmpty(botName) && (botName[0] != '.'))) {
|
foreach (string botName in Directory.EnumerateFiles(SharedInfo.ConfigDirectory, "*.json").Select(Path.GetFileNameWithoutExtension).Where(botName => !string.IsNullOrEmpty(botName) && IsValidBotName(botName)).OrderBy(botName => botName)) {
|
||||||
switch (botName) {
|
|
||||||
case SharedInfo.ASF:
|
|
||||||
case "example":
|
|
||||||
case "minimal":
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bot.RegisterBot(botName);
|
Bot.RegisterBot(botName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +263,27 @@ namespace ArchiSteamFarm {
|
|||||||
Bot.RegisterBot(botName);
|
Bot.RegisterBot(botName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsVersionValid(string version) {
|
private static bool IsValidBotName(string botName) {
|
||||||
|
if (string.IsNullOrEmpty(botName)) {
|
||||||
|
ArchiLogger.LogNullError(nameof(botName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (botName[0] == '.') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (botName) {
|
||||||
|
case SharedInfo.ASF:
|
||||||
|
case "example":
|
||||||
|
case "minimal":
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidVersion(string version) {
|
||||||
if (string.IsNullOrEmpty(version)) {
|
if (string.IsNullOrEmpty(version)) {
|
||||||
ArchiLogger.LogNullError(nameof(version));
|
ArchiLogger.LogNullError(nameof(version));
|
||||||
return false;
|
return false;
|
||||||
@@ -278,9 +291,10 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case "generic":
|
case "generic":
|
||||||
case "win-x64":
|
case "linux-arm":
|
||||||
case "linux-x64":
|
case "linux-x64":
|
||||||
case "osx-x64":
|
case "osx-x64":
|
||||||
|
case "win-x64":
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -438,7 +452,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
// Move top-level runtime in-use files to other directory
|
// Move top-level runtime in-use files to other directory
|
||||||
// We must do it in order to not crash at later stage - all libraries/executables must keep original names
|
// We must do it in order to not crash at later stage - all libraries/executables must keep original names
|
||||||
foreach (string file in Directory.GetFiles(targetDirectory)) {
|
foreach (string file in Directory.EnumerateFiles(targetDirectory)) {
|
||||||
string target = Path.Combine(backupDirectory, Path.GetFileName(file));
|
string target = Path.Combine(backupDirectory, Path.GetFileName(file));
|
||||||
File.Move(file, target);
|
File.Move(file, target);
|
||||||
}
|
}
|
||||||
@@ -446,7 +460,7 @@ namespace ArchiSteamFarm {
|
|||||||
// In generic ASF variant there can also be "runtimes" directory in need of same approach
|
// In generic ASF variant there can also be "runtimes" directory in need of same approach
|
||||||
string runtimesDirectory = Path.Combine(targetDirectory, "runtimes");
|
string runtimesDirectory = Path.Combine(targetDirectory, "runtimes");
|
||||||
if (Directory.Exists(runtimesDirectory)) {
|
if (Directory.Exists(runtimesDirectory)) {
|
||||||
foreach (string file in Directory.GetFiles(runtimesDirectory, "*", SearchOption.AllDirectories)) {
|
foreach (string file in Directory.EnumerateFiles(runtimesDirectory, "*", SearchOption.AllDirectories)) {
|
||||||
string directory = Path.Combine(backupDirectory, Path.GetDirectoryName(Path.GetRelativePath(targetDirectory, file)));
|
string directory = Path.Combine(backupDirectory, Path.GetDirectoryName(Path.GetRelativePath(targetDirectory, file)));
|
||||||
Directory.CreateDirectory(directory);
|
Directory.CreateDirectory(directory);
|
||||||
|
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ namespace ArchiSteamFarm {
|
|||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
Trading = 1,
|
Trading = 1,
|
||||||
|
|
||||||
// Only custom below, different than ones available as user_notification_type
|
// Only custom below, different than ones available as user_notification_type
|
||||||
Items = 254
|
Items = 254
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.2</AssemblyVersion>
|
<AssemblyVersion>3.0.0.3</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.2</FileVersion>
|
<FileVersion>3.0.0.3</FileVersion>
|
||||||
<LangVersion>7</LangVersion>
|
<LangVersion>7</LangVersion>
|
||||||
<ErrorReport>none</ErrorReport>
|
<ErrorReport>none</ErrorReport>
|
||||||
<ApplicationIcon>ASF.ico</ApplicationIcon>
|
<ApplicationIcon>ASF.ico</ApplicationIcon>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="HtmlAgilityPack" Version="1.5.0" />
|
<PackageReference Include="HtmlAgilityPack" Version="1.5.2-beta1" />
|
||||||
<PackageReference Include="Humanizer" Version="2.2.0" />
|
<PackageReference Include="Humanizer" Version="2.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||||
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.0.0-pre-02" />
|
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.0.0-pre-02" />
|
||||||
|
|||||||
@@ -50,10 +50,12 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
// We must use HTTPS for SteamCommunity, as http would make certain POST requests failing (trades)
|
// We must use HTTPS for SteamCommunity, as http would make certain POST requests failing (trades)
|
||||||
private const string SteamCommunityHost = "steamcommunity.com";
|
private const string SteamCommunityHost = "steamcommunity.com";
|
||||||
|
|
||||||
private const string SteamCommunityURL = "https://" + SteamCommunityHost;
|
private const string SteamCommunityURL = "https://" + SteamCommunityHost;
|
||||||
|
|
||||||
// We could (and should) use HTTPS for SteamStore, but that would make certain POST requests failing
|
// We could (and should) use HTTPS for SteamStore, but that would make certain POST requests failing
|
||||||
private const string SteamStoreHost = "store.steampowered.com";
|
private const string SteamStoreHost = "store.steampowered.com";
|
||||||
|
|
||||||
private const string SteamStoreURL = "http://" + SteamStoreHost;
|
private const string SteamStoreURL = "http://" + SteamStoreHost;
|
||||||
|
|
||||||
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1);
|
private static readonly SemaphoreSlim InventorySemaphore = new SemaphoreSlim(1);
|
||||||
@@ -177,7 +179,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyValue response = null;
|
KeyValue response = null;
|
||||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
|
||||||
await Task.Run(() => {
|
await Task.Run(() => {
|
||||||
using (dynamic iEconService = WebAPI.GetInterface(IEconService, steamApiKey)) {
|
using (dynamic iEconService = WebAPI.GetInterface(IEconService, steamApiKey)) {
|
||||||
iEconService.Timeout = Timeout;
|
iEconService.Timeout = Timeout;
|
||||||
@@ -196,7 +198,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxRetries));
|
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +230,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyValue response = null;
|
KeyValue response = null;
|
||||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
|
||||||
await Task.Run(() => {
|
await Task.Run(() => {
|
||||||
using (dynamic iEconService = WebAPI.GetInterface(IEconService, steamApiKey)) {
|
using (dynamic iEconService = WebAPI.GetInterface(IEconService, steamApiKey)) {
|
||||||
iEconService.Timeout = Timeout;
|
iEconService.Timeout = Timeout;
|
||||||
@@ -249,7 +251,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxRetries));
|
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,7 +627,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeyValue response = null;
|
KeyValue response = null;
|
||||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
|
||||||
await Task.Run(() => {
|
await Task.Run(() => {
|
||||||
using (dynamic iPlayerService = WebAPI.GetInterface(IPlayerService, steamApiKey)) {
|
using (dynamic iPlayerService = WebAPI.GetInterface(IPlayerService, steamApiKey)) {
|
||||||
iPlayerService.Timeout = Timeout;
|
iPlayerService.Timeout = Timeout;
|
||||||
@@ -644,7 +646,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxRetries));
|
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,7 +666,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
internal async Task<uint> GetServerTime() {
|
internal async Task<uint> GetServerTime() {
|
||||||
KeyValue response = null;
|
KeyValue response = null;
|
||||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
for (byte i = 0; (i < WebBrowser.MaxTries) && (response == null); i++) {
|
||||||
await Task.Run(() => {
|
await Task.Run(() => {
|
||||||
using (dynamic iTwoFactorService = WebAPI.GetInterface(ITwoFactorService)) {
|
using (dynamic iTwoFactorService = WebAPI.GetInterface(ITwoFactorService)) {
|
||||||
iTwoFactorService.Timeout = Timeout;
|
iTwoFactorService.Timeout = Timeout;
|
||||||
@@ -685,7 +687,7 @@ namespace ArchiSteamFarm {
|
|||||||
return response["server_time"].AsUnsignedInteger();
|
return response["server_time"].AsUnsignedInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxRetries));
|
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, WebBrowser.MaxTries));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
ArchiSteamFarm/AssemblyInfo.cs
Normal file
27
ArchiSteamFarm/AssemblyInfo.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
_ _ _ ____ _ _____
|
||||||
|
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||||
|
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||||
|
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||||
|
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||||
|
|
||||||
|
Copyright 2015-2017 Ł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.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("ArchiSteamFarm.Tests")]
|
||||||
@@ -1276,7 +1276,7 @@ namespace ArchiSteamFarm {
|
|||||||
// This is pretty rare, but SK2 SteamFriends handler and this handler could execute at the same time
|
// This is pretty rare, but SK2 SteamFriends handler and this handler could execute at the same time
|
||||||
// So we wait for nickname to be registered (with timeout of 5 tries/seconds)
|
// So we wait for nickname to be registered (with timeout of 5 tries/seconds)
|
||||||
string nickname = SteamFriends.GetPersonaName();
|
string nickname = SteamFriends.GetPersonaName();
|
||||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (string.IsNullOrEmpty(nickname) || nickname.Equals("[unassigned]")); i++) {
|
for (byte i = 0; (i < WebBrowser.MaxTries) && (string.IsNullOrEmpty(nickname) || nickname.Equals("[unassigned]")); i++) {
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
await Task.Delay(1000).ConfigureAwait(false);
|
||||||
nickname = SteamFriends.GetPersonaName();
|
nickname = SteamFriends.GetPersonaName();
|
||||||
}
|
}
|
||||||
@@ -2699,6 +2699,7 @@ namespace ArchiSteamFarm {
|
|||||||
response.Append(FormatBotResponse(string.Format(Strings.BotOwnedAlreadyWithName, ownedGame.Key, ownedGame.Value)));
|
response.Append(FormatBotResponse(string.Format(Strings.BotOwnedAlreadyWithName, ownedGame.Key, ownedGame.Value)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
query = query.Replace('_', ' ');
|
||||||
string[] games = query.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
string[] games = query.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
foreach (string game in games) {
|
foreach (string game in games) {
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ namespace ArchiSteamFarm {
|
|||||||
Steam.Item.EType.TradingCard
|
Steam.Item.EType.TradingCard
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)]
|
||||||
|
internal readonly HashSet<Steam.Item.EType> MatchableTypes = new HashSet<Steam.Item.EType> {
|
||||||
|
Steam.Item.EType.FoilTradingCard,
|
||||||
|
Steam.Item.EType.TradingCard
|
||||||
|
};
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal readonly CryptoHelper.ECryptoMethod PasswordFormat = CryptoHelper.ECryptoMethod.PlainText;
|
internal readonly CryptoHelper.ECryptoMethod PasswordFormat = CryptoHelper.ECryptoMethod.PlainText;
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
@@ -152,21 +151,19 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This call verifies if JSON is alright
|
|
||||||
// We don't wrap it in try catch as it should always be the case
|
|
||||||
// And if it's not, we want to know about it (in a crash) and correct it in future version
|
|
||||||
JsonConvert.DeserializeObject<BotDatabase>(json);
|
|
||||||
|
|
||||||
lock (FileLock) {
|
lock (FileLock) {
|
||||||
for (byte i = 0; i < 5; i++) {
|
string newFilePath = FilePath + ".new";
|
||||||
try {
|
|
||||||
File.WriteAllText(FilePath, json);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
ASF.ArchiLogger.LogGenericException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(1000);
|
try {
|
||||||
|
File.WriteAllText(newFilePath, json);
|
||||||
|
|
||||||
|
if (File.Exists(FilePath)) {
|
||||||
|
File.Replace(newFilePath, FilePath, null);
|
||||||
|
} else {
|
||||||
|
File.Move(newFilePath, FilePath);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
ASF.ArchiLogger.LogGenericException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace ArchiSteamFarm {
|
|||||||
internal const string UlongStringPrefix = "s_";
|
internal const string UlongStringPrefix = "s_";
|
||||||
|
|
||||||
// This is hardcoded blacklist which should not be possible to change
|
// This is hardcoded blacklist which should not be possible to change
|
||||||
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 425280, 480730, 566020, 639900 };
|
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 402590, 425280, 480730, 566020, 639900 };
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal readonly bool AutoRestart = true;
|
internal readonly bool AutoRestart = true;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
@@ -114,21 +113,19 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This call verifies if JSON is alright
|
|
||||||
// We don't wrap it in try catch as it should always be the case
|
|
||||||
// And if it's not, we want to know about it (in a crash) and correct it in future version
|
|
||||||
JsonConvert.DeserializeObject<GlobalDatabase>(json, CustomSerializerSettings);
|
|
||||||
|
|
||||||
lock (FileLock) {
|
lock (FileLock) {
|
||||||
for (byte i = 0; i < 5; i++) {
|
string newFilePath = FilePath + ".new";
|
||||||
try {
|
|
||||||
File.WriteAllText(FilePath, json);
|
|
||||||
break;
|
|
||||||
} catch (Exception e) {
|
|
||||||
ASF.ArchiLogger.LogGenericException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(1000);
|
try {
|
||||||
|
File.WriteAllText(newFilePath, json);
|
||||||
|
|
||||||
|
if (File.Exists(FilePath)) {
|
||||||
|
File.Replace(newFilePath, FilePath, null);
|
||||||
|
} else {
|
||||||
|
File.Move(newFilePath, FilePath);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
ASF.ArchiLogger.LogGenericException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal static void Start() {
|
internal static void Start() {
|
||||||
if (KeepRunning) {
|
if (KeepRunning || (HttpListener.Prefixes.Count == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, HttpListener.Prefixes.FirstOrDefault()));
|
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, HttpListener.Prefixes.First()));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HttpListener.Start();
|
HttpListener.Start();
|
||||||
@@ -84,56 +84,60 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Program.GlobalConfig.SteamOwnerID == 0) {
|
try {
|
||||||
ASF.ArchiLogger.LogGenericInfo(Strings.ErrorIPCAccessDenied);
|
if (Program.GlobalConfig.SteamOwnerID == 0) {
|
||||||
await context.Response.WriteAsync(HttpStatusCode.Forbidden, Strings.ErrorIPCAccessDenied).ConfigureAwait(false);
|
ASF.ArchiLogger.LogGenericWarning(Strings.ErrorIPCAccessDenied);
|
||||||
return;
|
await context.Response.WriteAsync(HttpStatusCode.Forbidden, Strings.ErrorIPCAccessDenied).ConfigureAwait(false);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!context.Request.RawUrl.StartsWith("/" + nameof(IPC), StringComparison.Ordinal)) {
|
if (!context.Request.RawUrl.StartsWith("/" + nameof(IPC), StringComparison.Ordinal)) {
|
||||||
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (context.Request.HttpMethod) {
|
|
||||||
case WebRequestMethods.Http.Get:
|
|
||||||
for (int i = 0; i < context.Request.QueryString.Count; i++) {
|
|
||||||
string key = context.Request.QueryString.GetKey(i);
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case "command":
|
|
||||||
string command = context.Request.QueryString.Get(i);
|
|
||||||
if (string.IsNullOrEmpty(command)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bot bot = Bot.Bots.Values.FirstOrDefault();
|
|
||||||
if (bot == null) {
|
|
||||||
await context.Response.WriteAsync(HttpStatusCode.NotAcceptable, Strings.ErrorNoBotsDefined).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command[0] != '!') {
|
|
||||||
command = "!" + command;
|
|
||||||
}
|
|
||||||
|
|
||||||
string response = await bot.Response(Program.GlobalConfig.SteamOwnerID, command).ConfigureAwait(false);
|
|
||||||
|
|
||||||
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCAnswered, command, response));
|
|
||||||
|
|
||||||
await context.Response.WriteAsync(HttpStatusCode.OK, response).ConfigureAwait(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
|
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Response.ContentLength64 == 0) {
|
switch (context.Request.HttpMethod) {
|
||||||
await context.Response.WriteAsync(HttpStatusCode.MethodNotAllowed, nameof(HttpStatusCode.MethodNotAllowed)).ConfigureAwait(false);
|
case WebRequestMethods.Http.Get:
|
||||||
|
for (int i = 0; i < context.Request.QueryString.Count; i++) {
|
||||||
|
string key = context.Request.QueryString.GetKey(i);
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case "command":
|
||||||
|
string command = context.Request.QueryString.Get(i);
|
||||||
|
if (string.IsNullOrEmpty(command)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bot bot = Bot.Bots.Values.FirstOrDefault();
|
||||||
|
if (bot == null) {
|
||||||
|
await context.Response.WriteAsync(HttpStatusCode.NotAcceptable, Strings.ErrorNoBotsDefined).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command[0] != '!') {
|
||||||
|
command = "!" + command;
|
||||||
|
}
|
||||||
|
|
||||||
|
string response = await bot.Response(Program.GlobalConfig.SteamOwnerID, command).ConfigureAwait(false);
|
||||||
|
|
||||||
|
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCAnswered, command, response));
|
||||||
|
|
||||||
|
await context.Response.WriteAsync(HttpStatusCode.OK, response).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.Response.ContentLength64 == 0) {
|
||||||
|
await context.Response.WriteAsync(HttpStatusCode.MethodNotAllowed, nameof(HttpStatusCode.MethodNotAllowed)).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
context.Response.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +152,7 @@ namespace ArchiSteamFarm {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
await HandleRequest(context).ConfigureAwait(false);
|
Utilities.StartBackgroundFunction(() => HandleRequest(context));
|
||||||
context.Response.Close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +167,14 @@ namespace ArchiSteamFarm {
|
|||||||
response.StatusCode = (ushort) statusCode;
|
response.StatusCode = (ushort) statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] buffer = Encoding.UTF8.GetBytes(message);
|
Encoding encoding = Encoding.UTF8;
|
||||||
|
response.ContentEncoding = encoding;
|
||||||
|
|
||||||
|
string html = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><p>" + message + "</p></body></html>";
|
||||||
|
|
||||||
|
byte[] buffer = encoding.GetBytes(html);
|
||||||
response.ContentLength64 = buffer.Length;
|
response.ContentLength64 = buffer.Length;
|
||||||
|
|
||||||
await response.OutputStream.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
await response.OutputStream.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
response.StatusCode = (ushort) HttpStatusCode.InternalServerError;
|
response.StatusCode = (ushort) HttpStatusCode.InternalServerError;
|
||||||
|
|||||||
@@ -486,7 +486,15 @@ namespace ArchiSteamFarm.JSON {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool IsSteamCardsRequest() => ItemsToGive.All(item => (item.AppID == Item.SteamAppID) && (item.ContextID == Item.SteamCommunityContextID) && (item.Type == Item.EType.TradingCard));
|
internal bool IsValidSteamItemsRequest(HashSet<Item.EType> acceptedTypes) {
|
||||||
|
if ((acceptedTypes == null) || (acceptedTypes.Count == 0)) {
|
||||||
|
ASF.ArchiLogger.LogNullError(nameof(acceptedTypes));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = ItemsToGive.All(item => (item.AppID == Item.SteamAppID) && (item.ContextID == Item.SteamCommunityContextID) && acceptedTypes.Contains(item.Type));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||||
internal enum ETradeOfferState : byte {
|
internal enum ETradeOfferState : byte {
|
||||||
|
|||||||
@@ -94,8 +94,6 @@ namespace ArchiSteamFarm {
|
|||||||
internal enum EExecutionState : uint {
|
internal enum EExecutionState : uint {
|
||||||
Error = 0,
|
Error = 0,
|
||||||
SystemRequired = 0x00000001,
|
SystemRequired = 0x00000001,
|
||||||
//DisplayRequired = 0x00000002,
|
|
||||||
//UserPresent = 0x00000004,
|
|
||||||
AwayModeRequired = 0x00000040,
|
AwayModeRequired = 0x00000040,
|
||||||
Continuous = 0x80000000
|
Continuous = 0x80000000
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,8 +143,9 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static async Task Init(string[] args) {
|
private static async Task Init(string[] args) {
|
||||||
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
|
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
|
||||||
TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionHandler;
|
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||||
|
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
||||||
|
|
||||||
// We must register our logging target as soon as possible
|
// We must register our logging target as soon as possible
|
||||||
Target.Register<SteamTarget>(SteamTarget.TargetName);
|
Target.Register<SteamTarget>(SteamTarget.TargetName);
|
||||||
@@ -183,6 +184,8 @@ namespace ArchiSteamFarm {
|
|||||||
ParsePostInitArgs(args);
|
ParsePostInitArgs(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPC.Start();
|
||||||
|
|
||||||
if (!Debugging.IsDebugBuild) {
|
if (!Debugging.IsDebugBuild) {
|
||||||
await ASF.CheckForUpdate().ConfigureAwait(false);
|
await ASF.CheckForUpdate().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -319,8 +322,6 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
ShutdownSequenceInitialized = true;
|
ShutdownSequenceInitialized = true;
|
||||||
|
|
||||||
IPC.Stop();
|
|
||||||
|
|
||||||
if (Bot.Bots.Count == 0) {
|
if (Bot.Bots.Count == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -330,12 +331,12 @@ namespace ArchiSteamFarm {
|
|||||||
switch (GlobalConfig.OptimizationMode) {
|
switch (GlobalConfig.OptimizationMode) {
|
||||||
case GlobalConfig.EOptimizationMode.MinMemoryUsage:
|
case GlobalConfig.EOptimizationMode.MinMemoryUsage:
|
||||||
foreach (Task task in tasks) {
|
foreach (Task task in tasks) {
|
||||||
await Task.WhenAny(task, Task.Delay(WebBrowser.MaxRetries * 1000)).ConfigureAwait(false);
|
await Task.WhenAny(task, Task.Delay(WebBrowser.MaxTries * 1000)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(Bot.Bots.Count * WebBrowser.MaxRetries * 1000)).ConfigureAwait(false);
|
await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(Bot.Bots.Count * WebBrowser.MaxTries * 1000)).ConfigureAwait(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,6 +354,31 @@ namespace ArchiSteamFarm {
|
|||||||
Exit().Wait();
|
Exit().Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void OnProcessExit(object sender, EventArgs e) => IPC.Stop();
|
||||||
|
|
||||||
|
private static async void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
||||||
|
if (e?.ExceptionObject == null) {
|
||||||
|
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.ExceptionObject));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF.ArchiLogger.LogFatalException((Exception) e.ExceptionObject);
|
||||||
|
await Exit(1).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) {
|
||||||
|
if (e?.Exception == null) {
|
||||||
|
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.Exception));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASF.ArchiLogger.LogFatalException(e.Exception);
|
||||||
|
|
||||||
|
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
|
||||||
|
// Thanks Valve.
|
||||||
|
e.SetObserved();
|
||||||
|
}
|
||||||
|
|
||||||
private static void ParsePostInitArgs(IEnumerable<string> args) {
|
private static void ParsePostInitArgs(IEnumerable<string> args) {
|
||||||
if (args == null) {
|
if (args == null) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||||
@@ -407,28 +433,5 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
ShutdownResetEvent.Set();
|
ShutdownResetEvent.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e) {
|
|
||||||
if (e?.ExceptionObject == null) {
|
|
||||||
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.ExceptionObject));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASF.ArchiLogger.LogFatalException((Exception) e.ExceptionObject);
|
|
||||||
await Exit(1).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs e) {
|
|
||||||
if (e?.Exception == null) {
|
|
||||||
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.Exception));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASF.ArchiLogger.LogFatalException(e.Exception);
|
|
||||||
|
|
||||||
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
|
|
||||||
// Thanks Valve.
|
|
||||||
e.SetObserved();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ using ArchiSteamFarm.Localization;
|
|||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal sealed class Trading : IDisposable {
|
internal sealed class Trading : IDisposable {
|
||||||
internal const byte MaxItemsPerTrade = 150; // This is due to limit on POST size in WebBrowser
|
internal const byte MaxItemsPerTrade = byte.MaxValue; // This is due to limit on POST size in WebBrowser
|
||||||
internal const byte MaxTradesPerAccount = 5; // This is limit introduced by Valve
|
internal const byte MaxTradesPerAccount = 5; // This is limit introduced by Valve
|
||||||
|
|
||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
@@ -173,7 +173,7 @@ namespace ArchiSteamFarm {
|
|||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, tradeOffer.ItemsToGive.Count > 0 ? ParseTradeResult.EResult.AcceptedWithItemLose : ParseTradeResult.EResult.AcceptedWithoutItemLose);
|
return new ParseTradeResult(tradeOffer.TradeOfferID, tradeOffer.ItemsToGive.Count > 0 ? ParseTradeResult.EResult.AcceptedWithItemLose : ParseTradeResult.EResult.AcceptedWithoutItemLose);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always deny trades from blacklistem steamIDs
|
// Always deny trades from blacklisted steamIDs
|
||||||
if (Bot.IsBlacklistedFromTrades(tradeOffer.OtherSteamID64)) {
|
if (Bot.IsBlacklistedFromTrades(tradeOffer.OtherSteamID64)) {
|
||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently);
|
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently);
|
||||||
}
|
}
|
||||||
@@ -214,8 +214,8 @@ namespace ArchiSteamFarm {
|
|||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently);
|
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decline trade if we're losing anything but steam cards, or if it's non-dupes trade
|
// Decline trade if it's not fair games/types exchange or if we're requested to handle any not-accepted item type
|
||||||
if (!tradeOffer.IsSteamCardsRequest() || !tradeOffer.IsFairTypesExchange()) {
|
if (!tradeOffer.IsFairTypesExchange() || !tradeOffer.IsValidSteamItemsRequest(Bot.BotConfig.MatchableTypes)) {
|
||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently);
|
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedPermanently);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,17 +241,35 @@ namespace ArchiSteamFarm {
|
|||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.AcceptedWithItemLose);
|
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.AcceptedWithItemLose);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get appIDs we're interested in
|
// Get appIDs/types we're interested in
|
||||||
HashSet<uint> appIDs = new HashSet<uint>(tradeOffer.ItemsToGive.Select(item => item.RealAppID));
|
HashSet<uint> appIDs = new HashSet<uint>();
|
||||||
|
HashSet<Steam.Item.EType> types = new HashSet<Steam.Item.EType>();
|
||||||
|
|
||||||
|
foreach (Steam.Item item in tradeOffer.ItemsToGive) {
|
||||||
|
appIDs.Add(item.RealAppID);
|
||||||
|
types.Add(item.Type);
|
||||||
|
}
|
||||||
|
|
||||||
// Now check if it's worth for us to do the trade
|
// Now check if it's worth for us to do the trade
|
||||||
HashSet<Steam.Item> inventory = await Bot.ArchiWebHandler.GetMySteamInventory(false, new HashSet<Steam.Item.EType> { Steam.Item.EType.TradingCard }, appIDs).ConfigureAwait(false);
|
HashSet<Steam.Item> inventory = await Bot.ArchiWebHandler.GetMySteamInventory(false, types, appIDs).ConfigureAwait(false);
|
||||||
if ((inventory == null) || (inventory.Count == 0)) {
|
if ((inventory == null) || (inventory.Count == 0)) {
|
||||||
// If we can't check our inventory when not using MatchEverything, this is a temporary failure
|
// If we can't check our inventory when not using MatchEverything, this is a temporary failure
|
||||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
|
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
|
||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedTemporarily);
|
return new ParseTradeResult(tradeOffer.TradeOfferID, ParseTradeResult.EResult.RejectedTemporarily);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool accept = IsTradeNeutralOrBetter(inventory, tradeOffer.ItemsToGive, tradeOffer.ItemsToReceive);
|
||||||
|
|
||||||
|
// Even if trade is not neutral+ for us right now, it might be in the future, unless we're bot account where we assume that inventory doesn't change
|
||||||
|
return new ParseTradeResult(tradeOffer.TradeOfferID, accept ? ParseTradeResult.EResult.AcceptedWithItemLose : (Bot.BotConfig.IsBotAccount ? ParseTradeResult.EResult.RejectedPermanently : ParseTradeResult.EResult.RejectedTemporarily));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsTradeNeutralOrBetter(HashSet<Steam.Item> inventory, HashSet<Steam.Item> itemsToGive, HashSet<Steam.Item> itemsToReceive) {
|
||||||
|
if ((inventory == null) || (inventory.Count == 0) || (itemsToGive == null) || (itemsToGive.Count == 0) || (itemsToReceive == null) || (itemsToReceive.Count == 0)) {
|
||||||
|
ASF.ArchiLogger.LogNullError(nameof(inventory) + " || " + nameof(itemsToGive) + " || " + nameof(itemsToReceive));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Now let's create a map which maps items to their amount in our EQ
|
// Now let's create a map which maps items to their amount in our EQ
|
||||||
// This has to be done as we might have multiple items of given ClassID with multiple amounts
|
// This has to be done as we might have multiple items of given ClassID with multiple amounts
|
||||||
Dictionary<ulong, uint> itemAmounts = new Dictionary<ulong, uint>();
|
Dictionary<ulong, uint> itemAmounts = new Dictionary<ulong, uint>();
|
||||||
@@ -264,12 +282,12 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate our value of items to give on per-game basis
|
// Calculate our value of items to give on per-game basis
|
||||||
Dictionary<uint, List<uint>> itemAmountToGivePerGame = new Dictionary<uint, List<uint>>(appIDs.Count);
|
Dictionary<(Steam.Item.EType Type, uint AppID), List<uint>> itemAmountToGivePerGame = new Dictionary<(Steam.Item.EType Type, uint AppID), List<uint>>();
|
||||||
Dictionary<ulong, uint> itemAmountsToGive = new Dictionary<ulong, uint>(itemAmounts);
|
Dictionary<ulong, uint> itemAmountsToGive = new Dictionary<ulong, uint>(itemAmounts);
|
||||||
foreach (Steam.Item item in tradeOffer.ItemsToGive) {
|
foreach (Steam.Item item in itemsToGive) {
|
||||||
if (!itemAmountToGivePerGame.TryGetValue(item.RealAppID, out List<uint> amountsToGive)) {
|
if (!itemAmountToGivePerGame.TryGetValue((item.Type, item.RealAppID), out List<uint> amountsToGive)) {
|
||||||
amountsToGive = new List<uint>();
|
amountsToGive = new List<uint>();
|
||||||
itemAmountToGivePerGame[item.RealAppID] = amountsToGive;
|
itemAmountToGivePerGame[(item.Type, item.RealAppID)] = amountsToGive;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!itemAmountsToGive.TryGetValue(item.ClassID, out uint amount)) {
|
if (!itemAmountsToGive.TryGetValue(item.ClassID, out uint amount)) {
|
||||||
@@ -287,12 +305,12 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate our value of items to receive on per-game basis
|
// Calculate our value of items to receive on per-game basis
|
||||||
Dictionary<uint, List<uint>> itemAmountToReceivePerGame = new Dictionary<uint, List<uint>>(appIDs.Count);
|
Dictionary<(Steam.Item.EType Type, uint AppID), List<uint>> itemAmountToReceivePerGame = new Dictionary<(Steam.Item.EType Type, uint AppID), List<uint>>();
|
||||||
Dictionary<ulong, uint> itemAmountsToReceive = new Dictionary<ulong, uint>(itemAmounts);
|
Dictionary<ulong, uint> itemAmountsToReceive = new Dictionary<ulong, uint>(itemAmounts);
|
||||||
foreach (Steam.Item item in tradeOffer.ItemsToReceive) {
|
foreach (Steam.Item item in itemsToReceive) {
|
||||||
if (!itemAmountToReceivePerGame.TryGetValue(item.RealAppID, out List<uint> amountsToReceive)) {
|
if (!itemAmountToReceivePerGame.TryGetValue((item.Type, item.RealAppID), out List<uint> amountsToReceive)) {
|
||||||
amountsToReceive = new List<uint>();
|
amountsToReceive = new List<uint>();
|
||||||
itemAmountToReceivePerGame[item.RealAppID] = amountsToReceive;
|
itemAmountToReceivePerGame[(item.Type, item.RealAppID)] = amountsToReceive;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!itemAmountsToReceive.TryGetValue(item.ClassID, out uint amount)) {
|
if (!itemAmountsToReceive.TryGetValue(item.ClassID, out uint amount)) {
|
||||||
@@ -313,10 +331,7 @@ namespace ArchiSteamFarm {
|
|||||||
// This is quite complex operation of taking minimum difference from all differences on per-game basis
|
// This is quite complex operation of taking minimum difference from all differences on per-game basis
|
||||||
// When calculating per-game difference, we sum only amounts at proper indexes, because user might be overpaying
|
// When calculating per-game difference, we sum only amounts at proper indexes, because user might be overpaying
|
||||||
int difference = itemAmountToGivePerGame.Min(kv => kv.Value.Select((t, i) => (int) (t - itemAmountToReceivePerGame[kv.Key][i])).Sum());
|
int difference = itemAmountToGivePerGame.Min(kv => kv.Value.Select((t, i) => (int) (t - itemAmountToReceivePerGame[kv.Key][i])).Sum());
|
||||||
|
return difference > 0;
|
||||||
// Trade is neutral+ for us if the difference is greater than 0
|
|
||||||
// If not, we assume that the trade might be good for us in the future, unless we're bot account where we assume that inventory doesn't change
|
|
||||||
return new ParseTradeResult(tradeOffer.TradeOfferID, difference > 0 ? ParseTradeResult.EResult.AcceptedWithItemLose : (Bot.BotConfig.IsBotAccount ? ParseTradeResult.EResult.RejectedPermanently : ParseTradeResult.EResult.RejectedTemporarily));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class ParseTradeResult {
|
private sealed class ParseTradeResult {
|
||||||
|
|||||||
@@ -95,22 +95,34 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void StartBackgroundAction(Action action) {
|
internal static void StartBackgroundAction(Action action, bool longRunning = true) {
|
||||||
if (action == null) {
|
if (action == null) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(action));
|
ASF.ArchiLogger.LogNullError(nameof(action));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.Factory.StartNew(action, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
|
TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
|
||||||
|
|
||||||
|
if (longRunning) {
|
||||||
|
options |= TaskCreationOptions.LongRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task.Factory.StartNew(action, options).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void StartBackgroundFunction(Func<Task> function) {
|
internal static void StartBackgroundFunction(Func<Task> function, bool longRunning = true) {
|
||||||
if (function == null) {
|
if (function == null) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(function));
|
ASF.ArchiLogger.LogNullError(nameof(function));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task.Factory.StartNew(function, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
|
TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
|
||||||
|
|
||||||
|
if (longRunning) {
|
||||||
|
options |= TaskCreationOptions.LongRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task.Factory.StartNew(function, options).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IEnumerable<T> ToEnumerable<T>(this T item) where T : struct {
|
internal static IEnumerable<T> ToEnumerable<T>(this T item) where T : struct {
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ using Newtonsoft.Json.Linq;
|
|||||||
|
|
||||||
namespace ArchiSteamFarm {
|
namespace ArchiSteamFarm {
|
||||||
internal sealed class WebBrowser {
|
internal sealed class WebBrowser {
|
||||||
internal const byte MaxRetries = 5; // Defines maximum number of retries, UrlRequest() does not handle retry by itself (it's app responsibility)
|
internal const byte MaxTries = 5; // Defines maximum number of recommended tries for a single request
|
||||||
|
|
||||||
private const byte ExtendedTimeoutMultiplier = 10; // Multiplier for WebBrowsers dealing with huge data
|
private const byte ExtendedTimeoutMultiplier = 10; // Defines multiplier of timeout for WebBrowsers dealing with huge data (ASF update)
|
||||||
private const byte MaxConnections = ServicePointManager.DefaultNonPersistentConnectionLimit; // Defines maximum number of connections per ServicePoint. Be careful, as it also defines maximum number of sockets in CLOSE_WAIT state
|
private const byte MaxConnections = 10; // Defines maximum number of connections per ServicePoint. Be careful, as it also defines maximum number of sockets in CLOSE_WAIT state
|
||||||
private const byte MaxIdleTime = 15; // In seconds, how long socket is allowed to stay in CLOSE_WAIT state after there are no connections to it
|
private const byte MaxIdleTime = 15; // Defines in seconds, how long socket is allowed to stay in CLOSE_WAIT state after there are no connections to it
|
||||||
|
|
||||||
internal readonly CookieContainer CookieContainer = new CookieContainer();
|
internal readonly CookieContainer CookieContainer = new CookieContainer();
|
||||||
|
|
||||||
@@ -51,7 +51,8 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
HttpClientHandler httpClientHandler = new HttpClientHandler {
|
HttpClientHandler httpClientHandler = new HttpClientHandler {
|
||||||
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
|
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
|
||||||
CookieContainer = CookieContainer
|
CookieContainer = CookieContainer,
|
||||||
|
MaxConnectionsPerServer = MaxConnections
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpClient = new HttpClient(httpClientHandler) {
|
HttpClient = new HttpClient(httpClientHandler) {
|
||||||
@@ -95,7 +96,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] result = null;
|
byte[] result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && (result == null); i++) {
|
for (byte i = 0; (i < MaxTries) && (result == null); i++) {
|
||||||
result = await UrlGetToBytes(request, referer).ConfigureAwait(false);
|
result = await UrlGetToBytes(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +104,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -115,7 +116,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HtmlDocument result = null;
|
HtmlDocument result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && (result == null); i++) {
|
for (byte i = 0; (i < MaxTries) && (result == null); i++) {
|
||||||
result = await UrlGetToHtmlDocument(request, referer).ConfigureAwait(false);
|
result = await UrlGetToHtmlDocument(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -135,7 +136,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JObject result = null;
|
JObject result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && (result == null); i++) {
|
for (byte i = 0; (i < MaxTries) && (result == null); i++) {
|
||||||
result = await UrlGetToJObject(request, referer).ConfigureAwait(false);
|
result = await UrlGetToJObject(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +144,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -179,7 +180,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
XmlDocument result = null;
|
XmlDocument result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && (result == null); i++) {
|
for (byte i = 0; (i < MaxTries) && (result == null); i++) {
|
||||||
result = await UrlGetToXML(request, referer).ConfigureAwait(false);
|
result = await UrlGetToXML(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +188,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -199,7 +200,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
for (byte i = 0; (i < MaxRetries) && !result; i++) {
|
for (byte i = 0; (i < MaxTries) && !result; i++) {
|
||||||
result = await UrlHead(request, referer).ConfigureAwait(false);
|
result = await UrlHead(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +208,7 @@ namespace ArchiSteamFarm {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -219,7 +220,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Uri result = null;
|
Uri result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && (result == null); i++) {
|
for (byte i = 0; (i < MaxTries) && (result == null); i++) {
|
||||||
result = await UrlHeadToUri(request, referer).ConfigureAwait(false);
|
result = await UrlHeadToUri(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +228,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -250,7 +251,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
for (byte i = 0; (i < MaxRetries) && !result; i++) {
|
for (byte i = 0; (i < MaxTries) && !result; i++) {
|
||||||
result = await UrlPost(request, data, referer).ConfigureAwait(false);
|
result = await UrlPost(request, data, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +259,7 @@ namespace ArchiSteamFarm {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -334,7 +335,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string result = null;
|
string result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && string.IsNullOrEmpty(result); i++) {
|
for (byte i = 0; (i < MaxTries) && string.IsNullOrEmpty(result); i++) {
|
||||||
result = await UrlGetToContent(request, referer).ConfigureAwait(false);
|
result = await UrlGetToContent(request, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +343,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -466,7 +467,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string result = null;
|
string result = null;
|
||||||
for (byte i = 0; (i < MaxRetries) && string.IsNullOrEmpty(result); i++) {
|
for (byte i = 0; (i < MaxTries) && string.IsNullOrEmpty(result); i++) {
|
||||||
result = await UrlPostToContent(request, data, referer).ConfigureAwait(false);
|
result = await UrlPostToContent(request, data, referer).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +475,7 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxRetries));
|
ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorRequestFailedTooManyTimes, MaxTries));
|
||||||
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, request));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -488,7 +489,7 @@ namespace ArchiSteamFarm {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<HttpResponseMessage> UrlRequest(Uri requestUri, HttpMethod httpMethod, ICollection<KeyValuePair<string, string>> data = null, string referer = null, byte maxRedirections = MaxRetries) {
|
private async Task<HttpResponseMessage> UrlRequest(Uri requestUri, HttpMethod httpMethod, ICollection<KeyValuePair<string, string>> data = null, string referer = null, byte maxRedirections = MaxTries) {
|
||||||
if ((requestUri == null) || (httpMethod == null)) {
|
if ((requestUri == null) || (httpMethod == null)) {
|
||||||
ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod));
|
ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod));
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
3,
|
3,
|
||||||
5
|
5
|
||||||
],
|
],
|
||||||
|
"MatchableTypes": [
|
||||||
|
3,
|
||||||
|
5
|
||||||
|
],
|
||||||
"PasswordFormat": 0,
|
"PasswordFormat": 0,
|
||||||
"Paused": false,
|
"Paused": false,
|
||||||
"RedeemingPreferences": 0,
|
"RedeemingPreferences": 0,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ build:
|
|||||||
project: ArchiSteamFarm.sln
|
project: ArchiSteamFarm.sln
|
||||||
parallel: true
|
parallel: true
|
||||||
verbosity: minimal
|
verbosity: minimal
|
||||||
after_build:
|
after_test:
|
||||||
- ps: >-
|
- ps: >-
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
@@ -35,13 +35,13 @@ after_build:
|
|||||||
|
|
||||||
Add-Content "ArchiSteamFarm\out\$RUNTIME\ArchiSteamFarm.version" "$RUNTIME"
|
Add-Content "ArchiSteamFarm\out\$RUNTIME\ArchiSteamFarm.version" "$RUNTIME"
|
||||||
|
|
||||||
7z a -bd -tzip -mm=Deflate64 -mx=1 "ArchiSteamFarm\out\ASF-$RUNTIME.zip" "$env:APPVEYOR_BUILD_FOLDER\ArchiSteamFarm\out\$RUNTIME\*"
|
7z a -bd -tzip -mm=Deflate64 -mx=5 "ArchiSteamFarm\out\ASF-$RUNTIME.zip" "$env:APPVEYOR_BUILD_FOLDER\ArchiSteamFarm\out\$RUNTIME\*"
|
||||||
Push-AppveyorArtifact "ArchiSteamFarm\out\ASF-$RUNTIME.zip" -FileName "ASF-$RUNTIME.zip" -DeploymentName "ASF-$RUNTIME.zip"
|
Push-AppveyorArtifact "ArchiSteamFarm\out\ASF-$RUNTIME.zip" -FileName "ASF-$RUNTIME.zip" -DeploymentName "ASF-$RUNTIME.zip"
|
||||||
}
|
}
|
||||||
deploy:
|
deploy:
|
||||||
- provider: GitHub
|
- provider: GitHub
|
||||||
tag: $(appveyor_repo_tag_name)
|
tag: $(appveyor_repo_tag_name)
|
||||||
release: ASF V$(appveyor_repo_tag_name)
|
release: ArchiSteamFarm V$(appveyor_repo_tag_name)
|
||||||
description: '**NOTICE:** Pre-releases are experimental versions that often contain unpatched bugs, work-in-progress features or rewritten implementations. If you don''t consider yourself advanced user, please download **[latest stable release](https://github.com/JustArchi/ArchiSteamFarm/releases/latest)** instead. Pre-release versions are dedicated to users who know how to report bugs, deal with issues and give feedback - no technical support will be given. Check out ASF **[release cycle](https://github.com/JustArchi/ArchiSteamFarm/wiki/Release-cycle)** if you''d like to learn more.\n\n---\n\nThis is automated AppVeyor GitHub deployment, human-readable changelog should be available soon. In the meantime please refer to **[GitHub commits](https://github.com/JustArchi/ArchiSteamFarm/commits/$(appveyor_repo_tag_name))**.\n\n---\n\nASF is available for free. If you''re grateful for what we''re doing, please consider donating. Developing ASF requires massive amount of time and knowledge, especially when it comes to Steam (and its problems). Even 1$ is highly appreciated and shows that you care!\n\n [](https://www.patreon.com/JustArchi) [](https://www.paypal.me/JustArchi/1usd) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4) [](https://blockchain.info/payment_request?address=1Archi6M1r5b41Rvn1SY2FfJAzsrEUT7aT) [](https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_)'
|
description: '**NOTICE:** Pre-releases are experimental versions that often contain unpatched bugs, work-in-progress features or rewritten implementations. If you don''t consider yourself advanced user, please download **[latest stable release](https://github.com/JustArchi/ArchiSteamFarm/releases/latest)** instead. Pre-release versions are dedicated to users who know how to report bugs, deal with issues and give feedback - no technical support will be given. Check out ASF **[release cycle](https://github.com/JustArchi/ArchiSteamFarm/wiki/Release-cycle)** if you''d like to learn more.\n\n---\n\nThis is automated AppVeyor GitHub deployment, human-readable changelog should be available soon. In the meantime please refer to **[GitHub commits](https://github.com/JustArchi/ArchiSteamFarm/commits/$(appveyor_repo_tag_name))**.\n\n---\n\nASF is available for free. If you''re grateful for what we''re doing, please consider donating. Developing ASF requires massive amount of time and knowledge, especially when it comes to Steam (and its problems). Even 1$ is highly appreciated and shows that you care!\n\n [](https://www.patreon.com/JustArchi) [](https://www.paypal.me/JustArchi/1usd) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HD2P2P3WGS5Y4) [](https://blockchain.info/payment_request?address=1Archi6M1r5b41Rvn1SY2FfJAzsrEUT7aT) [](https://steamcommunity.com/tradeoffer/new/?partner=46697991&token=0ix2Ruv_)'
|
||||||
auth_token:
|
auth_token:
|
||||||
secure: QC5gIDMvSpd43EG6qW8d1E3ZHiVU4aR7pbKQonXstjj/JtAABf5S1IbtoY4OsnOR
|
secure: QC5gIDMvSpd43EG6qW8d1E3ZHiVU4aR7pbKQonXstjj/JtAABf5S1IbtoY4OsnOR
|
||||||
|
|||||||
Reference in New Issue
Block a user