diff --git a/FAQ-RU.md b/FAQ-RU.md new file mode 100644 index 0000000..21e2c5c --- /dev/null +++ b/FAQ-RU.md @@ -0,0 +1,104 @@ +# FAQ RU + +Это краткая русскоязычная версия частых вопросов о дизайне Laniakea. Полная и наиболее актуальная страница: [[FAQ]]. + +## Почему handlers возвращают `error`? + +Чтобы ошибки проходили через единый, централизованный flow, а не обрабатывались вручную в каждом command или payload handler. + +Это дает несколько плюсов: +- handlers остаются проще; +- user-facing error format можно контролировать через `ErrorTemplate(...)`; +- command, payload и non-command update handlers используют один и тот же контракт. + +Если тебе нужен полностью ручной ответ пользователю, ты все еще можешь ответить сам и вернуть `nil`. + +Подробности: [[Error-Handling]] + +## Почему `Bot` single-use? + +Потому что один run владеет реальным runtime state: +- polling lifecycle; +- worker pool; +- update offsets; +- runner execution; +- API и logger resources. + +Из-за этого модель “создал -> настроил -> запустил -> закрыл -> создал новый” безопаснее и проще для понимания, чем попытка перезапускать один и тот же `Bot`. + +Подробности: [[Bot-Lifecycle]] + +## Почему `AnswerLong(...)` существует отдельно от `Answer(...)`? + +Потому что `Answer(...)` сохраняет простую семантику “одно сообщение”. + +А `AnswerLong(...)` — это уже явный режим, где: +- текст может быть разбит на несколько сообщений; +- возможен partial success; +- клавиатура в `KeyboardLong(...)` вешается только на последний chunk. + +Такой split сделан специально, чтобы длинные ответы не меняли поведение обычных helper methods неявно. + +## Зачем есть и JSON, и Base64 payload formats? + +Они решают разные задачи: + +- `BotPayloadJson` удобен для читаемости, логов и тестов +- `BotPayloadBase64` удобен как более компактная и “непрозрачная” transport-форма того же payload + +Логическая структура callback payload при этом одна и та же: меняется только encoding. + +Подробности: [[Inline-Keyboards-and-Payloads]] + +## Когда использовать `MsgContext`, а когда `tgapi`? + +Используй `MsgContext`, когда ты уже внутри handler'а и тебе нужен удобный reply/edit/delete flow с текущим chat, message и logger. + +Используй `tgapi`, когда: +- нужного helper method нет в `MsgContext` +- ты работаешь вне handler flow +- нужен lower-level control над Telegram methods, uploads или downloads + +Коротко: +- `MsgContext` — ergonomic default +- `tgapi` — lower-level escape hatch + +Подробности: [[tgapi-Overview]] + +## Почему `RunWithContext(...)` не заменяет `Close()`? + +Потому что это две разные ответственности: + +- `RunWithContext(...)` управляет run loop, graceful stop и ожиданием runner'ов +- `Close()` освобождает API, uploader, plugin shutdown hooks и loggers + +Поэтому `Close()` все равно нужен. + +## Почему plugin нужно полностью настроить до `AddPlugins(...)`? + +Потому что `AddPlugins(...)` — это configuration snapshot point. + +После регистрации bot хранит внутреннюю копию plugin state, и изменения исходного `*Plugin` уже не считаются поддерживаемым API. + +До `AddPlugins(...)` стоит завершить: +- commands +- payloads +- update handlers +- plugin middleware +- logger choice +- `OnClose` + +## Почему async middleware игнорирует `false`? + +Потому что async middleware задуман как side-effect path, а не как механизм flow control. + +Когда middleware уходит в goroutine, он уже не может надежно остановить основной execution path. Поэтому для блокировки и отказов нужно использовать обычный synchronous middleware. + +Подробности: [[Middleware]] + +## Что читать дальше + +- [[FAQ]] +- [[Getting-Started-RU]] +- [[Commands-and-Plugins]] +- [[Bot-Lifecycle]] diff --git a/Getting-Started-RU.md b/Getting-Started-RU.md new file mode 100644 index 0000000..1817686 --- /dev/null +++ b/Getting-Started-RU.md @@ -0,0 +1,197 @@ +# Getting Started RU + +Начни с этой страницы, если ты впервые подключаешь Laniakea к новому боту. Это сокращенная русскоязычная версия старта. Полная и наиболее актуальная страница: [[Getting-Started]]. + +## Что нужно сначала + +- Go 1.24 или новее +- токен Telegram-бота от `@BotFather` +- Go-модуль, который может импортировать `git.nix13.pw/scuroneko/laniakea` + +Установка: + +```bash +go get git.nix13.pw/scuroneko/laniakea +``` + +или: + +```bash +go get github.com/scuroneko/laniakea +``` + +## Самый маленький полезный бот + +```go +package main + +import ( + "log" + + "git.nix13.pw/scuroneko/laniakea" +) + +func ping(ctx *laniakea.MsgContext, db laniakea.NoDB) error { + ctx.Answer("Pong") + return nil +} + +func main() { + bot, err := laniakea.NewBot[laniakea.NoDB](&laniakea.BotOpts{ + Token: "TOKEN", + }) + if err != nil { + log.Fatal(err) + } + defer bot.Close() + + plugin := laniakea.NewPlugin[laniakea.NoDB]("main") + plugin.AddCommand(plugin.NewCommand(ping, "ping")) + + bot.AddPlugins(plugin) + + if err := bot.Run(); err != nil { + log.Fatal(err) + } +} +``` + +Если пользователь отправит `/ping`, бот ответит `Pong`. + +## Что важно понять сразу + +### 1. `NewBot[T]` использует generic-тип зависимости + +Параметр `T` — это общий dependency context, который попадает в handlers, middleware и runners. + +Используй: +- `laniakea.NoDB`, если dependency injection не нужен +- pointer type, например `*sql.DB`, `*Store` или `*App`, если общий state нужен + +Пример: + +```go +type App struct { + Users *sql.DB +} + +app := &App{Users: db} + +bot, err := laniakea.NewBot[*App](opts) +if err != nil { + return err +} + +bot.DatabaseContext(app) +``` + +### 2. Команды живут внутри plugins + +Обычный путь такой: + +1. создать bot +2. создать plugin +3. добавить команды в plugin +4. зарегистрировать plugin через `AddPlugins(...)` + +Пример: + +```go +plugin := laniakea.NewPlugin[laniakea.NoDB]("admin") +plugin.AddCommand(plugin.NewCommand(ping, "ping")) +bot.AddPlugins(plugin) +``` + +Подробности: [[Commands-and-Plugins]] + +### 3. Handlers возвращают `error` + +Сигнатура handler'а: + +```go +func(ctx *laniakea.MsgContext, db T) error +``` + +То есть: +- на успехе возвращай `nil` +- если хочешь централизованный error flow, возвращай `error` + +Пример: + +```go +func profile(ctx *laniakea.MsgContext, db *App) error { + user, err := db.LoadUser(ctx.FromID) + if err != nil { + return err + } + + ctx.Answerf("Hello, %s", user.Name) + return nil +} +``` + +Подробности: [[Error-Handling]] + +### 4. `Bot` single-use + +После `Run()` или `RunWithContext(...)` нельзя снова запускать тот же экземпляр `Bot`. + +Правильная модель: +- создать bot +- настроить +- запустить один раз +- закрыть +- создать новый bot для следующего запуска + +Подробности: [[Bot-Lifecycle]] + +### 5. `Close()` все равно нужен + +Даже если ты используешь `Run()` или `RunWithContext(...)`, ресурсы нужно закрывать явно: + +```go +defer bot.Close() +``` + +## Рекомендуемый порядок старта + +Для большинства ботов удобнее всего такой порядок: + +1. Собрать `BotOpts` +2. Вызвать `NewBot[T](opts)` +3. Подключить database context, localization и другие настройки +4. Создать plugins +5. Добавить commands, payloads и middleware в plugins +6. Зарегистрировать plugins через `AddPlugins(...)` +7. При необходимости вызвать `AutoGenerateCommands()` +8. Вызвать `Run()` или `RunWithContext(...)` +9. Закрыть bot через `Close()` + +## Частые ошибки на старте + +### Нет токена + +`NewBot(...)` вернет ошибку, если токен не настроен. + +### Нет plugins + +Запуск бота без зарегистрированных plugins невалиден. + +### Неожидание, что `ctx.Text` уже очищен от команды + +Для message command flow: +- сообщение: `/echo hello world` +- имя команды: `echo` +- `ctx.Text`: `hello world` +- `ctx.Args`: `[]string{"hello", "world"}` + +### Использование value types для shared state + +Обычно лучше использовать pointer types, чтобы не копировать общий state по значению. + +## Куда идти дальше + +- [[FAQ-RU]] +- [[Getting-Started]] +- [[Commands-and-Plugins]] +- [[MsgContext]] diff --git a/Home-RU.md b/Home-RU.md new file mode 100644 index 0000000..333634a --- /dev/null +++ b/Home-RU.md @@ -0,0 +1,44 @@ +# Laniakea Wiki RU + +Это краткая русскоязычная точка входа в wiki Laniakea. Подробная и наиболее полная документация остается в основной англоязычной wiki, поэтому для глубоких API-деталей лучше переходить по ссылкам на соответствующие английские страницы. + +## С чего начать + +- [[Getting-Started-RU]] +- [[FAQ-RU]] +- [[Getting-Started]] +- [[Commands-and-Plugins]] +- [[MsgContext]] + +## Что уже есть на русском + +- [[Getting-Started-RU]] +- [[FAQ-RU]] + +## Основные англоязычные страницы + +Если нужен полный и актуальный reference, начни отсюда: + +- [[Getting-Started]] +- [[Bot-Options-and-Configuration]] +- [[Commands-and-Plugins]] +- [[MsgContext]] +- [[Inline-Keyboards-and-Payloads]] +- [[tgapi-Overview]] + +## Практические и служебные страницы + +- [[Recipes]] +- [[Migration]] +- [[Semver-and-Releases]] +- [[Page-Priority]] + +## Как использовать русскую wiki + +Рекомендуемый маршрут для русскоязычного пользователя: + +1. Прочитать [[Getting-Started-RU]]. +2. Посмотреть [[FAQ-RU]]. +3. Перейти в англоязычные страницы по нужной теме, если требуется полный reference. + +Это позволяет держать русскоязычный входной слой полезным, но не дублировать всю wiki целиком. diff --git a/Home.md b/Home.md index 9bae1e0..64c0c04 100644 --- a/Home.md +++ b/Home.md @@ -4,6 +4,11 @@ Laniakea is a Go framework and Telegram Bot API wrapper built around plugins, ty Use this wiki as the structured companion to the README: start with setup, then move through commands, context, keyboards, and lower-level API usage. +## Russian Entry Pages +- [[Home-RU]] +- [[Getting-Started-RU]] +- [[FAQ-RU]] + ## Start here - [[Getting-Started]] - [[Bot-Options-and-Configuration]]