@@ -3,6 +3,7 @@ package laniakea
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"sync"
|
||||
)
|
||||
@@ -55,18 +56,27 @@ func (s *Scene[T]) setPluginName(name string) *Scene[T] {
|
||||
|
||||
// OnStep registers a handler for a named scene step.
|
||||
func (s *Scene[T]) OnStep(step string, handler SceneHandler[T]) *Scene[T] {
|
||||
if handler == nil {
|
||||
return s
|
||||
}
|
||||
s.steps[step] = handler
|
||||
return s
|
||||
}
|
||||
|
||||
// OnCommand registers a command handler active while the scene is running.
|
||||
func (s *Scene[T]) OnCommand(cmd string, handler SceneHandler[T]) *Scene[T] {
|
||||
if handler == nil {
|
||||
return s
|
||||
}
|
||||
s.commands[cmd] = handler
|
||||
return s
|
||||
}
|
||||
|
||||
// OnPayload registers a callback payload handler active while the scene is running.
|
||||
func (s *Scene[T]) OnPayload(cmd string, handler SceneHandler[T]) *Scene[T] {
|
||||
if handler == nil {
|
||||
return s
|
||||
}
|
||||
s.payloads[cmd] = handler
|
||||
return s
|
||||
}
|
||||
@@ -82,7 +92,7 @@ func (s *Scene[T]) executeCommand(cmd string, ctx *SceneContext, db T) (SceneRes
|
||||
if !ok {
|
||||
return SceneResult{}, false, nil
|
||||
}
|
||||
result, err := handler(ctx, db)
|
||||
result, err := callSceneHandler(handler, ctx, db)
|
||||
return result, true, err
|
||||
}
|
||||
func (s *Scene[T]) executePayload(cmd string, ctx *SceneContext, db T) (SceneResult, bool, error) {
|
||||
@@ -90,7 +100,7 @@ func (s *Scene[T]) executePayload(cmd string, ctx *SceneContext, db T) (SceneRes
|
||||
if !ok {
|
||||
return SceneResult{}, false, nil
|
||||
}
|
||||
result, err := handler(ctx, db)
|
||||
result, err := callSceneHandler(handler, ctx, db)
|
||||
return result, true, err
|
||||
}
|
||||
func (s *Scene[T]) executeStep(step string, ctx *SceneContext, db T) (SceneResult, bool, error) {
|
||||
@@ -98,17 +108,30 @@ func (s *Scene[T]) executeStep(step string, ctx *SceneContext, db T) (SceneResul
|
||||
if !ok {
|
||||
return SceneResult{}, false, nil
|
||||
}
|
||||
result, err := handler(ctx, db)
|
||||
result, err := callSceneHandler(handler, ctx, db)
|
||||
return result, true, err
|
||||
}
|
||||
func (s *Scene[T]) executeMessage(ctx *SceneContext, db T) (SceneResult, bool, error) {
|
||||
if s.message == nil {
|
||||
return SceneResult{}, false, nil
|
||||
}
|
||||
result, err := s.message(ctx, db)
|
||||
result, err := callSceneHandler(s.message, ctx, db)
|
||||
return result, true, err
|
||||
}
|
||||
|
||||
func callSceneHandler[T any](handler SceneHandler[T], ctx *SceneContext, db T) (result SceneResult, err error) {
|
||||
if handler == nil {
|
||||
return SceneResult{}, ErrHandlerExecutorNil
|
||||
}
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
result = SceneResult{}
|
||||
err = fmt.Errorf("%w: %v", ErrHandlerPanic, recovered)
|
||||
}
|
||||
}()
|
||||
return handler(ctx, db)
|
||||
}
|
||||
|
||||
func (s *Scene[T]) clone() *Scene[T] {
|
||||
if s == nil {
|
||||
return nil
|
||||
@@ -223,8 +246,10 @@ func (s *MemorySessionStore) Delete(key string) error {
|
||||
|
||||
// SceneResult describes how scene execution should proceed after a handler returns.
|
||||
type SceneResult struct {
|
||||
// Action controls the scene state transition.
|
||||
Action SceneAction
|
||||
Next string
|
||||
// Next names the destination step for SceneActionNext.
|
||||
Next string
|
||||
}
|
||||
|
||||
// SceneAction controls how the bot updates scene state after a handler returns.
|
||||
|
||||
Reference in New Issue
Block a user