FILE / ScuroNeko/Laniakea
observer.go
Исходный файл и его история в репозитории.
(fix): observer rename, panic emits ErrorEvent (refactor): Runner.Once removed, Scene.PluginName unexported (doc): godoc hygiene pre-1.0.0
189 lines
5.4 KiB
Go
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 {
|
|
OnUpdateReceived(ctx context.Context, event UpdateReceivedEvent)
|
|
OnUpdateHandled(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.OnUpdateReceived(ctx, e)
|
|
case UpdateHandledEvent:
|
|
bot.observer.OnUpdateHandled(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)
|
|
}
|
|
}
|