Files
telegram-bot/Core/Handler/SettingsHandler.cs
T

196 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BotFramework.Attributes;
using BotFramework.Enums;
using Kruzya.TelegramBot.Core.Data;
using Kruzya.TelegramBot.Core.Extensions;
using Kruzya.TelegramBot.Core.Options;
using Microsoft.Extensions.DependencyInjection;
using Telegram.Bot;
using Telegram.Bot.Types;
using Telegram.Bot.Types.ReplyMarkups;
namespace Kruzya.TelegramBot.Core.Handler;
public class SettingsHandler : CommonHandler
{
private readonly IEnumerable<IOption> _options;
public SettingsHandler(CoreContext db, IServiceProvider serviceProvider) : base(db)
{
_options = serviceProvider.GetServices<IOption>();
}
[Command(InChat.Public, "settings", CommandParseMode.WithUsername)]
public async Task HandleSettings()
{
if (!await Bot.IsUserAdminAsync(Chat, From))
{
return;
}
await Bot.SendTextMessageAsync(
Chat.Id,
"What do you want to change?",
replyMarkup: GetSettingsMarkup()
);
}
[Update(InChat.Public, UpdateFlag.CallbackQuery)]
public async Task HandleCallback()
{
var query = CallbackQuery;
var queryData = query.Data;
if (queryData == null || !queryData.StartsWith("option") || !await Bot.IsUserAdminAsync(Chat, From))
{
return;
}
var paramList = queryData.Split('|');
if (!long.TryParse(paramList[1], out var senderId))
{
return;
}
if (senderId != From.Id)
{
await AnswerQuery(query.Id, "Keyboard called by another user");
return;
}
if (paramList[2] == "main_menu")
{
await AnswerQuery(query.Id);
await Bot.EditMessageTextAsync(Chat.Id, query.Message!.MessageId, "What do you want to change?",
replyMarkup: GetSettingsMarkup());
return;
}
if (paramList[2] == "edit" || paramList[2] == "select")
{
var option = GetOptionById(paramList[3]);
if (option == null)
{
await AnswerQuery(query.Id, "Invalid option ID");
return;
}
switch (paramList[2])
{
case "edit":
await HandleOptionEdit(option, paramList, query);
break;
case "select":
await HandleOptionSelect(option, paramList, query);
break;
}
}
}
private async Task HandleOptionEdit(IOption option, string[] paramList, CallbackQuery query)
{
var chatId = Chat.Id;
var messageId = query.Message!.MessageId;
switch (option.OptionType)
{
case OptionType.OnOff:
var onOffOpt = (IOption<bool>) option;
await onOffOpt.SetValueAsync(chatId, !await onOffOpt.GetValueAsync(chatId));
await AnswerQuery(query.Id);
await Bot.EditMessageReplyMarkupAsync(chatId, messageId, GetSettingsMarkup());
break;
case OptionType.Select:
var selectOpt = (IOption<string>) option;
await AnswerQuery(query.Id);
await Bot.EditMessageTextAsync(Chat.Id, messageId, "Here's what you can choose:",
replyMarkup: await GetChoiceSelectKeyboard(selectOpt));
break;
default:
await AnswerQuery(query.Id, "Not implemented");
break;
}
}
private async Task HandleOptionSelect(IOption option, string[] paramList, CallbackQuery query)
{
var choice = option.ChoiceList.SingleOrDefault(x => x.Id == paramList[4]);
if (choice == null)
{
await AnswerQuery(query.Id, "Invalid option choice");
return;
}
var selectOption = (IOption<string>) option;
await selectOption.SetValueAsync(Chat.Id, choice.Id);
await AnswerQuery(query.Id);
await Bot.EditMessageReplyMarkupAsync(Chat.Id, query.Message!.MessageId, await GetChoiceSelectKeyboard(selectOption));
}
private async Task<InlineKeyboardButton> GetKeyboardButton(IOption option)
{
var button = new InlineKeyboardButton(option.OptionName)
{
CallbackData = $"option|{From.Id}|edit|{option.OptionId}"
};
switch (option.OptionType)
{
case OptionType.OnOff:
{
var isEnabled = await ((IOption<bool>) option).GetValueAsync(Chat.Id);
button.Text += isEnabled ? " 🟢" : " 🔴";
break;
}
case OptionType.Select:
{
var value = await ((IOption<string>) option).GetValueAsync(Chat.Id);
var currentChoice = option.ChoiceList.Single(x => x.Id == value);
button.Text += $" ({currentChoice.ShortName})";
break;
}
}
return button;
}
private async Task<InlineKeyboardMarkup> GetChoiceSelectKeyboard(IOption<string> option)
{
var value = await option.GetValueAsync(Chat.Id);
var choices = option.ChoiceList.Select(x => x.ToButton(From.Id, option.OptionId, x.Id == value))
.ToList();
choices.Add(new []
{
new InlineKeyboardButton("Main menu")
{
CallbackData = $"option|{From.Id}|main_menu"
}
});
return new InlineKeyboardMarkup(choices);
}
private InlineKeyboardMarkup GetSettingsMarkup()
{
var keyboardLayout = _options.ToAsyncEnumerable()
.SelectAwait(async x => await GetKeyboardButton(x))
.ToEnumerable()
.Chunk(3);
return new InlineKeyboardMarkup(keyboardLayout);
}
private IOption GetOptionById(string optionId)
{
return _options.SingleOrDefault(x => x.OptionId == optionId);
}
}