Skip to content

Aufbau eines Moduls ​

Jedes Modul erfüllt goroku.Module. Das Einbetten von goroku.Base liefert einen Standardwert für alles außer Name und Commands — nur diese beiden Methoden musst du schreiben.

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
}

Pflicht ​

Name ​

Die Identität des Moduls in .help, .unloadmod und der Konfigurationsoberfläche. Es ist zugleich der Go-Typname und der Schlüssel, unter dem deine Daten liegen.

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

Commands ​

Ordnet einem Befehlswort einen Handler zu. Nutzer tippen das Wort nach dem Präfix, aus "weather" wird also .weather.

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

Ein CommandHandler ist func(msg *goroku.Message) error. Ein zurückgegebener Fehler wird dem Nutzer gemeldet; der Dispatcher fängt zudem Panics ab, ein Absturz in deinem Handler legt den Bot also nicht lahm.

Optional, mit Standardwerten aus Base ​

Strings ​

Text für Nutzer und Quelle für m.T. Zwei Schlüsselpräfixe sind besonders:

SchlüsselBedeutung
nameAnzeigename in .help
_cls_docWas das Modul tut
_cmd_doc_<Befehl>Was dieser Befehl tut

Alles andere gehört dir und wird mit m.T abgerufen.

go
func (m *Weather) Strings() map[string]string {
	return map[string]string{
		"name":             "Weather",
		"_cls_doc":         "Aktuelles Wetter für eine Stadt",
		"_cmd_doc_weather": "[Stadt] — Wetter anzeigen",
		"no_city":          "❌ <b>Welche Stadt?</b>",
	}
}

Init ​

Läuft einmal bei der Registrierung, bevor irgendein Befehl auslösen kann. Base hat m.Client, m.DB und m.Translator zu diesem Zeitpunkt schon gefüllt — nutze Init also nur für deine eigene Einrichtung.

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
}

Rufe m.Base.Init zuerst auf

Der Loader füllt die Felder vor dem Init-Aufruf, im Normalbetrieb ist dieser Aufruf also überflüssig. Lass ihn trotzdem stehen: so funktioniert das Modul auch, wenn es in einem Test direkt erzeugt wird, ohne den Loader.

ClientReady ​

Läuft, sobald die Telegram-Verbindung steht. Für alles, was beim Start die API braucht; Init kann vor dem Verbindungsaufbau laufen.

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

OnUnload ​

Läuft, wenn das Modul entfernt wird. Gib hier Goroutinen, Timer und Dateihandles frei.

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

WARNING

Ein Panic in OnUnload wird abgefangen und geloggt, das Modul wird aber trotzdem entfernt. Verlass dich für korrektheitskritische Aufräumarbeiten nicht auf OnUnload.

OnDlmod ​

Läuft direkt nach der Installation über .dlmod. Praktisch für eine einmalige Begrüßung oder Ersteinrichtung.

Watchers ​

Handler, die jede Nachricht sehen, nicht nur Befehle. Siehe Watcher.

Jenseits des Interface ​

Mehrere Fähigkeiten sind über eigene Interfaces optional — deklariere die Methode, und Goroku greift sie auf:

InterfaceMethodeZweck
ModuleWithMetaCommandMetas()Aliase und Einschränkungen
ModuleWithConfigSchemaConfigSchema()Typisierte Einstellungen
ModuleWithConfigReadyConfigReady(map[string]any)Auf Änderungen reagieren
ModuleWithTranslationAliasesTranslationAliases()Zusätzliche Namen für Übersetzungsdateien

Vollständige Liste unter Optionale Interfaces.

Released under the GNU AGPL v3 License.