Skip to content

Устройство модуля

Каждый модуль реализует goroku.Module. Встраивание goroku.Base даёт значение по умолчанию для всего, кроме Name и Commands, — только эти два метода писать обязательно.

go
type Module interface {
	Name() string
	Strings() map[string]string
	Init(client *CustomTelegramClient, db *Database) error
	ClientReady() error
	OnUnload() error
	OnDlmod() error
	Commands() map[string]CommandHandler
	Watchers() []WatcherHandler
}

Обязательные

Name

Идентичность модуля в .help, .unloadmod и интерфейсе настроек. Это же имя типа Go и ключ, под которым хранятся ваши данные.

go
func (m *Weather) Name() string { return "Weather" }

Commands

Сопоставляет слово команды обработчику. Пользователь набирает слово после префикса, поэтому "weather" превращается в .weather.

go
func (m *Weather) Commands() map[string]goroku.CommandHandler {
	return map[string]goroku.CommandHandler{
		"weather":  m.WeatherCmd,
		"forecast": m.ForecastCmd,
	}
}

CommandHandler — это func(msg *goroku.Message) error. Возврат ошибки покажет её пользователю; диспетчер к тому же перехватывает паники, так что падение обработчика не уронит бота.

Необязательные, со значениями из Base

Strings

Текст для пользователя и источник для m.T. Два префикса ключей особые:

КлючСмысл
nameОтображаемое имя в .help
_cls_docЧто делает модуль
_cmd_doc_<команда>Что делает эта команда

Все остальные ключи — ваши, доставайте их через m.T.

go
func (m *Weather) Strings() map[string]string {
	return map[string]string{
		"name":             "Weather",
		"_cls_doc":         "Погода в городе",
		"_cmd_doc_weather": "[город] — показать погоду",
		"no_city":          "❌ <b>Какой город?</b>",
	}
}

Init

Выполняется один раз при регистрации, до того как сработает любая команда. Base к этому моменту уже заполнил m.Client, m.DB и m.Translator, так что Init нужен только для вашей собственной настройки.

go
func (m *Weather) Init(client *goroku.CustomTelegramClient, db *goroku.Database) error {
	if err := m.Base.Init(client, db); err != nil {
		return err
	}
	m.cache = make(map[string]string)
	return nil
}

Вызывайте m.Base.Init первым

Загрузчик заполняет поля до вызова Init, поэтому в обычной работе этот вызов избыточен. Всё равно оставьте его: так модуль будет работать и когда его создают напрямую в тесте, минуя загрузчик.

ClientReady

Выполняется, когда соединение с Telegram установлено. Сюда — всё, чему нужен API при старте; Init может отработать раньше, чем клиент подключится.

go
func (m *Weather) ClientReady() error {
	me := m.Client.Me()
	_ = me
	return nil
}

OnUnload

Выполняется при удалении модуля. Здесь освобождайте горутины, таймеры и файловые дескрипторы.

go
func (m *Weather) OnUnload() error {
	close(m.stop)
	return nil
}

WARNING

Паника в OnUnload перехватывается и логируется, но модуль всё равно удаляется. Не полагайтесь на OnUnload там, где очистка критична для корректности.

OnDlmod

Выполняется сразу после установки через .dlmod. Удобно для одноразового приветствия или начальной настройки.

Watchers

Обработчики, которые видят каждое сообщение, а не только команды. См. Вотчеры.

За пределами интерфейса

Часть возможностей подключается отдельными интерфейсами — просто объявите метод, и Goroku его подхватит:

ИнтерфейсМетодНазначение
ModuleWithMetaCommandMetas()Алиасы и ограничения
ModuleWithConfigSchemaConfigSchema()Типизированные настройки
ModuleWithConfigReadyConfigReady(map[string]any)Реакция на смену настроек
ModuleWithTranslationAliasesTranslationAliases()Дополнительные имена файлов перевода

Полный список — в Опциональных интерфейсах.

Released under the GNU AGPL v3 License.