doodle/pkg/chatbot/chatbot.go

95 lines
2.0 KiB
Go

// Package chatbot provides the RiveScript bot that lives in the developer shell.
package chatbot
import (
"errors"
"git.kirsle.net/SketchyMaze/doodle/assets"
"git.kirsle.net/SketchyMaze/doodle/pkg/log"
"github.com/aichaos/rivescript-go"
)
var (
Bot *rivescript.RiveScript
Username = "player"
)
// RiveScript source code snippets to be SURE get included even if
// the external brain fails to load.
const (
RiveScriptBase = `
! array boolean = true false t f on off yes no 1 0
+ echo *
- <call>echo *</call>
+ error *
- <call>error *</call>
+ alert *
- <call>alert *</call>
+ boolprop * (@boolean)
- <call>boolprop <star1> <star2></call>
+ rivescript command *
@ <star>
`
RiveScriptBasic = `
+ hello *
- Hello <id>.
`
)
// Bind functions.
type Functions struct {
Echo func(string)
Error func(string)
Alert func(string)
Confirm func(string)
New func()
Save func()
Edit func()
Play func()
Close func()
TitleScreen func(string)
BoolProp func(string, bool)
}
// Setup the RiveScript interpreter.
func Setup() {
log.Info("Initializing chatbot")
Bot = rivescript.New(rivescript.WithUTF8())
if err := Bot.Stream(RiveScriptBase + RiveScriptBasic); err != nil {
log.Error("Error streaming RiveScript base: %s", err)
}
// Load all the built-in .rive scripts.
if filenames, err := assets.AssetDir("assets/rivescript"); err == nil {
for _, filename := range filenames {
if data, err := assets.Asset("assets/rivescript/" + filename); err == nil {
err = Bot.Stream(string(data))
if err != nil {
log.Error("RiveScript.Stream(%s): %s", filename, err)
}
} else {
log.Error("chatbot.Setup: Asset(%s): %s", filename, err)
}
}
} else {
log.Error("chatbot.Setup: AssetDir: %s", err)
}
Bot.SortReplies()
}
// Handle a message from the user.
func Handle(message string) (string, error) {
if Bot != nil {
return Bot.Reply(Username, message)
}
return "", errors.New("bot not ready")
}