203 lines
13 KiB
Markdown
203 lines
13 KiB
Markdown
# Laniakea
|
||
|
||
[](https://go.dev/)
|
||
[](LICENSE)
|
||

|
||
|
||
Легковесная, простая в использовании и производительная обёртка для Telegram Bot API на Go. Она упрощает разработку ботов благодаря чистой системе плагинов, поддержке中间件, автоматической генерации команд и встроенному ограничителю скорости запросов.
|
||
|
||
[English](README.md)
|
||
|
||
---
|
||
|
||
## ✨ Возможности
|
||
|
||
* **Простой и интуитивный API:** Разработан для лёгкости использования, основан на практических примерах.
|
||
* **Система плагинов:** Организуйте функциональность бота в независимые, переиспользуемые плагины.
|
||
* **Обработка команд:** Легко регистрируйте команды и извлекайте аргументы.
|
||
* **Поддержка промежуточных слоёв (Middleware):** Выполняйте код до или после команд (например, логирование, проверка доступа).
|
||
* **Автоматическая генерация команд:** Генерируйте справку и списки команд автоматически.
|
||
* **Встроенный ограничитель запросов (Rate Limiter):** Защитите бота от превышения лимитов Telegram API (с обработкой `retry_after`).
|
||
* **Контекст данных:** Передавайте свой контекст базы данных или состояния в обработчики.
|
||
* **Текучий интерфейс (Fluent Interface):** Стройте цепочки методов для чистой конфигурации (например, `bot.ErrorTemplate(...).AddPlugins(...)`).
|
||
|
||
---
|
||
|
||
## 📦 Установка
|
||
|
||
```bash
|
||
go get git.nix13.pw/scuroneko/laniakea
|
||
```
|
||
|
||
## 🚀 Быстрый старт (с пошаговыми комментариями)
|
||
Вот минимальный пример бота "echo/ping" с подробными комментариями.
|
||
|
||
```go
|
||
package main
|
||
|
||
import (
|
||
"log"
|
||
|
||
"git.nix13.pw/scuroneko/laniakea" // Импортируем библиотеку Laniakea
|
||
)
|
||
|
||
// echo — это функция-обработчик команды.
|
||
// Она получает два параметра:
|
||
// - ctx: контекст сообщения (содержит информацию о сообщении, отправителе, чате и т.д.)
|
||
// - db: ваш пользовательский контекст базы данных (здесь мы используем NoDB — заглушку)
|
||
func echo(ctx *laniakea.MsgContext, db *laniakea.NoDB) {
|
||
// Отвечаем пользователю текстом, который он прислал, без префикса команды.
|
||
// ctx.Text содержит сообщение пользователя, из которого удалена часть с командой.
|
||
ctx.Answer(ctx.Text) // Ввод пользователя БЕЗ команды
|
||
}
|
||
|
||
func main() {
|
||
// 1. Создаём опции бота. Замените "TOKEN" на реальный токен от @BotFather.
|
||
opts := &laniakea.BotOpts{Token: "TOKEN"}
|
||
|
||
// 2. Инициализируем новый экземпляр бота.
|
||
// Используем laniakea.NoDB как тип контекста базы данных (база не нужна для примера).
|
||
bot := laniakea.NewBot[laniakea.NoDB](opts)
|
||
// Гарантируем освобождение ресурсов бота при выходе.
|
||
defer bot.Close()
|
||
|
||
// 3. Создаём новый плагин с именем "ping".
|
||
// Плагины помогают группировать связанные команды и промежуточные обработчики.
|
||
p := laniakea.NewPlugin[laniakea.NoDB]("ping")
|
||
|
||
// 4. Добавляем команду в плагин.
|
||
// p.NewCommand(echo, "echo") создаёт команду, которая вызывает функцию 'echo' по команде "/echo".
|
||
p.AddCommand(p.NewCommand(echo, "echo"))
|
||
|
||
// 5. Добавляем ещё одну команду, используя анонимную функцию (замыкание).
|
||
// Эта команда просто отвечает "Pong", когда пользователь отправляет "/ping".
|
||
p.AddCommand(p.NewCommand(func(ctx *laniakea.MsgContext, db *laniakea.NoDB) {
|
||
ctx.Answer("Pong")
|
||
}, "ping"))
|
||
|
||
// 6. Настраиваем бота: задаём шаблон ошибки и добавляем плагин.
|
||
// ErrorTemplate устанавливает формат для сообщений об ошибках (где %s будет заменён на текст ошибки).
|
||
// AddPlugins(p) регистрирует наш плагин "ping" в боте.
|
||
bot = bot.ErrorTemplate("Ошибка\n\n%s").AddPlugins(p)
|
||
|
||
// 7. Автоматически генерируем команды, такие как /start, /help и список всех зарегистрированных команд.
|
||
// Это необязательно, но очень полезно для большинства ботов.
|
||
if err := bot.AutoGenerateCommands(); err != nil {
|
||
log.Println(err)
|
||
}
|
||
|
||
// 8. Запускаем бота, начиная прослушивание обновлений (long polling).
|
||
bot.Run()
|
||
}
|
||
```
|
||
|
||
### Как это работает
|
||
1. `BotOpts`: Содержит конфигурацию, например, токен API.
|
||
2. `NewBot[T]`: Создаёт экземпляр бота. Параметр типа T позволяет передать пользовательский контекст базы данных (например, *sql.DB), который будет доступен во всех обработчиках. Используйте laniakea.NoDB, если он не нужен.
|
||
3. `NewPlugin`: Создаёт логическую группу для команд и Middleware.
|
||
4. `AddCommand`: Регистрирует команду. Первый аргумент — функция-обработчик (func(*MsgContext, T)), второй — имя команды (без слеша).
|
||
5. **Функции-обработчики**: Получают *MsgContext (детали сообщения, методы типа Answer) и ваш контекст базы данных T.
|
||
6. `ErrorTemplate`: Устанавливает шаблон для сообщений об ошибках. Плейсхолдер %s заменяется на текст ошибки.
|
||
7. `AutoGenerateCommands`: Добавляет встроенные команды (/start, /help) и команду, показывающую список всех доступных команд.
|
||
8. `Run()`: Запускает цикл опроса обновлений бота.
|
||
|
||
## 📖 Основные концепции
|
||
### Плагины (Plugins)
|
||
Плагины — основной способ организации кода. Плагин может содержать несколько команд и Middleware.
|
||
|
||
```go
|
||
plugin := laniakea.NewPlugin[MyDB]("admin")
|
||
plugin.AddCommand(plugin.NewCommand(banUser, "ban"))
|
||
bot.AddPlugins(plugin)
|
||
```
|
||
|
||
### Команды (Commands)
|
||
Команда — это функция, которая обрабатывает конкретную команду бота (например, /start).
|
||
|
||
```go
|
||
func myHandler(ctx *laniakea.MsgContext, db *MyDB) {
|
||
// Доступ к аргументам команды через ctx.Args ([]string)
|
||
// Ответ пользователю: ctx.Answer("какой-то текст")
|
||
}
|
||
```
|
||
|
||
### Контекст сообщения (MsgContext)
|
||
Предоставляет доступ к входящему сообщению и полезные методы для ответа:
|
||
|
||
- `Answer(text string)`: Отправляет обычный текст, автоматически экранируя MarkdownV2.
|
||
- `AnswerMarkdown(text string)`: Отправляет сообщение, отформатированное MarkdownV2 (экранирование на вашей стороне).
|
||
- `AnswerText(text string)`: Отправляет сообщение без parse_mode.
|
||
- `SendChatAction(action string)`: Отправляет действие "печатает", "загружает фото" и т.д.
|
||
- Поля: `Text`, `Args`, `From`, `Chat`, `Msg` и другие.
|
||
|
||
### Контекст базы данных (Database Context)
|
||
Параметр типа `T` в `NewBot[T]` — мощная функция. Вы можете передать любой тип (например, пул соединений с БД), и он будет доступен в каждом обработчике команды и中间件.
|
||
|
||
```go
|
||
type MyDB struct { /* ... */ }
|
||
db := &MyDB{...}
|
||
bot := laniakea.NewBot[*MyDB](opts, db) // Передаём экземпляр db
|
||
```
|
||
|
||
## 🧩 Промежуточные слои (Middleware)
|
||
Middleware — это функции, которые выполняются перед обработчиком команды. Они идеально подходят для сквозных задач, таких как логирование, контроль доступа, ограничение скорости запросов или модификация контекста.
|
||
|
||
### Сигнатура
|
||
Функция middleware имеет ту же сигнатуру, что и обработчик команды, но должна возвращать bool:
|
||
|
||
```go
|
||
func(ctx *MsgContext, db T) bool
|
||
```
|
||
|
||
- Если возвращается true, выполняется следующий middleware (или сама команда).
|
||
- Если возвращается false, цепочка выполнения немедленно прерывается (команда не запускается).
|
||
|
||
### Добавление middleware
|
||
Используйте метод Use плагина для добавления одной или нескольких функций middleware. Они выполняются в порядке добавления.
|
||
|
||
```go
|
||
plugin := laniakea.NewPlugin[MyDB]("admin")
|
||
plugin.Use(loggingMiddleware, adminOnlyMiddleware)
|
||
plugin.AddCommand(plugin.NewCommand(banUser, "ban"))
|
||
```
|
||
|
||
### Примеры middleware
|
||
|
||
1. Логирующий middleware – логирует каждое выполнение команды.
|
||
```go
|
||
func loggingMiddleware(ctx *laniakea.MsgContext, db *MyDB) bool {
|
||
log.Printf("Пользователь %d выполнил команду: %s", ctx.FromID, ctx.Msg.Text)
|
||
return true // продолжаем к следующему middleware/команде
|
||
}
|
||
```
|
||
|
||
2. Middleware только для администраторов – ограничивает доступ пользователям с определённой ролью.
|
||
```go
|
||
func adminOnlyMiddleware(ctx *laniakea.MsgContext, db *MyDB) bool {
|
||
if !db.IsAdmin(ctx.FromID) { // предполагается, что db имеет метод IsAdmin
|
||
ctx.Answer("⛔ Доступ запрещён. Только для администраторов.")
|
||
return false // останавливаем выполнение
|
||
}
|
||
return true
|
||
}
|
||
```
|
||
|
||
### Важные замечания
|
||
- Middleware может изменять MsgContext (например, добавлять пользовательские поля) перед запуском команды.
|
||
- Если нужно выполнить код после команды, это можно сделать внутри самой команды или использовать отложенный вызов (defer) в middleware, который оборачивает следующий вызов (более продвинутый подход).
|
||
|
||
## ⚙️ Расширенная настройка
|
||
**Инлайн-клавиатуры**: Создавайте клавиатуры с помощью laniakea.NewKeyboard() и AddRow().
|
||
**Ограничение запросов**: Передайте настроенный utils.RateLimiter через BotOpts для корректной обработки лимитов Telegram.
|
||
**Пользовательский HTTP-клиент**: Предоставьте свой http.Client в BotOpts для точного контроля.
|
||
|
||
## 📝 Лицензия
|
||
Этот проект лицензирован под GNU General Public License v3.0 - подробности см. в файле [LICENSE](LICENSE).
|
||
|
||
## 📚 Дополнительная информация
|
||
[GoDoc Laniakea](https://pkg.go.dev/git.nix13.pw/scuroneko/laniakea)
|
||
|
||
[Telegram Bot API](https://core.telegram.org/bots/api)
|
||
|
||
✅ Создано с ❤️ scuroneko
|