Documentation ¶
Overview ¶
Package bot provides the interfaces for creating a chatops bot.
Index ¶
- Variables
- func Log(l LogLevel, v ...interface{})
- func RegisterConnector(name string, connstarter func(Handler, *log.Logger) Connector)
- func RegisterElevator(name string, provider func(Handler) Elevate)
- func RegisterPlugin(name string, plug PluginHandler)
- func RegisterSimpleBrain(name string, provider func(Handler, *log.Logger) SimpleBrain)
- func Start()
- type AttrRet
- type Connector
- type Elevate
- type Handler
- type InputMatcher
- type LogLevel
- type Logger
- type MessageFormat
- type Plugin
- type PluginHandler
- type PluginHelp
- type RetVal
- type Robot
- func (r *Robot) CheckAdmin() bool
- func (r *Robot) CheckinDatum(key, locktoken string)
- func (r *Robot) CheckoutDatum(key string, datum interface{}, rw bool) (locktoken string, exists bool, ret RetVal)
- func (r *Robot) Direct() *Robot
- func (r *Robot) Elevate(immediate bool) bool
- func (r *Robot) Email(subject string, messageBody *bytes.Buffer) (ret RetVal)
- func (r *Robot) Fixed() *Robot
- func (r *Robot) GetBotAttribute(a string) *AttrRet
- func (r *Robot) GetPluginConfig(dptr interface{}) RetVal
- func (r *Robot) GetSenderAttribute(a string) *AttrRet
- func (r *Robot) GetUserAttribute(u, a string) *AttrRet
- func (r *Robot) Log(l LogLevel, v ...interface{})
- func (r *Robot) Pause(s float64)
- func (r *Robot) RandomInt(n int) int
- func (r *Robot) RandomString(s []string) string
- func (r *Robot) Recall(key string) string
- func (r *Robot) Remember(key, value string)
- func (r *Robot) RememberContext(context, value string)
- func (r *Robot) Reply(msg string) RetVal
- func (r *Robot) Say(msg string) RetVal
- func (r *Robot) SendChannelMessage(channel, msg string) RetVal
- func (r *Robot) SendUserChannelMessage(user, channel, msg string) RetVal
- func (r *Robot) SendUserMessage(user, msg string) RetVal
- func (r *Robot) UpdateDatum(key, locktoken string, datum interface{}) (ret RetVal)
- func (r *Robot) WaitForReply(regexID string, timeout int) (string, RetVal)
- func (r *Robot) WaitForReplyRegex(regex string, timeout int) (string, RetVal)
- type SimpleBrain
Constants ¶
This section is empty.
Variables ¶
var Version = "0.9.0-pre2"
Version is the current version of Gopherbot
Functions ¶
func Log ¶
func Log(l LogLevel, v ...interface{})
Log logs messages whenever the connector log level is less than the given level
func RegisterConnector ¶
RegisterConnector should be called in an init function to register a type of connector. Currently only Slack is implemented.
func RegisterElevator ¶
RegisterElevator allows elevate methods to register themselves.
func RegisterPlugin ¶
func RegisterPlugin(name string, plug PluginHandler)
RegisterPlugin allows plugins to register a PluginHandler in a func init(). When the bot initializes, it will call each plugin's handler with a command "init", empty channel, the bot's username, and no arguments, so the plugin can store this information for, e.g., scheduled jobs.
func RegisterSimpleBrain ¶
func RegisterSimpleBrain(name string, provider func(Handler, *log.Logger) SimpleBrain)
RegisterSimpleBrain allows brain implementations to register a function with a named brain type that returns an SimpleBrain interface. This can only be called from a brain provider's init() function(s). Pass in a Logger so the brain can log it's own error messages if needed.
Types ¶
type AttrRet ¶
AttrRet implements Stringer so it can be interpolated with fmt if the plugin author is ok with ignoring the RetVal.
type Connector ¶
type Connector interface { // GetProtocolUserAttribute retrieves a piece of information about a user // from the connector protocol, or "",!ok if the connector doesn't have the // information. Plugins should normally call GetUserAttribute, which // supplements protocol data with data from users.json. // The current attributes are: // email, realName, firstName, lastName, phone, sms, connections GetProtocolUserAttribute(user, attr string) (value string, ret RetVal) // JoinChannel joins a channel given it's human-readable name, e.g. "general" JoinChannel(c string) RetVal // SendProtocolChannelMessage sends a message to a channel SendProtocolChannelMessage(channelname, msg string, format MessageFormat) RetVal // SendProtocolUserChannelMessage directs a message to a user in a channel SendProtocolUserChannelMessage(user, channelname, msg string, format MessageFormat) RetVal // SendProtocolUserMessage sends a direct message to a user if supported. // For protocols not supportint DM, the bot should send a message addressed // to the user in an implementation-specific channel. SendProtocolUserMessage(user, msg string, format MessageFormat) RetVal // The Run method starts the main loop, and never returns; if it's // called a second time, it just returns. Run(stopchannel chan struct{}) }
Connector is the interface defining methods that should be provided by the connector for use by plugins/robot.
type Elevate ¶
Elevate is a configurable plugin function for elevating privileges. It take a Robot and bool indicating whether to always check regardless of any timeouts in effect. It returns a bool indicating success or failure.
type Handler ¶
type Handler interface { // IncomingMessage is called by the connector for all messages the bot // can hear. The channelName and userName should be human-readable, // not internal representations. If channelName is blank, it's a direct message IncomingMessage(channelName, userName, message string) // GetProtocolConfig unmarshals the ProtocolConfig section of gopherbot.json // into a connector-provided struct GetProtocolConfig(interface{}) error // GetBrainConfig unmarshals the BrainConfig section of gopherbot.json // into a struct provided by the brain provider GetBrainConfig(interface{}) error // GetElevateConfig unmarshals the ElevateConfig section of gopherbot.json // into a struct provided by the elevate provider GetElevateConfig(interface{}) error // SetFullName allows the connector to set the robot's full name if it // has access to it. SetFullName(n string) // SetName allows the connect to set the robot's name that it should be addressed // by, if it has access to it. SetName(n string) // GetLogLevel allows the connector to check the robot's configured log level // to make it's own decision about how much it should log. For slack, this // determines whether the plugin does api logging. GetLogLevel() LogLevel // GetInstallPath returns the installation path of the gopherbot GetInstallPath() string // GetLocalPath returns the path to the local config of the gopherbot GetLocalPath() string // Log provides a standard logging interface with a level as defined in // bot/logging.go Log(l LogLevel, v ...interface{}) }
Handler is the interface that defines the callback API for Connectors
type InputMatcher ¶
type InputMatcher struct { Regex string // The regular expression string to match - bot adds ^\w* & \w*$ Command string // The name of the command to pass to the plugin with it's arguments Label string // ReplyMatchers use "Label" instead of "Command" Contexts []string // label the contexts corresponding to capture groups, for supporting "it" & optional args // contains filtered or unexported fields }
InputMatcher specifies the command or message to match and what to pass to the plugin
type Logger ¶
type Logger interface {
Log(l LogLevel, v ...interface{})
}
Logger is used by a Brain for logging errors
type MessageFormat ¶
type MessageFormat int
MessageFormat indicates how the connector should display the content of the message. One of Variable, Fixed or Raw (To Be Implemented)
const ( Variable MessageFormat = iota // variable font width Fixed Raw )
Outgoing message format, Variable or Fixed
type Plugin ¶
type Plugin struct { Disabled bool // Set true to disable the plugin AllowDirect bool // Set this true if this plugin can be accessed via direct message DirectOnly bool // Set this true if this plugin ONLY accepts direct messages Channels []string // Channels where the plugin is active - rifraf like "memes" should probably only be in random, but it's configurable. If empty uses DefaultChannels AllChannels bool // If the Channels list is empty and AllChannels is true, the plugin should be active in all the channels the bot is in RequireAdmin bool // Set to only allow administrators to access a plugin ElevatedCommands []string // Commands that require elevation, usually via 2fa ElevateImmediateCommands []string // Commands that always require elevation promting, regardless of timeouts Users []string // If non-empty, list of all the users with access to this plugin Help []PluginHelp // All the keyword sets / help texts for this plugin CommandMatchers []InputMatcher // Input matchers for messages that need to be directed to the 'bot ReplyMatchers []InputMatcher // Input matchers for replies to questions, only match after a RequestContinuation MessageMatchers []InputMatcher // Input matchers for messages the 'bot hears even when it's not being spoken to CatchAll bool // Whenever the robot is spoken to, but no plugin matches, plugins with CatchAll=true get called with command="catchall" and argument=<full text of message to robot> Config json.RawMessage // Arbitrary Plugin configuration, will be stored and provided in a thread-safe manner via GetPluginConfig() // contains filtered or unexported fields }
Plugin specifies the structure of a plugin configuration - plugins should include an example / default config
type PluginHandler ¶
type PluginHandler struct { DefaultConfig string /* A yaml-formatted multiline string defining the default Plugin configuration. It should be liberally commented for use in generating local/custom configuration for the plugin. If a Config: section is defined, it should match the structure of the optional Config interface{} */ Handler func(bot *Robot, command string, args ...string) // The callback function called by the robot whenever a Command is matched Config interface{} // An optional empty struct defining custom configuration for the plugin }
PluginHandler is the struct a plugin registers for the Gopherbot plugin API.
type PluginHelp ¶
type PluginHelp struct { Keywords []string // match words for 'help XXX' Helptext []string // help string to give for the keywords, conventionally starting with (bot) for commands or (hear) when the bot needn't be addressed directly }
PluginHelp specifies keywords and help text for the 'bot help system
type RetVal ¶
type RetVal int
RetVal is a bit field for returning error conditions, or 0 for Ok
const ( // Ok indicates a successful result Ok RetVal = iota // success // UserNotFound - failed lookup UserNotFound // ChannelNotFound - failed lookup ChannelNotFound // AttributeNotFound - failed looking up user/robot attributes like email, name, etc. AttributeNotFound // FailedUserDM - the bot was not able to send an direct message (DM) to a given user FailedUserDM // FailedChannelJoin - the robot couldn't join a channel; e.g. slack doesn't allow bots to join FailedChannelJoin // DatumNotFound - key not found in the global hash when update called DatumNotFound // DatumLockExpired - A datum was checked out for too long, and the lock expired DatumLockExpired // DataFormatError - Problem unmarshalling JSON DataFormatError // BrainFailed - An error condition prevented the brain from storing/retrieving; redis down, file write failed, etc. BrainFailed // InvalidDatumKey - Key name didn't match the regex for valid key names InvalidDatumKey // InvalidDblPtr - GetPluginConfig wasn't called with a double-pointer to a config struct InvalidDblPtr // InvalidCfgStruct - The struct type in GetPluginConfig doesn't match the struct registered for the plugin InvalidCfgStruct // NoConfigFound - The plugin doesn't have any config data NoConfigFound /* Elevator */ // TechnicalProblem - There was a problem with the elevator (e.g. service unreachable) TechnicalProblem // GeneralError - Only indicates an error occurred, vs. e.g. failure GeneralError // ReplyNotMatched - The user reply didn't match the pattern waited for ReplyNotMatched // UseDefaultValue - The user replied with a single '=', meaning use a default value UseDefaultValue // TimeoutExpired - The user didn't reply within the given timeout TimeoutExpired // Interrupted - The user issued another command instead of replying Interrupted // MatcherNotFound - There was no matcher configured with the given string, or the regex didn't compile MatcherNotFound // NoUserEmail - Couldn't look up the user's email address NoUserEmail // NoBotEmail - Couldn't look up the robot's email address NoBotEmail // MailError - There was an error sending email MailError )
type Robot ¶
type Robot struct { User string // The user who sent the message; this can be modified for replying to an arbitrary user Channel string // The channel where the message was received, or "" for a direct message. This can be modified to send a message to an arbitrary channel. Format MessageFormat // The outgoing message format, one of Fixed or Variable // contains filtered or unexported fields }
Robot is passed to the plugin to enable convenience functions Say and Reply
func (*Robot) CheckAdmin ¶
CheckAdmin returns true if the user is a configured administrator of the robot. Should be used sparingly, when a single plugin has multiple commands, some which require admin. Otherwise the plugin should just configure RequireAdmin: true
func (*Robot) CheckinDatum ¶
CheckinDatum unlocks a datum without updating it, it always succeeds
func (*Robot) CheckoutDatum ¶
func (r *Robot) CheckoutDatum(key string, datum interface{}, rw bool) (locktoken string, exists bool, ret RetVal)
CheckoutDatum gets a datum from the robot's brain and unmarshals it into a struct. If rw is set, the datum is checked out read-write and a non-empty lock token is returned that expires after lockTimeout (250ms). The bool return indicates whether the datum exists.
func (*Robot) Direct ¶
Direct is a convenience function for initiating a DM conversation with a user. Created initially so a plugin could prompt for a password in a DM.
func (*Robot) Elevate ¶
Elevate lets a plugin request elevation on the fly. When immediate = true, the elevator should always prompt for 2fa; otherwise a configured timeout should apply.
func (*Robot) Email ¶
Email provides a simple interface for sending the user an email from the robot.. It relies on both the robot and the user having an email address. For the robot, this can be conifigured in gopherbot.conf, Email attribute. For the user, this should be provided by the chat protocol, or in gopherbot.conf. (TODO: not yet implemented) It returns an error and RetVal != 0 if there's a problem.
func (*Robot) Fixed ¶
Fixed is a convenience function for sending a message with fixed width font. e.g. r.Reply(xxx) replies in variable width font, but r.Fixed().Reply(xxx) replies in a fixed-width font.
func (*Robot) GetBotAttribute ¶
GetBotAttribute returns an attribute of the robot or "" if unknown. Current attributes: name, alias, fullName, contact
func (*Robot) GetPluginConfig ¶
GetPluginConfig sets a struct pointer to point to a config struct populated from configuration when plugins were loaded. To use, a plugin should define a struct for it's configuration data, e.g.:
type pConf struct { Username, Password string }
In conf/plugins/<pluginname>.yaml, you would add a Config: stanza, e.g.:
Config: Username: foo Password: bar
When registering the plugin, you pass a pointer to an empty config template, which the robot will use to populate a struct when configuration is loaded:
func init() { bot.RegisterPlugin("memes", bot.PluginHandler{ DefaultConfig: defaultConfig, // yaml string providing default configuration Handler: plugfunc, // callback function Config: &pConf{}, // pointer to empty config struct }) }
Then, to get a current copy of configuration when the plugin runs, define a struct pointer and call GetPluginConfig with a double-pointer:
var c *pConf r.GetPluginConfig(&c)
... And voila! *pConf is populated with the contents from the configured Config: stanza
func (*Robot) GetSenderAttribute ¶
GetSenderAttribute returns a AttrRet with - The string Attribute of the sender, or "" if unknown/error - A RetVal which is one of Ok, UserNotFound, AttributeNotFound Current attributes: name(handle), fullName, email, firstName, lastName, phone TODO: supplement data with gopherbot.json user's table
func (*Robot) GetUserAttribute ¶
GetUserAttribute returns a AttrRet with - The string Attribute of a user, or "" if unknown/error - A RetVal which is one of Ok, UserNotFound, AttributeNotFound Current attributes: name(handle), fullName, email, firstName, lastName, phone TODO: supplement data with gopherbot.json user's table
func (*Robot) Log ¶
Log logs a message to the robot's log file (or stderr) if the level is lower than or equal to the robot's current log level
func (*Robot) RandomInt ¶
RandomInt uses the robot's seeded random to return a random int 0 <= retval < n
func (*Robot) RandomString ¶
RandomString is a convenience function for returning a random string from a slice of strings, so that replies can vary.
func (*Robot) Remember ¶
Remember adds a short-term memory (with no backing store) to the robot's brain. This is used internally for resolving the meaning of "it", but can be used by plugins to remember other contextual facts. Since memories are indexed by user and channel, but not plugin, these facts can be referenced between plugins. This functionality is considered EXPERIMENTAL.
func (*Robot) RememberContext ¶
RememberContext is a convenience function that stores a context reference in short term memories. e.g. RememberContext("server", "web1.my.dom") means that next time the user uses "it" in the context of a "server", the robot will substitute "web1.my.dom".
func (*Robot) SendChannelMessage ¶
SendChannelMessage lets a plugin easily send a message to an arbitrary channel. Use Robot.Fixed().SencChannelMessage(...) for fixed-width font.
func (*Robot) SendUserChannelMessage ¶
SendUserChannelMessage lets a plugin easily send a message directed to a specific user in a specific channel without fiddling with the robot object. Use Robot.Fixed().SencChannelMessage(...) for fixed-width font.
func (*Robot) SendUserMessage ¶
SendUserMessage lets a plugin easily send a DM to a user. If a DM isn't possible, the connector should message the user in a channel.
func (*Robot) UpdateDatum ¶
UpdateDatum tries to update a piece of data in the robot's brain, providing a struct to marshall and a (hopefully good) lock token. If err != nil, the update failed.
func (*Robot) WaitForReply ¶
WaitForReply lets a plugin temporarily register a regex for a reply expected to an multi-step command when the robot needs more info. If the regular expression matches, it returns the matched text and RetVal = Ok. If the regular expression doesn't match, it returns an empty string with one of the following RetVals:
Interrupted - the user issued a new command that ran UseDefaultValue - user supplied a single "=", meaning "use the default value" ReplyNotMatched - didn't successfully match for any reason MatcherNotFound - the regexId didn't correspond to a valid regex TimeoutExpired - the user didn't respond within the timeout window given
Plugin authors can define regex's for regexId's in the plugin's JSON config, with the restriction that the regexId must start with a lowercase letter. A pre-definied regex from the following list can also be used:
Email Domain - an alpha-numeric domain name OTP - a 6-digit one-time password code IPAddr SimpleString - Characters commonly found in most english sentences, doesn't include special characters like @, {, etc. YesNo
func (*Robot) WaitForReplyRegex ¶
WaitForReplyRegex is identical to WaitForReply except that the first argument is the regex to compile and use. If the regex doesn't compile an error will be logged and ("", MatcherNotFound) will be returned.
type SimpleBrain ¶
type SimpleBrain interface { // Store stores a blob of data with a string key, returns error // if there's a problem storing the datum. Store(key string, blob []byte) error // Retrieve returns a blob of data (probably JSON) given a string key, // and exists=true if the data blob was found, or error if the brain // malfunctions. Retrieve(key string) (blob []byte, exists bool, err error) }
SimpleBrain is the simple interface for a configured brain, where the robot handles all locking issues.