Compare commits

..

24 Commits

Author SHA1 Message Date
JustArchi
28fa7ac538 Migrate lock-bot to GitHub actions 2020-08-18 11:44:36 +02:00
GitHub Action
3292816967 Automatic translations update 2020-08-18 02:08:02 +00:00
dependabot-preview[bot]
19aa60cccd Bump Markdig.Signed from 0.20.0 to 0.21.1
Bumps [Markdig.Signed](https://github.com/lunet-io/markdig) from 0.20.0 to 0.21.1.
- [Release notes](https://github.com/lunet-io/markdig/releases)
- [Changelog](https://github.com/lunet-io/markdig/blob/master/changelog.md)
- [Commits](https://github.com/lunet-io/markdig/compare/0.20.0...0.21.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-17 11:41:42 +00:00
GitHub Action
0efb3eea8e Automatic translations update 2020-08-17 02:07:58 +00:00
JustArchi
1a6e554ee9 Misc correction towards previous commit 2020-08-16 13:39:01 +02:00
JustArchi
8587667e27 Handle InvalidPassword Steam screwup
Works exactly the same as TwoFactorCodeMismatch, apparently it's too hard for Valve to tell the client "hey, our password validator module is currently down and we're unable to log you in", no, "INVALID PASSWORD" is the right answer.
2020-08-16 13:33:05 +02:00
GitHub Action
0c79b17163 Automatic translations update 2020-08-16 02:07:47 +00:00
GitHub Action
0a5ac68df4 Automatic translations update 2020-08-14 02:07:58 +00:00
GitHub Action
64eda2b44f Automatic translations update 2020-08-13 02:07:53 +00:00
dependabot-preview[bot]
3e978f44e7 Bump ASF-ui from f6e73f9 to 74f0562
Bumps [ASF-ui](https://github.com/JustArchiNET/ASF-ui) from `f6e73f9` to `74f0562`.
- [Release notes](https://github.com/JustArchiNET/ASF-ui/releases)
- [Commits](f6e73f9c90...74f056221d)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-13 01:23:11 +00:00
dependabot-preview[bot]
370ab4f5d0 Bump Microsoft.Extensions.Configuration.Json from 3.1.6 to 3.1.7
Bumps [Microsoft.Extensions.Configuration.Json](https://github.com/aspnet/Extensions) from 3.1.6 to 3.1.7.
- [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-08-11 15:07:12 +00:00
dependabot-preview[bot]
8e84dd0af6 Bump Microsoft.AspNetCore.Mvc.NewtonsoftJson from 3.1.6 to 3.1.7
Bumps [Microsoft.AspNetCore.Mvc.NewtonsoftJson](https://github.com/aspnet/AspNetCore) from 3.1.6 to 3.1.7.
- [Release notes](https://github.com/aspnet/AspNetCore/releases)
- [Commits](https://github.com/aspnet/AspNetCore/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-11 14:48:39 +00:00
dependabot-preview[bot]
f2875b1b2b Bump Microsoft.Extensions.Logging.Configuration from 3.1.6 to 3.1.7
Bumps [Microsoft.Extensions.Logging.Configuration](https://github.com/aspnet/Extensions) from 3.1.6 to 3.1.7.
- [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-08-11 14:40:44 +00:00
JustArchi
702a525893 Bump 2020-08-11 11:52:33 +02:00
JustArchi
c4c11cf61f Update Strings.resx 2020-08-11 11:44:32 +02:00
JustArchi
06b1b8deeb Misc trade logging enhancements 2020-08-11 11:34:32 +02:00
GitHub Action
0beb000d4b Automatic translations update 2020-08-11 02:07:38 +00:00
dependabot-preview[bot]
acc871e609 Bump ASF-ui from 6e066d0 to f6e73f9
Bumps [ASF-ui](https://github.com/JustArchiNET/ASF-ui) from `6e066d0` to `f6e73f9`.
- [Release notes](https://github.com/JustArchiNET/ASF-ui/releases)
- [Commits](6e066d0edc...f6e73f9c90)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-11 01:28:55 +00:00
dependabot-preview[bot]
e8545176e7 Bump wiki from 424e013 to c04af74
Bumps [wiki](https://github.com/JustArchiNET/ArchiSteamFarm.wiki) from `424e013` to `c04af74`.
- [Release notes](https://github.com/JustArchiNET/ArchiSteamFarm.wiki/releases)
- [Commits](424e0133fd...c04af74ce5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-11 01:22:20 +00:00
JustArchi
532a47bda5 Update config.yml 2020-08-11 01:10:30 +02:00
JustArchi
ddc2d956ba Misc 2020-08-11 01:07:15 +02:00
JustArchi
563f57e3aa Keep readme in project's root
Even if it's not critical, it's a good practice to have a readme, not to mention that it can be used in other sources, such as docker page
2020-08-11 01:06:27 +02:00
JustArchi
0a973cefd2 Move non-critical md resources into .github directory 2020-08-11 01:05:16 +02:00
JustArchi
2563ade159 Bump 2020-08-10 15:07:37 +02:00
49 changed files with 234 additions and 59 deletions

View File

@@ -15,9 +15,6 @@ ArchiSteamFarm/logs
# Ignore standard out folders for publishing
**/out
# Ignore crowdin CLI secret (if exists)
tools/ArchiCrowdin/crowdin_identity.yml
# _ ____ _____ ____ _
# / \ / ___|| ___| | _ \ ___ ___| | _____ _ __
# / _ \ \___ \| |_ _____| | | |/ _ \ / __| |/ / _ \ '__|

View File

@@ -7,7 +7,7 @@ contact_links:
url: https://github.com/JustArchiNET/ArchiSteamFarm/wiki/Localization
about: Please use our crowdin platform.
- name: Support question or technical issue
url: https://github.com/JustArchiNET/ArchiSteamFarm/blob/master/SUPPORT.md
url: https://github.com/JustArchiNET/ArchiSteamFarm/blob/master/.github/SUPPORT.md
about: Please review our support guidelines.
- name: Negative feedback, complaints and demands
url: https://www.youtube.com/watch?v=dQw4w9WgXcQ

View File

View File

31
.github/lock.yml vendored
View File

@@ -1,31 +0,0 @@
# Configuration for lock-threads - https://github.com/dessant/lock-threads
# Number of days of inactivity before a closed issue or pull request is locked
daysUntilLock: 30
# Issues and pull requests with these labels will not be locked. Set to `[]` to disable
exemptLabels: []
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
# Comment to post before locking. Set to `false` to disable
lockComment: false
# Assign `resolved` as the reason for locking. Set to `false` to disable
setLockReason: true
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings just for `issues` or `pulls`
# issues:
# exemptLabels:
# - help-wanted
# lockLabel: outdated
# pulls:
# daysUntilLock: 30
# Repository to extend settings from
# _extends: repo

16
.github/workflows/lock.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: ASF-lock-threads
on:
schedule:
- cron: '0 1 * * *'
jobs:
lock:
runs-on: ubuntu-latest
steps:
- name: Lock inactive threads
uses: dessant/lock-threads@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-lock-inactive-days: 30
pr-lock-inactive-days: 30

3
.gitignore vendored
View File

@@ -15,9 +15,6 @@ ArchiSteamFarm/logs
# Ignore standard out folders for publishing
**/out
# Ignore crowdin CLI secret (if exists)
tools/ArchiCrowdin/crowdin_identity.yml
# _ _
# | | (_) _ __ _ _ __ __
# | | | || '_ \ | | | |\ \/ /

2
ASF-ui

Submodule ASF-ui updated: 6e066d0edc...74f056221d

View File

@@ -138,6 +138,28 @@ namespace ArchiSteamFarm.Tests {
Assert.IsTrue(IsTradeNeutralOrBetter(inventory, itemsToGive, itemsToReceive));
}
[TestMethod]
public void SingleGameAbrynosWasWrongNeutralAccept() {
HashSet<Steam.Asset> inventory = new HashSet<Steam.Asset> {
CreateItem(1),
CreateItem(2, 2),
CreateItem(3),
CreateItem(4),
CreateItem(5)
};
HashSet<Steam.Asset> itemsToGive = new HashSet<Steam.Asset> {
CreateItem(2)
};
HashSet<Steam.Asset> itemsToReceive = new HashSet<Steam.Asset> {
CreateItem(3)
};
Assert.IsTrue(IsFairExchange(itemsToGive, itemsToReceive));
Assert.IsTrue(IsTradeNeutralOrBetter(inventory, itemsToGive, itemsToReceive));
}
[TestMethod]
public void SingleGameDonationAccept() {
HashSet<Steam.Asset> inventory = new HashSet<Steam.Asset> {

View File

@@ -286,6 +286,8 @@ namespace ArchiSteamFarm {
try {
inventory = await Bot.ArchiWebHandler.GetInventoryAsync(Bot.SteamID, appID, contextID).Where(item => item.Tradable && filterFunction(item)).ToHashSetAsync().ConfigureAwait(false);
} catch (HttpRequestException e) {
Bot.ArchiLogger.LogGenericWarningException(e);
return (false, string.Format(Strings.WarningFailedWithError, e.Message));
} catch (Exception e) {
Bot.ArchiLogger.LogGenericException(e);

View File

@@ -21,7 +21,7 @@
<PackageReference Include="CryptSharpStandard" Version="1.0.0" />
<PackageReference Include="Humanizer" Version="2.8.26" />
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
<PackageReference Include="Markdig.Signed" Version="0.20.0" />
<PackageReference Include="Markdig.Signed" Version="0.21.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.0.0" />
<PackageReference Include="NLog" Version="4.7.3" />
@@ -35,7 +35,7 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.1'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.7" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.7.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
</ItemGroup>
@@ -48,8 +48,8 @@
<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.6" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Logging.Configuration" Version="3.1.7" />
<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

@@ -49,6 +49,7 @@ namespace ArchiSteamFarm {
private const char DefaultBackgroundKeysRedeemerSeparator = '\t';
private const byte LoginCooldownInMinutes = 25; // Captcha disappears after around 20 minutes, so we make it 25
private const uint LoginID = 1242; // This must be the same for all ASF bots and all ASF processes
private const byte MaxInvalidPasswordFailures = WebBrowser.MaxTries; // Max InvalidPassword failures in a row before we determine that our password is invalid (because Steam wrongly returns those, of course)
private const ushort MaxMessageLength = 5000; // This is a limitation enforced by Steam
private const byte MaxTwoFactorCodeFailures = WebBrowser.MaxTries; // Max TwoFactorCodeMismatch failures in a row before we determine that our 2FA credentials are invalid (because Steam wrongly returns those, of course)
private const byte RedeemCooldownInHours = 1; // 1 hour since first redeem attempt, this is a limitation enforced by Steam
@@ -209,6 +210,7 @@ namespace ArchiSteamFarm {
private bool FirstTradeSent;
private Timer GamesRedeemerInBackgroundTimer;
private byte HeartBeatFailures;
private byte InvalidPasswordFailures;
private EResult LastLogOnResult;
private DateTime LastLogonSessionReplaced;
private bool LibraryLocked;
@@ -2183,18 +2185,19 @@ namespace ArchiSteamFarm {
switch (lastLogOnResult) {
case EResult.AccountDisabled:
case EResult.InvalidPassword when string.IsNullOrEmpty(BotDatabase.LoginKey):
// Do not attempt to reconnect, those failures are permanent
return;
case EResult.InvalidPassword:
case EResult.InvalidPassword when !string.IsNullOrEmpty(BotDatabase.LoginKey):
BotDatabase.LoginKey = null;
ArchiLogger.LogGenericInfo(Strings.BotRemovedExpiredLoginKey);
break;
case EResult.InvalidPassword:
case EResult.NoConnection:
case EResult.ServiceUnavailable:
case EResult.Timeout:
case EResult.TryAnotherCM:
case EResult.TwoFactorCodeMismatch:
await Task.Delay(5000).ConfigureAwait(false);
break;
@@ -2483,7 +2486,6 @@ namespace ArchiSteamFarm {
switch (callback.Result) {
case EResult.AccountDisabled:
case EResult.InvalidPassword when string.IsNullOrEmpty(BotDatabase.LoginKey):
// Those failures are permanent, we should Stop() the bot if any of those happen
ArchiLogger.LogGenericWarning(string.Format(Strings.BotUnableToLogin, callback.Result, callback.ExtendedResult));
Stop();
@@ -2522,7 +2524,7 @@ namespace ArchiSteamFarm {
ArchiLogger.LogGenericInfo(string.Format(Strings.BotLoggedOn, SteamID + (!string.IsNullOrEmpty(callback.VanityURL) ? "/" + callback.VanityURL : "")));
// Old status for these doesn't matter, we'll update them if needed
TwoFactorCodeFailures = 0;
InvalidPasswordFailures = TwoFactorCodeFailures = 0;
LibraryLocked = PlayingBlocked = false;
if (PlayingWasBlocked && (PlayingWasBlockedTimer == null)) {
@@ -2659,17 +2661,25 @@ namespace ArchiSteamFarm {
case EResult.TwoFactorCodeMismatch:
ArchiLogger.LogGenericWarning(string.Format(Strings.BotUnableToLogin, callback.Result, callback.ExtendedResult));
if ((callback.Result == EResult.TwoFactorCodeMismatch) && HasMobileAuthenticator) {
if (++TwoFactorCodeFailures >= MaxTwoFactorCodeFailures) {
switch (callback.Result) {
case EResult.InvalidPassword when string.IsNullOrEmpty(BotDatabase.LoginKey) && (++InvalidPasswordFailures >= MaxInvalidPasswordFailures):
InvalidPasswordFailures = 0;
ArchiLogger.LogGenericError(string.Format(Strings.BotInvalidPasswordDuringLogin, MaxInvalidPasswordFailures));
Stop();
break;
case EResult.TwoFactorCodeMismatch when HasMobileAuthenticator && (++TwoFactorCodeFailures >= MaxTwoFactorCodeFailures):
TwoFactorCodeFailures = 0;
ArchiLogger.LogGenericError(string.Format(Strings.BotInvalidAuthenticatorDuringLogin, MaxTwoFactorCodeFailures));
Stop();
}
break;
}
break;
default:
// Unexpected result, shutdown immediately
ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(callback.Result), callback.Result));
ArchiLogger.LogGenericError(string.Format(Strings.BotUnableToLogin, callback.Result, callback.ExtendedResult));
Stop();

View File

@@ -2864,7 +2864,9 @@ namespace ArchiSteamFarm {
completeSuccess = false;
}
}
} catch (HttpRequestException) {
} catch (HttpRequestException e) {
Bot.ArchiLogger.LogGenericWarningException(e);
completeSuccess = false;
} catch (Exception e) {
Bot.ArchiLogger.LogGenericException(e);

View File

@@ -375,6 +375,15 @@ namespace ArchiSteamFarm.Localization {
}
}
/// <summary>
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Received InvalidPassword error code {0} times in a row. Your password for this account is most likely wrong, aborting!.
/// </summary>
public static string BotInvalidPasswordDuringLogin {
get {
return ResourceManager.GetString("BotInvalidPasswordDuringLogin", resourceCulture);
}
}
/// <summary>
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Bot has level {0}..
/// </summary>
@@ -691,6 +700,15 @@ namespace ArchiSteamFarm.Localization {
}
}
/// <summary>
/// Wyszukuje zlokalizowany ciąg podobny do ciągu The trade offer {0} is determined to be {1} due to {2}..
/// </summary>
public static string BotTradeOfferResult {
get {
return ResourceManager.GetString("BotTradeOfferResult", resourceCulture);
}
}
/// <summary>
/// Wyszukuje zlokalizowany ciąg podobny do ciągu Unable to login to Steam: {0}/{1}.
/// </summary>

View File

@@ -721,4 +721,6 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC настройките са били променени!</value>
</data>
</root>

View File

@@ -720,4 +720,6 @@ StackTrace:
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC nastavení bylo změněno!</value>
</data>
</root>

View File

@@ -720,4 +720,6 @@ StackTrace:
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC konfiguration er blevet ændret!</value>
</data>
</root>

View File

@@ -724,4 +724,6 @@ Prozesslaufzeit: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>Die IPC-Konfiguration wurde geändert!</value>
</data>
</root>

View File

@@ -689,4 +689,6 @@ StackTrace:
</data>
</root>

View File

@@ -723,4 +723,12 @@ Tiempo de actividad del proceso: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>¡La configuración IPC ha sido cambiada!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>La oferta de intercambio {0} se determina a ser {1} debido a {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
<data name="BotInvalidPasswordDuringLogin" xml:space="preserve">
<value>Recibido el código de error InvalidPassword {0} veces seguidas. Es posible que la contraseña para esta cuenta sea incorrecta, ¡abortando!</value>
<comment>{0} will be replaced by maximum allowed number of failed login attempts</comment>
</data>
</root>

View File

@@ -714,4 +714,6 @@ StackTrace:
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC asetusta on muutettu!</value>
</data>
</root>

View File

@@ -724,4 +724,6 @@ Durée de fonctionnement : {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>La configuration IPC a été modifiée !</value>
</data>
</root>

View File

@@ -639,6 +639,8 @@ StackTrace:

View File

@@ -718,4 +718,6 @@ StackTrace: {2}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>Az IPC konfig megváltozott!</value>
</data>
</root>

View File

@@ -670,4 +670,6 @@
</root>

View File

@@ -718,4 +718,6 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>Configurazione IPC modificata!</value>
</data>
</root>

View File

@@ -713,4 +713,6 @@
</data>
</root>

View File

@@ -720,4 +720,6 @@ StackTrace:
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC 환경설정이 변경되었습니다.</value>
</data>
</root>

View File

@@ -720,4 +720,6 @@ StackTrace:
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC konfigūracija buvo pakeista!</value>
</data>
</root>

View File

@@ -723,4 +723,9 @@ Proces uptime: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC-configuratie is gewijzigd!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>Het ruilaanbod {0} is als {1} gemarkeerd vanwege {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
</root>

View File

@@ -724,4 +724,12 @@ Czas procesu: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>Konfiguracja IPC została zmieniona!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>Oferta wymiany {0} jest ustalona jako {1} z powodu {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
<data name="BotInvalidPasswordDuringLogin" xml:space="preserve">
<value>Otrzymano kod błędu InvalidPassword {0} razy z rzędu. Twoje hasło do tego konta jest najprawdopodobniej błędne, przerywam!</value>
<comment>{0} will be replaced by maximum allowed number of failed login attempts</comment>
</data>
</root>

View File

@@ -724,4 +724,12 @@ Tempo de execução: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>A configuração IPC foi alterada!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>A oferta de troca {0} será determinada como {1} devido à {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
<data name="BotInvalidPasswordDuringLogin" xml:space="preserve">
<value>O código de erro InvalidPassword foi recebido {0} vezes seguidas. A sua senha para essa conta provavelmente está errada, abortando!</value>
<comment>{0} will be replaced by maximum allowed number of failed login attempts</comment>
</data>
</root>

View File

@@ -554,4 +554,6 @@ StackTrace:
</root>

View File

@@ -724,4 +724,12 @@ Process uptime: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC config has been changed!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>The trade offer {0} is determined to be {1} due to {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
<data name="BotInvalidPasswordDuringLogin" xml:space="preserve">
<value>Received InvalidPassword error code {0} times in a row. Your password for this account is most likely wrong, aborting!</value>
<comment>{0} will be replaced by maximum allowed number of failed login attempts</comment>
</data>
</root>

View File

@@ -724,4 +724,6 @@ Proces: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>Configurația IPC a fost schimbată!</value>
</data>
</root>

View File

@@ -724,4 +724,9 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>Конфигурация IPC была изменена!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>По предложению обмена {0} принято решение {1} по причине {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
</root>

View File

@@ -702,4 +702,6 @@ Interaktívna konzola je teraz aktívna, napíšte "c" pre vstup do príkazovéh
<data name="IPCConfigChanged" xml:space="preserve">
<value>Konfigurácia IPC bola zmenená!</value>
</data>
</root>

View File

@@ -568,6 +568,8 @@ StackTrace:

View File

@@ -621,6 +621,8 @@ StackTrace:

View File

@@ -724,4 +724,6 @@ Süreç çalışma zamanı: {1}</value>
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC yapılandırması değiştirildi!</value>
</data>
</root>

View File

@@ -724,4 +724,9 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>Конфігурацію IPC було змінено!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>Пропозицію обміну {0} вирішено {1} через {2}.</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
</root>

View File

@@ -720,4 +720,6 @@ StackTrace:
<data name="IPCConfigChanged" xml:space="preserve">
<value>Cấu hình IPC đã được thay đổi!</value>
</data>
</root>

View File

@@ -724,4 +724,12 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC 配置文件已被更改!</value>
</data>
<data name="BotTradeOfferResult" xml:space="preserve">
<value>交易报价 {0} 被确定为 {1},原因是:{2}。</value>
<comment>{0} will be replaced by trade offer ID (number), {1} will be replaced by internal ASF enum name, {2} will be replaced by technical reason why the trade was determined to be in this state</comment>
</data>
<data name="BotInvalidPasswordDuringLogin" xml:space="preserve">
<value>连续收到无效密码InvalidPassword错误代码 {0} 次。您对此帐户的密码很可能是错误的,正在中止操作!</value>
<comment>{0} will be replaced by maximum allowed number of failed login attempts</comment>
</data>
</root>

View File

@@ -720,4 +720,6 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC 設定檔已變更!</value>
</data>
</root>

View File

@@ -723,4 +723,6 @@
<data name="IPCConfigChanged" xml:space="preserve">
<value>IPC 設定檔已變更!</value>
</data>
</root>

View File

@@ -180,7 +180,9 @@ namespace ArchiSteamFarm {
try {
inventory = await Bot.ArchiWebHandler.GetInventoryAsync().Where(item => item.Tradable && acceptedMatchableTypes.Contains(item.Type)).ToHashSetAsync().ConfigureAwait(false);
} catch (HttpRequestException) {
} catch (HttpRequestException e) {
Bot.ArchiLogger.LogGenericWarningException(e);
// This is actually inventory failure, so we'll stop sending heartbeats but not record it as valid check
ShouldSendHeartBeats = false;
@@ -364,7 +366,9 @@ namespace ArchiSteamFarm {
try {
ourInventory = await Bot.ArchiWebHandler.GetInventoryAsync().Where(item => acceptedMatchableTypes.Contains(item.Type)).ToHashSetAsync().ConfigureAwait(false);
} catch (HttpRequestException) {
} catch (HttpRequestException e) {
Bot.ArchiLogger.LogGenericWarningException(e);
return (false, false);
} catch (Exception e) {
Bot.ArchiLogger.LogGenericException(e);
@@ -432,7 +436,9 @@ namespace ArchiSteamFarm {
try {
theirInventory = await Bot.ArchiWebHandler.GetInventoryAsync(listedUser.SteamID).Where(item => (!listedUser.MatchEverything || item.Tradable) && wantedSets.Contains((item.RealAppID, item.Type, item.Rarity)) && ((holdDuration.Value == 0) || !(((item.Type == Steam.Asset.EType.FoilTradingCard) || (item.Type == Steam.Asset.EType.TradingCard)) && CardsFarmer.SalesBlacklist.Contains(item.RealAppID)))).ToHashSetAsync().ConfigureAwait(false);
} catch (HttpRequestException) {
} catch (HttpRequestException e) {
Bot.ArchiLogger.LogGenericWarningException(e);
continue;
} catch (Exception e) {
Bot.ArchiLogger.LogGenericException(e);

View File

@@ -527,11 +527,15 @@ namespace ArchiSteamFarm {
if (tradeOffer.OtherSteamID64 != 0) {
// Always accept trades from SteamMasterID
if (Bot.HasPermission(tradeOffer.OtherSteamID64, BotConfig.EPermission.Master)) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, nameof(tradeOffer.OtherSteamID64) + " " + tradeOffer.OtherSteamID64 + ": " + BotConfig.EPermission.Master));
return ParseTradeResult.EResult.Accepted;
}
// Always deny trades from blacklisted steamIDs
if (Bot.IsBlacklistedFromTrades(tradeOffer.OtherSteamID64)) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Blacklisted, nameof(tradeOffer.OtherSteamID64) + " " + tradeOffer.OtherSteamID64));
return ParseTradeResult.EResult.Blacklisted;
}
}
@@ -540,6 +544,8 @@ namespace ArchiSteamFarm {
switch (tradeOffer.ItemsToGive.Count) {
case 0 when tradeOffer.ItemsToReceive.Count == 0:
// If it's steam issue, try again later
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(tradeOffer.ItemsToReceive.Count) + " = 0"));
return ParseTradeResult.EResult.TryAgain;
case 0:
// Otherwise react accordingly, depending on our preference
@@ -548,32 +554,46 @@ namespace ArchiSteamFarm {
// If we accept donations and bot trades, accept it right away
if (acceptDonations && acceptBotTrades) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, nameof(acceptDonations) + " = " + true + " && " + nameof(acceptBotTrades) + " = " + true));
return ParseTradeResult.EResult.Accepted;
}
// If we don't accept donations, neither bot trades, deny it right away
if (!acceptDonations && !acceptBotTrades) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(acceptDonations) + " = " + false + " && " + nameof(acceptBotTrades) + " = " + false));
return ParseTradeResult.EResult.Rejected;
}
// Otherwise we either accept donations but not bot trades, or we accept bot trades but not donations
bool isBotTrade = (tradeOffer.OtherSteamID64 != 0) && Bot.Bots.Values.Any(bot => bot.SteamID == tradeOffer.OtherSteamID64);
return (acceptDonations && !isBotTrade) || (acceptBotTrades && isBotTrade) ? ParseTradeResult.EResult.Accepted : ParseTradeResult.EResult.Rejected;
ParseTradeResult.EResult result = (acceptDonations && !isBotTrade) || (acceptBotTrades && isBotTrade) ? ParseTradeResult.EResult.Accepted : ParseTradeResult.EResult.Rejected;
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, result, nameof(acceptDonations) + " = " + acceptDonations + " && " + nameof(acceptBotTrades) + " = " + acceptBotTrades + " && " + nameof(isBotTrade) + " = " + isBotTrade));
return result;
}
// If we don't have SteamTradeMatcher enabled, this is the end for us
if (!Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.SteamTradeMatcher)) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(BotConfig.ETradingPreferences.SteamTradeMatcher) + " = " + false));
return ParseTradeResult.EResult.Rejected;
}
// Decline trade if we're giving more count-wise, this is a very naive pre-check, it'll be strengthened in more detailed fair types exchange next
if (tradeOffer.ItemsToGive.Count > tradeOffer.ItemsToReceive.Count) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(tradeOffer.ItemsToGive.Count) + ": " + tradeOffer.ItemsToGive.Count + " > " + tradeOffer.ItemsToReceive.Count));
return ParseTradeResult.EResult.Rejected;
}
// Decline trade if we're requested to handle any not-accepted item type or if it's not fair games/types exchange
if (!tradeOffer.IsValidSteamItemsRequest(Bot.BotConfig.MatchableTypes) || !IsFairExchange(tradeOffer.ItemsToGive, tradeOffer.ItemsToReceive)) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(tradeOffer.IsValidSteamItemsRequest) + " || " + nameof(IsFairExchange)));
return ParseTradeResult.EResult.Rejected;
}
@@ -584,6 +604,8 @@ namespace ArchiSteamFarm {
if (!holdDuration.HasValue) {
// If we can't get trade hold duration, try again later
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(holdDuration)));
return ParseTradeResult.EResult.TryAgain;
}
@@ -591,12 +613,16 @@ namespace ArchiSteamFarm {
if (holdDuration.Value > 0) {
// If trade hold duration exceeds our max, or user asks for cards with short lifespan, reject the trade
if ((holdDuration.Value > ASF.GlobalConfig.MaxTradeHoldDuration) || tradeOffer.ItemsToGive.Any(item => ((item.Type == Steam.Asset.EType.FoilTradingCard) || (item.Type == Steam.Asset.EType.TradingCard)) && CardsFarmer.SalesBlacklist.Contains(item.RealAppID))) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Rejected, nameof(holdDuration) + " > 0: " + holdDuration.Value));
return ParseTradeResult.EResult.Rejected;
}
}
// If we're matching everything, this is enough for us
if (Bot.BotConfig.TradingPreferences.HasFlag(BotConfig.ETradingPreferences.MatchEverything)) {
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.Accepted, BotConfig.ETradingPreferences.MatchEverything));
return ParseTradeResult.EResult.Accepted;
}
@@ -612,12 +638,16 @@ namespace ArchiSteamFarm {
try {
inventory = await Bot.ArchiWebHandler.GetInventoryAsync(Bot.SteamID).Where(item => wantedSets.Contains((item.RealAppID, item.Type, item.Rarity))).ToHashSetAsync().ConfigureAwait(false);
} catch (HttpRequestException) {
} catch (HttpRequestException e) {
// If we can't check our inventory when not using MatchEverything, this is a temporary failure, try again later
Bot.ArchiLogger.LogGenericWarningException(e);
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(inventory)));
return ParseTradeResult.EResult.TryAgain;
} catch (Exception e) {
// If we can't check our inventory when not using MatchEverything, this is a temporary failure, try again later
Bot.ArchiLogger.LogGenericException(e);
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(inventory)));
return ParseTradeResult.EResult.TryAgain;
}
@@ -625,6 +655,7 @@ namespace ArchiSteamFarm {
if (inventory.Count == 0) {
// If we can't check our inventory when not using MatchEverything, this is a temporary failure, try again later
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.ErrorIsEmpty, nameof(inventory)));
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, ParseTradeResult.EResult.TryAgain, nameof(inventory)));
return ParseTradeResult.EResult.TryAgain;
}
@@ -632,7 +663,11 @@ namespace ArchiSteamFarm {
bool accept = IsTradeNeutralOrBetter(inventory, tradeOffer.ItemsToGive.Select(item => item.CreateShallowCopy()).ToHashSet(), tradeOffer.ItemsToReceive.Select(item => item.CreateShallowCopy()).ToHashSet());
// We're now sure whether the trade is neutral+ for us or not
return accept ? ParseTradeResult.EResult.Accepted : ParseTradeResult.EResult.Rejected;
ParseTradeResult.EResult acceptResult = accept ? ParseTradeResult.EResult.Accepted : ParseTradeResult.EResult.Rejected;
Bot.ArchiLogger.LogGenericDebug(string.Format(Strings.BotTradeOfferResult, tradeOffer.TradeOfferID, acceptResult, nameof(IsTradeNeutralOrBetter)));
return acceptResult;
}
public sealed class ParseTradeResult {

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>4.2.3.8</Version>
<Version>4.2.4.0</Version>
</PropertyGroup>
<PropertyGroup>

2
wiki

Submodule wiki updated: 424e0133fd...cf5d49a9de