Skip to content

CommandPropsBuilder

Oklahomer edited this page Mar 11, 2018 · 4 revisions

Its Goal

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 later section.

Usage

Basic

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").
        InputExample(".echo knock knock").
        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()

Customized User Input Matching

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.

var SlackProps = sarah.NewCommandPropsBuilder().
	BotType(slack.SLACK).
	Identifier("morning").
	InputExample(".morning").
	MatchFunc(func(input sarah.Input) bool {
		// 1. See if the input message starts with ".morning"
		match := strings.HasPrefix(input.Message(), ".morning")
		if !match {
			return false
		}

		// 2. 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()

Live Configuration Update

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").
	InputExample(".morning").
	MatchFunc(func(input sarah.Input) bool {
		return true
	}).
	ConfigurableFunc(config, func(_ context.Context, _ sarah.Input, cfg sarah.CommandConfig) (*sarah.CommandResponse, error) {
		typedConfig := cfg.(*myConfig)
		return slack.NewStringResponse(typedConfig.Foo), nil
	}).
	MustBuild()

Returned sarah.CommandProps

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").
        InputExample(".echo knock knock").
        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()

runner, _ := sarah.NewRunner(config, sarah.WithCommandProps(props))
runner.Run(context.TODO())
Clone this wiki locally