Update to the Settings interface.

- Methods are now suffixed async
- Extension methods moved to the actual class and class renamed from SettingValue to Setting
- "Helpers" renamed to "SettingsProvider"
- Removed the ghetto CSV list method. Only setting using it was Pusher Channels which was orphaned by the new Kick channel feature. The call to ToList in the Chips.gg integration was incorrect and just proves lists should be consistently based around JSON objects instead of randomly string splitting
This commit is contained in:
barelyprofessional
2025-05-06 14:07:52 -05:00
parent 4fecdbce06
commit e2c70cc5c5
17 changed files with 167 additions and 229 deletions

View File

@@ -69,33 +69,47 @@ public static class BuiltIn
return;
}
await Helpers.SetValue(Keys.PusherEndpoint, oldConfig.PusherEndpoint.ToString());
await Helpers.SetValue(Keys.KiwiFarmsWsEndpoint, oldConfig.KfWsEndpoint.ToString());
await Helpers.SetValueAsList(Keys.PusherChannels, oldConfig.PusherChannels);
await Helpers.SetValue(Keys.KiwiFarmsRoomId, oldConfig.KfChatRoomId);
await Helpers.SetValue(Keys.Proxy, oldConfig.Proxy);
await Helpers.SetValue(Keys.KiwiFarmsWsReconnectTimeout, oldConfig.KfReconnectTimeout);
await Helpers.SetValue(Keys.PusherReconnectTimeout, oldConfig.PusherReconnectTimeout);
await Helpers.SetValueAsBoolean(Keys.GambaSeshDetectEnabled, oldConfig.EnableGambaSeshDetect);
await Helpers.SetValue(Keys.GambaSeshUserId, oldConfig.GambaSeshUserId);
await Helpers.SetValue(Keys.KickIcon, oldConfig.KickIcon);
await Helpers.SetValue(Keys.KiwiFarmsDomain, oldConfig.KfDomain);
await Helpers.SetValue(Keys.KiwiFarmsUsername, oldConfig.KfUsername);
await Helpers.SetValue(Keys.KiwiFarmsPassword, oldConfig.KfPassword);
await Helpers.SetValue(Keys.TwitchBossmanJackId, oldConfig.BossmanJackTwitchId);
await Helpers.SetValue(Keys.TwitchBossmanJackUsername, oldConfig.BossmanJackTwitchUsername);
await Helpers.SetValueAsBoolean(Keys.KiwiFarmsSuppressChatMessages, oldConfig.SuppressChatMessages);
await Helpers.SetValue(Keys.DiscordToken, oldConfig.DiscordToken);
await Helpers.SetValue(Keys.DiscordBmjId, oldConfig.DiscordBmjId);
await SettingsProvider.SetValueAsync(Keys.PusherEndpoint, oldConfig.PusherEndpoint.ToString());
await SettingsProvider.SetValueAsync(Keys.KiwiFarmsWsEndpoint, oldConfig.KfWsEndpoint.ToString());
await SettingsProvider.SetValueAsync(Keys.KiwiFarmsRoomId, oldConfig.KfChatRoomId);
await SettingsProvider.SetValueAsync(Keys.Proxy, oldConfig.Proxy);
await SettingsProvider.SetValueAsync(Keys.KiwiFarmsWsReconnectTimeout, oldConfig.KfReconnectTimeout);
await SettingsProvider.SetValueAsync(Keys.PusherReconnectTimeout, oldConfig.PusherReconnectTimeout);
await SettingsProvider.SetValueAsBooleanAsync(Keys.GambaSeshDetectEnabled, oldConfig.EnableGambaSeshDetect);
await SettingsProvider.SetValueAsync(Keys.GambaSeshUserId, oldConfig.GambaSeshUserId);
await SettingsProvider.SetValueAsync(Keys.KickIcon, oldConfig.KickIcon);
await SettingsProvider.SetValueAsync(Keys.KiwiFarmsDomain, oldConfig.KfDomain);
await SettingsProvider.SetValueAsync(Keys.KiwiFarmsUsername, oldConfig.KfUsername);
await SettingsProvider.SetValueAsync(Keys.KiwiFarmsPassword, oldConfig.KfPassword);
await SettingsProvider.SetValueAsync(Keys.TwitchBossmanJackId, oldConfig.BossmanJackTwitchId);
await SettingsProvider.SetValueAsync(Keys.TwitchBossmanJackUsername, oldConfig.BossmanJackTwitchUsername);
await SettingsProvider.SetValueAsBooleanAsync(Keys.KiwiFarmsSuppressChatMessages, oldConfig.SuppressChatMessages);
await SettingsProvider.SetValueAsync(Keys.DiscordToken, oldConfig.DiscordToken);
await SettingsProvider.SetValueAsync(Keys.DiscordBmjId, oldConfig.DiscordBmjId);
logger.Info($"{oldConfigPath} migration done.");
logger.Info("Renaming files no longer in use");
// Utils.SafelyRenameFile will attempt to rename and swallow any exception (with logging) if it fails
Utils.SafelyRenameFile(oldConfigPath, $"{oldConfigPath}.migrated");
SafelyRenameFile(oldConfigPath, $"{oldConfigPath}.migrated");
logger.Info("File renamed");
}
private static void SafelyRenameFile(string oldName, string newName)
{
var logger = LogManager.GetCurrentClassLogger();
logger.Debug($"Renaming {oldName} to {newName}");
try
{
File.Move(oldName, newName);
}
catch (Exception e)
{
logger.Error($"Failed to rename {oldName} to {newName}");
logger.Error(e);
}
}
public static List<BuiltInSettingsModel> BuiltInSettings =
[
new BuiltInSettingsModel
@@ -121,17 +135,6 @@ public static class BuiltIn
ValueType = SettingValueType.Text
},
new BuiltInSettingsModel
{
Key = Keys.PusherChannels,
Regex = @".+",
Description =
"List of Pusher channels to subscribe to",
Default = null,
IsSecret = false,
CacheDuration = TimeSpan.FromHours(1),
ValueType = SettingValueType.Array
},
new BuiltInSettingsModel
{
Key = Keys.KiwiFarmsRoomId,
Regex = @"\d+",
@@ -861,7 +864,6 @@ public static class BuiltIn
{
public static string PusherEndpoint = "Pusher.Endpoint";
public static string KiwiFarmsWsEndpoint = "KiwiFarms.WsEndpoint";
public static string PusherChannels = "Pusher.Channels";
public static string KiwiFarmsRoomId = "KiwiFarms.RoomId";
public static string Proxy = "Proxy";
public static string KiwiFarmsWsReconnectTimeout = "KiwiFarms.WsReconnectTimeout";

View File

@@ -0,0 +1,31 @@
using System.Text.Json;
using KfChatDotNetBot.Models.DbModels;
namespace KfChatDotNetBot.Settings;
public class Setting(string? value, SettingDbModel dbEntry, bool cached)
{
public string? Value { get; set; } = value;
public SettingDbModel DbEntry { get; set; } = dbEntry;
public bool Cached { get; set; } = cached;
public T? JsonDeserialize<T>()
{
if (Value == null)
{
return default;
}
return JsonSerializer.Deserialize<T>(Value) ?? default(T);
}
public bool ToBoolean()
{
return Value is not (null or "null") && Value.Equals("true", StringComparison.CurrentCultureIgnoreCase);
}
public T ToType<T>()
{
return (T)Convert.ChangeType(Value, typeof(T))!;
}
}

View File

@@ -1,10 +0,0 @@
using KfChatDotNetBot.Models.DbModels;
namespace KfChatDotNetBot.Settings;
public class SettingValue(string? value, SettingDbModel dbEntry, bool cached)
{
public string? Value { get; set; } = value;
public SettingDbModel DbEntry { get; set; } = dbEntry;
public bool Cached { get; set; } = cached;
}

View File

@@ -6,9 +6,9 @@ using NLog;
namespace KfChatDotNetBot.Settings;
public static class Helpers
public static class SettingsProvider
{
public static async Task<SettingValue> GetValue(string key, bool caseInsensitive = false, bool bypassCache = false)
public static async Task<Setting> GetValueAsync(string key, bool caseInsensitive = false, bool bypassCache = false)
{
var logger = LogManager.GetCurrentClassLogger();
var cache = MemoryCache.Default;
@@ -17,7 +17,7 @@ public static class Helpers
var cachedSetting = cache.Get(key) as SettingDbModel;
var value = cachedSetting.Value;
if (cachedSetting.Value == "null") value = null;
return new SettingValue(value, cachedSetting, true);
return new Setting(value, cachedSetting, true);
}
await using var db = new ApplicationDbContext();
logger.Trace($"Retrieving value for {key}");
@@ -45,7 +45,7 @@ public static class Helpers
if (setting.Value == "null")
{
logger.Debug($"{key}'s value is null so returning SettingValue(null)");
return new SettingValue(null, setting, false);
return new Setting(null, setting, false);
}
if (setting.IsSecret)
@@ -58,24 +58,24 @@ public static class Helpers
logger.Info($"Cache Miss! Returning '{setting.Value}' for {key}");
}
return new SettingValue(setting.Value, setting, false);
return new Setting(setting.Value, setting, false);
}
public static async Task<Dictionary<string, SettingValue>> GetMultipleValues(string[] keys, bool caseInsensitive = false, bool bypassCache = false)
public static async Task<Dictionary<string, Setting>> GetMultipleValuesAsync(string[] keys, bool caseInsensitive = false, bool bypassCache = false)
{
var logger = LogManager.GetCurrentClassLogger();
logger.Trace($"Getting values for keys {string.Join(", ", keys)}");
Dictionary<string, SettingValue> values = new Dictionary<string, SettingValue>();
var values = new Dictionary<string, Setting>();
foreach (var key in keys)
{
values.Add(key, await GetValue(key, caseInsensitive, bypassCache));
values.Add(key, await GetValueAsync(key, caseInsensitive, bypassCache));
}
return values;
}
public static async Task SetValue(string key, object? value)
public static async Task SetValueAsync(string key, object? value)
{
var logger = LogManager.GetCurrentClassLogger();
await using var db = new ApplicationDbContext();
@@ -107,28 +107,7 @@ public static class Helpers
if (cache.Contains(key)) cache.Remove(key);
}
public static async Task SetValueAsList<T>(string key, List<T> values, char separator = ',')
{
var logger = LogManager.GetCurrentClassLogger();
await using var db = new ApplicationDbContext();
List<string> stringValues = values.Select(val => (string)Convert.ChangeType(val, TypeCode.String)).ToList();
string joinedValue = string.Join(separator, stringValues);
logger.Debug($"Setting {key} to {joinedValue}");
var setting = await db.Settings.FirstOrDefaultAsync(s => s.Key == key);
if (setting == null)
{
logger.Debug($"{key} does not exist, throwing KeyNotFoundException()");
throw new KeyNotFoundException();
}
setting.Value = joinedValue;
await db.SaveChangesAsync();
var cache = MemoryCache.Default;
if (cache.Contains(key)) cache.Remove(key);
}
public static async Task SetValueAsJsonObject<T>(string key, T data)
public static async Task SetValueAsJsonObjectAsync<T>(string key, T data)
{
var logger = LogManager.GetCurrentClassLogger();
await using var db = new ApplicationDbContext();
@@ -150,7 +129,7 @@ public static class Helpers
if (cache.Contains(key)) cache.Remove(key);
}
public static async Task SetValueAsBoolean(string key, bool value)
public static async Task SetValueAsBooleanAsync(string key, bool value)
{
var logger = LogManager.GetCurrentClassLogger();
await using var db = new ApplicationDbContext();

View File

@@ -1,59 +0,0 @@
using System.Text.Json;
using NLog;
namespace KfChatDotNetBot.Settings;
public static class Utils
{
public static List<string> ToList(this SettingValue settingValue, char separator = ',')
{
if (settingValue.Value == null) return new List<string>();
return settingValue.Value.Split(separator).ToList();
}
public static T? JsonDeserialize<T>(this SettingValue settingValue)
{
if (settingValue.Value == null)
{
return default;
}
return JsonSerializer.Deserialize<T>(settingValue.Value) ?? default(T);
}
public static bool ToBoolean(this SettingValue settingValue)
{
var logger = LogManager.GetCurrentClassLogger();
if (settingValue.Value is null or "null")
{
return default;
}
return settingValue.Value.Equals("true", StringComparison.CurrentCultureIgnoreCase);
}
public static T ValueToType<T>(string value)
{
return (T)Convert.ChangeType(value, typeof(T));
}
public static T ToType<T>(this SettingValue settingValue)
{
return (T)Convert.ChangeType(settingValue.Value, typeof(T));
}
public static void SafelyRenameFile(string oldName, string newName)
{
var logger = LogManager.GetCurrentClassLogger();
logger.Debug($"Renaming {oldName} to {newName}");
try
{
File.Move(oldName, newName);
}
catch (Exception e)
{
logger.Error($"Failed to rename {oldName} to {newName}");
logger.Error(e);
}
}
}