# Laniakea [![Go Version](https://img.shields.io/badge/Go-1.24+-00ADD8?logo=go&style=flat-square)](https://go.dev/) [![License: GPL-3.0](https://img.shields.io/badge/License-GPL%203.0-blue.svg?style=flat-square)](LICENSE) ![Gitea Release](https://img.shields.io/gitea/v/release/ScuroNeko/Laniakea?gitea_url=https%3A%2F%2Fgit.nix13.pw&sort=semver&display_name=release&style=flat-square&color=purple&link=https%3A%2F%2Fgit.nix13.pw%2FScuroNeko%2FLaniakea%2Freleases) Легковесная, простая в использовании и производительная обёртка для 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