mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Killed history
This commit is contained in:
122
NadekoBot.Core/Services/Settings/BotConfigMigrator.cs
Normal file
122
NadekoBot.Core/Services/Settings/BotConfigMigrator.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Globalization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Core.Common.Configs;
|
||||
using Serilog;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
public sealed class BotConfigMigrator : IConfigMigrator
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly BotConfigService _bss;
|
||||
|
||||
public BotConfigMigrator(DbService dbService, BotConfigService bss)
|
||||
{
|
||||
_db = dbService;
|
||||
_bss = bss;
|
||||
}
|
||||
|
||||
public void EnsureMigrated()
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
using var conn = uow._context.Database.GetDbConnection();
|
||||
|
||||
// check if bot config exists
|
||||
using (var checkTableCommand = conn.CreateCommand())
|
||||
{
|
||||
// make sure table still exists
|
||||
checkTableCommand.CommandText =
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='BotConfig';";
|
||||
var checkReader = checkTableCommand.ExecuteReader();
|
||||
if (!checkReader.HasRows)
|
||||
return;
|
||||
}
|
||||
|
||||
MigrateBotConfig(conn);
|
||||
|
||||
using var dropBlockedTable = conn.CreateCommand();
|
||||
dropBlockedTable.CommandText = "DROP TABLE IF EXISTS BlockedCmdOrMdl;";
|
||||
dropBlockedTable.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private void MigrateBotConfig(DbConnection conn)
|
||||
{
|
||||
|
||||
|
||||
using (var checkMigratedCommand = conn.CreateCommand())
|
||||
{
|
||||
checkMigratedCommand.CommandText =
|
||||
"UPDATE BotConfig SET HasMigratedBotSettings = 1 WHERE HasMigratedBotSettings = 0;";
|
||||
var changedRows = checkMigratedCommand.ExecuteNonQuery();
|
||||
if (changedRows == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Information("Migrating bot settings...");
|
||||
|
||||
var blockedCommands = new HashSet<string>();
|
||||
using (var cmdCom = conn.CreateCommand())
|
||||
{
|
||||
cmdCom.CommandText = $"SELECT Name from BlockedCmdOrMdl WHERE BotConfigId is not NULL";
|
||||
var cmdReader = cmdCom.ExecuteReader();
|
||||
while (cmdReader.Read())
|
||||
blockedCommands.Add(cmdReader.GetString(0));
|
||||
}
|
||||
|
||||
var blockedModules = new HashSet<string>();
|
||||
using (var mdlCom = conn.CreateCommand())
|
||||
{
|
||||
mdlCom.CommandText = $"SELECT Name from BlockedCmdOrMdl WHERE BotConfigId is NULL";
|
||||
var mdlReader = mdlCom.ExecuteReader();
|
||||
while (mdlReader.Read())
|
||||
blockedModules.Add(mdlReader.GetString(0));
|
||||
}
|
||||
|
||||
using var com = conn.CreateCommand();
|
||||
com.CommandText = $@"SELECT DefaultPrefix, ForwardMessages, ForwardToAllOwners,
|
||||
OkColor, ErrorColor, ConsoleOutputType, DMHelpString, HelpString, RotatingStatuses, Locale, GroupGreets
|
||||
FROM BotConfig";
|
||||
|
||||
using var reader = com.ExecuteReader();
|
||||
if (!reader.Read())
|
||||
return;
|
||||
|
||||
_bss.ModifyConfig((x) =>
|
||||
{
|
||||
x.Prefix = reader.GetString(0);
|
||||
x.ForwardMessages = reader.GetBoolean(1);
|
||||
x.ForwardToAllOwners = reader.GetBoolean(2);
|
||||
x.Color = new ColorConfig()
|
||||
{
|
||||
Ok = Rgba32.TryParseHex(reader.GetString(3), out var okColor)
|
||||
? okColor
|
||||
: Rgba32.ParseHex("00e584"),
|
||||
Error = Rgba32.TryParseHex(reader.GetString(4), out var errorColor)
|
||||
? errorColor
|
||||
: Rgba32.ParseHex("ee281f"),
|
||||
};
|
||||
x.ConsoleOutputType = (ConsoleOutputType) reader.GetInt32(5);
|
||||
x.DmHelpText = reader.IsDBNull(6) ? string.Empty : reader.GetString(6);
|
||||
x.HelpText = reader.IsDBNull(7) ? string.Empty : reader.GetString(7);
|
||||
x.RotateStatuses = reader.GetBoolean(8);
|
||||
try
|
||||
{
|
||||
x.DefaultLocale = new CultureInfo(reader.GetString(9));
|
||||
}
|
||||
catch
|
||||
{
|
||||
x.DefaultLocale = new CultureInfo("en-US");
|
||||
}
|
||||
|
||||
x.GroupGreets = reader.GetBoolean(10);
|
||||
x.Blocked.Commands = blockedCommands;
|
||||
x.Blocked.Modules = blockedModules;
|
||||
});
|
||||
|
||||
Log.Information("Data written to data/bot.yml");
|
||||
}
|
||||
}
|
||||
}
|
50
NadekoBot.Core/Services/Settings/BotConfigService.cs
Normal file
50
NadekoBot.Core/Services/Settings/BotConfigService.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Discord;
|
||||
using NadekoBot.Core.Common;
|
||||
using NadekoBot.Core.Common.Configs;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings service for bot-wide configuration.
|
||||
/// </summary>
|
||||
public sealed class BotConfigService : ConfigServiceBase<BotConfig>
|
||||
{
|
||||
public override string Name { get; } = "bot";
|
||||
|
||||
private const string FilePath = "data/bot.yml";
|
||||
private static TypedKey<BotConfig> changeKey = new TypedKey<BotConfig>("config.bot.updated");
|
||||
|
||||
public BotConfigService(IConfigSeria serializer, IPubSub pubSub)
|
||||
: base(FilePath, serializer, pubSub, changeKey)
|
||||
{
|
||||
AddParsedProp("color.ok", bs => bs.Color.Ok, Rgba32.TryParseHex, ConfigPrinters.Color);
|
||||
AddParsedProp("color.error", bs => bs.Color.Error, Rgba32.TryParseHex, ConfigPrinters.Color);
|
||||
AddParsedProp("color.pending", bs => bs.Color.Pending, Rgba32.TryParseHex, ConfigPrinters.Color);
|
||||
AddParsedProp("help.text", bs => bs.HelpText, ConfigParsers.String, ConfigPrinters.ToString);
|
||||
AddParsedProp("help.dmtext", bs => bs.DmHelpText, ConfigParsers.String, ConfigPrinters.ToString);
|
||||
AddParsedProp("console.type", bs => bs.ConsoleOutputType, Enum.TryParse, ConfigPrinters.ToString);
|
||||
AddParsedProp("locale", bs => bs.DefaultLocale, ConfigParsers.Culture, ConfigPrinters.Culture);
|
||||
AddParsedProp("prefix", bs => bs.Prefix, ConfigParsers.String, ConfigPrinters.ToString);
|
||||
|
||||
UpdateColors();
|
||||
}
|
||||
|
||||
private void UpdateColors()
|
||||
{
|
||||
var ok = _data.Color.Ok;
|
||||
var error = _data.Color.Error;
|
||||
var pend = _data.Color.Pending;
|
||||
// todo future remove these static props once cleanup is done
|
||||
NadekoBot.OkColor = new Color(ok.R, ok.G, ok.B);
|
||||
NadekoBot.ErrorColor = new Color(error.R, error.G, error.B);
|
||||
NadekoBot.PendingColor = new Color(pend.R, pend.G, pend.B);
|
||||
}
|
||||
|
||||
protected override void OnStateUpdate()
|
||||
{
|
||||
UpdateColors();
|
||||
}
|
||||
}
|
||||
}
|
46
NadekoBot.Core/Services/Settings/ConfigParsers.cs
Normal file
46
NadekoBot.Core/Services/Settings/ConfigParsers.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System.Globalization;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Custom setting value parsers for types which don't have them by default
|
||||
/// </summary>
|
||||
public static class ConfigParsers
|
||||
{
|
||||
/// <summary>
|
||||
/// Default string parser. Passes input to output and returns true.
|
||||
/// </summary>
|
||||
public static bool String(string input, out string output)
|
||||
{
|
||||
output = input;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Culture(string input, out CultureInfo output)
|
||||
{
|
||||
try
|
||||
{
|
||||
output = new CultureInfo(input);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
output = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigPrinters
|
||||
{
|
||||
public static string ToString<TAny>(TAny input)
|
||||
=> input.ToString();
|
||||
|
||||
public static string Culture(CultureInfo culture)
|
||||
=> culture.Name;
|
||||
|
||||
public static string Color(Rgba32 color)
|
||||
=> ((uint) (color.B << 0 | color.G << 8 | color.R << 16)).ToString("X6");
|
||||
}
|
||||
}
|
227
NadekoBot.Core/Services/Settings/ConfigServiceBase.cs
Normal file
227
NadekoBot.Core/Services/Settings/ConfigServiceBase.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Yml;
|
||||
using NadekoBot.Core.Common;
|
||||
using NadekoBot.Core.Common.Configs;
|
||||
using NadekoBot.Core.Common.JsonConverters;
|
||||
using Rgba32Converter = NadekoBot.Core.Common.JsonConverters.Rgba32Converter;
|
||||
using CultureInfoConverter = NadekoBot.Core.Common.JsonConverters.CultureInfoConverter;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Base service for all settings services
|
||||
/// </summary>
|
||||
/// <typeparam name="TSettings">Type of the settings</typeparam>
|
||||
public abstract class ConfigServiceBase<TSettings> : IConfigService
|
||||
where TSettings : new()
|
||||
{
|
||||
protected readonly string _filePath;
|
||||
protected readonly IConfigSeria _serializer;
|
||||
protected readonly IPubSub _pubSub;
|
||||
private readonly TypedKey<TSettings> _changeKey;
|
||||
|
||||
protected TSettings _data;
|
||||
public TSettings Data => CreateCopy();
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialized an instance of <see cref="ConfigServiceBase{TSettings}"/>
|
||||
/// </summary>
|
||||
/// <param name="filePath">Path to the file where the settings are serialized/deserialized to and from</param>
|
||||
/// <param name="serializer">Serializer which will be used</param>
|
||||
/// <param name="pubSub">Pubsub implementation for signaling when settings are updated</param>
|
||||
/// <param name="changeKey">Key used to signal changed event</param>
|
||||
protected ConfigServiceBase(string filePath, IConfigSeria serializer, IPubSub pubSub,
|
||||
TypedKey<TSettings> changeKey)
|
||||
{
|
||||
_filePath = filePath;
|
||||
_serializer = serializer;
|
||||
_pubSub = pubSub;
|
||||
_changeKey = changeKey;
|
||||
|
||||
Load();
|
||||
_pubSub.Sub(_changeKey, OnChangePublished);
|
||||
}
|
||||
|
||||
private void PublishChange()
|
||||
{
|
||||
_pubSub.Pub(_changeKey, _data);
|
||||
}
|
||||
|
||||
private ValueTask OnChangePublished(TSettings newData)
|
||||
{
|
||||
_data = newData;
|
||||
OnStateUpdate();
|
||||
return default;
|
||||
}
|
||||
|
||||
private static readonly JsonSerializerOptions serializerOptions = new JsonSerializerOptions()
|
||||
{
|
||||
MaxDepth = 0,
|
||||
Converters = { new Rgba32Converter(), new CultureInfoConverter() }
|
||||
};
|
||||
private TSettings CreateCopy()
|
||||
{
|
||||
var serializedData = JsonSerializer.Serialize(_data, serializerOptions);
|
||||
return JsonSerializer.Deserialize<TSettings>(serializedData, serializerOptions);
|
||||
|
||||
// var serializedData = _serializer.Serialize(_data);
|
||||
//
|
||||
// return _serializer.Deserialize<TSettings>(serializedData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads data from disk. If file doesn't exist, it will be created with default values
|
||||
/// </summary>
|
||||
protected void Load()
|
||||
{
|
||||
// if file is deleted, regenerate it with default values
|
||||
if (!File.Exists(_filePath))
|
||||
{
|
||||
_data = new TSettings();
|
||||
Save();
|
||||
}
|
||||
|
||||
_data = _serializer.Deserialize<TSettings>(File.ReadAllText(_filePath));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads new data and publishes the new state
|
||||
/// </summary>
|
||||
public void Reload()
|
||||
{
|
||||
Load();
|
||||
_pubSub.Pub(_changeKey, _data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Doesn't do anything by default. This method will be executed after
|
||||
/// <see cref="_data"/> is reloaded from <see cref="_filePath"/> or new data is recieved
|
||||
/// from the publish event
|
||||
/// </summary>
|
||||
protected virtual void OnStateUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ModifyConfig(Action<TSettings> action)
|
||||
{
|
||||
var copy = CreateCopy();
|
||||
action(copy);
|
||||
_data = copy;
|
||||
Save();
|
||||
PublishChange();
|
||||
}
|
||||
private void Save()
|
||||
{
|
||||
var strData = _serializer.Serialize(_data);
|
||||
File.WriteAllText(_filePath, strData);
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, Func<TSettings, string, bool>> _propSetters = new Dictionary<string, Func<TSettings, string, bool>>();
|
||||
private readonly Dictionary<string, Func<object>> _propSelectors = new Dictionary<string, Func<object>>();
|
||||
private readonly Dictionary<string, Func<object, string>> _propPrinters = new Dictionary<string, Func<object, string>>();
|
||||
private readonly Dictionary<string, string> _propComments = new Dictionary<string, string>();
|
||||
|
||||
protected void AddParsedProp<TProp>(
|
||||
string key,
|
||||
Expression<Func<TSettings, TProp>> selector,
|
||||
SettingParser<TProp> parser,
|
||||
Func<TProp, string> printer,
|
||||
Func<TProp, bool> checker = null)
|
||||
{
|
||||
checker ??= _ => true;
|
||||
key = key.ToLowerInvariant();
|
||||
_propPrinters[key] = obj => printer((TProp)obj);
|
||||
_propSelectors[key] = () => selector.Compile()(_data);
|
||||
_propSetters[key] = Magic(selector, parser, checker);
|
||||
_propComments[key] = ((MemberExpression)selector.Body).Member.GetCustomAttribute<CommentAttribute>()?.Comment;
|
||||
}
|
||||
|
||||
private Func<TSettings, string, bool> Magic<TProp>(Expression<Func<TSettings, TProp>> selector,
|
||||
SettingParser<TProp> parser, Func<TProp, bool> checker)
|
||||
=> (target, input) =>
|
||||
{
|
||||
if (!parser(input, out var value))
|
||||
return false;
|
||||
|
||||
if (!checker(value))
|
||||
return false;
|
||||
|
||||
object targetObject = target;
|
||||
var expr = (MemberExpression)selector.Body;
|
||||
var prop = (PropertyInfo)expr.Member;
|
||||
|
||||
var expressions = new List<MemberExpression>()
|
||||
{
|
||||
};
|
||||
|
||||
while (true)
|
||||
{
|
||||
expr = expr.Expression as MemberExpression;
|
||||
if (expr is null)
|
||||
break;
|
||||
|
||||
expressions.Add(expr);
|
||||
}
|
||||
|
||||
foreach (var memberExpression in expressions.AsEnumerable().Reverse())
|
||||
{
|
||||
var localProp = (PropertyInfo) memberExpression.Member;
|
||||
targetObject = localProp.GetValue(targetObject);
|
||||
}
|
||||
|
||||
prop!.SetValue(targetObject, value, null);
|
||||
return true;
|
||||
};
|
||||
|
||||
public IReadOnlyList<string> GetSettableProps()
|
||||
=> _propSetters.Keys.ToList();
|
||||
|
||||
public string GetSetting(string prop)
|
||||
{
|
||||
prop = prop.ToLowerInvariant();
|
||||
if (!_propSelectors.TryGetValue(prop, out var selector) ||
|
||||
!_propPrinters.TryGetValue(prop, out var printer))
|
||||
return default;
|
||||
|
||||
return printer(selector());
|
||||
}
|
||||
|
||||
public string GetComment(string prop)
|
||||
{
|
||||
if (_propComments.TryGetValue(prop, out var comment))
|
||||
return comment;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool SetProperty(TSettings target, string key, string value)
|
||||
=> _propSetters.TryGetValue(key.ToLowerInvariant(), out var magic)
|
||||
&& magic(target, value);
|
||||
|
||||
public bool SetSetting(string prop, string newValue)
|
||||
{
|
||||
var success = true;
|
||||
ModifyConfig(bs =>
|
||||
{
|
||||
success = SetProperty(bs, prop, newValue);
|
||||
});
|
||||
|
||||
if(success)
|
||||
PublishChange();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public TSettings GetRawData() => _data;
|
||||
}
|
||||
}
|
155
NadekoBot.Core/Services/Settings/GamblingConfigMigrator.cs
Normal file
155
NadekoBot.Core/Services/Settings/GamblingConfigMigrator.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Core.Modules.Gambling.Common;
|
||||
using NadekoBot.Core.Modules.Gambling.Services;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
public sealed class GamblingConfigMigrator : IConfigMigrator
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly GamblingConfigService _gss;
|
||||
|
||||
public GamblingConfigMigrator(DbService dbService, GamblingConfigService gss)
|
||||
{
|
||||
_db = dbService;
|
||||
_gss = gss;
|
||||
}
|
||||
|
||||
public void EnsureMigrated()
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
using var conn = uow._context.Database.GetDbConnection();
|
||||
Migrate(conn);
|
||||
}
|
||||
|
||||
private void Migrate(DbConnection conn)
|
||||
{
|
||||
using (var checkTableCommand = conn.CreateCommand())
|
||||
{
|
||||
// make sure table still exists
|
||||
checkTableCommand.CommandText =
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='BotConfig';";
|
||||
var checkReader = checkTableCommand.ExecuteReader();
|
||||
if (!checkReader.HasRows)
|
||||
return;
|
||||
}
|
||||
|
||||
using (var checkMigratedCommand = conn.CreateCommand())
|
||||
{
|
||||
checkMigratedCommand.CommandText =
|
||||
"UPDATE BotConfig SET HasMigratedGamblingSettings = 1 WHERE HasMigratedGamblingSettings = 0;";
|
||||
var changedRows = checkMigratedCommand.ExecuteNonQuery();
|
||||
if (changedRows == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Information("Migrating gambling settings...");
|
||||
|
||||
using var com = conn.CreateCommand();
|
||||
com.CommandText = $@"SELECT CurrencyGenerationChance, CurrencyGenerationCooldown,
|
||||
CurrencySign, CurrencyName, CurrencyGenerationPassword, MinBet, MaxBet, BetflipMultiplier,
|
||||
TimelyCurrency, TimelyCurrencyPeriod, CurrencyDropAmount, CurrencyDropAmountMax, DailyCurrencyDecay,
|
||||
DivorcePriceMultiplier, PatreonCurrencyPerCent, MinWaifuPrice, WaifuGiftMultiplier
|
||||
FROM BotConfig";
|
||||
|
||||
using var reader = com.ExecuteReader();
|
||||
if (!reader.Read())
|
||||
return;
|
||||
|
||||
|
||||
using (var itemsCommand = conn.CreateCommand())
|
||||
{
|
||||
itemsCommand.CommandText = WaifuItemUpdateQuery;
|
||||
itemsCommand.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
|
||||
_gss.ModifyConfig(ModifyAction(reader));
|
||||
|
||||
Log.Information("Data written to data/gambling.yml");
|
||||
}
|
||||
|
||||
private static Action<GamblingConfig> ModifyAction(DbDataReader reader)
|
||||
=> realConfig =>
|
||||
{
|
||||
realConfig.Currency.Sign = (string) reader["CurrencySign"];
|
||||
realConfig.Currency.Name = (string) reader["CurrencyName"];
|
||||
realConfig.MinBet = (int) (long) reader["MinBet"];
|
||||
realConfig.MaxBet = (int) (long) reader["MaxBet"];
|
||||
realConfig.BetFlip = new GamblingConfig.BetFlipConfig()
|
||||
{
|
||||
Multiplier = (decimal) (double) reader["BetflipMultiplier"],
|
||||
};
|
||||
realConfig.Generation = new GamblingConfig.GenerationConfig()
|
||||
{
|
||||
MaxAmount = (int) (reader["CurrencyDropAmountMax"] as long? ?? (long) reader["CurrencyDropAmount"]),
|
||||
MinAmount = (int) (long) reader["CurrencyDropAmount"],
|
||||
Chance = (decimal) (double) reader["CurrencyGenerationChance"],
|
||||
GenCooldown = (int) (long) reader["CurrencyGenerationCooldown"],
|
||||
HasPassword = reader.GetBoolean(4),
|
||||
};
|
||||
realConfig.Timely = new GamblingConfig.TimelyConfig()
|
||||
{
|
||||
Amount = (int) (long) reader["TimelyCurrency"],
|
||||
Cooldown = (int) (long) reader["TimelyCurrencyPeriod"],
|
||||
};
|
||||
realConfig.Decay = new GamblingConfig.DecayConfig()
|
||||
{Percent = (decimal) (double) reader["DailyCurrencyDecay"],};
|
||||
realConfig.Waifu = new GamblingConfig.WaifuConfig()
|
||||
{
|
||||
MinPrice = (int) (long) reader["MinWaifuPrice"],
|
||||
Multipliers = new GamblingConfig.WaifuConfig.MultipliersData()
|
||||
{
|
||||
AllGiftPrices = (decimal) (long) reader["WaifuGiftMultiplier"],
|
||||
WaifuReset = (int) (long) reader["DivorcePriceMultiplier"]
|
||||
}
|
||||
};
|
||||
realConfig.PatreonCurrencyPerCent = (decimal) (double) reader["PatreonCurrencyPerCent"];
|
||||
};
|
||||
|
||||
private const string WaifuItemUpdateQuery = @"UPDATE WaifuItem
|
||||
SET Name = CASE ItemEmoji
|
||||
WHEN '🥔' THEN 'potato'
|
||||
WHEN '🍪' THEN 'cookie'
|
||||
WHEN '🥖' THEN 'bread'
|
||||
WHEN '🍭' THEN 'lollipop'
|
||||
WHEN '🌹' THEN 'rose'
|
||||
WHEN '🍺' THEN 'beer'
|
||||
WHEN '🌮' THEN 'taco'
|
||||
WHEN '💌' THEN 'loveletter'
|
||||
WHEN '🥛' THEN 'milk'
|
||||
WHEN '🍕' THEN 'pizza'
|
||||
WHEN '🍫' THEN 'chocolate'
|
||||
WHEN '🍦' THEN 'icecream'
|
||||
WHEN '🍣' THEN 'sushi'
|
||||
WHEN '🍚' THEN 'rice'
|
||||
WHEN '🍉' THEN 'watermelon'
|
||||
WHEN '🍱' THEN 'bento'
|
||||
WHEN '🎟' THEN 'movieticket'
|
||||
WHEN '🍰' THEN 'cake'
|
||||
WHEN '📔' THEN 'book'
|
||||
WHEN '🐱' THEN 'cat'
|
||||
WHEN '🐶' THEN 'dog'
|
||||
WHEN '🐼' THEN 'panda'
|
||||
WHEN '💄' THEN 'lipstick'
|
||||
WHEN '👛' THEN 'purse'
|
||||
WHEN '📱' THEN 'iphone'
|
||||
WHEN '👗' THEN 'dress'
|
||||
WHEN '💻' THEN 'laptop'
|
||||
WHEN '🎻' THEN 'violin'
|
||||
WHEN '🎹' THEN 'piano'
|
||||
WHEN '🚗' THEN 'car'
|
||||
WHEN '💍' THEN 'ring'
|
||||
WHEN '🛳' THEN 'ship'
|
||||
WHEN '🏠' THEN 'house'
|
||||
WHEN '🚁' THEN 'helicopter'
|
||||
WHEN '🚀' THEN 'spaceship'
|
||||
WHEN '🌕' THEN 'moon'
|
||||
ELSE 'unknown'
|
||||
END
|
||||
";
|
||||
}
|
||||
}
|
7
NadekoBot.Core/Services/Settings/IConfigMigrator.cs
Normal file
7
NadekoBot.Core/Services/Settings/IConfigMigrator.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
public interface IConfigMigrator
|
||||
{
|
||||
public void EnsureMigrated();
|
||||
}
|
||||
}
|
45
NadekoBot.Core/Services/Settings/IConfigService.cs
Normal file
45
NadekoBot.Core/Services/Settings/IConfigService.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface that all services which deal with configs should implement
|
||||
/// </summary>
|
||||
public interface IConfigService
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the config
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
/// <summary>
|
||||
/// Loads new data and publishes the new state
|
||||
/// </summary>
|
||||
void Reload();
|
||||
/// <summary>
|
||||
/// Gets the list of props you can set
|
||||
/// </summary>
|
||||
/// <returns>List of props</returns>
|
||||
IReadOnlyList<string> GetSettableProps();
|
||||
/// <summary>
|
||||
/// Gets the value of the specified property
|
||||
/// </summary>
|
||||
/// <param name="prop">Prop name</param>
|
||||
/// <returns>Value of the prop</returns>
|
||||
string GetSetting(string prop);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the specified property
|
||||
/// </summary>
|
||||
/// <param name="prop">Prop name</param>
|
||||
/// <returns>Value of the prop</returns>
|
||||
string GetComment(string prop);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the specified property
|
||||
/// </summary>
|
||||
/// <param name="prop">Property to set</param>
|
||||
/// <param name="newValue">Value to set the property to</param>
|
||||
/// <returns>Success</returns>
|
||||
bool SetSetting(string prop, string newValue);
|
||||
}
|
||||
}
|
8
NadekoBot.Core/Services/Settings/SettingParser.cs
Normal file
8
NadekoBot.Core/Services/Settings/SettingParser.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace NadekoBot.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate which describes a parser which can convert string input into given data type
|
||||
/// </summary>
|
||||
/// <typeparam name="TData">Data type to convert string to</typeparam>
|
||||
public delegate bool SettingParser<TData>(string input, out TData output);
|
||||
}
|
Reference in New Issue
Block a user