2023-07-21 17:14:11 +03:00
|
|
|
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>();
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-29 01:50:28 +03:00
|
|
|
[InChat(InChat.Public)]
|
|
|
|
|
[Command("settings", CommandParseMode.WithUsername)]
|
2023-07-21 17:14:11 +03:00
|
|
|
public async Task HandleSettings()
|
|
|
|
|
{
|
|
|
|
|
if (!await Bot.IsUserAdminAsync(Chat, From))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await Bot.SendTextMessageAsync(
|
|
|
|
|
Chat.Id,
|
|
|
|
|
"What do you want to change?",
|
|
|
|
|
replyMarkup: GetSettingsMarkup()
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-07-29 01:50:28 +03:00
|
|
|
|
|
|
|
|
[InChat(InChat.Public)]
|
|
|
|
|
[Update(UpdateFlag.CallbackQuery)]
|
2023-07-21 17:14:11 +03:00
|
|
|
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}"
|
|
|
|
|
};
|
|
|
|
|
|
2023-07-21 19:50:48 +03:00
|
|
|
switch (option.OptionType)
|
2023-07-21 17:14:11 +03:00
|
|
|
{
|
2023-07-21 19:50:48 +03:00
|
|
|
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;
|
|
|
|
|
}
|
2024-05-29 00:16:58 +03:00
|
|
|
|
|
|
|
|
case OptionType.Hidden:
|
|
|
|
|
{
|
|
|
|
|
button = null;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-07-21 17:14:11 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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))
|
2024-05-29 00:16:58 +03:00
|
|
|
.Where(x => x != null) // for OptionType.Hidden
|
2023-07-21 17:14:11 +03:00
|
|
|
.ToEnumerable()
|
2023-07-28 17:22:28 +03:00
|
|
|
.Chunk(2);
|
2023-07-21 17:14:11 +03:00
|
|
|
|
|
|
|
|
return new InlineKeyboardMarkup(keyboardLayout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private IOption GetOptionById(string optionId)
|
|
|
|
|
{
|
|
|
|
|
return _options.SingleOrDefault(x => x.OptionId == optionId);
|
|
|
|
|
}
|
|
|
|
|
}
|