Version: v0.2.0 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Jul 1, 2016 License: MIT Imports: 18 Imported by: 0



Package dt offers a collection of commonly used datatypes. These datatypes are shared and used by Abot's core and shared packages as well as plugins themselves.



View Source
const StateKey string = "__state"

StateKey is a reserved key in the state of a plugin that tracks which state the plugin is currently in for each user.


View Source
var ErrInvalidFlexIDType = errors.New("invalid flexid type")

ErrInvalidFlexIDType is returned when a FlexIDType is invalid not matching one of the pre-defined FlexIDTypes for email (1) or phone (2).

View Source
var ErrMissingFlexID = errors.New("missing flexid")

ErrMissingFlexID is returned when a FlexID is expected, but none found.

View Source
var ErrMissingFlexIDType = errors.New("missing flexidtype")

ErrMissingFlexIDType is returned when a FlexIDType is expected, but none found.

View Source
var ErrNoAddress = errors.New("no address")

ErrNoAddress signals that no address could be found when one was expected.

View Source
var QuoteEscapeRegex = regexp.MustCompile(`([^\\]([\\]{2})*)\\"`)

QuoteEscapeRegex replaces escaped quotes except if it is preceded by a literal backslash, e.g. "\\" should translate to a quoted element whose value is \


func CallPlugin added in v0.2.0

func CallPlugin(p *Plugin, in *Msg, followup bool) (resp string,
	stateMachineAnswered bool)

CallPlugin sends a plugin the user's preprocessed message. The followup bool dictates whether this is the first consecutive time the user has sent that plugin a message, or if the user is engaged in a conversation with the plugin. This difference enables plugins to respond differently--like reset state--when messaged for the first time in each new conversation.


type Address

type Address struct {
	ID             uint64
	Name           string
	Line1          string
	Line2          string
	City           string
	State          string
	Zip            string
	Zip5           string
	Zip4           string
	Country        string
	DisplayAddress string

Address holds all relevant information in an address for presentation to the user and communication to external services, including the USPS address validation tool. Right now, an effort is only made to support US-based addresses.

type Card

type Card struct {
	ID             int
	AddressID      sql.NullInt64
	Last4          string
	CardholderName string
	ExpMonth       int
	ExpYear        int
	Brand          string
	ServiceToken   string
	Zip5Hash       []byte `sql:"zip5hash"`

Card represents a credit card. Note that information such as the card number, security code and zip code are not present in this struct, since that data should never hit the server and thus can never be stored. Storage of that sensitive data is outsourced to a payment provider (initially Stripe) and is sent directly from the client to that payment provider, bypassing the server entirely.

type CardParams

type CardParams struct {
	ServiceToken   string
	CardholderName string
	Last4          string
	Brand          string
	ExpMonth       int
	ExpYear        int
	AddressZip     string

CardParams is used when saving a new card.

type City

type City struct {
	Name        string
	CountryCode string

City represents a city within a specific country.

type EventRequest

type EventRequest int

EventRequest is sent to the state machine to request safely jumping between states (directly to a specific Label) with guards checking that each new state is valid.

type FlexIDType

type FlexIDType int

FlexIDType is used to identify a user when only an email, phone, or other "flexible" ID is available.

const (
	FIDTEmail FlexIDType = iota + 1 // 1
	FIDTPhone                       // 2

	// FIDTSession is used to track a user's session where no other
	// information like email or phone is obtained, e.g. communicating to
	// Abot via a website.
	FIDTSession // 3

FlexIDTypes are named enum values for the various methods of communicating with Abot.

type HTTPRoute

type HTTPRoute struct {
	Method string
	Path   string

HTTPRoute defines a route to be used within a HandlerMap.

type HandlerMap

type HandlerMap map[HTTPRoute]http.HandlerFunc

HandlerMap maps HTTPRoutes (the method and URL path) to a echo router handler.

func NewHandlerMap

func NewHandlerMap(rhs []RouteHandler) HandlerMap

NewHandlerMap builds a HandlerMap from a slice of RouteHandlers. This is a convenience function, since using RouteHandlers directly is very verbose for plugins.

func (HandlerMap) AddRoutes

func (hm HandlerMap) AddRoutes(prefix string, r *httprouter.Router)

AddRoutes to the router dynamically, enabling drivers to add routes to an application at runtime usually as part of their initialization.

type KeywordFn added in v0.2.0

type KeywordFn func(in *Msg) (response string)

KeywordFn is a function run when the user sends a matched keyword as defined by a plugin. The response returned is a user-presentable string from the KeywordFn.

type KeywordHandler added in v0.2.0

type KeywordHandler struct {
	Fn      KeywordFn
	Trigger *StructuredInput

KeywordHandler maintains sets of Commands and Objects recognized by plugins as well as the functions to be performed when such Commands or Objects are found.

type Keywords added in v0.2.0

type Keywords struct {
	Dict map[string]KeywordFn

Keywords maintains sets of Commands and Objects recognized by plugins as well as the functions to be performed when such Commands or Objects are found.

type Location

type Location struct {
	Name      string
	Lat       float64
	Lon       float64
	CreatedAt time.Time

Location represents some location saved for a user or plugin. This is used by itsabot.org/abot/shared/knowledge to quickly retrieve either the user's last location (if recent) or request another location using the previous as a hint, e.g. "Are you still in Los Angeles?"

func (Location) IsRecent

func (l Location) IsRecent() bool

IsRecent is a helper function to determine if the user's location was last recorded in the past day. Beyond that, itsabot.org/abot/shared/knowledge will request an updated location.

type Memory

type Memory struct {
	Key string
	Val []byte
	// contains filtered or unexported fields

Memory holds a generic "memory" of Ava's usually set by a plugin, such as the current state of a plugin, selected products, results of a search, current offset in those search results, etc. Since the value is returned as a a []byte (and stored in the database in the same way), it can represent any datatype, and it's up to the plugin developer to recall which memories correspond to which datatypes.

func (Memory) Bool

func (m Memory) Bool() bool

Bool is a helper method making it easier to perform a common use-case, converting a memory's []byte Val into bool and protecting against a common error.

func (Memory) Int64

func (m Memory) Int64() int64

Int64 is a helper method making it easier to perform a common use-case, converting a memory's []byte Val into an int64 and protecting against a common error.

func (Memory) String

func (m Memory) String() string

String is a helper method making it easier to perform a common use-case, converting a memory's []byte Val into a string.

type Msg

type Msg struct {
	ID              uint64
	FlexID          string
	FlexIDType      FlexIDType
	Sentence        string
	User            *User
	StructuredInput *StructuredInput
	Stems           []string
	Plugin          *Plugin
	CreatedAt       *time.Time
	// AbotSent determines if msg is from the user or Abot
	AbotSent      bool
	NeedsTraining bool
	Trained       bool
	// Tokens breaks the sentence into words. Tokens like ,.' are treated as
	// individual words.
	Tokens []string
	Route  string

	Usage []string

Msg is a message received by a user. It holds various fields that are useful for plugins which are populated by Abot core in core/process.

func GetMsg

func GetMsg(db *sqlx.DB, id uint64) (*Msg, error)

GetMsg returns a message for a given message ID.

func (*Msg) GetLastPlugin added in v0.2.0

func (m *Msg) GetLastPlugin(db *sqlx.DB) (string, string, error)

GetLastPlugin for a given user so the previous plugin can be called again if no new trigger is detected.

func (*Msg) Save

func (m *Msg) Save(db *sqlx.DB) error

Save a message to the database, updating the message ID.

func (*Msg) Update

func (m *Msg) Update(db *sqlx.DB) error

Update a message as needing training.

type Person added in v0.2.0

type Person struct {
	Name string
	Sex  Sex

Person is a human being discussed.

type Phone

type Phone struct {
	ID     uint64
	Number string `db:"flexid"`

Phone represents a phone as a flexid from the database.

type Plugin added in v0.2.0

type Plugin struct {
	Config      PluginConfig
	SM          *StateMachine
	Keywords    *Keywords
	Trigger     *StructuredInput
	States      []State
	DB          *sqlx.DB
	Log         *log.Logger
	Events      *PluginEvents
	SetBranches func(in *Msg) [][]State

Plugin is a self-contained unit that holds everything an Abot plugin developer needs.

func (*Plugin) DeleteMemory added in v0.2.0

func (p *Plugin) DeleteMemory(in *Msg, k string)

DeleteMemory deletes a memory for a given key. It is not an error to delete a key that does not exist.

func (*Plugin) GetMemory added in v0.2.0

func (p *Plugin) GetMemory(in *Msg, k string) Memory

GetMemory retrieves a memory for a given key. Accessing that Memory's value is described in itsabot.org/abot/shared/datatypes/memory.go.

func (*Plugin) GetSetting added in v0.2.0

func (p *Plugin) GetSetting(name string) string

GetSetting retrieves a specific setting's value. It throws a fatal error if the setting has not been declared in the plugin's plugin.json file.

func (*Plugin) HasMemory added in v0.2.0

func (p *Plugin) HasMemory(in *Msg, k string) bool

HasMemory is a helper function to simply a common use-case, determing if some key/value has been set in Ava, i.e. if the memory exists.

func (*Plugin) Schedule added in v0.2.0

func (p *Plugin) Schedule(in *Msg, content string, sendat time.Time) error

Schedule a message to the user to be delivered at a future time. This is particularly useful for reminders. The method of delivery, e.g. SMS or email, will be determined automatically by Abot at the time of sending the message. Abot will contact the user using that user's the most recently used communication method. This method returns an error if the event could not be scheduled.

func (*Plugin) SetMemory added in v0.2.0

func (p *Plugin) SetMemory(in *Msg, k string, v interface{})

SetMemory saves to some key to some value in Abot's memory, which can be accessed by any state or plugin. Memories are stored in a key-value format, and any marshalable/unmarshalable datatype can be stored and retrieved. Note that Ava's memory is global, peristed across plugins. This enables plugins that subscribe to an agreed-upon memory API to communicate between themselves. Thus, if it's absolutely necessary that no some other plugins modify or access a memory, use a long key unlikely to collide with any other plugin's.

type PluginConfig added in v0.2.0

type PluginConfig struct {
	// Name is the user-presentable name of the plugin and must be
	// unique.It's defined in plugin.json
	Name string

	// Icon is the relative path to an icon image. It's defined in
	// plugin.json.
	Icon string

	// Maintainer is the owner/publisher of the plugin.
	Maintainer string

	// ID is the remote ID of the plugin. This is pulled automatically at
	// time of plugin install from ITSABOT_URL.
	ID uint64

	// Usage contains examples of how to interact with the plugin. Users
	// will encounter these examples after asking for "help" or confusing
	Usage []string

	// Settings is a collection of options for use by a plugin, such as a
	// required API key.
	Settings map[string]*PluginSetting

PluginConfig holds options for a plugin.

type PluginEvents added in v0.2.0

type PluginEvents struct {
	PostReceive    func(cmd *string)
	PreProcessing  func(cmd *string, u *User)
	PostProcessing func(in *Msg)
	PreResponse    func(in *Msg, resp *string)

PluginEvents allow plugins to listen to events as they happen in Abot core. Simply overwrite the plugin's function

type PluginSetting added in v0.2.0

type PluginSetting struct {
	Required bool
	Default  string

PluginSetting defines whether a plugin's setting is required (empty values panic on boot), and whether there's a default value.

type Request added in v0.2.0

type Request struct {
	CMD        string     `json:"cmd"`
	UserID     uint64     `json:"uid"`
	FlexID     string     `json:"flexid"`
	FlexIDType FlexIDType `json:"flexidtype"`

Request for Abot to perform some command.

type RouteHandler

type RouteHandler struct {
	Method  string
	Path    string
	Handler http.HandlerFunc

RouteHandler is a complete struct containing both an HTTPRoute and a handler.

type SIT added in v0.2.0

type SIT int

SIT is a Structured Input Type. It corresponds to either a Command or an Object with additional Structured Input Types to be added later.

type ScheduledEvent added in v0.2.0

type ScheduledEvent struct {
	ID         uint64
	Content    string
	FlexID     string
	FlexIDType FlexIDType

ScheduledEvent for Abot to send a message at some point in the future. No time.Time is necessary in this struct because it's only created when it's known to be time to send. See core/boot:NewServer().

func (*ScheduledEvent) Send added in v0.2.0

func (s *ScheduledEvent) Send(c *sms.Conn) error

Send a scheduled event. Currently only phones are supported.

type Sex added in v0.2.0

type Sex int

Sex represents the sex of the person being discussed.

const (
	SexInvalid Sex = iota

Define constants for all possible sexes for the purpose of maintaining context in sentences across requests. For example, "Send a bottle of wine to Jim and Pam, and tell her that I miss her." Here we can identify the "her" most likely refers to Pam.

type State

type State struct {
	// OnEntry preprocesses and asks the user for information. If you need
	// to do something when the state begins, like run a search or hit an
	// endpoint, do that within the OnEntry function, since it's only called
	// once.
	OnEntry func(*Msg) string

	// OnInput sets the category in the cache/DB. Note that if invalid, this
	// state's Complete function will return false, preventing the user from
	// continuing. User messages will continue to hit this OnInput func
	// until Complete returns true.
	// A note on error handling: errors should be logged but are not
	// propogated up to the user. Due to the preferred style of thin
	// States, you should generally avoid logging errors directly in
	// the OnInput function and instead log them within any called functions
	// (e.g. setPreference).
	OnInput func(*Msg)

	// Complete will determine if the state machine continues. If true,
	// it'll move to the next state. If false, the user's next response will
	// hit this state's OnInput function again.
	Complete func(*Msg) (bool, string)

	// SkipIfComplete will run Complete() on entry. If Complete() == true,
	// then it'll skip to the next state.
	SkipIfComplete bool

	// Label enables jumping directly to a State with stateMachine.SetState.
	// Think of it as enabling a safe goto statement. This is especially
	// useful when combined with a KeywordHandler, enabling a user to jump
	// straight to something like a "checkout" state. The state machine
	// checks before jumping that it has all required information before
	// jumping ensuring Complete() == true at all skipped states, so the
	// developer can be sure, for example, that the user has selected some
	// products and picked a shipping address before arriving at the
	// checkout step. In the case where one of the jumped Complete()
	// functions returns false, the state machine will stop at that state,
	// i.e. as close to the desired state as possible.
	Label string

State is a collection of pre-defined functions that are run when a user reaches the appropriate state within a stateMachine.

type StateMachine

type StateMachine struct {
	Handlers []State
	// contains filtered or unexported fields

StateMachine enables plugin developers to easily build complex state machines given the constraints and use-cases of an A.I. bot. It primarily holds a slice of function Handlers, which is all possible states for a given stateMachine. The unexported variables are useful internally in keeping track of state automatically for developers and make an easy API like stateMachine.Next() possible.

func NewStateMachine

func NewStateMachine(p *Plugin) *StateMachine

NewStateMachine initializes a stateMachine to its starting state.

func (*StateMachine) LoadState

func (sm *StateMachine) LoadState(in *Msg)

LoadState upserts state into the database. If there is an existing state for a given user and plugin, the stateMachine will load it. If not, the stateMachine will insert a starting state into the database.

func (*StateMachine) Next

func (sm *StateMachine) Next(in *Msg) (response string)

Next moves a stateMachine from its current state to its next state. Next handles a variety of corner cases such as reaching the end of the states, ensuring that the current state's Complete() == true, etc. It directly returns the next response of the stateMachine, whether that's the Complete() failed string or the OnEntry() string.

func (*StateMachine) ReplayState added in v0.2.0

func (sm *StateMachine) ReplayState(in *Msg) string

ReplayState returns you to the current state's OnEntry function. This is only useful when you're iterating over results in a state machine. If you're reading this, you should probably be using task.Iterate() instead. If you've already considered task.Iterate(), and you've decided to use this underlying function instead, you should only call it when Complete returns false, like so:

Complete: func(in *dt.Msg) (bool, string) {
	if p.HasMemory(in, "memkey") {
		return true, ""
	return false, p.SM.ReplayState(in)

That said, the *vast* majority of the time you should NOT be using this function. Instead use task.Iterate(), which uses this function safely.

func (*StateMachine) Reset

func (sm *StateMachine) Reset(in *Msg)

Reset the stateMachine both in memory and in the database. This also runs the programmer-defined reset function (SetOnReset) to reset memories to some starting state for running the same plugin multiple times.

func (*StateMachine) SetOnReset

func (sm *StateMachine) SetOnReset(reset func(in *Msg))

SetOnReset sets the OnReset function for the stateMachine, which is used to clear Abot's memory of temporary things between runs.

func (*StateMachine) SetState

func (sm *StateMachine) SetState(in *Msg, label string) string

SetState jumps from one state to another by its label. It will safely jump forward but NO safety checks are performed on backward jumps. It's therefore up to the developer to ensure that data is still OK when jumping backward. Any forward jump will check the Complete() function of each state and get as close as it can to the desired state as long as each Complete() == true at each state.

func (*StateMachine) SetStates

func (sm *StateMachine) SetStates(ssss ...[][]State)

SetStates takes [][]State as an argument. Note that it's a slice of a slice, which is used to enable tasks like requesting a user's shipping address, which themselves are []Slice, to be included inline when defining the states of a stateMachine.

func (*StateMachine) State

func (sm *StateMachine) State() int

State returns the current state of a stateMachine. state is an unexported field to protect programmers from directly editing it. While reading state can be done through this function, changing state should happen only through the provided stateMachine API (stateMachine.Next(), stateMachine.SetState()), which allows for safely moving between states.

type StringSlice added in v0.2.0

type StringSlice []string

StringSlice replaces []string, adding custom sql support for arrays in lieu of pq.

func (StringSlice) Last added in v0.2.0

func (s StringSlice) Last() string

Last safely returns the last item in a StringSlice, which is most often the target of a pronoun, e.g. (In "Where is that?", "that" will most often refer to the last Object named in the previous sentence.

func (StringSlice) Map added in v0.2.0

func (s StringSlice) Map() map[string]struct{}

Map converts a StringSlice into a map to check quickly if words exist within it.

func (*StringSlice) Scan added in v0.2.0

func (s *StringSlice) Scan(src interface{}) error

Scan converts to a slice of strings. See: http://www.postgresql.org/docs/9.1/static/arrays.html#ARRAYS-IO

func (StringSlice) String added in v0.2.0

func (s StringSlice) String() string

String converts a StringSlice into a string with each word separated by spaces.

func (StringSlice) StringSlice added in v0.2.0

func (s StringSlice) StringSlice() []string

StringSlice converts a StringSlice into a []string.

func (StringSlice) Value added in v0.2.0

func (s StringSlice) Value() (driver.Value, error)

Value converts to a slice of strings. See: http://www.postgresql.org/docs/9.1/static/arrays.html#ARRAYS-IO

type StructuredInput added in v0.2.0

type StructuredInput struct {
	Commands []string
	Objects  []string
	Intents  []string
	People   []Person
	Times    []time.Time

StructuredInput is generated by Abot and sent to plugins as a helper tool. Additional fields should be added, covering Times, Places, etc. to make plugin development even easier. Note that right now People is unused.

type TimeRange

type TimeRange struct {
	Start *time.Time
	End   *time.Time

TimeRange defines a range of time.

type Uint64Slice added in v0.2.0

type Uint64Slice []uint64

Uint64Slice extends []uint64 with support for arrays in pq.

func (*Uint64Slice) Scan added in v0.2.0

func (u *Uint64Slice) Scan(src interface{}) error

Scan converts to a slice of uint64.

func (Uint64Slice) Value added in v0.2.0

func (u Uint64Slice) Value() (driver.Value, error)

Value converts to a slice of uint64.

type User

type User struct {
	Name     string
	Email    string
	Password string // temp storage prior to hashing
	ID       uint64
	Admin    bool

	// FlexID and FlexIDType are particularly useful when a user has not
	// yet registered.
	FlexID     string
	FlexIDType FlexIDType

	// Trainer determines whether the user has access to the training
	// interface and will be notified via email when new training is
	// required
	Trainer bool

User represents a user, which is usually the user that sent a message to Abot.

func GetUser

func GetUser(db *sqlx.DB, req *Request) (*User, error)

GetUser from an HTTP request.

func (*User) Create

func (u *User) Create(db *sqlx.DB, fidT FlexIDType, fid string) error

Create a new user in the database.

func (*User) DeleteSessions

func (u *User) DeleteSessions(db *sqlx.DB) error

DeleteSessions removes any open sessions by the user. This enables "logging out" of the web-based client.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL