-
Notifications
You must be signed in to change notification settings - Fork 16
CommandPropsBuilder
Command wiki page introduced that any implementation of sarah.Command
interface can be a command. That is the simplest form of sarah.Command
creation. Use of sarah.CommandPropsBuilder
is an alternate to construct sarah.Command
on the fly. Its goal is...
- to validate input and create a non-contradicting set of arguments to construct
sarah.Command
- to ease
sarah.Command
creation by providing handy builder method without damaging customizability
To use Live Configuration Update, the use of sarah.CommandProps
returned from CommandPropsBuilder.Build
is required. This is covered in the later section.
Here is the simplest form of sarah.CommandPropsBuilder
usage.
// This is a simple command that echos whenever user input starts with ".echo".
var matchPattern = regexp.MustCompile(`^\.echo`)
var SlackProps = sarah.NewCommandPropsBuilder().
BotType(slack.SLACK).
Identifier("echo").
InstructionFunc(func(_ *sarah.HelpInput) string {
return `Input .echo "foo" to get "foo"`
}).
MatchPattern(matchPattern).
Func(func(_ context.Context, input sarah.Input) (*sarah.CommandResponse, error) {
// ".echo foo" to "foo"
return slack.NewStringResponse(sarah.StripMessage(matchPattern, input.Message())), nil
}).
MustBuild()
Use CommandPropsBuilder.MatchFunc
instead of CommandPropsBuilder.MatchPattern
like below to have more customized input matching. With this setting the whole sarah.Input
can be passed on matching.
func isAdminRoom(input sarah.Input) bool {
// Do something with input to
return string(input.ReplyTo()) == "#admin"
}
var slackProps = sarah.NewCommandPropsBuilder().
BotType(slack.SLACK).
Identifier("morning").
InstructionFunc(func(input *sarah.HelpInput) string {
// 1. See if the input is from a privileged room.
// If not return empty string so the instruction is not returned to the non-admin user.
if !isAdminRoom(input) {
return ""
}
return `Input ".morning" to greet.`
}).
MatchFunc(func(input sarah.Input) bool {
// 1. See if the input is from a privileged room.
if !isAdminRoom(input) {
return false
}
// 2. See if the input message starts with ".morning"
match := strings.HasPrefix(input.Message(), ".morning")
if !match {
return false
}
// 3. See if current time between 00:00 - 11:59
hour := time.Now().Hour()
return hour >= 0 && hour < 12
}).
Func(func(_ context.Context, _ sarah.Input) (*sarah.CommandResponse, error) {
return slack.NewStringResponse("Good morning."), nil
}).
MustBuild()
sarah.RegisterCommandProps(slackProps)
Live Configuration Update feature detects configuration file update event, and applies changes to corresponding configuration struct. During this process, sarah.Command
is re-built. Since sarah.CommandProps
represents a non-contradicting set of arguments, sarah.Runner
does not have to worry about arguments' inconsistency.
// When config is passed to ConfigurableFunc and if sarah.Config.PluginConfigRoot is defined,
// sarah.Runner's internal watcher, sarah.Watcher implementation, supervises config directory to re-configure on file update event.
// File located at sarah.Config.PluginConfigRoot + "/" + BotType + "/" Identifier ".(yaml|yml|json) is subject to supervise.
config := &myConfig{}
var slackProps = sarah.NewCommandPropsBuilder().
BotType(slack.SLACK).
Identifier("morning").
InstructionFunc(func(input *sarah.HelpInput) string {
return `Input ".morning" to greet`
}).
MatchFunc(func(input sarah.Input) bool {
return input.Message() == ".morning"
}).
ConfigurableFunc(config, func(_ context.Context, _ sarah.Input, cfg sarah.CommandConfig) (*sarah.CommandResponse, error) {
typedConfig := cfg.(*myConfig)
return slack.NewStringResponse(typedConfig.Foo), nil
}).
MustBuild()
sarah.RegisterCommandProps(slackProps)
On CommandPropsBuilder.Build
or CommandPropsBuilder.MustBuild
, previously given arguments are validated and, if they are valid, an instance that represents a non-contradicting set of arguments to construct sarah.Command
is returned. That is sarah.CommandProps
. This can be passed to sarah.Runner
as sarah.RunnerOption
.
While sarah.Command
can be directly added to sarah.Bot
via Bot.AppendCommand
, sarah.CommandProps
is passed to sarah.Runner
. This is because sarah.Runner
is responsible for managing other components' life cycle.
var matchPattern = regexp.MustCompile(`^\.echo`)
var props = sarah.NewCommandPropsBuilder().
BotType(slack.SLACK).
Identifier("echo").
InstructionFunc(func(input *sarah.HelpInput) string {
return `Send ".echo knock knock" and see what happens.`
}).
MatchPattern(matchPattern).
Func(func(_ context.Context, input sarah.Input) (*sarah.CommandResponse, error) {
// ".echo foo" to "foo"
return slack.NewStringResponse(sarah.StripMessage(matchPattern, input.Message())), nil
}).
MustBuild()
sarah.RegisterCommandProps(props)
To have a grasp of overall architecture, have a look at Components.