Reimplemented error handling for SettingsFile

This commit is contained in:
2023-08-06 17:14:57 +03:00
parent ed3128b940
commit 361ed37362
9 changed files with 235 additions and 76 deletions

View File

@@ -46,59 +46,8 @@ public static class Installer
public static async Task SetupPluginDatabase() public static async Task SetupPluginDatabase()
{ {
Console.WriteLine("The plugin database is required to run the bot but there is nothing configured yet."); Console.WriteLine("The plugin database is required to run the bot but there is nothing configured yet.");
Console.WriteLine("Please select one option : "); Console.WriteLine("Downloading the default database...");
Console.WriteLine("1. Download the official database file");
Console.WriteLine("2. Create a new (CUSTOM) database file");
var choice = 0;
Console.Write("Choice : ");
choice = int.Parse(Console.ReadLine());
if (choice != 1 && choice != 2)
{
Console.WriteLine("Invalid choice !");
Console.WriteLine("Please restart the installer !");
Console.ReadKey();
Environment.Exit(0);
}
if (choice == 1)
await DownloadPluginDatabase(); await DownloadPluginDatabase();
if (choice == 2)
{
Console.WriteLine("Do you have a url to a valid database file ? (y/n)");
var answer = Console.ReadLine();
if (answer == "y")
{
Console.WriteLine("Please enter the url :");
var url = Console.ReadLine();
await DownloadPluginDatabase(url);
return;
}
Console.WriteLine("Do you want to create a new database file ? (y/n)");
answer = Console.ReadLine();
if (answer == "y")
{
Console.WriteLine("A new file will be generated at ./Data/Resources/URLs.json");
Console.WriteLine("Please edit the file and restart the bot !");
Directory.CreateDirectory("./Data/Resources");
await File.WriteAllTextAsync("./Data/Resources/URLs.json",
@"
{
""PluginList"": """",
""PluginVersions"": """",
""StartupMessage"": """",
""SetupKeys"": """",
""Versions"": """",
""Changelog"": """",
""LinuxBot"": """",
""WindowsLauncher"": """",
}
".Replace(" ", "")
);
Environment.Exit(0);
}
}
} }
private static async Task DownloadPluginDatabase( private static async Task DownloadPluginDatabase(

View File

@@ -164,15 +164,8 @@ public class Program
{ {
await Initialize(); await Initialize();
if (!Directory.Exists("./Data/Resources") || !File.Exists("./Data/Resources/URLs.json"))
await Installer.SetupPluginDatabase();
URLs = new SettingsDictionary<string, string>("./Data/Resources/URLs.json");
Logger.LogEvent += (message, type, isInternal) => Logger.LogEvent += (message, type, isInternal) =>
{ {
if (isInternal) return;
if (type == LogLevel.INFO) if (type == LogLevel.INFO)
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
else if (type == LogLevel.WARNING) else if (type == LogLevel.WARNING)
@@ -186,6 +179,12 @@ public class Program
Console.ResetColor(); Console.ResetColor();
}; };
if (!Directory.Exists("./Data/Resources") || !File.Exists("./Data/Resources/URLs.json"))
await Installer.SetupPluginDatabase();
URLs = new SettingsDictionary<string, string>("./Data/Resources/URLs.json");
Console.WriteLine("Loading resources ..."); Console.WriteLine("Loading resources ...");
@@ -213,7 +212,6 @@ public class Program
} }
} }
var onlineSettingsList = await ServerCom.ReadTextFromURL(URLs["Versions"]); var onlineSettingsList = await ServerCom.ReadTextFromURL(URLs["Versions"]);
foreach (var key in onlineSettingsList) foreach (var key in onlineSettingsList)
{ {

View File

@@ -1,4 +1,5 @@
using System.IO; using System;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using PluginManager.Bot; using PluginManager.Bot;
using PluginManager.Others; using PluginManager.Others;

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
namespace PluginManager.Interfaces.Exceptions;
public interface IException
{
public List<string> Messages { get; set; }
public bool isFatal { get; }
public string GenerateFullMessage();
public void HandleException();
public IException AppendError(string message);
public IException AppendError(List<string> messages);
public IException IsFatal(bool isFatal = true);
}

View File

@@ -39,3 +39,9 @@ public enum InternalActionRunType
ON_STARTUP, ON_STARTUP,
ON_CALL ON_CALL
} }
internal enum ExceptionExitCode : int
{
CONFIG_FAILED_TO_LOAD = 1,
CONFIG_KEY_NOT_FOUND = 2,
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using PluginManager.Interfaces.Exceptions;
namespace PluginManager.Others.Exceptions;
public class ConfigFailedToLoad : IException
{
public List<string>? Messages { get; set; }
public bool isFatal { get; private set; }
public string? File { get; }
public ConfigFailedToLoad(string message, bool isFatal, string file)
{
this.isFatal = isFatal;
Messages = new List<string>() {message};
this.File = file;
}
public ConfigFailedToLoad(string message, bool isFatal)
{
this.isFatal = isFatal;
Messages = new List<string>() {message};
this.File = null;
}
public ConfigFailedToLoad(string message)
{
this.isFatal = false;
Messages = new List<string>() {message};
this.File = null;
}
public string GenerateFullMessage()
{
string messages = "";
foreach (var message in Messages)
{
messages += message + "\n";
}
return $"\nMessage: {messages}\nIsFatal: {isFatal}\nFile: {File ?? "null"}";
}
public void HandleException()
{
if (isFatal)
{
Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true);
Environment.Exit((int)ExceptionExitCode.CONFIG_FAILED_TO_LOAD);
}
Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING);
}
public IException AppendError(string message)
{
Messages.Add(message);
return this;
}
public IException AppendError(List<string> messages)
{
Messages.AddRange(messages);
return this;
}
public IException IsFatal(bool isFatal = true)
{
this.isFatal = isFatal;
return this;
}
public static ConfigFailedToLoad CreateError(string message, bool isFatal, string? file = null)
{
if (file is not null)
return new ConfigFailedToLoad(message, isFatal, file);
return new ConfigFailedToLoad(message, isFatal);
}
public static ConfigFailedToLoad CreateError(string message)
{
return new ConfigFailedToLoad(message);
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using PluginManager.Interfaces.Exceptions;
namespace PluginManager.Others.Exceptions;
public class ConfigNoKeyWasPresent: IException
{
public List<string> Messages { get; set; }
public bool isFatal { get; private set; }
public ConfigNoKeyWasPresent(string message, bool isFatal)
{
this.Messages = new List<string>() { message };
this.isFatal = isFatal;
}
public ConfigNoKeyWasPresent(string message)
{
this.Messages = new List<string>() { message };
this.isFatal = false;
}
public string GenerateFullMessage()
{
string messages = "";
foreach (var message in Messages)
{
messages += message + "\n";
}
return $"\nMessage: {messages}\nIsFatal: {isFatal}";
}
public void HandleException()
{
if (isFatal)
{
Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true);
Environment.Exit((int)ExceptionExitCode.CONFIG_KEY_NOT_FOUND);
}
Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING);
}
public IException AppendError(string message)
{
Messages.Add(message);
return this;
}
public IException AppendError(List<string> messages)
{
Messages.AddRange(messages);
return this;
}
public IException IsFatal(bool isFatal = true)
{
this.isFatal = isFatal;
return this;
}
public static ConfigNoKeyWasPresent CreateError(string message)
{
return new ConfigNoKeyWasPresent(message);
}
public static ConfigNoKeyWasPresent CreateError(string message, bool isFatal)
{
return new ConfigNoKeyWasPresent(message, isFatal);
}
}

View File

@@ -23,7 +23,7 @@ public class DBLogger
public IReadOnlyList<LogMessage> Logs => LogHistory; public IReadOnlyList<LogMessage> Logs => LogHistory;
public IReadOnlyList<LogMessage> Errors => ErrorHistory; public IReadOnlyList<LogMessage> Errors => ErrorHistory;
public event LogHandler LogEvent; public event LogHandler? LogEvent;
public void Log(string message, LogLevel type = LogLevel.INFO) public void Log(string message, LogLevel type = LogLevel.INFO)
{ {
@@ -52,7 +52,6 @@ public class DBLogger
public void Log(LogMessage message) public void Log(LogMessage message)
{ {
if (LogEvent is not null)
LogEvent?.Invoke(message.Message, message.Type); LogEvent?.Invoke(message.Message, message.Type);
if (message.Type != LogLevel.ERROR && message.Type != LogLevel.CRITICAL) if (message.Type != LogLevel.ERROR && message.Type != LogLevel.CRITICAL)

View File

@@ -1,8 +1,8 @@
using System; using System.Collections;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using PluginManager.Others.Exceptions;
namespace PluginManager.Others; namespace PluginManager.Others;
@@ -16,7 +16,10 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
_file = file; _file = file;
if (!LoadFromFile()) if (!LoadFromFile())
{ {
throw new Exception($"Failed to load {file}. Please check the file and try again."); ConfigFailedToLoad.CreateError("Failed to load config")
.AppendError("The file is empty or does not exist")
.IsFatal()
.HandleException();
} }
} }
@@ -31,8 +34,13 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
if (!string.IsNullOrEmpty(_file)) if (!string.IsNullOrEmpty(_file))
try try
{ {
if (File.Exists(_file)){ if (File.Exists(_file))
if (!File.ReadAllText(_file).Contains('{') && !File.ReadAllText(_file).Contains('}')) {
string FileContent = File.ReadAllText(_file);
if (string.IsNullOrEmpty(FileContent))
File.WriteAllText(_file, "{}");
if(!FileContent.Contains("{") || !FileContent.Contains("}"))
File.WriteAllText(_file, "{}"); File.WriteAllText(_file, "{}");
} }
else else
@@ -40,9 +48,12 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
_dictionary = JsonManager.ConvertFromJson<IDictionary<TKey, TValue>>(_file).Result; _dictionary = JsonManager.ConvertFromJson<IDictionary<TKey, TValue>>(_file).Result;
return true; return true;
} }
catch (Exception e) catch
{ {
Config.Logger.Error(e); ConfigFailedToLoad
.CreateError("Failed to load config")
.IsFatal()
.HandleException();
return false; return false;
} }
@@ -109,7 +120,19 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
public TValue this[TKey key] public TValue this[TKey key]
{ {
get => this._dictionary![key]; get
{
if (this._dictionary!.ContainsKey(key))
if(this._dictionary[key] is string s && !string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s))
return this._dictionary[key];
ConfigNoKeyWasPresent.CreateError($"Key {(key is string ? key : typeof(TKey).Name)} was not present in {_file ?? "config"}")
.AppendError("Deleting the file may fix this issue")
.IsFatal()
.HandleException();
return default!;
}
set => this._dictionary![key] = value; set => this._dictionary![key] = value;
} }