Work on GlobalConfig, #131

This commit is contained in:
JustArchi
2016-03-06 23:28:56 +01:00
parent 238cc2ad46
commit 292ec97b1c
10 changed files with 138 additions and 29 deletions

View File

@@ -106,6 +106,7 @@
<Compile Include="CardsFarmer.cs" />
<Compile Include="CMsgClientClanInviteAction.cs" />
<Compile Include="Debugging.cs" />
<Compile Include="GlobalConfig.cs" />
<Compile Include="Logging.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@@ -120,6 +121,9 @@
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="config\ASF.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="config\example.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@@ -34,13 +34,17 @@ using System.Threading.Tasks;
namespace ArchiSteamFarm {
internal sealed class ArchiWebHandler {
private const int Timeout = 1000 * WebBrowser.HttpTimeout; // In miliseconds
private static int Timeout;
private readonly Bot Bot;
private readonly Dictionary<string, string> Cookie = new Dictionary<string, string>(4);
private ulong SteamID;
internal static void Init() {
Timeout = Program.GlobalConfig.HttpTimeout * 1000;
}
internal ArchiWebHandler(Bot bot) {
Bot = bot;
}

View File

@@ -30,8 +30,6 @@ using System.Xml;
namespace ArchiSteamFarm {
internal sealed class BotConfig {
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 303700, 335590, 368020, 425280 };
[JsonProperty(Required = Required.DisallowNull)]
internal bool Enabled { get; private set; } = false;

View File

@@ -329,7 +329,7 @@ namespace ArchiSteamFarm {
continue;
}
if (BotConfig.GlobalBlacklist.Contains(appID)) {
if (GlobalConfig.GlobalBlacklist.Contains(appID) || Program.GlobalConfig.Blacklist.Contains(appID)) {
continue;
}

View File

@@ -0,0 +1,83 @@
/*
_ _ _ ____ _ _____
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
Contact: JustArchi@JustArchi.net
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using Newtonsoft.Json;
using SteamAuth;
using System;
using System.Collections.Generic;
using System.IO;
namespace ArchiSteamFarm {
internal sealed class GlobalConfig {
internal enum EUpdateChannel : byte {
Unknown,
Stable,
Experimental
}
// This is hardcoded blacklist which should not be possible to change
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 303700, 335590, 368020, 425280 };
[JsonProperty(Required = Required.DisallowNull)]
internal bool AutoUpdates { get; private set; } = true;
[JsonProperty(Required = Required.DisallowNull)]
internal EUpdateChannel UpdateChannel { get; private set; } = GlobalConfig.EUpdateChannel.Stable;
[JsonProperty(Required = Required.DisallowNull)]
internal byte HttpTimeout { get; private set; } = 30;
[JsonProperty(Required = Required.DisallowNull)]
internal byte RequestLimiterDelay { get; private set; } = 7;
[JsonProperty(Required = Required.DisallowNull)]
internal string WCFHostname { get; private set; } = "localhost";
[JsonProperty(Required = Required.DisallowNull)]
internal ushort WCFPort { get; private set; } = 1242;
[JsonProperty(Required = Required.DisallowNull)]
internal HashSet<uint> Blacklist { get; private set; } = new HashSet<uint>(GlobalBlacklist);
internal static GlobalConfig Load() {
string filePath = Path.Combine(Program.ConfigDirectory, Program.GlobalConfigFile);
if (!File.Exists(filePath)) {
return null;
}
GlobalConfig globalConfig;
try {
globalConfig = JsonConvert.DeserializeObject<GlobalConfig>(File.ReadAllText(filePath));
} catch (Exception e) {
Logging.LogGenericException(e);
return null;
}
return globalConfig;
}
// This constructor is used only by deserializer
private GlobalConfig() { }
}
}

View File

@@ -31,17 +31,18 @@ namespace ArchiSteamFarm {
internal static class Logging {
private static readonly object FileLock = new object();
internal static bool LogToFile { get; set; } = false;
internal static bool? LogToFile { get; set; } = null;
internal static void Init() {
if (!LogToFile.HasValue) {
LogToFile = true;
}
lock (FileLock) {
try {
File.Delete(Program.LogFile);
} catch (Exception e) {
bool logToFile = LogToFile;
LogToFile = false;
LogGenericException(e);
LogToFile = logToFile;
}
}
}
@@ -121,15 +122,14 @@ namespace ArchiSteamFarm {
Console.Write(loggedMessage);
}
if (LogToFile) {
if (LogToFile.GetValueOrDefault()) {
lock (FileLock) {
try {
File.AppendAllText(Program.LogFile, loggedMessage);
} catch (Exception e) {
bool logToFile = LogToFile;
LogToFile = false;
LogGenericException(e);
LogToFile = logToFile;
LogToFile = true;
}
}
}

View File

@@ -51,6 +51,7 @@ namespace ArchiSteamFarm {
private const string LatestGithubReleaseURL = "https://api.github.com/repos/JustArchi/ArchiSteamFarm/releases/latest";
internal const string ConfigDirectory = "config";
internal const string LogFile = "log.txt";
internal const string GlobalConfigFile = "ASF.json";
private static readonly object ConsoleLock = new object();
private static readonly SemaphoreSlim SteamSemaphore = new SemaphoreSlim(1);
@@ -62,10 +63,11 @@ namespace ArchiSteamFarm {
internal static readonly string Version = Assembly.GetName().Version.ToString();
private static EMode Mode;
internal static GlobalConfig GlobalConfig { get; private set; }
internal static bool ConsoleIsBusy { get; private set; } = false;
private static EMode Mode = EMode.Normal;
private static async Task CheckForUpdate() {
JObject response = await WebBrowser.UrlGetToJObject(LatestGithubReleaseURL).ConfigureAwait(false);
if (response == null) {
@@ -105,7 +107,7 @@ namespace ArchiSteamFarm {
internal static async Task LimitSteamRequestsAsync() {
await SteamSemaphore.WaitAsync().ConfigureAwait(false);
Task.Run(async () => {
await Utilities.SleepAsync(7000).ConfigureAwait(false); // We must add some delay to not get caught by Steam rate limiter
await Utilities.SleepAsync(GlobalConfig.RequestLimiterDelay * 1000).ConfigureAwait(false);
SteamSemaphore.Release();
}).Forget();
}
@@ -166,8 +168,16 @@ namespace ArchiSteamFarm {
}
private static void InitServices() {
Logging.Init();
GlobalConfig = GlobalConfig.Load();
if (GlobalConfig == null) {
Logging.LogGenericError("Global config could not be loaded, please make sure that ASF.db exists and is valid!");
Thread.Sleep(5000);
Exit(1);
}
ArchiWebHandler.Init();
WebBrowser.Init();
WCF.Init();
}
private static void ParseArgs(string[] args) {
@@ -244,11 +254,7 @@ namespace ArchiSteamFarm {
}
}
// By default we're operating on normal mode
Mode = EMode.Normal;
Logging.LogToFile = true;
// But that can be overriden by arguments
// Parse args
ParseArgs(args);
// If we ran ASF as a client, we're done by now
@@ -256,7 +262,8 @@ namespace ArchiSteamFarm {
return;
}
Task.Run(async () => await CheckForUpdate().ConfigureAwait(false)).Wait();
// From now on it's server mode
Logging.Init();
if (!Directory.Exists(ConfigDirectory)) {
Logging.LogGenericError("Config directory doesn't exist!");
@@ -264,11 +271,19 @@ namespace ArchiSteamFarm {
Exit(1);
}
Task.Run(async () => await CheckForUpdate().ConfigureAwait(false)).Wait();
// Before attempting to connect, initialize our list of CMs
Bot.RefreshCMs().Wait();
string globalConfigName = GlobalConfigFile.Substring(0, GlobalConfigFile.LastIndexOf('.'));
foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.json")) {
string botName = Path.GetFileNameWithoutExtension(configFile);
if (botName.Equals(globalConfigName)) {
continue;
}
Bot bot = new Bot(botName);
if (!bot.BotConfig.Enabled) {
Logging.LogGenericInfo("Not starting this instance because it's disabled in config file", botName);

View File

@@ -40,7 +40,7 @@ namespace ArchiSteamFarm {
internal static async Task LimitInventoryRequestsAsync() {
await InventorySemaphore.WaitAsync().ConfigureAwait(false);
Task.Run(async () => {
await Utilities.SleepAsync(3000).ConfigureAwait(false); // We must add some delay to not get caught by Steam rate limiter
await Utilities.SleepAsync(Program.GlobalConfig.RequestLimiterDelay * 1000).ConfigureAwait(false);
InventorySemaphore.Release();
}).Forget();
}

View File

@@ -35,11 +35,15 @@ namespace ArchiSteamFarm {
internal sealed class WCF : IWCF {
private const string URL = "http://localhost:1242/ASF"; // 1242 = 1024 + A(65) + S(83) + F(70)
private static string URL = "http://localhost:1242/ASF"; // 1242 = 1024 + A(65) + S(83) + F(70)
private ServiceHost ServiceHost;
private Client Client;
internal static void Init() {
URL = "http://" + Program.GlobalConfig.WCFHostname + ":" + Program.GlobalConfig.WCFPort + "/ASF";
}
internal bool IsServerRunning() {
return ServiceHost != null;
}

View File

@@ -33,19 +33,20 @@ using System.Threading.Tasks;
namespace ArchiSteamFarm {
internal static class WebBrowser {
internal const byte HttpTimeout = 180; // In seconds, how long we can wait for server's response
internal const byte MaxConnections = 10; // Defines maximum number of connections per ServicePoint. Be careful, as it also defines maximum number of sockets in CLOSE_WAIT state
internal const byte MaxIdleTime = 15; // In seconds, how long socket is allowed to stay in CLOSE_WAIT state after there are no connections to it
internal const byte MaxRetries = 5; // Defines maximum number of retries, UrlRequest() does not handle retry by itself (it's app responsibility)
private static readonly string DefaultUserAgent = "ArchiSteamFarm/" + Program.Version;
private static readonly HttpClient HttpClient = new HttpClient(new HttpClientHandler {
UseCookies = false
}) {
Timeout = TimeSpan.FromSeconds(HttpTimeout)
};
private static HttpClient HttpClient;
internal static void Init() {
HttpClient = new HttpClient(new HttpClientHandler {
UseCookies = false
}) {
Timeout = TimeSpan.FromSeconds(Program.GlobalConfig.HttpTimeout)
};
// Most web services expect that UserAgent is set, so we declare it globally
// Any request can override that on as-needed basis (see: RequestOptions.FakeUserAgent)
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(DefaultUserAgent);