mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-17 23:10:30 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ada8595bd | ||
|
|
bc64c43748 | ||
|
|
f4f7935d4c | ||
|
|
aacc0a1720 | ||
|
|
e5ee909b96 | ||
|
|
f3f444d0bd | ||
|
|
43d18b6d49 | ||
|
|
f24be67c8c | ||
|
|
6ce4f2941b | ||
|
|
ef5398fae8 | ||
|
|
ce600fdf42 | ||
|
|
7a6485775d | ||
|
|
d39e7a32d6 | ||
|
|
b4cbe85b36 | ||
|
|
4d83417c9d | ||
|
|
25bfbf4862 | ||
|
|
e539e1bdc7 | ||
|
|
b0f83fcd6d | ||
|
|
4880a4e60b |
@@ -50,11 +50,10 @@ matrix:
|
|||||||
fast_finish: true
|
fast_finish: true
|
||||||
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
|
|
||||||
- os: linux
|
- os: linux
|
||||||
# Ref: https://docs.travis-ci.com/user/trusty-ci-environment/
|
# Ref: https://docs.travis-ci.com/user/reference/trusty/
|
||||||
dist: trusty
|
dist: trusty
|
||||||
sudo: false
|
sudo: false
|
||||||
- os: osx
|
- os: osx
|
||||||
# Ref: https://docs.travis-ci.com/user/osx-ci-environment/
|
# Ref: https://docs.travis-ci.com/user/reference/osx/
|
||||||
osx_image: xcode9
|
osx_image: xcode9
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0-preview-20170727-01" />
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0-beta" />
|
<PackageReference Include="MSTest.TestAdapter" Version="1.2.0-beta" />
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="1.2.0-beta" />
|
<PackageReference Include="MSTest.TestFramework" Version="1.2.0-beta" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<AssemblyVersion>3.0.0.6</AssemblyVersion>
|
<AssemblyVersion>3.0.0.9</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.6</FileVersion>
|
<FileVersion>3.0.0.9</FileVersion>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<ErrorReport>none</ErrorReport>
|
<ErrorReport>none</ErrorReport>
|
||||||
<ApplicationIcon>ASF.ico</ApplicationIcon>
|
<ApplicationIcon>ASF.ico</ApplicationIcon>
|
||||||
|
|||||||
@@ -58,15 +58,15 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
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, 1);
|
||||||
|
|
||||||
private static int Timeout = GlobalConfig.DefaultConnectionTimeout * 1000; // This must be int type
|
private static int Timeout = GlobalConfig.DefaultConnectionTimeout * 1000; // This must be int type
|
||||||
|
|
||||||
private readonly SemaphoreSlim ApiKeySemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim ApiKeySemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
private readonly SemaphoreSlim PublicInventorySemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim PublicInventorySemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly SemaphoreSlim SessionSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim SessionSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly SemaphoreSlim TradeTokenSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim TradeTokenSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly WebBrowser WebBrowser;
|
private readonly WebBrowser WebBrowser;
|
||||||
|
|
||||||
private string CachedApiKey;
|
private string CachedApiKey;
|
||||||
@@ -74,6 +74,7 @@ namespace ArchiSteamFarm {
|
|||||||
private string CachedTradeToken;
|
private string CachedTradeToken;
|
||||||
private DateTime LastSessionRefreshCheck = DateTime.MinValue;
|
private DateTime LastSessionRefreshCheck = DateTime.MinValue;
|
||||||
private ulong SteamID;
|
private ulong SteamID;
|
||||||
|
private string VanityURL;
|
||||||
|
|
||||||
internal ArchiWebHandler(Bot bot) {
|
internal ArchiWebHandler(Bot bot) {
|
||||||
Bot = bot ?? throw new ArgumentNullException(nameof(bot));
|
Bot = bot ?? throw new ArgumentNullException(nameof(bot));
|
||||||
@@ -867,12 +868,16 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
internal static void Init() => Timeout = Program.GlobalConfig.ConnectionTimeout * 1000;
|
internal static void Init() => Timeout = Program.GlobalConfig.ConnectionTimeout * 1000;
|
||||||
|
|
||||||
internal async Task<bool> Init(ulong steamID, EUniverse universe, string webAPIUserNonce, string parentalPin) {
|
internal async Task<bool> Init(ulong steamID, EUniverse universe, string webAPIUserNonce, string parentalPin, string vanityURL = null) {
|
||||||
if ((steamID == 0) || (universe == EUniverse.Invalid) || string.IsNullOrEmpty(webAPIUserNonce) || string.IsNullOrEmpty(parentalPin)) {
|
if ((steamID == 0) || (universe == EUniverse.Invalid) || string.IsNullOrEmpty(webAPIUserNonce) || string.IsNullOrEmpty(parentalPin)) {
|
||||||
Bot.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(universe) + " || " + nameof(webAPIUserNonce) + " || " + nameof(parentalPin));
|
Bot.ArchiLogger.LogNullError(nameof(steamID) + " || " + nameof(universe) + " || " + nameof(webAPIUserNonce) + " || " + nameof(parentalPin));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(vanityURL)) {
|
||||||
|
VanityURL = vanityURL;
|
||||||
|
}
|
||||||
|
|
||||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(steamID.ToString()));
|
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(steamID.ToString()));
|
||||||
|
|
||||||
// Generate an AES session key
|
// Generate an AES session key
|
||||||
@@ -1104,7 +1109,7 @@ namespace ArchiSteamFarm {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string request = SteamCommunityURL + "/profiles/" + SteamID + "/ajaxunpackbooster";
|
string request = GetAbsoluteProfileURL() + "/ajaxunpackbooster";
|
||||||
Dictionary<string, string> data = new Dictionary<string, string>(3) {
|
Dictionary<string, string> data = new Dictionary<string, string>(3) {
|
||||||
{ "sessionid", sessionID },
|
{ "sessionid", sessionID },
|
||||||
{ "appid", appID.ToString() },
|
{ "appid", appID.ToString() },
|
||||||
@@ -1115,6 +1120,14 @@ namespace ArchiSteamFarm {
|
|||||||
return response?.Result == EResult.OK;
|
return response?.Result == EResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetAbsoluteProfileURL() {
|
||||||
|
if (!string.IsNullOrEmpty(VanityURL)) {
|
||||||
|
return SteamCommunityURL + "/id/" + VanityURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SteamCommunityURL + "/profiles/" + SteamID;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<string> GetApiKey() {
|
private async Task<string> GetApiKey() {
|
||||||
if (CachedApiKey != null) {
|
if (CachedApiKey != null) {
|
||||||
// We fetched API key already, and either got valid one, or permanent AccessDenied
|
// We fetched API key already, and either got valid one, or permanent AccessDenied
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
internal static readonly ConcurrentDictionary<string, Bot> Bots = new ConcurrentDictionary<string, Bot>();
|
internal static readonly ConcurrentDictionary<string, Bot> Bots = new ConcurrentDictionary<string, Bot>();
|
||||||
|
|
||||||
private static readonly SemaphoreSlim GiftsSemaphore = new SemaphoreSlim(1);
|
private static readonly SemaphoreSlim GiftsSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private static readonly SemaphoreSlim LoginSemaphore = new SemaphoreSlim(1);
|
private static readonly SemaphoreSlim LoginSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private static readonly SteamConfiguration SteamConfiguration = new SteamConfiguration();
|
private static readonly SteamConfiguration SteamConfiguration = new SteamConfiguration();
|
||||||
|
|
||||||
internal readonly ArchiLogger ArchiLogger;
|
internal readonly ArchiLogger ArchiLogger;
|
||||||
@@ -73,15 +73,16 @@ namespace ArchiSteamFarm {
|
|||||||
private readonly BotDatabase BotDatabase;
|
private readonly BotDatabase BotDatabase;
|
||||||
private readonly string BotName;
|
private readonly string BotName;
|
||||||
private readonly CallbackManager CallbackManager;
|
private readonly CallbackManager CallbackManager;
|
||||||
private readonly SemaphoreSlim CallbackSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim CallbackSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
private readonly CardsFarmer CardsFarmer;
|
private readonly CardsFarmer CardsFarmer;
|
||||||
|
|
||||||
private readonly ConcurrentHashSet<ulong> HandledGifts = new ConcurrentHashSet<ulong>();
|
private readonly ConcurrentHashSet<ulong> HandledGifts = new ConcurrentHashSet<ulong>();
|
||||||
private readonly Timer HeartBeatTimer;
|
private readonly Timer HeartBeatTimer;
|
||||||
private readonly SemaphoreSlim InitializationSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim InitializationSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly SemaphoreSlim LootingSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim LootingSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
private readonly SemaphoreSlim PICSSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly Statistics Statistics;
|
private readonly Statistics Statistics;
|
||||||
private readonly SteamApps SteamApps;
|
private readonly SteamApps SteamApps;
|
||||||
private readonly SteamClient SteamClient;
|
private readonly SteamClient SteamClient;
|
||||||
@@ -235,6 +236,8 @@ namespace ArchiSteamFarm {
|
|||||||
CardsFarmer.Dispose();
|
CardsFarmer.Dispose();
|
||||||
HeartBeatTimer.Dispose();
|
HeartBeatTimer.Dispose();
|
||||||
InitializationSemaphore.Dispose();
|
InitializationSemaphore.Dispose();
|
||||||
|
LootingSemaphore.Dispose();
|
||||||
|
PICSSemaphore.Dispose();
|
||||||
Trading.Dispose();
|
Trading.Dispose();
|
||||||
|
|
||||||
// Those are objects that might be null and the check should be in-place
|
// Those are objects that might be null and the check should be in-place
|
||||||
@@ -349,11 +352,15 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
AsyncJobMultiple<SteamApps.PICSProductInfoCallback>.ResultSet productInfoResultSet;
|
AsyncJobMultiple<SteamApps.PICSProductInfoCallback>.ResultSet productInfoResultSet;
|
||||||
|
|
||||||
|
await PICSSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
productInfoResultSet = await SteamApps.PICSGetProductInfo(appID, null, false);
|
productInfoResultSet = await SteamApps.PICSGetProductInfo(appID, null, false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ArchiLogger.LogGenericException(e);
|
ArchiLogger.LogGenericException(e);
|
||||||
return (0, DateTime.MinValue);
|
return (0, DateTime.MinValue);
|
||||||
|
} finally {
|
||||||
|
PICSSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReSharper disable once LoopCanBePartlyConvertedToQuery - C# 7.0 out can't be used within LINQ query yet | https://github.com/dotnet/roslyn/issues/15619
|
// ReSharper disable once LoopCanBePartlyConvertedToQuery - C# 7.0 out can't be used within LINQ query yet | https://github.com/dotnet/roslyn/issues/15619
|
||||||
@@ -452,11 +459,15 @@ namespace ArchiSteamFarm {
|
|||||||
internal async Task<Dictionary<uint, HashSet<uint>>> GetAppIDsToPackageIDs(IEnumerable<uint> packageIDs) {
|
internal async Task<Dictionary<uint, HashSet<uint>>> GetAppIDsToPackageIDs(IEnumerable<uint> packageIDs) {
|
||||||
AsyncJobMultiple<SteamApps.PICSProductInfoCallback>.ResultSet productInfoResultSet;
|
AsyncJobMultiple<SteamApps.PICSProductInfoCallback>.ResultSet productInfoResultSet;
|
||||||
|
|
||||||
|
await PICSSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
productInfoResultSet = await SteamApps.PICSGetProductInfo(Enumerable.Empty<uint>(), packageIDs);
|
productInfoResultSet = await SteamApps.PICSGetProductInfo(Enumerable.Empty<uint>(), packageIDs);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ArchiLogger.LogGenericException(e);
|
ArchiLogger.LogGenericException(e);
|
||||||
return null;
|
return null;
|
||||||
|
} finally {
|
||||||
|
PICSSemaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<uint, HashSet<uint>> result = new Dictionary<uint, HashSet<uint>>();
|
Dictionary<uint, HashSet<uint>> result = new Dictionary<uint, HashSet<uint>>();
|
||||||
@@ -510,6 +521,17 @@ namespace ArchiSteamFarm {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void IdleGame(uint gameID) => IdleGames(gameID.ToEnumerable());
|
||||||
|
|
||||||
|
internal void IdleGames(IEnumerable<uint> gameIDs) {
|
||||||
|
if (gameIDs == null) {
|
||||||
|
ArchiLogger.LogNullError(nameof(gameIDs));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArchiHandler.PlayGames(gameIDs, BotConfig.CustomGamePlayedWhileFarming);
|
||||||
|
}
|
||||||
|
|
||||||
internal static async Task InitializeSteamConfiguration(ProtocolTypes protocolTypes, uint cellID, InMemoryServerListProvider serverListProvider) {
|
internal static async Task InitializeSteamConfiguration(ProtocolTypes protocolTypes, uint cellID, InMemoryServerListProvider serverListProvider) {
|
||||||
if (serverListProvider == null) {
|
if (serverListProvider == null) {
|
||||||
ASF.ArchiLogger.LogNullError(nameof(serverListProvider));
|
ASF.ArchiLogger.LogNullError(nameof(serverListProvider));
|
||||||
@@ -635,17 +657,6 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void PlayGame(uint gameID, string gameName = null) => PlayGames(gameID.ToEnumerable(), gameName);
|
|
||||||
|
|
||||||
internal void PlayGames(IEnumerable<uint> gameIDs, string gameName = null) {
|
|
||||||
if (gameIDs == null) {
|
|
||||||
ArchiLogger.LogNullError(nameof(gameIDs));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArchiHandler.PlayGames(gameIDs, gameName);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task<bool> RefreshSession() {
|
internal async Task<bool> RefreshSession() {
|
||||||
if (!IsConnectedAndLoggedOn) {
|
if (!IsConnectedAndLoggedOn) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1123,7 +1134,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (DateTime.UtcNow.Subtract(ArchiHandler.LastPacketReceived).TotalSeconds > MinHeartBeatTTL) {
|
if (DateTime.UtcNow.Subtract(ArchiHandler.LastPacketReceived).TotalSeconds > MinHeartBeatTTL) {
|
||||||
await SteamApps.PICSGetProductInfo(0, null);
|
await SteamFriends.RequestProfileInfo(SteamClient.SteamID);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeartBeatFailures = 0;
|
HeartBeatFailures = 0;
|
||||||
@@ -1810,7 +1821,7 @@ namespace ArchiSteamFarm {
|
|||||||
ArchiLogger.LogGenericWarning(Strings.BotAccountLocked);
|
ArchiLogger.LogGenericWarning(Strings.BotAccountLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((callback.CellID != 0) && (Program.GlobalDatabase.CellID != callback.CellID)) {
|
if (callback.CellID != 0) {
|
||||||
Program.GlobalDatabase.CellID = callback.CellID;
|
Program.GlobalDatabase.CellID = callback.CellID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1832,7 +1843,7 @@ namespace ArchiSteamFarm {
|
|||||||
SetUserInput(ASF.EUserInputType.SteamParentalPIN, steamParentalPIN);
|
SetUserInput(ASF.EUserInputType.SteamParentalPIN, steamParentalPIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await ArchiWebHandler.Init(callback.ClientSteamID, SteamClient.Universe, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN).ConfigureAwait(false)) {
|
if (!await ArchiWebHandler.Init(callback.ClientSteamID, SteamClient.Universe, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN, callback.VanityURL).ConfigureAwait(false)) {
|
||||||
if (!await RefreshSession().ConfigureAwait(false)) {
|
if (!await RefreshSession().ConfigureAwait(false)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ namespace ArchiSteamFarm {
|
|||||||
);
|
);
|
||||||
|
|
||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
private readonly SemaphoreSlim EventSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim EventSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly SemaphoreSlim FarmingSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim FarmingInitializationSemaphore = new SemaphoreSlim(1, 1);
|
||||||
private readonly ManualResetEventSlim FarmResetEvent = new ManualResetEventSlim(false);
|
private readonly SemaphoreSlim FarmingResetSemaphore = new SemaphoreSlim(0, 1);
|
||||||
private readonly Timer IdleFarmingTimer;
|
private readonly Timer IdleFarmingTimer;
|
||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
@@ -87,8 +87,8 @@ namespace ArchiSteamFarm {
|
|||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
// Those are objects that are always being created if constructor doesn't throw exception
|
// Those are objects that are always being created if constructor doesn't throw exception
|
||||||
EventSemaphore.Dispose();
|
EventSemaphore.Dispose();
|
||||||
FarmingSemaphore.Dispose();
|
FarmingInitializationSemaphore.Dispose();
|
||||||
FarmResetEvent.Dispose();
|
FarmingResetSemaphore.Dispose();
|
||||||
|
|
||||||
// Those are objects that might be null and the check should be in-place
|
// Those are objects that might be null and the check should be in-place
|
||||||
IdleFarmingTimer?.Dispose();
|
IdleFarmingTimer?.Dispose();
|
||||||
@@ -140,7 +140,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
internal async Task OnNewItemsNotification() {
|
internal async Task OnNewItemsNotification() {
|
||||||
if (NowFarming) {
|
if (NowFarming) {
|
||||||
FarmResetEvent.Set();
|
FarmingResetSemaphore.Release();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await FarmingSemaphore.WaitAsync().ConfigureAwait(false);
|
await FarmingInitializationSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (NowFarming || Paused || !Bot.IsPlayingPossible) {
|
if (NowFarming || Paused || !Bot.IsPlayingPossible) {
|
||||||
@@ -231,7 +231,7 @@ namespace ArchiSteamFarm {
|
|||||||
KeepFarming = NowFarming = true;
|
KeepFarming = NowFarming = true;
|
||||||
Utilities.StartBackgroundFunction(Farm);
|
Utilities.StartBackgroundFunction(Farm);
|
||||||
} finally {
|
} finally {
|
||||||
FarmingSemaphore.Release();
|
FarmingInitializationSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ namespace ArchiSteamFarm {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await FarmingSemaphore.WaitAsync().ConfigureAwait(false);
|
await FarmingInitializationSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!NowFarming) {
|
if (!NowFarming) {
|
||||||
@@ -248,7 +248,7 @@ namespace ArchiSteamFarm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KeepFarming = false;
|
KeepFarming = false;
|
||||||
FarmResetEvent.Set();
|
FarmingResetSemaphore.Release();
|
||||||
|
|
||||||
for (byte i = 0; (i < 5) && NowFarming; i++) {
|
for (byte i = 0; (i < 5) && NowFarming; i++) {
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
await Task.Delay(1000).ConfigureAwait(false);
|
||||||
@@ -261,7 +261,7 @@ namespace ArchiSteamFarm {
|
|||||||
Bot.ArchiLogger.LogGenericInfo(Strings.IdlingStopped);
|
Bot.ArchiLogger.LogGenericInfo(Strings.IdlingStopped);
|
||||||
Bot.OnFarmingStopped();
|
Bot.OnFarmingStopped();
|
||||||
} finally {
|
} finally {
|
||||||
FarmingSemaphore.Release();
|
FarmingInitializationSemaphore.Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,65 +556,68 @@ namespace ArchiSteamFarm {
|
|||||||
// If we have restricted card drops, we use complex algorithm
|
// If we have restricted card drops, we use complex algorithm
|
||||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Complex"));
|
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Complex"));
|
||||||
while (GamesToFarm.Count > 0) {
|
while (GamesToFarm.Count > 0) {
|
||||||
HashSet<Game> playableGamesToFarmSolo = new HashSet<Game>();
|
HashSet<Game> gamesToCheck = new HashSet<Game>(GamesToFarm.Where(game => game.HoursPlayed >= HoursToBump));
|
||||||
foreach (Game game in GamesToFarm.Where(game => game.HoursPlayed >= HoursToBump)) {
|
|
||||||
if (await IsPlayableGame(game).ConfigureAwait(false)) {
|
foreach (Game game in gamesToCheck) {
|
||||||
playableGamesToFarmSolo.Add(game);
|
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
||||||
|
GamesToFarm.Remove(game);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await FarmSolo(game).ConfigureAwait(false)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NowFarming = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gamesToCheck = new HashSet<Game>(GamesToFarm.OrderByDescending(game => game.HoursPlayed));
|
||||||
|
HashSet<Game> playableGamesToFarmMultiple = new HashSet<Game>();
|
||||||
|
|
||||||
|
foreach (Game game in gamesToCheck) {
|
||||||
|
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
||||||
|
GamesToFarm.Remove(game);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
playableGamesToFarmMultiple.Add(game);
|
||||||
|
if (playableGamesToFarmMultiple.Count >= ArchiHandler.MaxGamesPlayedConcurrently) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playableGamesToFarmSolo.Count > 0) {
|
if (playableGamesToFarmMultiple.Count == 0) {
|
||||||
while (playableGamesToFarmSolo.Count > 0) {
|
break;
|
||||||
Game playableGame = playableGamesToFarmSolo.First();
|
}
|
||||||
if (await FarmSolo(playableGame).ConfigureAwait(false)) {
|
|
||||||
playableGamesToFarmSolo.Remove(playableGame);
|
if (await FarmMultiple(playableGamesToFarmMultiple).ConfigureAwait(false)) {
|
||||||
} else {
|
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingFinishedForGames, string.Join(", ", playableGamesToFarmMultiple.Select(game => game.AppID))));
|
||||||
NowFarming = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
HashSet<Game> playableGamesToFarmMultiple = new HashSet<Game>();
|
NowFarming = false;
|
||||||
foreach (Game game in GamesToFarm.Where(game => game.HoursPlayed < HoursToBump).OrderByDescending(game => game.HoursPlayed)) {
|
return;
|
||||||
if (await IsPlayableGame(game).ConfigureAwait(false)) {
|
|
||||||
playableGamesToFarmMultiple.Add(game);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playableGamesToFarmMultiple.Count >= ArchiHandler.MaxGamesPlayedConcurrently) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FarmMultiple(playableGamesToFarmMultiple)) {
|
|
||||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.IdlingFinishedForGames, string.Join(", ", playableGamesToFarmMultiple.Select(game => game.AppID))));
|
|
||||||
} else {
|
|
||||||
NowFarming = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If we have unrestricted card drops, we use simple algorithm
|
// If we have unrestricted card drops, we use simple algorithm
|
||||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Simple"));
|
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.ChosenFarmingAlgorithm, "Simple"));
|
||||||
|
|
||||||
while (GamesToFarm.Count > 0) {
|
while (GamesToFarm.Count > 0) {
|
||||||
Game playableGame = null;
|
HashSet<Game> gamesToCheck = new HashSet<Game>(GamesToFarm);
|
||||||
foreach (Game game in GamesToFarm) {
|
|
||||||
|
foreach (Game game in gamesToCheck) {
|
||||||
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
if (!await IsPlayableGame(game).ConfigureAwait(false)) {
|
||||||
|
GamesToFarm.Remove(game);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
playableGame = game;
|
if (await FarmSolo(game).ConfigureAwait(false)) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playableGame != null) {
|
|
||||||
if (await FarmSolo(playableGame).ConfigureAwait(false)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
NowFarming = false;
|
NowFarming = false;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ((await IsAnythingToFarm().ConfigureAwait(false)).GetValueOrDefault());
|
} while ((await IsAnythingToFarm().ConfigureAwait(false)).GetValueOrDefault());
|
||||||
@@ -638,7 +641,7 @@ namespace ArchiSteamFarm {
|
|||||||
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningIdlingGameMismatch, game.AppID, game.GameName, game.PlayableAppID));
|
Bot.ArchiLogger.LogGenericWarning(string.Format(Strings.WarningIdlingGameMismatch, game.AppID, game.GameName, game.PlayableAppID));
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot.PlayGame(game.PlayableAppID, Bot.BotConfig.CustomGamePlayedWhileFarming);
|
Bot.IdleGame(game.PlayableAppID);
|
||||||
DateTime endFarmingDate = DateTime.UtcNow.AddHours(Program.GlobalConfig.MaxFarmingTime);
|
DateTime endFarmingDate = DateTime.UtcNow.AddHours(Program.GlobalConfig.MaxFarmingTime);
|
||||||
|
|
||||||
bool? keepFarming = await ShouldFarm(game).ConfigureAwait(false);
|
bool? keepFarming = await ShouldFarm(game).ConfigureAwait(false);
|
||||||
@@ -646,8 +649,7 @@ namespace ArchiSteamFarm {
|
|||||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdling, game.AppID, game.GameName));
|
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdling, game.AppID, game.GameName));
|
||||||
|
|
||||||
DateTime startFarmingPeriod = DateTime.UtcNow;
|
DateTime startFarmingPeriod = DateTime.UtcNow;
|
||||||
if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
|
if (await FarmingResetSemaphore.WaitAsync(60 * 1000 * Program.GlobalConfig.FarmingDelay).ConfigureAwait(false)) {
|
||||||
FarmResetEvent.Reset();
|
|
||||||
success = KeepFarming;
|
success = KeepFarming;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,7 +667,7 @@ namespace ArchiSteamFarm {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FarmHours(ConcurrentHashSet<Game> games) {
|
private async Task<bool> FarmHours(ConcurrentHashSet<Game> games) {
|
||||||
if ((games == null) || (games.Count == 0)) {
|
if ((games == null) || (games.Count == 0)) {
|
||||||
Bot.ArchiLogger.LogNullError(nameof(games));
|
Bot.ArchiLogger.LogNullError(nameof(games));
|
||||||
return false;
|
return false;
|
||||||
@@ -682,15 +684,14 @@ namespace ArchiSteamFarm {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bot.PlayGames(games.Select(game => game.AppID), Bot.BotConfig.CustomGamePlayedWhileFarming);
|
Bot.IdleGames(games.Select(game => game.PlayableAppID));
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
while (maxHour < 2) {
|
while (maxHour < 2) {
|
||||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdlingList, string.Join(", ", games.Select(game => game.AppID))));
|
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.StillIdlingList, string.Join(", ", games.Select(game => game.AppID))));
|
||||||
|
|
||||||
DateTime startFarmingPeriod = DateTime.UtcNow;
|
DateTime startFarmingPeriod = DateTime.UtcNow;
|
||||||
if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
|
if (await FarmingResetSemaphore.WaitAsync(60 * 1000 * Program.GlobalConfig.FarmingDelay).ConfigureAwait(false)) {
|
||||||
FarmResetEvent.Reset();
|
|
||||||
success = KeepFarming;
|
success = KeepFarming;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,7 +712,7 @@ namespace ArchiSteamFarm {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FarmMultiple(IEnumerable<Game> games) {
|
private async Task<bool> FarmMultiple(IEnumerable<Game> games) {
|
||||||
if (games == null) {
|
if (games == null) {
|
||||||
Bot.ArchiLogger.LogNullError(nameof(games));
|
Bot.ArchiLogger.LogNullError(nameof(games));
|
||||||
return false;
|
return false;
|
||||||
@@ -721,7 +722,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.NowIdlingList, string.Join(", ", CurrentGamesFarming.Select(game => game.AppID))));
|
Bot.ArchiLogger.LogGenericInfo(string.Format(Strings.NowIdlingList, string.Join(", ", CurrentGamesFarming.Select(game => game.AppID))));
|
||||||
|
|
||||||
bool result = FarmHours(CurrentGamesFarming);
|
bool result = await FarmHours(CurrentGamesFarming).ConfigureAwait(false);
|
||||||
CurrentGamesFarming.Clear();
|
CurrentGamesFarming.Clear();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -926,7 +927,7 @@ namespace ArchiSteamFarm {
|
|||||||
case BotConfig.EFarmingOrder.RedeemDateTimesDescending:
|
case BotConfig.EFarmingOrder.RedeemDateTimesDescending:
|
||||||
Dictionary<uint, DateTime> redeemDates = new Dictionary<uint, DateTime>(GamesToFarm.Count);
|
Dictionary<uint, DateTime> redeemDates = new Dictionary<uint, DateTime>(GamesToFarm.Count);
|
||||||
|
|
||||||
foreach (Game game in gamesToFarm) {
|
foreach (Game game in GamesToFarm) {
|
||||||
DateTime redeemDate = DateTime.MinValue;
|
DateTime redeemDate = DateTime.MinValue;
|
||||||
if (Program.GlobalDatabase.AppIDsToPackageIDs.TryGetValue(game.AppID, out ConcurrentHashSet<uint> packageIDs)) {
|
if (Program.GlobalDatabase.AppIDsToPackageIDs.TryGetValue(game.AppID, out ConcurrentHashSet<uint> packageIDs)) {
|
||||||
// ReSharper disable once LoopCanBePartlyConvertedToQuery - C# 7.0 out can't be used within LINQ query yet | https://github.com/dotnet/roslyn/issues/15619
|
// ReSharper disable once LoopCanBePartlyConvertedToQuery - C# 7.0 out can't be used within LINQ query yet | https://github.com/dotnet/roslyn/issues/15619
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace ArchiSteamFarm {
|
|||||||
public bool IsReadOnly => false;
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
private readonly HashSet<T> BackingCollection = new HashSet<T>();
|
private readonly HashSet<T> BackingCollection = new HashSet<T>();
|
||||||
private readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
public bool Add(T item) {
|
public bool Add(T item) {
|
||||||
SemaphoreSlim.Wait();
|
SemaphoreSlim.Wait();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ namespace ArchiSteamFarm {
|
|||||||
internal readonly bool Statistics = true;
|
internal readonly bool Statistics = true;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal readonly ProtocolTypes SteamProtocols = ProtocolTypes.All;
|
internal readonly ProtocolTypes SteamProtocols = ProtocolTypes.Tcp;
|
||||||
|
|
||||||
[JsonProperty(Required = Required.DisallowNull)]
|
[JsonProperty(Required = Required.DisallowNull)]
|
||||||
internal readonly EUpdateChannel UpdateChannel = EUpdateChannel.Stable;
|
internal readonly EUpdateChannel UpdateChannel = EUpdateChannel.Stable;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
private readonly object FileLock = new object();
|
private readonly object FileLock = new object();
|
||||||
|
|
||||||
private readonly SemaphoreSlim PackagesRefreshSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim PackagesRefreshSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
internal uint CellID {
|
internal uint CellID {
|
||||||
get => _CellID;
|
get => _CellID;
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>Procházení fronty doporučení #{0} dokončeno.</value>
|
<value>Procházení fronty doporučení #{0} dokončeno.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>{0}/{1} botů již vlastní všechny uvedené hry.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>Fertig mit Löschung der Steam Entdeckungsliste #{0}.</value>
|
<value>Fertig mit Löschung der Steam Entdeckungsliste #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Es gibt {0}/{1}-Bots, die bereits alle geprüften Spiele besitzen.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>Ολοκληρώθηκε η εκκαθάριση σειράς ανακαλύψεων Steam #{0}.</value>
|
<value>Ολοκληρώθηκε η εκκαθάριση σειράς ανακαλύψεων Steam #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Υπάρχουν {0}/{1} bot που κατέχουν ήδη όλα τα παιχνίδια για τα οποία γίνεται έλεγχος.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -289,7 +289,9 @@
|
|||||||
</data>
|
</data>
|
||||||
|
|
||||||
|
|
||||||
|
<data name="IPCReady" xml:space="preserve">
|
||||||
|
<value>Server IPC siap!</value>
|
||||||
|
</data>
|
||||||
|
|
||||||
<data name="BotAlreadyStopped" xml:space="preserve">
|
<data name="BotAlreadyStopped" xml:space="preserve">
|
||||||
<value>Bot ini sudah berhenti!</value>
|
<value>Bot ini sudah berhenti!</value>
|
||||||
|
|||||||
@@ -184,14 +184,19 @@ StackTrace:
|
|||||||
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
|
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
|
||||||
<value>최신 버전을 확인할 수 없습니다!</value>
|
<value>최신 버전을 확인할 수 없습니다!</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ErrorUpdateNoAssetForThisVersion" xml:space="preserve">
|
||||||
|
<value>현재 실행 중인 버전과 관련된 자산이 없으므로 업데이트를 진행할 수 없습니다! 해당 버전으로 자동 업데이트가 불가능합니다.</value>
|
||||||
|
</data>
|
||||||
<data name="ErrorUpdateNoAssets" xml:space="preserve">
|
<data name="ErrorUpdateNoAssets" xml:space="preserve">
|
||||||
<value>해당 버전이 아무 내용도 포함되어 있지 않아 업데이트를 진행할 수 없습니다!</value>
|
<value>해당 버전이 아무 내용도 포함되어 있지 않아 업데이트를 진행할 수 없습니다!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ErrorUserInputRunningInHeadlessMode" xml:space="preserve">
|
<data name="ErrorUserInputRunningInHeadlessMode" xml:space="preserve">
|
||||||
<value>사용자 입력 요청을 받았지만, 프로세스는 Headless 모드로 실행 중입니다.</value>
|
<value>사용자 입력 요청을 받았지만, 프로세스는 Headless 모드로 실행 중입니다.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ErrorIPCAccessDenied" xml:space="preserve">
|
||||||
|
<value>SteamOwnerID가 설정되지 않았기 때문에 요청을 거절합니다!</value>
|
||||||
|
<comment>SteamOwnerID is name of bot config property, it should not be translated</comment>
|
||||||
|
</data>
|
||||||
<data name="Exiting" xml:space="preserve">
|
<data name="Exiting" xml:space="preserve">
|
||||||
<value>종료 중...</value>
|
<value>종료 중...</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -241,7 +246,10 @@ StackTrace:
|
|||||||
<data name="UpdateCheckingNewVersion" xml:space="preserve">
|
<data name="UpdateCheckingNewVersion" xml:space="preserve">
|
||||||
<value>새로운 버전 확인 중...</value>
|
<value>새로운 버전 확인 중...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="UpdateDownloadingNewVersion" xml:space="preserve">
|
||||||
|
<value>새로운 버전을 내려받는 중: {0} ({1} MB).... 기다리는 동안, 이 프로그램이 고맙다면, 기부하는 것을 고려해보세요! :)</value>
|
||||||
|
<comment>{0} will be replaced by version string, {1} will be replaced by update size (in megabytes)</comment>
|
||||||
|
</data>
|
||||||
<data name="UpdateFinished" xml:space="preserve">
|
<data name="UpdateFinished" xml:space="preserve">
|
||||||
<value>업데이트 작업 완료!</value>
|
<value>업데이트 작업 완료!</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -280,7 +288,10 @@ StackTrace:
|
|||||||
<value>등록되지 않은 {0}의 값을 입력하세요: </value>
|
<value>등록되지 않은 {0}의 값을 입력하세요: </value>
|
||||||
<comment>{0} will be replaced by property name. Please note that this translation should end with space</comment>
|
<comment>{0} will be replaced by property name. Please note that this translation should end with space</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="UserInputIPCHost" xml:space="preserve">
|
||||||
|
<value>IPC 호스트를 입력하세요: </value>
|
||||||
|
<comment>Please note that this translation should end with space</comment>
|
||||||
|
</data>
|
||||||
<data name="WarningUnknownValuePleaseReport" xml:space="preserve">
|
<data name="WarningUnknownValuePleaseReport" xml:space="preserve">
|
||||||
<value>{0}의 알 수 없는 값을 받았습니다. 이것을 보고 바랍니다: {1}</value>
|
<value>{0}의 알 수 없는 값을 받았습니다. 이것을 보고 바랍니다: {1}</value>
|
||||||
<comment>{0} will be replaced by object's name, {1} will be replaced by value for that object</comment>
|
<comment>{0} will be replaced by object's name, {1} will be replaced by value for that object</comment>
|
||||||
@@ -289,10 +300,20 @@ StackTrace:
|
|||||||
<value>동시에 {0}개 이상의 게임들을 플레이하는 것은 불가능합니다. {1}에 의해 단지 {0}개의 항목만 사용될 것입니다!</value>
|
<value>동시에 {0}개 이상의 게임들을 플레이하는 것은 불가능합니다. {1}에 의해 단지 {0}개의 항목만 사용될 것입니다!</value>
|
||||||
<comment>{0} will be replaced by max number of games, {1} will be replaced by name of the configuration property</comment>
|
<comment>{0} will be replaced by max number of games, {1} will be replaced by name of the configuration property</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ErrorIPCAddressAccessDeniedException" xml:space="preserve">
|
||||||
|
<value>AddressAccessDeniedException로 인해 IPC 서비스가 시작될 수 없습니다! ASF에서 제공하는 IPC 서비스를 사용하고 싶다면, ASF를 관리자 모드로 실행하거나 적절한 권한을 줘야 합니다!</value>
|
||||||
|
</data>
|
||||||
|
<data name="IPCAnswered" xml:space="preserve">
|
||||||
|
<value>{0} IPC 명령에 대한 응답: {1}</value>
|
||||||
|
<comment>{0} will be replaced by IPC command, {1} will be replaced by IPC answer</comment>
|
||||||
|
</data>
|
||||||
|
<data name="IPCReady" xml:space="preserve">
|
||||||
|
<value>IPC 서버 준비 완료!</value>
|
||||||
|
</data>
|
||||||
|
<data name="IPCStarting" xml:space="preserve">
|
||||||
|
<value>{0} 에서 IPC 서버 시작...</value>
|
||||||
|
<comment>{0} will be replaced by IPC hostname</comment>
|
||||||
|
</data>
|
||||||
<data name="BotAlreadyStopped" xml:space="preserve">
|
<data name="BotAlreadyStopped" xml:space="preserve">
|
||||||
<value>이 봇은 이미 중지되어 있습니다!</value>
|
<value>이 봇은 이미 중지되어 있습니다!</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -652,5 +673,8 @@ StackTrace:
|
|||||||
<value>스팀 맞춤 대기열 #{0}을 지웠습니다.</value>
|
<value>스팀 맞춤 대기열 #{0}을 지웠습니다.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>게임을 확인 중인 {0}/{1} 개의 봇이 있습니다.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -670,5 +670,8 @@
|
|||||||
<value>Baigta peržiūrėti Steam atradimo eilė #{0}.</value>
|
<value>Baigta peržiūrėti Steam atradimo eilė #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Šiuo metu {0}/{1} botai turi visus tikrinamus žaidimus.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>Steam-ontdekkingswachtrij voltooid #{0}.</value>
|
<value>Steam-ontdekkingswachtrij voltooid #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Er zijn {0}/{1} bots die de gecontroleerde spellen al in bezit hebben.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>Steam-ontdekkingswachtrij voltooid #{0}.</value>
|
<value>Steam-ontdekkingswachtrij voltooid #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Er zijn {0}/{1} bots die de gecontroleerde spellen al in bezit hebben.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>Limpeza da lista de descoberta da Steam #{0} concluída.</value>
|
<value>Limpeza da lista de descoberta da Steam #{0} concluída.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Os bots {0}/{1} já possuem todos os jogos que estão sendo verificados.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -674,5 +674,8 @@ inválidas, abortando!</value>
|
|||||||
<value>Fila de exploração da Steam feita #{0}.</value>
|
<value>Fila de exploração da Steam feita #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Os bots {0}/{1} já possuem todos os jogos que está sendo verificados.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ StackTrace:
|
|||||||
<value>S-a terminat ștergerea cozii pentru lista de descoperiri Steam #{0}.</value>
|
<value>S-a terminat ștergerea cozii pentru lista de descoperiri Steam #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>Există {0}/{1} boți care dețin deja toate jocurile verificate.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -673,5 +673,8 @@ Yığın izleme:
|
|||||||
<value>Steam keşif kuyruğu temizlenmesi bitti #{0}.</value>
|
<value>Steam keşif kuyruğu temizlenmesi bitti #{0}.</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>{0}/{1} bot zaten sahip olunan tüm oyunları denetliyor.</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -181,14 +181,19 @@
|
|||||||
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
|
<data name="ErrorUpdateCheckFailed" xml:space="preserve">
|
||||||
<value>无法检查最新版本 !</value>
|
<value>无法检查最新版本 !</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ErrorUpdateNoAssetForThisVersion" xml:space="preserve">
|
||||||
|
<value>无法继续更新,因为没有与当前正在运行的版本相关的版本! 无法自动更新到该版本。</value>
|
||||||
|
</data>
|
||||||
<data name="ErrorUpdateNoAssets" xml:space="preserve">
|
<data name="ErrorUpdateNoAssets" xml:space="preserve">
|
||||||
<value>不能进行更新,因为此版本没有任何资源!</value>
|
<value>不能进行更新,因为此版本没有任何资源!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ErrorUserInputRunningInHeadlessMode" xml:space="preserve">
|
<data name="ErrorUserInputRunningInHeadlessMode" xml:space="preserve">
|
||||||
<value>收到一个用户输入请求,但进程目前正在以无显示模式运行 !</value>
|
<value>收到一个用户输入请求,但进程目前正在以无显示模式运行 !</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ErrorIPCAccessDenied" xml:space="preserve">
|
||||||
|
<value>拒绝处理该请求,因为未设置 SteamOwnerID !</value>
|
||||||
|
<comment>SteamOwnerID is name of bot config property, it should not be translated</comment>
|
||||||
|
</data>
|
||||||
<data name="Exiting" xml:space="preserve">
|
<data name="Exiting" xml:space="preserve">
|
||||||
<value>正在退出...</value>
|
<value>正在退出...</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -238,7 +243,10 @@
|
|||||||
<data name="UpdateCheckingNewVersion" xml:space="preserve">
|
<data name="UpdateCheckingNewVersion" xml:space="preserve">
|
||||||
<value>正在检查新版本...</value>
|
<value>正在检查新版本...</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="UpdateDownloadingNewVersion" xml:space="preserve">
|
||||||
|
<value>更新中: {0} ({1} MB)...... 在你等待的时候,可以考虑趁现在进行捐赠!:)</value>
|
||||||
|
<comment>{0} will be replaced by version string, {1} will be replaced by update size (in megabytes)</comment>
|
||||||
|
</data>
|
||||||
<data name="UpdateFinished" xml:space="preserve">
|
<data name="UpdateFinished" xml:space="preserve">
|
||||||
<value>更新完毕</value>
|
<value>更新完毕</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -277,7 +285,10 @@
|
|||||||
<value>请输入非正式的值 {0}: </value>
|
<value>请输入非正式的值 {0}: </value>
|
||||||
<comment>{0} will be replaced by property name. Please note that this translation should end with space</comment>
|
<comment>{0} will be replaced by property name. Please note that this translation should end with space</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="UserInputIPCHost" xml:space="preserve">
|
||||||
|
<value>请输入你的IPC主机: </value>
|
||||||
|
<comment>Please note that this translation should end with space</comment>
|
||||||
|
</data>
|
||||||
<data name="WarningUnknownValuePleaseReport" xml:space="preserve">
|
<data name="WarningUnknownValuePleaseReport" xml:space="preserve">
|
||||||
<value>收到的{0} 为未知值,请报告此值:{1}</value>
|
<value>收到的{0} 为未知值,请报告此值:{1}</value>
|
||||||
<comment>{0} will be replaced by object's name, {1} will be replaced by value for that object</comment>
|
<comment>{0} will be replaced by object's name, {1} will be replaced by value for that object</comment>
|
||||||
@@ -286,10 +297,20 @@
|
|||||||
<value>目前无法同时挂 {0} 个以上的游戏,只有 {1} 里面的前 {0} 个游戏可用!</value>
|
<value>目前无法同时挂 {0} 个以上的游戏,只有 {1} 里面的前 {0} 个游戏可用!</value>
|
||||||
<comment>{0} will be replaced by max number of games, {1} will be replaced by name of the configuration property</comment>
|
<comment>{0} will be replaced by max number of games, {1} will be replaced by name of the configuration property</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ErrorIPCAddressAccessDeniedException" xml:space="preserve">
|
||||||
|
<value>由于目标地址访问受拒绝,无法启动 IPC 服务 !如果你想要使用ASF提供的 IPC 服务,请用管理员身份运行,或者给予更高的权限。</value>
|
||||||
|
</data>
|
||||||
|
<data name="IPCAnswered" xml:space="preserve">
|
||||||
|
<value>IPC 命令响应︰ {0} 及 {1}</value>
|
||||||
|
<comment>{0} will be replaced by IPC command, {1} will be replaced by IPC answer</comment>
|
||||||
|
</data>
|
||||||
|
<data name="IPCReady" xml:space="preserve">
|
||||||
|
<value>IPC 服务已就绪 !</value>
|
||||||
|
</data>
|
||||||
|
<data name="IPCStarting" xml:space="preserve">
|
||||||
|
<value>在 {0} 上的启动 IPC 服务...</value>
|
||||||
|
<comment>{0} will be replaced by IPC hostname</comment>
|
||||||
|
</data>
|
||||||
<data name="BotAlreadyStopped" xml:space="preserve">
|
<data name="BotAlreadyStopped" xml:space="preserve">
|
||||||
<value>这个帐号已停止运行!</value>
|
<value>这个帐号已停止运行!</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -649,5 +670,8 @@
|
|||||||
<value>已完成Steam探索队列 #{0}。</value>
|
<value>已完成Steam探索队列 #{0}。</value>
|
||||||
<comment>{0} will be replaced by queue number</comment>
|
<comment>{0} will be replaced by queue number</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BotOwnsOverview" xml:space="preserve">
|
||||||
|
<value>{0}/{1} 个BOT已经拥有所有正在被检查的游戏。</value>
|
||||||
|
<comment>{0} will be replaced by number of bots that already own games being checked, {1} will be replaced by total number of bots that were checked during the process</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ namespace ArchiSteamFarm {
|
|||||||
private const byte CodeInterval = 30;
|
private const byte CodeInterval = 30;
|
||||||
|
|
||||||
private static readonly char[] CodeCharacters = { '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y' };
|
private static readonly char[] CodeCharacters = { '2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y' };
|
||||||
private static readonly SemaphoreSlim TimeSemaphore = new SemaphoreSlim(1);
|
private static readonly SemaphoreSlim TimeSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private static int? SteamTimeDifference;
|
private static int? SteamTimeDifference;
|
||||||
|
|
||||||
// "ERROR" is being used by SteamDesktopAuthenticator
|
// "ERROR" is being used by SteamDesktopAuthenticator
|
||||||
internal bool HasCorrectDeviceID => !string.IsNullOrEmpty(DeviceID) && !DeviceID.Equals("ERROR");
|
internal bool HasCorrectDeviceID => !string.IsNullOrEmpty(DeviceID) && !DeviceID.Equals("ERROR");
|
||||||
|
|
||||||
private readonly SemaphoreSlim ConfirmationsSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim ConfirmationsSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
[JsonProperty(PropertyName = "identity_secret", Required = Required.Always)]
|
[JsonProperty(PropertyName = "identity_secret", Required = Required.Always)]
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace ArchiSteamFarm {
|
|||||||
private const string URL = "https://" + SharedInfo.StatisticsServer;
|
private const string URL = "https://" + SharedInfo.StatisticsServer;
|
||||||
|
|
||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
private readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private DateTime LastAnnouncementCheck = DateTime.MinValue;
|
private DateTime LastAnnouncementCheck = DateTime.MinValue;
|
||||||
private DateTime LastHeartBeat = DateTime.MinValue;
|
private DateTime LastHeartBeat = DateTime.MinValue;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace ArchiSteamFarm {
|
|||||||
|
|
||||||
private readonly Bot Bot;
|
private readonly Bot Bot;
|
||||||
private readonly ConcurrentHashSet<ulong> IgnoredTrades = new ConcurrentHashSet<ulong>();
|
private readonly ConcurrentHashSet<ulong> IgnoredTrades = new ConcurrentHashSet<ulong>();
|
||||||
private readonly SemaphoreSlim TradesSemaphore = new SemaphoreSlim(1);
|
private readonly SemaphoreSlim TradesSemaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
private bool ParsingScheduled;
|
private bool ParsingScheduled;
|
||||||
|
|
||||||
|
|||||||
@@ -535,7 +535,17 @@ namespace ArchiSteamFarm {
|
|||||||
ushort status = (ushort) responseMessage.StatusCode;
|
ushort status = (ushort) responseMessage.StatusCode;
|
||||||
if ((status >= 300) && (status <= 399) && (maxRedirections > 0)) {
|
if ((status >= 300) && (status <= 399) && (maxRedirections > 0)) {
|
||||||
redirectUri = responseMessage.Headers.Location;
|
redirectUri = responseMessage.Headers.Location;
|
||||||
if (!redirectUri.IsAbsoluteUri) {
|
|
||||||
|
if (redirectUri.IsAbsoluteUri) {
|
||||||
|
switch (redirectUri.Scheme) {
|
||||||
|
case "http":
|
||||||
|
case "https":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Invalid ones such as "steammobile"
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
redirectUri = new Uri(requestUri.GetLeftPart(UriPartial.Authority) + redirectUri);
|
redirectUri = new Uri(requestUri.GetLeftPart(UriPartial.Authority) + redirectUri);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -18,6 +18,6 @@
|
|||||||
"OptimizationMode": 0,
|
"OptimizationMode": 0,
|
||||||
"Statistics": true,
|
"Statistics": true,
|
||||||
"SteamOwnerID": 0,
|
"SteamOwnerID": 0,
|
||||||
"SteamProtocols": 7,
|
"SteamProtocols": 1,
|
||||||
"UpdateChannel": 1
|
"UpdateChannel": 1
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ deploy:
|
|||||||
- provider: GitHub
|
- provider: GitHub
|
||||||
tag: $(appveyor_repo_tag_name)
|
tag: $(appveyor_repo_tag_name)
|
||||||
release: ArchiSteamFarm 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
|
||||||
artifact: /.*/
|
artifact: /.*/
|
||||||
@@ -62,7 +62,7 @@ notifications:
|
|||||||
{
|
{
|
||||||
"avatar_url": "https://www.appveyor.com/assets/img/appveyor-logo-256.png",
|
"avatar_url": "https://www.appveyor.com/assets/img/appveyor-logo-256.png",
|
||||||
"username": "AppVeyor",
|
"username": "AppVeyor",
|
||||||
"content": "[{{projectName}}:{{branch}}] {{commitMessage}} - {{committerName}} ({{commitId}}) | **{{status}}** | {{buildUrl}}"
|
"content": "[{{projectName}}:{{branch}}] {{commitMessage}} - {{committerName}} ({{commitId}}) | {{buildUrl}}/artifacts | **{{status}}**"
|
||||||
}
|
}
|
||||||
on_build_success: true
|
on_build_success: true
|
||||||
on_build_failure: true
|
on_build_failure: true
|
||||||
|
|||||||
Reference in New Issue
Block a user