REPOSITORY / ScuroNeko/Laniakea

Wiki

KNOWLEDGE REPOSITORY
8
Getting Started RU
ScuroNeko edited this page 2026-08-19 14:59:10 +03:00

Getting Started RU

English version: Getting-Started

Начни с этой страницы, если ты впервые подключаешь Laniakea к новому боту. Это сокращенная русскоязычная версия старта. Полная и наиболее актуальная страница: Getting-Started.

Что нужно сначала

  • Go 1.26 или новее
  • токен Telegram-бота от @BotFather
  • Go-модуль, который может импортировать git.scuroneko.dev/scuroneko/laniakea

Установка:

go get git.scuroneko.dev/scuroneko/laniakea

или:

go get github.com/scuroneko/laniakea

Самый маленький полезный бот

package main

import (
	"log"

	"git.scuroneko.dev/scuroneko/laniakea"
)

func ping(ctx *laniakea.MessageContext, db laniakea.NoData) error {
	ctx.Answer("Pong")
	return nil
}

func main() {
	bot, err := laniakea.NewBot[laniakea.NoData](&laniakea.BotOpts{
		Token: "TOKEN",
	})
	if err != nil {
		log.Fatal(err)
	}
	defer bot.Close()

	plugin := laniakea.NewPlugin[laniakea.NoData]("main")
	plugin.Command("ping", ping)

	bot.AddPlugins(plugin)

	if err := bot.Run(); err != nil {
		log.Fatal(err)
	}
}

Если пользователь отправит /ping, бот ответит Pong.

Что важно понять сразу

1. NewBot[T] использует generic-параметр зависимости

Параметр T — это общий контекст зависимостей, который попадает в хендлеры, middleware и runners.

Используй:

  • laniakea.NoData, если dependency injection не нужен
  • pointer type, например *sql.DB, *Store или *App, если нужен общий state

Пример:

type App struct {
	Users *sql.DB
}

app := &App{Users: db}

bot, err := laniakea.NewBot[*App](opts)
if err != nil {
	return err
}

bot.SetAppData(app)

2. Команды живут внутри плагинов

Обычный путь такой:

  1. создать Bot
  2. создать Plugin
  3. добавить команды в Plugin
  4. зарегистрировать Plugin через AddPlugins(...)

Пример:

plugin := laniakea.NewPlugin[laniakea.NoData]("admin")
plugin.Command("ping", ping)
bot.AddPlugins(plugin)

Подробности: Commands-and-Plugins

3. Хендлеры возвращают error

Сигнатура хендлера:

func(ctx *laniakea.MessageContext, db T) error

То есть:

  • на успехе возвращай nil
  • если хочешь централизованный поток обработки ошибок, возвращай error

Пример:

func profile(ctx *laniakea.MessageContext, 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(...) или RunWebhookWithContext(...) нельзя снова запускать тот же экземпляр Bot.

Правильная модель:

  • создать bot
  • настроить
  • запустить один раз
  • закрыть
  • создать новый bot для следующего запуска

После завершения не надо повторно вызывать никакой runtime entry point на том же экземпляре.

Подробности: Bot-Lifecycle

5. Close() все равно нужен

Даже если ты используешь Run(), RunWithContext(...) или RunWebhookWithContext(...), ресурсы нужно закрывать явно:

defer bot.Close()

Рекомендуемый порядок старта

Для большинства ботов удобнее всего такой порядок:

  1. Собрать BotOpts
  2. Вызвать NewBot[T](opts)
  3. Подключить database context, localization и другие настройки
  4. Создать плагины
  5. Добавить команды, payloads и middleware в плагины
  6. Зарегистрировать плагины через AddPlugins(...)
  7. При необходимости вызвать AutoGenerateCommands()
  8. Вызвать Run(), RunWithContext(...) или RunWebhookWithContext(...)
  9. Закрыть bot через Close()

Частые ошибки на старте

Нет токена

NewBot(...) вернет ошибку, если токен не настроен.

Нет плагинов

Запуск бота без зарегистрированных плагинов невалиден.

Неожидание, что ctx.Text уже очищен от команды

Для обычного потока команд:

  • сообщение: /echo hello world
  • имя команды: echo
  • ctx.Text: hello world
  • ctx.Args: []string{"hello", "world"}

Использование value types для shared state

Обычно лучше использовать pointer types, чтобы не копировать общий state по значению.

Куда идти дальше