/
Laxerem
/
BaskBot
Обзор
Документация
Войти
/
Laxerem
/
BaskBot
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
BaskBot.Application/Bot/Extensions/KeyboardBuilder.cs
192 строки
6 KB
Laxerem
[SAVED]: Adding a tree structure to the builder
06 янв 2026, 10:30
06 янв 2026, 10:30
d4a2002
Код
Авторство
О чём код?
using BaskBot.Application.Bot.Abstractions; using Telegram.Bot.Types.ReplyMarkups; namespace BaskBot.Application.Bot.Extensions; public class Callback { public string ButtonName; public string Data; public CallbackHandler? Handler; public Callback() { ButtonName = string.Empty; Data = "default"; Handler = null; } } public interface ICreateCallbackBuilder { public ICreateCallbackBuilder WithCallback(string buttonName); public ICreateCallbackBuilder WithHandler(CallbackHandler callbackHandler); } public class CreateCallbackBuilder : ICreateCallbackBuilder { private Callback _callback; public CreateCallbackBuilder(string buttonName) { _callback = new Callback(); _callback.ButtonName = buttonName; } public ICreateCallbackBuilder WithCallback(string callbackName) { _callback.Data = callbackName; return this; } public ICreateCallbackBuilder WithHandler(CallbackHandler callbackHandler) { _callback.Handler = callbackHandler; return this; } public Callback BuildCallback() { return _callback; } } public class KeyboardBuilder { private readonly List<CreateCallbackBuilder> _callbacks; public KeyboardBuilder() { _callbacks = new List<CreateCallbackBuilder>(); } public ICreateCallbackBuilder CreateButton(string name) { var callbackBuilder = new CreateCallbackBuilder(name); _callbacks.Add(callbackBuilder); return callbackBuilder; } public InlineKeyboardMarkup Build() { var buttons = _callbacks.Select(callback => { var readyCallback = callback.BuildCallback(); return InlineKeyboardButton.WithCallbackData(readyCallback.ButtonName, readyCallback.Data); }); return new InlineKeyboardMarkup(buttons); } } public class MenuNode { public string Name { get; set; } public string? CallbackData { get; set; } public Dictionary<string, MenuNode> Children { get; set; } public MenuNode? Parent { get; set; } public MenuNode(string name, string? callbackData = null) { Name = name; CallbackData = callbackData; Children = new Dictionary<string, MenuNode>(); Parent = null; } public bool HasChildren => Children.Count > 0; } public class MenuTreeBuilder { private MenuNode _rootNode; private MenuNode _currentNode; private string _backButtonText; public MenuTreeBuilder(string rootName, string backButtonText = "◀ Назад") { _rootNode = new MenuNode(rootName); _currentNode = _rootNode; _backButtonText = backButtonText; } public MenuTreeBuilder AddButton(string buttonName, string callbackData) { var node = new MenuNode(buttonName, callbackData) { Parent = _currentNode }; _currentNode.Children[buttonName] = node; return this; } public MenuTreeBuilder AddSubmenu(string buttonName, Action<MenuTreeBuilder> submenuBuilder) { var node = new MenuNode(buttonName) { Parent = _currentNode }; _currentNode.Children[buttonName] = node; var previousNode = _currentNode; _currentNode = node; submenuBuilder(this); _currentNode = previousNode; return this; } public MenuTreeBuilder Back() { if (_currentNode.Parent != null) { _currentNode = _currentNode.Parent; } return this; } public MenuTree Build() { return new MenuTree(_rootNode, _backButtonText); } } public class MenuTree { private MenuNode _rootNode; private string _backButtonText; public MenuTree(MenuNode rootNode, string backButtonText) { _rootNode = rootNode; _backButtonText = backButtonText; } public InlineKeyboardMarkup GetKeyboard(string path) { var node = GetNodeByPath(path); if (node == null) { return new InlineKeyboardMarkup(Array.Empty<InlineKeyboardButton>()); } var buttons = new List<InlineKeyboardButton>(); foreach (var child in node.Children.Values) { var childPath = CombinePath(path, child.Name); var callbackData = child.HasChildren ? childPath : (child.CallbackData ?? childPath); buttons.Add(InlineKeyboardButton.WithCallbackData(child.Name, callbackData)); } if (node.Parent != null) { var parentPath = GetParentPath(path); buttons.Add(InlineKeyboardButton.WithCallbackData(_backButtonText, parentPath)); } return new InlineKeyboardMarkup(buttons.Select(b => new[] { b })); } public MenuNode? GetNodeByPath(string path) { if (string.IsNullOrEmpty(path)) { return _rootNode; } var parts = path.Split(':'); var current = _rootNode; foreach (var part in parts.Skip(1)) { if (!current.Children.TryGetValue(part, out var next)) { return null; } current = next; } return current; } private string CombinePath(string currentPath, string childName) { return string.IsNullOrEmpty(currentPath) || currentPath == _rootNode.Name ? $"{_rootNode.Name}:{childName}" : $"{currentPath}:{childName}"; } private string GetParentPath(string path) { if (string.IsNullOrEmpty(path) || !path.Contains(':')) { return _rootNode.Name; } var lastIndex = path.LastIndexOf(':'); return path.Substring(0, lastIndex); } }