Reworked the Config system
This commit is contained in:
@@ -8,6 +8,8 @@ namespace DiscordBotCore.Others;
|
||||
|
||||
public static class ArchiveManager
|
||||
{
|
||||
|
||||
private static readonly string _ArchivesFolder = "./Data/Archives";
|
||||
|
||||
public static void CreateFromFile(string file, string folder)
|
||||
{
|
||||
@@ -33,7 +35,13 @@ public static class ArchiveManager
|
||||
public static async Task<byte[]?> ReadAllBytes(string fileName, string archName)
|
||||
{
|
||||
|
||||
archName = Path.Combine(Application.CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"], archName);
|
||||
string? archiveFolderBasePath = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ArchiveFolder", _ArchivesFolder);
|
||||
if(archiveFolderBasePath is null)
|
||||
throw new Exception("Archive folder not found");
|
||||
|
||||
Directory.CreateDirectory(archiveFolderBasePath);
|
||||
|
||||
archName = Path.Combine(archiveFolderBasePath, archName);
|
||||
|
||||
if (!File.Exists(archName))
|
||||
throw new Exception("Failed to load file !");
|
||||
@@ -64,7 +72,14 @@ public static class ArchiveManager
|
||||
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
||||
public static async Task<string?> ReadFromPakAsync(string fileName, string archFile)
|
||||
{
|
||||
archFile = Application.CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"] + archFile;
|
||||
string? archiveFolderBasePath = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ArchiveFolder", _ArchivesFolder);
|
||||
if(archiveFolderBasePath is null)
|
||||
throw new Exception("Archive folder not found");
|
||||
|
||||
Directory.CreateDirectory(archiveFolderBasePath);
|
||||
|
||||
archFile = Path.Combine(archiveFolderBasePath, archFile);
|
||||
|
||||
if (!File.Exists(archFile))
|
||||
throw new Exception("Failed to load file !");
|
||||
|
||||
|
||||
93
DiscordBotCore/Others/Settings/CustomSettingsDictionary.cs
Normal file
93
DiscordBotCore/Others/Settings/CustomSettingsDictionary.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace DiscordBotCore.Others.Settings;
|
||||
|
||||
public class CustomSettingsDictionary : CustomSettingsDictionaryBase<string, object>
|
||||
{
|
||||
private bool _EnableAutoAddOnGetWithDefault;
|
||||
private CustomSettingsDictionary(string diskLocation, bool enableAutoAddOnGetWithDefault): base(diskLocation)
|
||||
{
|
||||
_EnableAutoAddOnGetWithDefault = enableAutoAddOnGetWithDefault;
|
||||
}
|
||||
|
||||
public override async Task SaveToFile()
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(_InternalDictionary, Formatting.Indented);
|
||||
await File.WriteAllTextAsync(_DiskLocation, json);
|
||||
}
|
||||
|
||||
public override T Get<T>(string key, T defaultValue)
|
||||
{
|
||||
T value = base.Get(key, defaultValue);
|
||||
|
||||
if (_EnableAutoAddOnGetWithDefault && value.Equals(defaultValue))
|
||||
{
|
||||
Add(key, defaultValue);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public override List<T> GetList<T>(string key, List<T> defaultValue)
|
||||
{
|
||||
List<T> result = base.GetList(key, defaultValue);
|
||||
|
||||
if (_EnableAutoAddOnGetWithDefault && defaultValue.All(result.Contains))
|
||||
{
|
||||
Add(key,defaultValue);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task LoadFromFile()
|
||||
{
|
||||
string jsonContent = await File.ReadAllTextAsync(_DiskLocation);
|
||||
var jObject = JsonConvert.DeserializeObject<JObject>(jsonContent);
|
||||
_InternalDictionary.Clear();
|
||||
|
||||
foreach (var kvp in jObject)
|
||||
{
|
||||
AddPairToDictionary(kvp, _InternalDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddPairToDictionary(KeyValuePair<string, JToken> kvp, IDictionary<string, object> dict)
|
||||
{
|
||||
if (kvp.Value is JObject nestedJObject)
|
||||
{
|
||||
dict[kvp.Key] = nestedJObject.ToObject<Dictionary<string, object>>();
|
||||
|
||||
foreach (var nestedKvp in nestedJObject)
|
||||
{
|
||||
AddPairToDictionary(nestedKvp, dict[kvp.Key] as Dictionary<string, object>);
|
||||
}
|
||||
}
|
||||
else if (kvp.Value is JArray nestedJArray)
|
||||
{
|
||||
dict[kvp.Key] = nestedJArray.ToObject<List<object>>();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
dict[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Settings Dictionary from a file
|
||||
/// </summary>
|
||||
/// <param name="baseFile">The file location</param>
|
||||
/// <param name="enableAutoAddOnGetWithDefault">Set this to true if you want to update the dictionary with default values on get</param>
|
||||
internal static async Task<CustomSettingsDictionary> CreateFromFile(string baseFile, bool enableAutoAddOnGetWithDefault)
|
||||
{
|
||||
var settings = new CustomSettingsDictionary(baseFile, enableAutoAddOnGetWithDefault);
|
||||
await settings.LoadFromFile();
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
160
DiscordBotCore/Others/Settings/CustomSettingsDictionaryBase.cs
Normal file
160
DiscordBotCore/Others/Settings/CustomSettingsDictionaryBase.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DiscordBotCore.Others.Settings;
|
||||
|
||||
public abstract class CustomSettingsDictionaryBase<TKey,TValue> : ICustomSettingsDictionary<TKey,TValue>
|
||||
{
|
||||
protected readonly IDictionary<TKey,TValue> _InternalDictionary = new Dictionary<TKey, TValue>();
|
||||
protected readonly string _DiskLocation;
|
||||
|
||||
protected CustomSettingsDictionaryBase(string diskLocation)
|
||||
{
|
||||
this._DiskLocation = diskLocation;
|
||||
}
|
||||
|
||||
public virtual void Add(TKey key, TValue value)
|
||||
{
|
||||
if (_InternalDictionary.ContainsKey(key))
|
||||
return;
|
||||
|
||||
if (value is null)
|
||||
return;
|
||||
|
||||
_InternalDictionary.Add(key, value);
|
||||
}
|
||||
|
||||
public virtual void Set(TKey key, TValue value)
|
||||
{
|
||||
_InternalDictionary[key] = value;
|
||||
}
|
||||
|
||||
public virtual TValue Get(TKey key)
|
||||
{
|
||||
return _InternalDictionary[key];
|
||||
}
|
||||
|
||||
public virtual T Get<T>(TKey key, T defaultValue)
|
||||
{
|
||||
if (_InternalDictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public virtual T? Get<T>(TKey key)
|
||||
{
|
||||
if (_InternalDictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public virtual List<T> GetList<T>(TKey key, List<T> defaultValue)
|
||||
{
|
||||
if(_InternalDictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
if (value is not IList)
|
||||
{
|
||||
throw new Exception("The value is not a list");
|
||||
}
|
||||
|
||||
var list = new List<T>();
|
||||
foreach (var item in (IList)value)
|
||||
{
|
||||
list.Add(ConvertValue<T>(item));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public virtual void Remove(TKey key)
|
||||
{
|
||||
_InternalDictionary.Remove(key);
|
||||
}
|
||||
|
||||
public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return _InternalDictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
_InternalDictionary.Clear();
|
||||
}
|
||||
|
||||
public virtual bool ContainsKey(TKey key)
|
||||
{
|
||||
return _InternalDictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
||||
{
|
||||
return _InternalDictionary.Where(predicate);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, int, bool> predicate)
|
||||
{
|
||||
return _InternalDictionary.Where(predicate);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, TResult> selector)
|
||||
{
|
||||
return _InternalDictionary.Select(selector);
|
||||
}
|
||||
|
||||
public virtual IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, int, TResult> selector)
|
||||
{
|
||||
return _InternalDictionary.Select(selector);
|
||||
}
|
||||
|
||||
public virtual KeyValuePair<TKey, TValue> FirstOrDefault(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
||||
{
|
||||
return _InternalDictionary.FirstOrDefault(predicate);
|
||||
}
|
||||
|
||||
public virtual KeyValuePair<TKey, TValue> FirstOrDefault()
|
||||
{
|
||||
return _InternalDictionary.FirstOrDefault();
|
||||
}
|
||||
|
||||
public virtual bool ContainsAllKeys(params TKey[] keys)
|
||||
{
|
||||
return keys.All(ContainsKey);
|
||||
}
|
||||
|
||||
public virtual bool TryGetValue(TKey key, out TValue? value)
|
||||
{
|
||||
return _InternalDictionary.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public abstract Task SaveToFile();
|
||||
|
||||
public abstract Task LoadFromFile();
|
||||
|
||||
protected virtual T? ConvertValue<T>(object value)
|
||||
{
|
||||
|
||||
if (typeof(T) == typeof(ulong) && value is long longValue)
|
||||
{
|
||||
return (T)(object)Convert.ToUInt64(longValue);
|
||||
}
|
||||
|
||||
if (typeof(T).IsEnum && value is string stringValue)
|
||||
{
|
||||
return (T)Enum.Parse(typeof(T), stringValue);
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
}
|
||||
136
DiscordBotCore/Others/Settings/ICustomSettingsDictionary.cs
Normal file
136
DiscordBotCore/Others/Settings/ICustomSettingsDictionary.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DiscordBotCore.Others.Settings;
|
||||
|
||||
internal interface ICustomSettingsDictionary<TKey,TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds an element to the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <param name="value">The value</param>
|
||||
void Add(TKey key, TValue value);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of a key in the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <param name="value">The value</param>
|
||||
void Set(TKey key, TValue value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a key in the custom settings dictionary. If the T type is different then the TValue type, it will try to convert it.
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <param name="defaultValue">The default value to be returned if the searched value is not found</param>
|
||||
/// <typeparam name="T">The type of the returned value</typeparam>
|
||||
/// <returns></returns>
|
||||
T Get<T>(TKey key, T defaultValue);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of a key in the custom settings dictionary. If the T type is different then the TValue type, it will try to convert it.
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <typeparam name="T">The type of the returned value</typeparam>
|
||||
/// <returns></returns>
|
||||
T? Get<T>(TKey key);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of values from the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <param name="defaultValue">The default list to be returned if nothing is found</param>
|
||||
/// <typeparam name="T">The type of the returned value</typeparam>
|
||||
/// <returns></returns>
|
||||
List<T> GetList<T>(TKey key, List<T> defaultValue);
|
||||
|
||||
/// <summary>
|
||||
/// Remove a key from the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
void Remove(TKey key);
|
||||
|
||||
/// <summary>
|
||||
/// Get the enumerator of the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Clear the custom settings dictionary
|
||||
/// </summary>
|
||||
void Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Check if the custom settings dictionary contains a key
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <returns></returns>
|
||||
bool ContainsKey(TKey key);
|
||||
|
||||
/// <summary>
|
||||
/// Filter the custom settings dictionary based on a predicate
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate</param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, bool> predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Filter the custom settings dictionary based on a predicate
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate</param>
|
||||
IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, int, bool> predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Filter the custom settings dictionary based on a predicate
|
||||
/// </summary>
|
||||
/// <param name="selector">The predicate</param>
|
||||
IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, TResult> selector);
|
||||
|
||||
/// <summary>
|
||||
/// Filter the custom settings dictionary based on a predicate
|
||||
/// </summary>
|
||||
/// <param name="selector">The predicate</param>
|
||||
IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, int, TResult> selector);
|
||||
|
||||
/// <summary>
|
||||
/// Get the first element of the custom settings dictionary based on a predicate
|
||||
/// </summary>
|
||||
/// <param name="predicate">The predicate</param>
|
||||
KeyValuePair<TKey, TValue> FirstOrDefault(Func<KeyValuePair<TKey, TValue>, bool> predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Get the first element of the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
KeyValuePair<TKey, TValue> FirstOrDefault();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the custom settings dictionary contains all the keys
|
||||
/// </summary>
|
||||
/// <param name="keys">A list of keys</param>
|
||||
/// <returns></returns>
|
||||
bool ContainsAllKeys(params TKey[] keys);
|
||||
|
||||
/// <summary>
|
||||
/// Try to get the value of a key in the custom settings dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The key</param>
|
||||
/// <param name="value">The value</param>
|
||||
/// <returns></returns>
|
||||
bool TryGetValue(TKey key, out TValue? value);
|
||||
|
||||
/// <summary>
|
||||
/// Save the custom settings dictionary to a file
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task SaveToFile();
|
||||
|
||||
/// <summary>
|
||||
/// Load the custom settings dictionary from a file
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task LoadFromFile();
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DiscordBotCore.Others;
|
||||
|
||||
public class SettingsDictionary<TKey, TValue>
|
||||
{
|
||||
private string _File { get; }
|
||||
protected IDictionary<TKey, TValue> _Dictionary;
|
||||
|
||||
public SettingsDictionary(string file)
|
||||
{
|
||||
this._File = file;
|
||||
_Dictionary = null!;
|
||||
}
|
||||
|
||||
public async Task SaveToFile()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_File))
|
||||
await JsonManager.SaveToJsonFile(_File, _Dictionary);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||
{
|
||||
return _Dictionary.GetEnumerator();
|
||||
}
|
||||
|
||||
public async Task<bool> LoadFromFile()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_File))
|
||||
return false;
|
||||
|
||||
if(!File.Exists(_File))
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>();
|
||||
await SaveToFile();
|
||||
return false;
|
||||
}
|
||||
|
||||
string fileAsText = await File.ReadAllTextAsync(_File);
|
||||
if(string.IsNullOrEmpty(fileAsText) || string.IsNullOrWhiteSpace(fileAsText))
|
||||
{
|
||||
_Dictionary = new Dictionary<TKey, TValue>();
|
||||
await SaveToFile();
|
||||
return false;
|
||||
}
|
||||
|
||||
_Dictionary = await JsonManager.ConvertFromJson<IDictionary<TKey,TValue>>(fileAsText);
|
||||
|
||||
if (_Dictionary.Keys.Count == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
if (_Dictionary.ContainsKey(key))
|
||||
return;
|
||||
|
||||
_Dictionary.Add(key, value);
|
||||
}
|
||||
|
||||
public bool ContainsAllKeys(params TKey[] keys)
|
||||
{
|
||||
return keys.All(key => _Dictionary.ContainsKey(key));
|
||||
}
|
||||
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _Dictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return _Dictionary.Remove(key);
|
||||
}
|
||||
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if(!_Dictionary.ContainsKey(key))
|
||||
throw new System.Exception($"The key {key} ({typeof(TKey)}) (file: {this._File}) was not present in the dictionary");
|
||||
|
||||
if(_Dictionary[key] is not TValue)
|
||||
throw new System.Exception("The dictionary is corrupted. This error is critical !");
|
||||
|
||||
return _Dictionary[key];
|
||||
}
|
||||
set => _Dictionary[key] = value;
|
||||
}
|
||||
|
||||
// First
|
||||
public KeyValuePair<TKey, TValue> FirstOrDefault(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
||||
{
|
||||
return _Dictionary.FirstOrDefault(predicate);
|
||||
}
|
||||
|
||||
// Where
|
||||
public IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
||||
{
|
||||
return _Dictionary.Where(predicate);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_Dictionary.Clear();
|
||||
}
|
||||
|
||||
public IEnumerable<TKey> Keys => _Dictionary.Keys;
|
||||
public IEnumerable<TValue> Values => _Dictionary.Values;
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user