readme
This commit is contained in:
152
README.md
152
README.md
@@ -1,100 +1,92 @@
|
|||||||
# BotPages.Core
|
# BotPages Framework
|
||||||
|
|
||||||
**BotPages.Core** — это универсальный фреймворк для построения ботов с декларативными страницами, навигацией и единым контекстом.
|
BotPages — это архитектурный фреймворк для построения Telegram/MAX‑ботов с чистыми слоями, расширяемыми API и удобным developer experience.
|
||||||
Поддерживает работу сразу с несколькими транспортами (например, Telegram и MAX), сохраняя чистую архитектуру и удобный developer experience.
|
|
||||||
|
|
||||||
---
|
## ✨ Возможности
|
||||||
|
- **Навигация через страницы**: каждая страница — отдельный обработчик логики.
|
||||||
## ✨ Основные идеи
|
- **Единый метод GoToAsync**: автоматически поддерживает как `SingletonPage`, так и `StatefulPage`.
|
||||||
|
- **StatefulPage**: свойства автоматически сохраняются в `StateStorage`.
|
||||||
- **PageResult** — декларативный результат обработки страницы (сообщение, файлы, кнопки, навигация).
|
- **SingletonPage**: один экземпляр на всё приложение, без состояния.
|
||||||
- **PageMessage** — объект сообщения с поддержкой форматов (Plain/Markdown/HTML), флагов (`IsSilent`, `DisableWebPreview`).
|
- **Middleware**: подключение промежуточных обработчиков (логирование, обработка ошибок).
|
||||||
- **PageNavigate** — объект навигации (переход на другую страницу, аргументы, режим Replace).
|
- **Автоматическая регистрация страниц**: через рефлексию.
|
||||||
- **PageAction** — кнопки (inline/reply, ссылки, запрос контакта/локации, стили).
|
- **Роутинг страниц**: возможность устанавливать пути вызова для страниц.
|
||||||
- **UpdateContext** — универсальный контекст обновления, независимый от транспорта, с полем `Transport` для разделения Telegram/MAX.
|
- **Команды**: возможность установки команд, которые работают приоритетнее обработчиков страниц.
|
||||||
- **PageRegistry** — реестр страниц, умеет собирать их автоматически из сборки (`CreateFromAssembly`, `CreateFromApplication`).
|
- **Минимум boilerplate**: декларативные интерфейсы и fluent API.
|
||||||
- **IStateStore** — хранилище состояния пользователя, ключом является `(Transport, ChatId)`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 Быстрый старт
|
## 🚀 Быстрый старт
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Создаём реестр страниц
|
var app = new BotPagesApp(factory, state, logger)
|
||||||
var registry = PageRegistry.CreateFromApplication(defaultPageId: "main");
|
.UseDefaultPage<WelcomePage>()
|
||||||
|
.MapCommand<WelcomePage>("/start")
|
||||||
// Хранилище состояния
|
.AddMiddleware(new LoggingMiddleware(logger))
|
||||||
IStateStore store = new InMemoryStateStore();
|
.AddMiddleware(new ErrorHandlingMiddleware(logger));
|
||||||
|
|
||||||
// Навигация
|
|
||||||
INavigationService nav = new NavigationService(registry, store);
|
|
||||||
|
|
||||||
// Запуск Telegram
|
|
||||||
var telegramBot = new TelegramBotClient("TELEGRAM_TOKEN");
|
|
||||||
telegramBot.StartReceiving(async (bot, update, ct) =>
|
|
||||||
{
|
|
||||||
var ctx = TelegramUpdateMapper.Map(bot, nav, store, update);
|
|
||||||
await nav.HandleAsync(ctx, ct);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Запуск MAX
|
|
||||||
var maxClient = new MaxClientAdapter("MAX_CONFIG");
|
|
||||||
maxClient.OnUpdate(async (update, ct) =>
|
|
||||||
{
|
|
||||||
var ctx = MaxUpdateMapper.Map(maxClient, nav, store, update);
|
|
||||||
ctx.Transport = "max";
|
|
||||||
await nav.HandleAsync(ctx, ct);
|
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## 📄 Пример страниц
|
||||||
|
|
||||||
## 📌 Пример страницы
|
|
||||||
|
|
||||||
|
### StatefulPage
|
||||||
```csharp
|
```csharp
|
||||||
public sealed class MainPage : IPage
|
public sealed class WelcomePage : StatefulPage
|
||||||
{
|
{
|
||||||
public string Id => "main";
|
[Statefull("visitCount")]
|
||||||
|
private int VisitCount;
|
||||||
|
|
||||||
public PageResult Handle(UpdateContext ctx)
|
private PageContext? Context { get; set; }
|
||||||
|
|
||||||
|
public override async Task OnEnter(PageContext ctx, CancellationToken ct)
|
||||||
{
|
{
|
||||||
return PageResult.Text("🏠 Главная страница", new[]
|
Context = ctx;
|
||||||
{
|
|
||||||
new PageAction { Label = "Перейти", Value = "inlinePage", Placement = ActionPlacement.Inline }
|
LoadState();
|
||||||
});
|
VisitCount++;
|
||||||
|
SaveState();
|
||||||
|
|
||||||
|
await ctx.SendTextAsync($"Добро пожаловать 🚀. Вы заходили сюда {VisitCount} раз(а).", ct: ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
### SingletonPage
|
||||||
|
```csharp
|
||||||
## 🛠️ Возможности
|
public sealed class HelpPage : SingletonPage
|
||||||
|
{
|
||||||
- ✅ Декларативные страницы (`PageResult`)
|
public override Task OnEnter(PageContext ctx, CancellationToken ct)
|
||||||
- ✅ Навигация (`PageNavigate`)
|
=> ctx.SendTextAsync("Это справка 📖", ct: ct);
|
||||||
- ✅ Сообщения с форматами и флагами (`PageMessage`)
|
}
|
||||||
- ✅ Кнопки с расширенными параметрами (`PageAction`)
|
|
||||||
- ✅ Поддержка нескольких транспортов (Telegram)
|
|
||||||
- ✅ Автоматическая регистрация страниц (`PageRegistry.CreateFromApplication`)
|
|
||||||
- ✅ Хранение состояния по `(ChatClientId, ChatId)`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📂 Структура проекта
|
|
||||||
|
|
||||||
```
|
|
||||||
BotPages/
|
|
||||||
├── BotPages.Core/ # Основные классы (PageResult, PageMessage, PageNavigate, UpdateContext)
|
|
||||||
├── Demo/ # Пример страниц и запуск
|
|
||||||
├── Adapters/ # Транспортные адаптеры (Telegram)
|
|
||||||
└── README.md
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
## 🧩 Навигация
|
||||||
|
```csharp
|
||||||
|
await ctx.Navigation.GoToAsync<WelcomePage>(ctx, ct); // Stateful
|
||||||
|
await ctx.Navigation.GoToAsync<WelcomePage>(ctx, agrs, ct); // Stateful with arguments
|
||||||
|
await ctx.Navigation.GoToAsync<HelpPage>(ctx, ct); // Singleton
|
||||||
|
await ctx.Navigation.GoToHome(ctx, ct); // Stateful
|
||||||
|
```
|
||||||
|
|
||||||
## 📖 TODO
|
## ⚙️ Middleware
|
||||||
|
```csharp
|
||||||
|
public sealed class LoggingMiddleware : IPageMiddleware
|
||||||
|
{
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
public LoggingMiddleware(ILogger logger) => _logger = logger;
|
||||||
|
|
||||||
- [ ] Поддержка медиагрупп (альбомов) в Telegram
|
public async Task InvokeAsync(PageContext ctx, Func<Task> next, CancellationToken ct)
|
||||||
- [ ] Расширенные стили кнопок
|
{
|
||||||
- [ ] TTL для сообщений
|
_logger.Log(LogLevel.Info, $"Update: {ctx.Update.Kind}");
|
||||||
- [ ] Плагины для сторонних транспортов
|
await next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗 Архитектурные принципы
|
||||||
|
- **Separation of concerns**: страницы не знают о транспорте, всё через адаптеры.
|
||||||
|
- **Расширяемость**: новые страницы и middleware подключаются декларативно.
|
||||||
|
- **Прозрачность**: минимум скрытой логики, всё явно через контекст.
|
||||||
|
- **Developer Experience**: удобные API, автоматическая регистрация, документация через `///summary`.
|
||||||
|
|
||||||
|
## 📌 Итог
|
||||||
|
BotPages позволяет писать чистые, расширяемые и удобные для команды боты:
|
||||||
|
- минимум boilerplate,
|
||||||
|
- декларативные интерфейсы,
|
||||||
|
- прозрачная навигация,
|
||||||
|
- автоматическое управление состоянием.
|
||||||
Reference in New Issue
Block a user