[core] Massive setting system update

- Get rid of attribute crap. Now only interface is required
- Rename canUse to isAdmin in `Bot.IsUserAdminAsync` to match the actual meaning of variable
- Made `AnswerQuery` reusable by moving it from ContentStore to Core's CommonHandler
- Chat Settings edit frontend (inline keyboard)
- Rename NsfwOption to AllowNsfw and move it to ContentStore module
- Remove option backend testing commands
- Add KarmaMode option as an example of Select option type
This commit is contained in:
Andriy
2023-07-21 17:14:11 +03:00
parent 467ccd4fde
commit 27ddfd39cc
21 changed files with 307 additions and 110 deletions
+9 -3
View File
@@ -1,4 +1,4 @@
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Kruzya.TelegramBot.Core.Options;
@@ -6,6 +6,12 @@ namespace Kruzya.TelegramBot.Core.Options;
public abstract class AbstractOption<TOption, TValue> : IOption<TValue>
where TOption: AbstractOption<TOption, TValue>
{
public abstract string OptionId { get; }
public abstract string OptionName { get; }
public abstract OptionType OptionType { get; }
public abstract TValue DefaultValue { get; }
public List<SelectChoice> ChoiceList { get; } = new();
private readonly IOptionProvider _optionProvider;
protected AbstractOption(IOptionProvider optionProvider)
@@ -15,11 +21,11 @@ public abstract class AbstractOption<TOption, TValue> : IOption<TValue>
public async Task<TValue> GetValueAsync(long chatId)
{
return await _optionProvider.GetValueAsync<TOption, TValue>(chatId);
return await _optionProvider.GetValueAsync(chatId, OptionId, DefaultValue);
}
public async Task SetValueAsync(long chatId, TValue value)
{
await _optionProvider.SetValueAsync<TOption, TValue>(chatId, value);
await _optionProvider.SetValueAsync(chatId, OptionId, value);
}
}
+4 -36
View File
@@ -1,6 +1,4 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Kruzya.TelegramBot.Core.Data;
using Kruzya.TelegramBot.Core.Extensions;
@@ -14,46 +12,16 @@ public class DbOptionProvider : IOptionProvider
{
_db = db;
}
public async Task<TValue> GetValueAsync<TOption, TValue>(long chatId)
{
return await GetValueAsync(
chatId,
GetOptionId<TOption>(),
GetDefaultValue<TOption, TValue>()
);
}
public async Task<TValue> GetValueAsync<TValue>(long chatId, string optionId, TValue defVal)
{
return (await _db.ChatOptionValues.FindOrCreateOption(chatId, optionId)).GetValue(defVal);
}
public async Task SetValueAsync<TOption, TValue>(long chatId, TValue value)
public async Task SetValueAsync<TValue>(long chatId, string optionId, TValue value)
{
var chatOption = await _db.ChatOptionValues.FindOrCreateOption(chatId, GetOptionId<TOption>());
var chatOption = await _db.ChatOptionValues.FindOrCreateOption(chatId, optionId);
chatOption.SetValue(value);
_db.AddOrUpdate(chatOption);
}
protected OptionAttribute GetOptionAttribute<TOption>()
{
return typeof(TOption).GetCustomAttribute<OptionAttribute>();
}
protected string GetOptionId<TOption>()
{
var optionId = GetOptionAttribute<TOption>()?.OptionId;
if (optionId == null)
{
throw new ArgumentException("Option must implement OptionAttribute");
}
return optionId;
}
protected TValue GetDefaultValue<TOption, TValue>()
{
return (TValue) GetOptionAttribute<TOption>().DefaultValue;
}
}
+12 -2
View File
@@ -1,10 +1,20 @@
using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Kruzya.TelegramBot.Core.Options;
public interface IOption<TValue>
public interface IOption
{
public string OptionId { get; }
public string OptionName { get; }
public OptionType OptionType { get; }
public List<SelectChoice> ChoiceList { get; }
}
public interface IOption<TValue> : IOption
{
public TValue DefaultValue { get; }
public Task<TValue> GetValueAsync(long chatId);
public Task SetValueAsync(long chatId, TValue value);
}
+2 -2
View File
@@ -4,6 +4,6 @@ namespace Kruzya.TelegramBot.Core.Options;
public interface IOptionProvider
{
public Task<TValue> GetValueAsync<TOption, TValue>(long chatId);
public Task SetValueAsync<TOption, TValue>(long chatId, TValue value);
public Task<TValue> GetValueAsync<TValue>(long chatId, string optionId, TValue defVal);
public Task SetValueAsync<TValue>(long chatId, string optionId, TValue value);
}
-17
View File
@@ -1,17 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace Kruzya.TelegramBot.Core.Options;
[AttributeUsage(AttributeTargets.Class)]
public class OptionAttribute : Attribute
{
public string OptionId { get; }
public object DefaultValue { get; }
public OptionAttribute(string optionId, object defaultValue = default)
{
OptionId = optionId;
DefaultValue = defaultValue;
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace Kruzya.TelegramBot.Core.Options;
public enum OptionType
{
OnOff,
Select
}
+29
View File
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using Telegram.Bot.Types.ReplyMarkups;
namespace Kruzya.TelegramBot.Core.Options;
public class SelectChoice
{
public string Id { get; }
public string FullName { get; }
public string ShortName { get; }
public SelectChoice(string id, string fullName, string shortName)
{
Id = id;
FullName = fullName;
ShortName = shortName;
}
public IEnumerable<InlineKeyboardButton> ToButton(long userId, string optionId, bool isActive = false)
{
return new[]
{
new InlineKeyboardButton((isActive ? "🟢 " : "🔴 ") + FullName)
{
CallbackData = $"option|{userId}|select|{optionId}|{Id}"
}
};
}
}