Documentation ¶
Overview ¶
Package sarah is a general purpose bot framework that comes with set of utility packages.
Index ¶
- Variables
- func NewBlockedInputError(i int) error
- func NewBotNonContinuableError(errorContent string) error
- func StripMessage(pattern *regexp.Regexp, input string) string
- type AbortInput
- type Adapter
- type Alerter
- type BlockedInputError
- type Bot
- type BotNonContinuableError
- type BotStatus
- type BotType
- type CacheConfig
- type Command
- type CommandConfig
- type CommandHelp
- type CommandHelps
- type CommandProps
- type CommandPropsBuilder
- func (builder *CommandPropsBuilder) BotType(botType BotType) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) Build() (*CommandProps, error)
- func (builder *CommandPropsBuilder) ConfigurableFunc(config CommandConfig, ...) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) Func(fn func(context.Context, Input) (*CommandResponse, error)) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) Identifier(id string) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) InputExample(example string) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) MatchFunc(matchFunc func(Input) bool) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) MatchPattern(pattern *regexp.Regexp) *CommandPropsBuilder
- func (builder *CommandPropsBuilder) MustBuild() *CommandProps
- type CommandResponse
- type Commands
- type Config
- type ContextualFunc
- type DefaultBotOption
- type DestinatedConfig
- type HelpInput
- type Input
- type Output
- type OutputDestination
- type OutputMessage
- type Runner
- type RunnerOption
- func WithAlerter(alerter Alerter) RunnerOption
- func WithBot(bot Bot) RunnerOption
- func WithCommandProps(props *CommandProps) RunnerOption
- func WithScheduledTask(botType BotType, task ScheduledTask) RunnerOption
- func WithScheduledTaskProps(props *ScheduledTaskProps) RunnerOption
- func WithWatcher(watcher watchers.Watcher) RunnerOption
- func WithWorker(worker workers.Worker) RunnerOption
- type RunnerOptions
- type ScheduledConfig
- type ScheduledTask
- type ScheduledTaskProps
- type ScheduledTaskPropsBuilder
- func (builder *ScheduledTaskPropsBuilder) BotType(botType BotType) *ScheduledTaskPropsBuilder
- func (builder *ScheduledTaskPropsBuilder) Build() (*ScheduledTaskProps, error)
- func (builder *ScheduledTaskPropsBuilder) ConfigurableFunc(config TaskConfig, ...) *ScheduledTaskPropsBuilder
- func (builder *ScheduledTaskPropsBuilder) DefaultDestination(dest OutputDestination) *ScheduledTaskPropsBuilder
- func (builder *ScheduledTaskPropsBuilder) Func(fn func(context.Context) ([]*ScheduledTaskResult, error)) *ScheduledTaskPropsBuilder
- func (builder *ScheduledTaskPropsBuilder) Identifier(id string) *ScheduledTaskPropsBuilder
- func (builder *ScheduledTaskPropsBuilder) MustBuild() *ScheduledTaskProps
- func (builder *ScheduledTaskPropsBuilder) Schedule(schedule string) *ScheduledTaskPropsBuilder
- type ScheduledTaskResult
- type SerializableArgument
- type Status
- type TaskConfig
- type UserContext
- type UserContextStorage
Constants ¶
This section is empty.
Variables ¶
var ( // ErrTaskInsufficientArgument is returned when required parameters are not set. ErrTaskInsufficientArgument = errors.New("one or more of required fields -- BotType, Identifier or Func -- are empty") // ErrTaskScheduleNotGiven is returned when schedule is provided by neither ScheduledTaskPropsBuilder's parameter nor config. ErrTaskScheduleNotGiven = errors.New("task schedule is not set or given from config struct") )
var ( // ErrCommandInsufficientArgument depicts an error that not enough arguments are set to CommandProps. // This is returned on CommandProps.Build() inside of runner.Run() ErrCommandInsufficientArgument = errors.New("BotType, Identifier, InputExample, MatchFunc, and (Configurable)Func must be set.") )
Functions ¶
func NewBlockedInputError ¶
NewBlockedInputError creates and return new BlockedInputError instance.
func NewBotNonContinuableError ¶
NewBotNonContinuableError creates and return new BotNonContinuableError instance.
Types ¶
type AbortInput ¶
type AbortInput struct {
// contains filtered or unexported fields
}
AbortInput is a common Input implementation that represents user's request for context cancellation. When this type is given, each Bot/Adapter implementation should cancel and remove corresponding user's conversational context.
func NewAbortInput ¶
func NewAbortInput(senderKey, message string, sentAt time.Time, replyTo OutputDestination) *AbortInput
NewAbortInput creates a new AbortInput instance with given arguments and returns it.
func (*AbortInput) ReplyTo ¶
func (ai *AbortInput) ReplyTo() OutputDestination
ReplyTo returns slack channel to send reply to.
func (*AbortInput) SenderKey ¶
func (ai *AbortInput) SenderKey() string
SenderKey returns string representing message sender.
func (*AbortInput) SentAt ¶
func (ai *AbortInput) SentAt() time.Time
SentAt returns message event's timestamp.
type Adapter ¶
type Adapter interface { // BotType represents what this Bot implements. e.g. slack, gitter, cli, etc... // This can be used as a unique ID to distinguish one from another. BotType() BotType // Run is called on Runner.Run by wrapping bot instance. // On this call, start interacting with corresponding service provider. // This may run in a blocking manner til given context is canceled since a new goroutine is allocated for this task. // When the service provider sends message to us, convert that message payload to Input and send to Input channel. // Runner will receive the Input instance and proceed to find and execute corresponding command. Run(context.Context, func(Input) error, func(error)) // SendMessage sends message to corresponding service provider. // This can be called by scheduled task or in response to input from service provider. // Be advised: this method may be called simultaneously from multiple workers. SendMessage(context.Context, Output) }
Adapter defines interface that each bot adapter implementation has to satisfy. Instance of its concrete struct and series of sarah.DefaultBotOptions can be fed to defaultBot via sarah.NewBot() to have sarah.Bot. Returned bot instance can be fed to Runner to have its life cycle managed.
type Alerter ¶
type Alerter interface { // Alert sends notification to developer/administrator so one may notify Bot's critical state. Alert(context.Context, BotType, error) error }
Alerter can be used to report Bot's critical state to developer/administrator. Anything that implements this interface can be registered as Alerter via Runner.RegisterAlerter.
type BlockedInputError ¶
type BlockedInputError struct {
ContinuationCount int
}
BlockedInputError indicates incoming input is blocked due to lack of resource. Excessive increase in message volume may result in this error. When this error occurs, Runner does not wait to enqueue input, but just skip the overflowing message and proceed.
Possible cure includes having more workers and/or more worker queue size, but developers MUST aware that this modification may cause more concurrent Command.Execute and Bot.SendMessage operation. With that said, increase workers by setting bigger number to worker.Config.WorkerNum to allow more concurrent executions and minimize the delay; increase worker queue size by setting bigger number to worker.Config.QueueSize to allow delay and have same concurrent execution number.
func (BlockedInputError) Error ¶
func (e BlockedInputError) Error() string
Error returns the detailed error about this blocking situation including the number of continuous occurrence. Do err.(*BlockedInputError).ContinuationCount to get the number of continuous occurrence. e.g. log if the remainder of this number divided by N is 0 to avoid excessive logging.
type Bot ¶
type Bot interface { // BotType represents what this Bot implements. e.g. slack, gitter, cli, etc... // This can be used as a unique ID to distinguish one from another. BotType() BotType // Respond receives user input, look for corresponding command, execute it, and send result back to user if possible. Respond(context.Context, Input) error // SendMessage sends message to destination depending on the Bot implementation. // This is mainly used to send scheduled task's result. // Be advised: this method may be called simultaneously from multiple workers. SendMessage(context.Context, Output) // AppendCommand appends given Command implementation to Bot internal stash. // Stashed commands are checked against user input in Bot.Respond, and if Command.Match returns true, the // Command is considered as "corresponds" to the input, hence its Command.Execute is called and the result is // sent back to user. AppendCommand(Command) // Run is called on Runner.Run to let this Bot interact with corresponding service provider. // For example, this is where Bot or Bot's corresponding Adapter initiates connection with service provider. // This may run in a blocking manner til given context is canceled since a new goroutine is allocated for this task. // When the service provider sends message to us, convert that message payload to Input and send to Input channel. // Runner will receive the Input instance and proceed to find and execute corresponding command. Run(context.Context, func(Input) error, func(error)) }
Bot provides interface for each bot implementation. Instance of concrete type can be fed to sarah.Runner to have its lifecycle under control. Multiple Bot implementation may be registered to single Runner.
func NewBot ¶
func NewBot(adapter Adapter, options ...DefaultBotOption) (Bot, error)
NewBot creates and returns new defaultBot instance with given Adapter. While Adapter takes care of actual collaboration with each chat service provider, defaultBot takes care of some common tasks including:
- receive Input
- see if sending user is in the middle of conversational context
- if so, execute the next step with given Input
- if not, find corresponding Command for given Input and execute it
- call Adapter.SendMessage to send output
The aim of defaultBot is to lessen the tasks of Adapter developer by providing some common tasks' implementations, and achieve easier creation of Bot implementation. Hence this method returns Bot interface instead of any concrete instance so this can be ONLY treated as Bot implementation to be fed to Runner.RegisterBot.
Some optional settings can be supplied by passing sarah.WithStorage and others that return DefaultBotOption.
// Use pre-defined storage. storage := sarah.NewUserContextStorage(sarah.NewCacheConfig()) bot, err := sarah.NewBot(myAdapter, sarah.WithStorage(sarah.NewUserContextStorage(sarah.NewCacheConfig())))
It is highly recommended to provide concrete implementation of sarah.UserContextStorage, so the users' conversational context can be stored and executed on next Input. sarah.userContextStorage is provided by default to store user context in memory. This storage can be initialized by sarah.NewUserContextStorage like above example.
type BotNonContinuableError ¶
type BotNonContinuableError struct {
// contains filtered or unexported fields
}
BotNonContinuableError represents critical error that Bot can't continue its operation. When Runner receives this, it must stop corresponding Bot, and should inform administrator by available mean.
func (BotNonContinuableError) Error ¶
func (e BotNonContinuableError) Error() string
Error returns detailed error about Bot's non-continuable state.
type BotType ¶
type BotType string
BotType indicates what bot implementation a particular Bot/Plugin is corresponding to.
type CacheConfig ¶
type CacheConfig struct { ExpiresIn time.Duration `json:"expires_in" yaml:"expires_in"` CleanupInterval time.Duration `json:"cleanup_interval" yaml:"cleanup_interval"` }
CacheConfig contains some configuration variables for cache mechanism.
func NewCacheConfig ¶
func NewCacheConfig() *CacheConfig
NewCacheConfig creates and returns new CacheConfig instance with default settings. Use json.Unmarshal, yaml.Unmarshal, or manual manipulation to overload default values.
type Command ¶
type Command interface { // Identifier returns unique id that represents this Command. Identifier() string // Execute receives input from user and returns response. Execute(context.Context, Input) (*CommandResponse, error) // InputExample returns example of user input. This should be used to provide command usage for end users. InputExample() string // Match is used to judge if this command corresponds to given user input. // If this returns true, Bot implementation should proceed to Execute with current user input. Match(Input) bool }
Command defines interface that all command MUST satisfy.
type CommandConfig ¶
type CommandConfig interface{}
CommandConfig provides an interface that every command configuration must satisfy, which actually means empty.
type CommandHelp ¶
CommandHelp represents help messages for corresponding Command.
type CommandHelps ¶
type CommandHelps []*CommandHelp
CommandHelps is an alias to slice of CommandHelps' pointers.
type CommandProps ¶
type CommandProps struct {
// contains filtered or unexported fields
}
CommandProps is a designated non-serializable configuration struct to be used in Command construction. This holds relatively complex set of Command construction arguments that should be treated as one in logical term.
type CommandPropsBuilder ¶
type CommandPropsBuilder struct {
// contains filtered or unexported fields
}
CommandPropsBuilder helps to construct CommandProps. Developer may set desired property as she goes and call CommandPropsBuilder.Build or CommandPropsBuilder.MustBuild to construct CommandProps at the end. A validation logic runs on build, so the returning CommandProps instant is safe to be passed to Runner.
func NewCommandPropsBuilder ¶
func NewCommandPropsBuilder() *CommandPropsBuilder
NewCommandPropsBuilder returns new CommandPropsBuilder instance.
func (*CommandPropsBuilder) BotType ¶
func (builder *CommandPropsBuilder) BotType(botType BotType) *CommandPropsBuilder
BotType is a setter to provide belonging BotType.
func (*CommandPropsBuilder) Build ¶
func (builder *CommandPropsBuilder) Build() (*CommandProps, error)
Build builds new CommandProps instance with provided values.
func (*CommandPropsBuilder) ConfigurableFunc ¶
func (builder *CommandPropsBuilder) ConfigurableFunc(config CommandConfig, fn func(context.Context, Input, CommandConfig) (*CommandResponse, error)) *CommandPropsBuilder
ConfigurableFunc is a setter to provide command function. While Func let developers set simple function, this allows them to provide function that requires some sort of configuration struct. On Runner.Run configuration is read from YAML/JSON file located at /path/to/config/dir/{commandIdentifier}.(yaml|yml|json) and mapped to given CommandConfig struct. If no YAML/JSON file is found, runner considers the given CommandConfig is fully configured and ready to use. This configuration struct is passed to command function as its third argument.
func (*CommandPropsBuilder) Func ¶
func (builder *CommandPropsBuilder) Func(fn func(context.Context, Input) (*CommandResponse, error)) *CommandPropsBuilder
Func is a setter to provide command function that requires no configuration. If ConfigurableFunc and Func are both called, later call overrides the previous one.
func (*CommandPropsBuilder) Identifier ¶
func (builder *CommandPropsBuilder) Identifier(id string) *CommandPropsBuilder
Identifier is a setter for Command identifier.
func (*CommandPropsBuilder) InputExample ¶
func (builder *CommandPropsBuilder) InputExample(example string) *CommandPropsBuilder
InputExample is a setter to provide example of command execution. This should be used to provide command usage for end users.
func (*CommandPropsBuilder) MatchFunc ¶
func (builder *CommandPropsBuilder) MatchFunc(matchFunc func(Input) bool) *CommandPropsBuilder
MatchFunc is a setter to provide a function that judges if an incoming input "matches" to this Command. When this returns true, this Command is considered as "corresponding to user input" and becomes Command execution candidate.
MatchPattern may be used to specify a regular expression that is checked against user input, Input.Message(); MatchFunc can specify more customizable matching logic. e.g. only return true on specific sender's specific message on specific time range.
func (*CommandPropsBuilder) MatchPattern ¶
func (builder *CommandPropsBuilder) MatchPattern(pattern *regexp.Regexp) *CommandPropsBuilder
MatchPattern is a setter to provide command match pattern. This regular expression is used to find matching command with given Input.
Use MatchFunc to set more customizable matching logic.
func (*CommandPropsBuilder) MustBuild ¶
func (builder *CommandPropsBuilder) MustBuild() *CommandProps
MustBuild is like Build but panics if any error occurs on Build. It simplifies safe initialization of global variables holding built CommandProps instances.
type CommandResponse ¶
type CommandResponse struct { Content interface{} UserContext *UserContext }
CommandResponse is returned by Command or Task when the execution is finished.
func NewSuppressedResponseWithNext ¶
func NewSuppressedResponseWithNext(next ContextualFunc) *CommandResponse
NewSuppressedResponseWithNext creates new sarah.CommandResponse instance with no message and next function to continue
type Commands ¶
type Commands struct {
// contains filtered or unexported fields
}
Commands stashes all registered Command.
func NewCommands ¶
func NewCommands() *Commands
NewCommands creates and returns new Commands instance.
func (*Commands) Append ¶
Append let developers register new Command to its internal stash. If any command is registered with the same ID, the old one is replaced in favor of new one.
func (*Commands) ExecuteFirstMatched ¶
func (commands *Commands) ExecuteFirstMatched(ctx context.Context, input Input) (*CommandResponse, error)
ExecuteFirstMatched tries find matching command with the given input, and execute it if one is available.
func (*Commands) FindFirstMatched ¶
FindFirstMatched look for first matching command by calling Command's Match method: First Command.Match to return true is considered as "first matched" and is returned.
This check is run in the order of Command registration: Earlier the Commands.Append is called, the command is checked earlier. So register important Command first.
func (*Commands) Helps ¶
func (commands *Commands) Helps() *CommandHelps
Helps returns underlying commands help messages in a form of *CommandHelps.
type Config ¶
type Config struct { PluginConfigRoot string `json:"plugin_config_root" yaml:"plugin_config_root"` TimeZone string `json:"timezone" yaml:"timezone"` }
Config contains some configuration variables for Runner.
type ContextualFunc ¶
type ContextualFunc func(context.Context, Input) (*CommandResponse, error)
ContextualFunc defines a function signature that defines user's next step. When a function or instance method is given as CommandResponse.Next, Bot implementation must store this with Input.SenderKey. On user's next input, inside of Bot.Respond, Bot retrieves stored ContextualFunc and execute this. If CommandResponse.Next is given again as part of result, the same step must be followed.
type DefaultBotOption ¶
type DefaultBotOption func(bot *defaultBot) error
DefaultBotOption defines function that defaultBot's functional option must satisfy.
func BotWithStorage ¶
func BotWithStorage(storage UserContextStorage) DefaultBotOption
BotWithStorage creates and returns DefaultBotOption to set preferred UserContextStorage implementation. Below example utilizes pre-defined in-memory storage.
config := sarah.NewCacheConfig() configBuf, _ := ioutil.ReadFile("/path/to/storage/config.yaml") yaml.Unmarshal(configBuf, config) bot, err := sarah.NewBot(myAdapter, storage)
type DestinatedConfig ¶
type DestinatedConfig interface {
DefaultDestination() OutputDestination
}
DestinatedConfig defines an interface that config with default destination MUST satisfy. When no default output destination is set with ScheduledTaskPropsBuilder.DefaultDestination, this value is taken as default on ScheduledTaskPropsBuilder.Build.
type HelpInput ¶
type HelpInput struct {
// contains filtered or unexported fields
}
HelpInput is a common Input implementation that represents user's request for help. When this type is given, each Bot/Adapter implementation should list up registered Commands' input examples, and send them back to user.
func NewHelpInput ¶
func NewHelpInput(senderKey, message string, sentAt time.Time, replyTo OutputDestination) *HelpInput
NewHelpInput creates a new HelpInput instance with given arguments and returns it.
func (*HelpInput) ReplyTo ¶
func (hi *HelpInput) ReplyTo() OutputDestination
ReplyTo returns slack channel to send reply to.
type Input ¶
type Input interface { // SenderKey returns the text form of sender identifier. // This value can be used internally as a key to store the sender's conversational context in UserContextStorage. // Generally, When connecting chat service has the concept of group or chat room, // this sender key should contain the group/room identifier along with user identifier // so the user's conversational context is only applied in the exact same group/room. // // e.g. senderKey := fmt.Sprintf("%d_%d", roomID, userID) SenderKey() string // Message returns the text form of user input. // This may return empty string when this Input implementation represents non-text payload such as photo, // video clip or file. Message() string // SentAt returns the timestamp when the message is sent. // This may return a message reception time if the connecting chat service does not provide one. // e.g. XMPP server only provides timestamp as part of XEP-0203 when delayed message is delivered. SentAt() time.Time // ReplyTo returns the sender's address or location to be used to reply message. // This may be passed to Bot.SendMessage() as part of Output value to specify the sending destination. // This typically contains chat room, member id or mail address. // e.g. JID of XMPP server/client. ReplyTo() OutputDestination }
Input defines interface that each incoming message must satisfy. Each Bot/Adapter implementation may define customized Input implementation for each messaging content.
See slack.MessageInput.
type Output ¶
type Output interface { Destination() OutputDestination Content() interface{} }
Output defines interface that each outgoing message must satisfy.
func NewOutputMessage ¶
func NewOutputMessage(destination OutputDestination, content interface{}) Output
NewOutputMessage creates and returns new OutputMessage instance. This satisfies Output interface so can be passed to Bot.SendMessage.
type OutputDestination ¶
type OutputDestination interface{}
OutputDestination defines interface that every Bot/Adapter MUST satisfy to represent where the sending message is heading to, which actually means empty interface.
type OutputMessage ¶
type OutputMessage struct {
// contains filtered or unexported fields
}
OutputMessage represents outgoing message.
func (*OutputMessage) Content ¶
func (output *OutputMessage) Content() interface{}
Content returns sending content. This is just an empty interface, so each Bot/Adapter developer may define depending on whatever the struct should contain.
func (*OutputMessage) Destination ¶
func (output *OutputMessage) Destination() OutputDestination
Destination returns its destination in a form of OutputDestination interface. Each Bot/Adapter implementation must explicitly define destination type that satisfies OutputDestination.
type Runner ¶
type Runner interface { // Run starts Bot interaction. // At this point Runner starts its internal workers and schedulers, runs each bot, and starts listening to incoming messages. Run(context.Context) // Status returns the status of Runner and belonging Bots. // The returned Status value represents a snapshot of the status when this method is called, // which means each field value is not subject to update. // To reflect the latest status, this is recommended to call this method whenever the value is needed. Status() Status }
Runner is the core of sarah.
This is responsible for each Bot implementation's lifecycle and plugin execution; Bot is responsible for bot-specific implementation such as connection handling, message reception and sending.
Developers can register desired number of Bots and Commands to create own bot experience. While developers may provide own implementation for interfaces in this project to customize behavior, this particular interface is not meant to be implemented and replaced. See https://github.com/oklahomer/go-sarah/pull/47
func NewRunner ¶
func NewRunner(config *Config, options ...RunnerOption) (Runner, error)
NewRunner creates and return new instance that satisfies Runner interface.
The reason for returning interface instead of concrete implementation is to avoid developers from executing RunnerOption outside of NewRunner, where sarah can not be aware of and severe side-effect may occur.
Ref. https://github.com/oklahomer/go-sarah/pull/47
So the aim is not to let developers switch its implementations.
type RunnerOption ¶
type RunnerOption func(*runner) error
RunnerOption defines a function signature that NewRunner's functional option must satisfy.
func WithAlerter ¶
func WithAlerter(alerter Alerter) RunnerOption
WithAlerter creates RunnerOperation that feeds given Alerter implementation to Runner.
func WithBot ¶
func WithBot(bot Bot) RunnerOption
WithBot creates RunnerOption that feeds given Bot implementation to Runner.
func WithCommandProps ¶
func WithCommandProps(props *CommandProps) RunnerOption
WithCommandProps creates RunnerOption that feeds given CommandProps to Runner. Command is built on runner.Run with given CommandProps. This props is re-used when configuration file is updated and Command needs to be re-built.
func WithScheduledTask ¶
func WithScheduledTask(botType BotType, task ScheduledTask) RunnerOption
WithScheduledTask creates RunnerOperation that feeds given ScheduledTask to Runner.
func WithScheduledTaskProps ¶
func WithScheduledTaskProps(props *ScheduledTaskProps) RunnerOption
WithScheduledTaskProps creates RunnerOption that feeds given ScheduledTaskProps to Runner. ScheduledTask is built on runner.Run with given ScheduledTaskProps. This props is re-used when configuration file is updated and ScheduledTask needs to be re-built.
func WithWatcher ¶
func WithWatcher(watcher watchers.Watcher) RunnerOption
WithWatcher creates RunnerOption that feeds given Watcher implementation to Runner. If Config.PluginConfigRoot is set without WithWatcher option, Runner creates Watcher with default configuration on Runner.Run.
func WithWorker ¶
func WithWorker(worker workers.Worker) RunnerOption
WithWorker creates RunnerOperation that feeds given Worker implementation to Runner. If no WithWorker is supplied, Runner creates worker with default configuration on runner.Run.
type RunnerOptions ¶
type RunnerOptions []RunnerOption
RunnerOptions stashes group of RunnerOption for later use with NewRunner().
On typical setup, especially when a process consists of multiple Bots and Commands, each construction step requires more lines of codes. Each step ends with creating new RunnerOption instance to be fed to NewRunner(), but as code gets longer it gets harder to keep track of each RunnerOption. In that case RunnerOptions becomes a handy helper to temporary stash RunnerOption.
options := NewRunnerOptions() // 5-10 lines of codes to configure Slack bot. slackBot, _ := sarah.NewBot(slack.NewAdapter(slackConfig), sarah.BotWithStorage(storage)) options.Append(sarah.WithBot(slackBot)) // Here comes other 5-10 codes to configure another bot. myBot, _ := NewMyBot(...) optionsAppend(sarah.WithBot(myBot)) // Some more codes to register Commands/ScheduledTasks. myTask := customizedTask() options.Append(sarah.WithScheduledTask(myTask)) // Finally feed stashed options to NewRunner at once runner, _ := NewRunner(sarah.NewConfig(), options.Arg()) runner.Run(ctx)
func NewRunnerOptions ¶
func NewRunnerOptions() *RunnerOptions
NewRunnerOptions creates and returns new RunnerOptions instance.
func (*RunnerOptions) Append ¶
func (options *RunnerOptions) Append(opt RunnerOption)
Append adds given RunnerOption to internal stash. When more than two RunnerOption instances are stashed, they are executed in the order of addition.
func (*RunnerOptions) Arg ¶
func (options *RunnerOptions) Arg() RunnerOption
Arg returns stashed RunnerOptions in a form that can be directly fed to NewRunner's second argument.
type ScheduledConfig ¶
type ScheduledConfig interface {
Schedule() string
}
ScheduledConfig defines an interface that config with schedule MUST satisfy. When no execution schedule is set with ScheduledTaskPropsBuilder.Schedule, this value is taken as default on ScheduledTaskPropsBuilder.Build.
type ScheduledTask ¶
type ScheduledTask interface { Identifier() string Execute(context.Context) ([]*ScheduledTaskResult, error) DefaultDestination() OutputDestination Schedule() string }
ScheduledTask defines interface that all scheduled task MUST satisfy. As long as a struct satisfies this interface, the struct can be registered as ScheduledTask via Runner.RegisterScheduledTask.
type ScheduledTaskProps ¶
type ScheduledTaskProps struct {
// contains filtered or unexported fields
}
ScheduledTaskProps is a designated non-serializable configuration struct to be used in ScheduledTask construction. This holds relatively complex set of ScheduledTask construction arguments that should be treated as one in logical term.
type ScheduledTaskPropsBuilder ¶
type ScheduledTaskPropsBuilder struct {
// contains filtered or unexported fields
}
ScheduledTaskPropsBuilder helps to construct ScheduledTaskProps. Developer may set desired property as she goes and call ScheduledTaskPropsBuilder.Build or ScheduledTaskPropsBuilder.MustBuild to construct ScheduledTaskProps at the end. A validation logic runs on build, so the returning ScheduledTaskProps instant is safe to be passed to Runner.
func NewScheduledTaskPropsBuilder ¶
func NewScheduledTaskPropsBuilder() *ScheduledTaskPropsBuilder
NewScheduledTaskPropsBuilder creates and returns ScheduledTaskPropsBuilder instance.
func (*ScheduledTaskPropsBuilder) BotType ¶
func (builder *ScheduledTaskPropsBuilder) BotType(botType BotType) *ScheduledTaskPropsBuilder
BotType is a setter to provide belonging BotType.
func (*ScheduledTaskPropsBuilder) Build ¶
func (builder *ScheduledTaskPropsBuilder) Build() (*ScheduledTaskProps, error)
Build builds new ScheduledProps instance with provided values.
func (*ScheduledTaskPropsBuilder) ConfigurableFunc ¶
func (builder *ScheduledTaskPropsBuilder) ConfigurableFunc(config TaskConfig, fn func(context.Context, TaskConfig) ([]*ScheduledTaskResult, error)) *ScheduledTaskPropsBuilder
ConfigurableFunc sets function for ScheduledTask with configuration struct. Passed configuration struct is passed to function as a third argument.
When resulting ScheduledTaskProps is passed to sarah.NewRunner() as part of sarah.WithScheduledTaskProps and Runner runs with Config.PluginConfigRoot, configuration struct gets updated automatically when corresponding configuration file is updated.
func (*ScheduledTaskPropsBuilder) DefaultDestination ¶
func (builder *ScheduledTaskPropsBuilder) DefaultDestination(dest OutputDestination) *ScheduledTaskPropsBuilder
DefaultDestination sets default output destination of this task. OutputDestination returned by task execution has higher priority.
func (*ScheduledTaskPropsBuilder) Func ¶
func (builder *ScheduledTaskPropsBuilder) Func(fn func(context.Context) ([]*ScheduledTaskResult, error)) *ScheduledTaskPropsBuilder
Func sets function to be called on task execution. To set function that requires some sort of configuration struct, use ConfigurableFunc.
func (*ScheduledTaskPropsBuilder) Identifier ¶
func (builder *ScheduledTaskPropsBuilder) Identifier(id string) *ScheduledTaskPropsBuilder
Identifier sets unique ID of this task. This is used to identify re-configure tasks and replace old ones.
func (*ScheduledTaskPropsBuilder) MustBuild ¶
func (builder *ScheduledTaskPropsBuilder) MustBuild() *ScheduledTaskProps
MustBuild is like Build, but panics if any error occurs on Build. It simplifies safe initialization of global variables holding built ScheduledTaskProps instances.
func (*ScheduledTaskPropsBuilder) Schedule ¶
func (builder *ScheduledTaskPropsBuilder) Schedule(schedule string) *ScheduledTaskPropsBuilder
Schedule sets execution schedule. Representation spec. is identical to that of github.com/robfig/cron.
type ScheduledTaskResult ¶
type ScheduledTaskResult struct { Content interface{} Destination OutputDestination }
ScheduledTaskResult is a struct that ScheduledTask returns on its execution.
type SerializableArgument ¶
type SerializableArgument struct { FuncIdentifier string Argument interface{} }
SerializableArgument defines user context data to be stored in external storage. This data is read from storage on next user input, deserialized, and executed to continue previous conversation.
type Status ¶ added in v1.5.0
Status represents the current status of the bot system including Runner and all registered Bots.
type TaskConfig ¶
type TaskConfig interface{}
TaskConfig provides an interface that every task configuration must satisfy, which actually means empty.
type UserContext ¶
type UserContext struct { // Next contains a function to be called on next user input. // Default implementation of UserContextStorage, defaultUserContextStorage, uses this to store conversational contexts. // // Since this is a plain function, this is stored in the exact same memory space the Bot is currently running, // which means this function can not be shared with other Bot instance or can not be stored in external storage such as Redis. // To store user context in externally, set Serializable to store serialized arguments in external storage. Next ContextualFunc // Serializable, on the other hand, contains arguments and function identifier to be stored in external storage. // When user input is given next time, serialized SerializableArgument is fetched from storage, deserialized, and fed to pre-registered function. // Pre-registered function is identified by SerializableArgument.FuncIdentifier. // A reference implementation is available at https://github.com/oklahomer/go-sarah-rediscontext Serializable *SerializableArgument }
UserContext represents a user's conversational context. If this is returned as part of CommandResponse, user is considered "in the middle of conversation," which means the next input of the user MUST be fed to a function declared in UserContext to continue the conversation. This has higher priority than finding and executing Command by checking Command.Match against Input.
Currently this structure supports two forms of context storage. See GitHub issue, https://github.com/oklahomer/go-sarah/issues/34, for detailed motives.
func NewUserContext ¶
func NewUserContext(next ContextualFunc) *UserContext
NewUserContext creates and returns new UserContext with given ContextualFunc. Once this instance is stored in Bot's internal storage, the next input from the same user must be fed to this ContextualFunc so the conversation continues.
type UserContextStorage ¶
type UserContextStorage interface { Get(string) (ContextualFunc, error) Set(string, *UserContext) error Delete(string) error Flush() error }
UserContextStorage defines an interface of Bot's storage mechanism for users' conversational contexts.
func NewUserContextStorage ¶
func NewUserContextStorage(config *CacheConfig) UserContextStorage
NewUserContextStorage creates and returns new defaultUserContextStorage instance to store users' conversational contexts.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package alerter and its sub packages provide alerting mechanisms that implement sarah.Alerter interface to inform bot's critical states to administrator.
|
Package alerter and its sub packages provide alerting mechanisms that implement sarah.Alerter interface to inform bot's critical states to administrator. |
line
Package line provides sarah.Alerter implementation for LINE Notify.
|
Package line provides sarah.Alerter implementation for LINE Notify. |
examples
|
|
simple
Package main provides a simple bot experience using slack.Adapter with multiple plugin commands and scheduled tasks.
|
Package main provides a simple bot experience using slack.Adapter with multiple plugin commands and scheduled tasks. |
simple/plugins/count
Package count provides example code to setup sarah.CommandProps.
|
Package count provides example code to setup sarah.CommandProps. |
simple/plugins/echo
Package echo provides example code to sarah.Command implementation.
|
Package echo provides example code to sarah.Command implementation. |
simple/plugins/fixedtimer
Package fixedtimer provides example code to setup ScheduledTaskProps with fixed schedule.
|
Package fixedtimer provides example code to setup ScheduledTaskProps with fixed schedule. |
simple/plugins/guess
Package guess provides example code to setup stateful command.
|
Package guess provides example code to setup stateful command. |
simple/plugins/hello
Package hello provides example code to setup relatively simple sarah.CommandProps.
|
Package hello provides example code to setup relatively simple sarah.CommandProps. |
simple/plugins/morning
Package morning provides example code to setup sarah.CommandProps with relatively complex matching function.
|
Package morning provides example code to setup sarah.CommandProps with relatively complex matching function. |
simple/plugins/timer
Package timer provides example code to setup ScheduledTaskProps with re-configurable schedule and sending room.
|
Package timer provides example code to setup ScheduledTaskProps with re-configurable schedule and sending room. |
simple/plugins/todo
Package todo is an example of stateful command that let users input required arguments step by step in a conversational manner.
|
Package todo is an example of stateful command that let users input required arguments step by step in a conversational manner. |
status
Package main provides an example that uses Runner.Status() to return current sarah.Runner and its belonging Bot status via HTTP server.
|
Package main provides an example that uses Runner.Status() to return current sarah.Runner and its belonging Bot status via HTTP server. |
Package gitter provides sarah.Adapter implementation for gitter.
|
Package gitter provides sarah.Adapter implementation for gitter. |
Package log provides logging mechanism including replaceable Logger interface and its default implementation.
|
Package log provides logging mechanism including replaceable Logger interface and its default implementation. |
Package plugins and its sub packages gives some reference implementations of sarah.Command.
|
Package plugins and its sub packages gives some reference implementations of sarah.Command. |
echo
Package echo is an reference implementation to provide the simplest form of sarah.CommandProps.
|
Package echo is an reference implementation to provide the simplest form of sarah.CommandProps. |
hello
Package hello is an reference implementation to provide the simplest form of sarah.CommandProps.
|
Package hello is an reference implementation to provide the simplest form of sarah.CommandProps. |
worldweather
Package worldweather is an reference implementation that provides relatively practical sarah.CommandProps.
|
Package worldweather is an reference implementation that provides relatively practical sarah.CommandProps. |
Package retry provides general retry logic and designated error structure that contains multiple errors.
|
Package retry provides general retry logic and designated error structure that contains multiple errors. |
Package slack provides sarah.Adapter implementation for Slack.
|
Package slack provides sarah.Adapter implementation for Slack. |
Package watchers provides mechanism to subscribe events under given directory.
|
Package watchers provides mechanism to subscribe events under given directory. |
Package workers provides general purpose worker mechanism that outputs stacktrace when given job panics.
|
Package workers provides general purpose worker mechanism that outputs stacktrace when given job panics. |