Various bugfixes

This commit is contained in:
JustArchi
2017-07-10 17:07:48 +02:00
parent 32b2ea9fb7
commit f4187e194e
6 changed files with 119 additions and 85 deletions

View File

@@ -19,7 +19,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.5.1" />
<PackageReference Include="HtmlAgilityPack" Version="1.5.2-beta1" />
<PackageReference Include="Humanizer" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Nito.AsyncEx.Coordination" Version="5.0.0-pre-02" />

View File

@@ -156,7 +156,12 @@ namespace ArchiSteamFarm {
try {
File.WriteAllText(newFilePath, json);
File.Replace(newFilePath, FilePath, null);
if (File.Exists(FilePath)) {
File.Replace(newFilePath, FilePath, null);
} else {
File.Move(newFilePath, FilePath);
}
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
}

View File

@@ -118,7 +118,12 @@ namespace ArchiSteamFarm {
try {
File.WriteAllText(newFilePath, json);
File.Replace(newFilePath, FilePath, null);
if (File.Exists(FilePath)) {
File.Replace(newFilePath, FilePath, null);
} else {
File.Move(newFilePath, FilePath);
}
} catch (Exception e) {
ASF.ArchiLogger.LogGenericException(e);
}

View File

@@ -50,11 +50,11 @@ namespace ArchiSteamFarm {
}
internal static void Start() {
if (KeepRunning) {
if (KeepRunning || (HttpListener.Prefixes.Count == 0)) {
return;
}
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, HttpListener.Prefixes.FirstOrDefault()));
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCStarting, HttpListener.Prefixes.First()));
try {
HttpListener.Start();
@@ -84,56 +84,60 @@ namespace ArchiSteamFarm {
return;
}
if (Program.GlobalConfig.SteamOwnerID == 0) {
ASF.ArchiLogger.LogGenericInfo(Strings.ErrorIPCAccessDenied);
await context.Response.WriteAsync(HttpStatusCode.Forbidden, Strings.ErrorIPCAccessDenied).ConfigureAwait(false);
return;
}
try {
if (Program.GlobalConfig.SteamOwnerID == 0) {
ASF.ArchiLogger.LogGenericWarning(Strings.ErrorIPCAccessDenied);
await context.Response.WriteAsync(HttpStatusCode.Forbidden, Strings.ErrorIPCAccessDenied).ConfigureAwait(false);
return;
}
if (!context.Request.RawUrl.StartsWith("/" + nameof(IPC), StringComparison.Ordinal)) {
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
return;
}
switch (context.Request.HttpMethod) {
case WebRequestMethods.Http.Get:
for (int i = 0; i < context.Request.QueryString.Count; i++) {
string key = context.Request.QueryString.GetKey(i);
switch (key) {
case "command":
string command = context.Request.QueryString.Get(i);
if (string.IsNullOrEmpty(command)) {
break;
}
Bot bot = Bot.Bots.Values.FirstOrDefault();
if (bot == null) {
await context.Response.WriteAsync(HttpStatusCode.NotAcceptable, Strings.ErrorNoBotsDefined).ConfigureAwait(false);
return;
}
if (command[0] != '!') {
command = "!" + command;
}
string response = await bot.Response(Program.GlobalConfig.SteamOwnerID, command).ConfigureAwait(false);
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCAnswered, command, response));
await context.Response.WriteAsync(HttpStatusCode.OK, response).ConfigureAwait(false);
break;
}
}
break;
default:
if (!context.Request.RawUrl.StartsWith("/" + nameof(IPC), StringComparison.Ordinal)) {
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
return;
}
}
if (context.Response.ContentLength64 == 0) {
await context.Response.WriteAsync(HttpStatusCode.MethodNotAllowed, nameof(HttpStatusCode.MethodNotAllowed)).ConfigureAwait(false);
switch (context.Request.HttpMethod) {
case WebRequestMethods.Http.Get:
for (int i = 0; i < context.Request.QueryString.Count; i++) {
string key = context.Request.QueryString.GetKey(i);
switch (key) {
case "command":
string command = context.Request.QueryString.Get(i);
if (string.IsNullOrEmpty(command)) {
break;
}
Bot bot = Bot.Bots.Values.FirstOrDefault();
if (bot == null) {
await context.Response.WriteAsync(HttpStatusCode.NotAcceptable, Strings.ErrorNoBotsDefined).ConfigureAwait(false);
return;
}
if (command[0] != '!') {
command = "!" + command;
}
string response = await bot.Response(Program.GlobalConfig.SteamOwnerID, command).ConfigureAwait(false);
ASF.ArchiLogger.LogGenericInfo(string.Format(Strings.IPCAnswered, command, response));
await context.Response.WriteAsync(HttpStatusCode.OK, response).ConfigureAwait(false);
break;
}
}
break;
default:
await context.Response.WriteAsync(HttpStatusCode.BadRequest, nameof(HttpStatusCode.BadRequest)).ConfigureAwait(false);
return;
}
if (context.Response.ContentLength64 == 0) {
await context.Response.WriteAsync(HttpStatusCode.MethodNotAllowed, nameof(HttpStatusCode.MethodNotAllowed)).ConfigureAwait(false);
}
} finally {
context.Response.Close();
}
}
@@ -148,8 +152,7 @@ namespace ArchiSteamFarm {
continue;
}
await HandleRequest(context).ConfigureAwait(false);
context.Response.Close();
Utilities.StartBackgroundFunction(() => HandleRequest(context));
}
}
@@ -164,8 +167,14 @@ namespace ArchiSteamFarm {
response.StatusCode = (ushort) statusCode;
}
byte[] buffer = Encoding.UTF8.GetBytes(message);
Encoding encoding = Encoding.UTF8;
response.ContentEncoding = encoding;
string html = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head><body><p>" + message + "</p></body></html>";
byte[] buffer = encoding.GetBytes(html);
response.ContentLength64 = buffer.Length;
await response.OutputStream.WriteAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
} catch (Exception e) {
response.StatusCode = (ushort) HttpStatusCode.InternalServerError;

View File

@@ -143,8 +143,9 @@ namespace ArchiSteamFarm {
}
private static async Task Init(string[] args) {
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionHandler;
AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
// We must register our logging target as soon as possible
Target.Register<SteamTarget>(SteamTarget.TargetName);
@@ -183,6 +184,8 @@ namespace ArchiSteamFarm {
ParsePostInitArgs(args);
}
IPC.Start();
if (!Debugging.IsDebugBuild) {
await ASF.CheckForUpdate().ConfigureAwait(false);
}
@@ -319,8 +322,6 @@ namespace ArchiSteamFarm {
ShutdownSequenceInitialized = true;
IPC.Stop();
if (Bot.Bots.Count == 0) {
return true;
}
@@ -353,6 +354,31 @@ namespace ArchiSteamFarm {
Exit().Wait();
}
private static void OnProcessExit(object sender, EventArgs e) => IPC.Stop();
private static async void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) {
if (e?.ExceptionObject == null) {
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.ExceptionObject));
return;
}
ASF.ArchiLogger.LogFatalException((Exception) e.ExceptionObject);
await Exit(1).ConfigureAwait(false);
}
private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) {
if (e?.Exception == null) {
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.Exception));
return;
}
ASF.ArchiLogger.LogFatalException(e.Exception);
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
// Thanks Valve.
e.SetObserved();
}
private static void ParsePostInitArgs(IEnumerable<string> args) {
if (args == null) {
ASF.ArchiLogger.LogNullError(nameof(args));
@@ -407,28 +433,5 @@ namespace ArchiSteamFarm {
ShutdownResetEvent.Set();
}
private static async void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e) {
if (e?.ExceptionObject == null) {
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.ExceptionObject));
return;
}
ASF.ArchiLogger.LogFatalException((Exception) e.ExceptionObject);
await Exit(1).ConfigureAwait(false);
}
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs e) {
if (e?.Exception == null) {
ASF.ArchiLogger.LogNullError(nameof(e) + " || " + nameof(e.Exception));
return;
}
ASF.ArchiLogger.LogFatalException(e.Exception);
// Normally we should abort the application here, but many tasks are in fact failing in SK2 code which we can't easily fix
// Thanks Valve.
e.SetObserved();
}
}
}

View File

@@ -95,22 +95,34 @@ namespace ArchiSteamFarm {
}
}
internal static void StartBackgroundAction(Action action) {
internal static void StartBackgroundAction(Action action, bool longRunning = true) {
if (action == null) {
ASF.ArchiLogger.LogNullError(nameof(action));
return;
}
Task.Factory.StartNew(action, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
if (longRunning) {
options |= TaskCreationOptions.LongRunning;
}
Task.Factory.StartNew(action, options).Forget();
}
internal static void StartBackgroundFunction(Func<Task> function) {
internal static void StartBackgroundFunction(Func<Task> function, bool longRunning = true) {
if (function == null) {
ASF.ArchiLogger.LogNullError(nameof(function));
return;
}
Task.Factory.StartNew(function, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
if (longRunning) {
options |= TaskCreationOptions.LongRunning;
}
Task.Factory.StartNew(function, options).Forget();
}
internal static IEnumerable<T> ToEnumerable<T>(this T item) where T : struct {