FILE / ScuroNeko/Laniakea

observer.go

Исходный файл и его история в репозитории.
FILE b0882a46d5527474bae4b2fea2127dae326f253d
Files
Laniakea/observer.go
T
ScuroNeko b0882a46d5
Golang lint / lint (push) Has been cancelled
(new): add scene payload routing
(fix): stabilize config file versions

(tests): cover routing and versions

(doc): improve exported godoc
2026-04-24 11:34:53 +03:00

189 lines
5.4 KiB
Go

package laniakea
import (
"context"
"fmt"
"time"
"git.scuroneko.dev/scuroneko/laniakea/tgapi"
)
// HandlerEventKind identifies the kind of handler observed by runtime events.
type HandlerEventKind string
const (
// HandlerCommandKind identifies a command handler.
HandlerCommandKind HandlerEventKind = "command"
// HandlerMessageKind identifies a message fallback handler.
HandlerMessageKind HandlerEventKind = "message"
// HandlerPayloadKind identifies a callback payload handler.
HandlerPayloadKind HandlerEventKind = "payload"
// HandlerUpdateKind identifies a generic update handler.
HandlerUpdateKind HandlerEventKind = "update"
// HandlerRunnerKind identifies a background runner execution.
HandlerRunnerKind HandlerEventKind = "runner"
// HandlerPollingKind identifies polling and getUpdates runtime work.
HandlerPollingKind HandlerEventKind = "polling"
// HandlerSceneKind identifies a scene runtime handler wrapper.
HandlerSceneKind HandlerEventKind = "scene"
// HandlerSceneStepKind identifies a scene step handler.
HandlerSceneStepKind HandlerEventKind = "scene_step"
// HandlerSceneCommandKind identifies a scene-local command handler.
HandlerSceneCommandKind HandlerEventKind = "scene_command"
// HandlerScenePayloadKind identifies a scene-local callback payload handler.
HandlerScenePayloadKind HandlerEventKind = "scene_payload"
// HandlerSceneMessageKind identifies a scene message fallback handler.
HandlerSceneMessageKind HandlerEventKind = "scene_message"
)
// Event is the marker interface implemented by all observer runtime events.
type Event interface {
isEvent()
}
// UpdateReceivedEvent describes an update entering the bot runtime.
type UpdateReceivedEvent struct {
UpdateID int
UpdateType tgapi.UpdateType
FromID int64
ChatID int64
}
// UpdateHandledEvent describes a completed update execution path.
type UpdateHandledEvent struct {
UpdateID int
UpdateType tgapi.UpdateType
FromID int64
ChatID int64
Duration time.Duration
Handled bool
}
// HandlerStartedEvent describes a handler about to execute.
type HandlerStartedEvent struct {
UpdateID int
UpdateType tgapi.UpdateType
Plugin string
HandlerKind HandlerEventKind
HandlerName string
FromID int64
ChatID int64
}
// HandlerFinishedEvent describes a handler that has completed.
type HandlerFinishedEvent struct {
UpdateID int
UpdateType tgapi.UpdateType
Plugin string
HandlerKind HandlerEventKind
HandlerName string
FromID int64
ChatID int64
Duration time.Duration
Err error
UserFacing bool
}
// SceneTransitionEvent describes a scene state transition.
type SceneTransitionEvent struct {
Plugin string
Scene string
From string
To string
Action SceneAction
FromID int64
ChatID int64
}
// PolicyCheckedEvent describes the result of a policy evaluation.
type PolicyCheckedEvent struct {
Name string
Plugin string
FromID int64
ChatID int64
Passed bool
Err error
Internal bool
}
// RunnerFinishedEvent describes a completed background runner execution.
type RunnerFinishedEvent struct {
Name string
Duration time.Duration
Err error
}
// PollingRetryEvent describes a polling retry after a failed getUpdates call.
type PollingRetryEvent struct {
Attempt int
Delay time.Duration
Err error
}
// ErrorEvent describes an error routed through framework error handling.
type ErrorEvent struct {
UpdateID int
UpdateType tgapi.UpdateType
Plugin string
HandlerKind HandlerEventKind
HandlerName string
FromID int64
ChatID int64
Err error
UserFacing bool
}
func (UpdateReceivedEvent) isEvent() {}
func (UpdateHandledEvent) isEvent() {}
func (HandlerStartedEvent) isEvent() {}
func (HandlerFinishedEvent) isEvent() {}
func (SceneTransitionEvent) isEvent() {}
func (PolicyCheckedEvent) isEvent() {}
func (RunnerFinishedEvent) isEvent() {}
func (PollingRetryEvent) isEvent() {}
func (ErrorEvent) isEvent() {}
// Observer receives best-effort runtime instrumentation events.
type Observer interface {
OnReceiveUpdate(ctx context.Context, event UpdateReceivedEvent)
OnHandledUpdate(ctx context.Context, event UpdateHandledEvent)
OnHandlerStarted(ctx context.Context, event HandlerStartedEvent)
OnHandlerFinished(ctx context.Context, event HandlerFinishedEvent)
OnSceneTransition(ctx context.Context, event SceneTransitionEvent)
OnPolicyChecked(ctx context.Context, event PolicyCheckedEvent)
OnRunnerFinished(ctx context.Context, event RunnerFinishedEvent)
OnPollingRetry(ctx context.Context, event PollingRetryEvent)
OnError(ctx context.Context, event ErrorEvent)
}
func (bot *Bot[T]) safeEmitEvent(ctx context.Context, event Event) {
if bot.observer == nil {
return
}
defer func() {
if r := recover(); r != nil {
bot.logger.Errorln(fmt.Sprintf("panic in observer: %v", r))
}
}()
switch e := event.(type) {
case UpdateReceivedEvent:
bot.observer.OnReceiveUpdate(ctx, e)
case UpdateHandledEvent:
bot.observer.OnHandledUpdate(ctx, e)
case HandlerStartedEvent:
bot.observer.OnHandlerStarted(ctx, e)
case HandlerFinishedEvent:
bot.observer.OnHandlerFinished(ctx, e)
case SceneTransitionEvent:
bot.observer.OnSceneTransition(ctx, e)
case PolicyCheckedEvent:
bot.observer.OnPolicyChecked(ctx, e)
case RunnerFinishedEvent:
bot.observer.OnRunnerFinished(ctx, e)
case PollingRetryEvent:
bot.observer.OnPollingRetry(ctx, e)
case ErrorEvent:
bot.observer.OnError(ctx, e)
}
}