FILE / ScuroNeko/Laniakea

scene.go

Исходный файл и его история в репозитории.
FILE 4f8d583b03ce3e633284c8c09f9074c8a63c8097
Files
Laniakea/scene.go
T
2026-03-27 16:05:20 +03:00

196 lines
4.3 KiB
Go

package laniakea
import (
"encoding/json"
"sync"
)
type SceneHandler[T any] func(ctx *SceneContext, db T) (SceneResult, error)
type Scene[T any] struct {
Name string
Scope SceneScope
Entry string // starting step
PluginName string
steps map[string]SceneHandler[T]
commands map[string]SceneHandler[T]
message SceneHandler[T]
}
func NewScene[T any](name string) *Scene[T] {
return &Scene[T]{
Name: name,
Scope: SceneScopeUserChat,
Entry: "",
steps: make(map[string]SceneHandler[T]),
commands: make(map[string]SceneHandler[T]),
message: nil,
}
}
func (s *Scene[T]) SetScope(scope SceneScope) *Scene[T] {
s.Scope = scope
return s
}
func (s *Scene[T]) SetEntry(step string) *Scene[T] {
s.Entry = step
return s
}
func (s *Scene[T]) setPluginName(name string) *Scene[T] {
s.PluginName = name
return s
}
func (s *Scene[T]) OnStep(step string, handler SceneHandler[T]) *Scene[T] {
s.steps[step] = handler
return s
}
func (s *Scene[T]) OnCommand(cmd string, handler SceneHandler[T]) *Scene[T] {
s.commands[cmd] = handler
return s
}
func (s *Scene[T]) OnMessage(handler SceneHandler[T]) *Scene[T] {
s.message = handler
return s
}
func (s *Scene[T]) executeCommand(cmd string, ctx *SceneContext, db T) (SceneResult, bool, error) {
handler, ok := s.commands[cmd]
if !ok {
return SceneResult{}, false, nil
}
result, err := handler(ctx, db)
return result, true, err
}
func (s *Scene[T]) executeStep(step string, ctx *SceneContext, db T) (SceneResult, bool, error) {
handler, ok := s.steps[step]
if !ok {
return SceneResult{}, false, nil
}
result, err := 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)
return result, true, err
}
type SceneSession struct {
Scene string
Step string
Data []byte
}
// SetData sets the session data. It is thread-safe and can be used to store any arbitrary data as a byte slice.
func (s *SceneSession) SetData(data []byte) {
s.Data = data
}
// GetData retrieves the session data. It is thread-safe and returns the data as a byte slice.
func (s *SceneSession) GetData() []byte {
return s.Data
}
func (s *SceneSession) HasData() bool {
return len(s.Data) > 0
}
// ClearData clears the session data. It is thread-safe and sets the data to nil.
func (s *SceneSession) ClearData() {
s.Data = nil
}
// BindData binds the session data to the provided struct.
func (s *SceneSession) BindData(v any) error {
if len(s.Data) == 0 {
return nil // No data to bind, return nil error
}
return json.Unmarshal(s.Data, v)
}
// SaveData saves the provided struct as JSON in the session data.
func (s *SceneSession) SaveData(v any) error {
data, err := json.Marshal(v)
if err != nil {
return err
}
s.Data = data
return nil
}
type SessionStore interface {
Get(key string) (SceneSession, error)
Set(key string, session SceneSession) error
Delete(key string) error
}
type MemorySessionStore struct {
store map[string]SceneSession
mu sync.RWMutex
}
func NewMemorySessionStore() *MemorySessionStore {
return &MemorySessionStore{
store: make(map[string]SceneSession),
}
}
func (s *MemorySessionStore) Get(key string) (SceneSession, error) {
s.mu.RLock()
defer s.mu.RUnlock()
if session, ok := s.store[key]; ok {
return session, nil
}
return SceneSession{}, nil
}
func (s *MemorySessionStore) Set(key string, session SceneSession) error {
s.mu.Lock()
s.store[key] = session
s.mu.Unlock()
return nil
}
func (s *MemorySessionStore) Delete(key string) error {
s.mu.Lock()
delete(s.store, key)
s.mu.Unlock()
return nil
}
type SceneResult struct {
Action SceneAction
Next string
}
type SceneAction int
const (
SceneActionStay SceneAction = iota
SceneActionNext
SceneActionExit
SceneActionPass
)
type SceneScope int
const (
SceneScopeUser SceneScope = iota
SceneScopeChat
SceneScopeUserChat
)
type sceneRuntime interface {
FindScene(name string) (*sceneMeta, bool)
GetSession(key string) (SceneSession, error)
SetSession(key string, session SceneSession) error
DeleteSession(key string) error
BuildSceneKey(scope SceneScope, ctx *MsgContext) (string, bool)
FindSceneSession(ctx *MsgContext) (string, SceneSession, error)
}
type sceneMeta struct {
Name string
Scope SceneScope
Entry string
Steps map[string]struct{}
}