Documentation ¶
Overview ¶
Package web implements custom websocket bots.
You start by creating a `Controller`, and calling `DirectMessages` on that returns a receive only channel, that'll give you incoming messages.
Calling `ConnectionHandler` returns an http.Handler that can be set as the handler for any endpoint that should accept websocket connections.
Index ¶
- Constants
- Variables
- func WithBotIDCreator(f BotIDCreator) func(*Controller) error
- func WithControllerStore(store ControllerStore) func(*Controller) error
- func WithConversationStore(store ConversationStore) func(*Controller) error
- func WithErrorHandler(f ErrorHandler) func(*Controller) error
- func WithText(text string) func(Attachment)
- func WithTitle(title string) func(Attachment)
- type Attachment
- func Audio(url string, options ...func(Attachment)) Attachment
- func FileDownload(url string, options ...func(Attachment)) Attachment
- func Image(url, alt string, options ...func(Attachment)) Attachment
- func Location(lat, long float64, options ...func(Attachment)) Attachment
- func Video(url string, options ...func(Attachment)) Attachment
- type AttachmentType
- type Bot
- type BotID
- type BotIDCreator
- type Controller
- type ControllerStore
- type Controls
- type Conversation
- type ConversationHandler
- type ConversationRegistry
- type ConversationStore
- type Cursor
- type ErrorHandler
- type Item
- type ItemID
- type ItemSource
- type ItemStore
- type ItemType
- type MemoryControllerStore
- type MemoryConversationStore
- func (s *MemoryConversationStore) Active(bot BotID) (id, state string, err error)
- func (s *MemoryConversationStore) End(bot BotID) error
- func (s *MemoryConversationStore) GetData(bot BotID, key string) (string, error)
- func (s *MemoryConversationStore) IsActive(bot BotID) bool
- func (s *MemoryConversationStore) SetData(bot BotID, key, value string) error
- func (s *MemoryConversationStore) SetState(bot BotID, state string) error
- func (s *MemoryConversationStore) Start(bot BotID, id string) error
- type MemoryItemStore
- type Message
- func (msg *Message) ItemID() ItemID
- func (msg *Message) ItemType() ItemType
- func (j *Message) MarshalJSON() ([]byte, error)
- func (j *Message) MarshalJSONBuf(buf fflib.EncodingBuffer) error
- func (msg *Message) ThreadItemID() ItemID
- func (j *Message) UnmarshalJSON(input []byte) error
- func (j *Message) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error
- type MessagePair
- type Thread
- func (t *Thread) ItemID() ItemID
- func (t *Thread) ItemType() ItemType
- func (j *Thread) MarshalJSON() ([]byte, error)
- func (j *Thread) MarshalJSONBuf(buf fflib.EncodingBuffer) error
- func (t *Thread) ThreadItemID() ItemID
- func (j *Thread) UnmarshalJSON(input []byte) error
- func (j *Thread) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error
Constants ¶
const ( ImageType AttachmentType = "image" AudioType = "audio" VideoType = "video" LocationType = "location" FileDownloadType = "file_download" )
Variables ¶
var ( ErrNilControllerStore = errors.New("Controller Store cannot be nil") ErrNilConversationStore = errors.New("Conversation Store cannot be nil") ErrNilErrorHandler = errors.New("ErrorHandler cannot be nil") ErrNilIDCreator = errors.New("ID Creator cannot be nil") ErrConversationExists = errors.New("Conversation Already Exists") ErrConversationNotFound = errors.New("Conversation Not Found") ErrConversationAlreadyActive = errors.New("Conversation Already Active") ErrNoStartState = errors.New("Conversation Has no start state") ErrStateAlreadyExists = errors.New("State Already Defined") ErrNilHandler = errors.New("Nil Handler") ErrIDNotSet = errors.New("cannot send a message without ID set") ErrPrevNextNotSet = errors.New("cannot send a message without either prev or next set") ErrSourceNotSet = errors.New("cannot send a message without source set") ErrTypeNotSet = errors.New("cannot send a message without type set") ErrItemNotFound = errors.New("Item Not Found") ErrThreadNotFound = errors.New("Thread Not Found") ErrBotNotFound = errors.New("Bot Not Found") ErrBotAlreadyAdded = errors.New("Bot Already Added") ErrCannotAddThreadZero = errors.New("Cannot explicitly add a thread with ID zero") ErrInvalidItem = errors.New("Invalid Item") )
Functions ¶
func WithBotIDCreator ¶
func WithBotIDCreator(f BotIDCreator) func(*Controller) error
WithBotIDCreator can be passed as an option to NewController with the desired implementation of BotIDCreator.
func WithControllerStore ¶
func WithControllerStore(store ControllerStore) func(*Controller) error
WithControllerStore can be passed as an option to NewController with the desired implementation of ControllerStore.
func WithConversationStore ¶
func WithConversationStore(store ConversationStore) func(*Controller) error
WithConversationStore can be passed as an option to NewController with the desired implementation of ConversationStore.
func WithErrorHandler ¶
func WithErrorHandler(f ErrorHandler) func(*Controller) error
WithErrorHandler can be passed as an option to NewController with the desired implementation of ErrorHandler.
func WithText ¶
func WithText(text string) func(Attachment)
WithText is a shorthand that can add text to any message attachment
func WithTitle ¶
func WithTitle(title string) func(Attachment)
WithTitle is a shorthand that can add a title to any message attachment
Types ¶
type Attachment ¶
type Attachment interface {
Type() AttachmentType
}
Attachment defines the interface for all message attachments
func Audio ¶
func Audio(url string, options ...func(Attachment)) Attachment
Audio defines a function to create an audio attachment
func FileDownload ¶
func FileDownload(url string, options ...func(Attachment)) Attachment
FileDownload defines a function to create a download attachment
func Image ¶
func Image(url, alt string, options ...func(Attachment)) Attachment
Image defines a function to create an image attachment
func Location ¶
func Location(lat, long float64, options ...func(Attachment)) Attachment
Location defines a function to create a location attachment
func Video ¶
func Video(url string, options ...func(Attachment)) Attachment
Video defines a function to create a video attachment
type AttachmentType ¶
type AttachmentType string
AttachmentType defines a string identifying the type of an message attachment
type Bot ¶
type Bot struct {
// contains filtered or unexported fields
}
Bot is essentially managing a single WebSocket connection for a controller. It can also start conversations registered with a Controller.
func (*Bot) Reply ¶
Reply replies to a client message, the outgoing message has the ID of the message being replied to set.
func (*Bot) ReplyInThread ¶
ReplyInThread replies to a client message in the same thread or creates a new thread, if the original message wasn't in a thread.
func (*Bot) Send ¶
Send adds an item to be sent without setting ID or cursors. This is typically used to send old messages from history that already have ID and cursors set, or cached items.
func (*Bot) StartConversation ¶
StartConversation starts a conversation with the given name with the client.
type BotIDCreator ¶
BotIDCreator is a callback that gets a http request before it is hijacked and upgraded to WebSocket. Its sole job is to identify the bot ID from the request and return it.
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller is the main interface to manage and control bots at a particular endpoint. Essentially, you create a Controller object, and set the ConnectionHandler as the request handler for a particular endpoint, and clients connecting to that endpoint will be managed by this object.
func NewController ¶
func NewController(options ...func(*Controller) error) (*Controller, error)
NewController creates a new Controller object. It can take options for specifying the ControllerStore, ConversationStore, BotIDCreator and ErrorHandler.
func (*Controller) BotAdded ¶
func (c *Controller) BotAdded() <-chan *Bot
BotAdded gets a receive only channel that'll get a bot payload whenever a new connection is obtained. You can use this to send messages like "Hi, I'm Online" to new users.
func (*Controller) ConnectionHandler ¶
func (c *Controller) ConnectionHandler() http.HandlerFunc
ConnectionHandler returns a http.HandlerFunc that can be used to intercept and handle connections from clients. It essentially creates a new Bot for each connection, and upgrades the connection to WebSocket.
func (*Controller) Messages ¶
func (c *Controller) Messages() <-chan *MessagePair
Messages returns a receive only channel that will get a bot-message pair every time a new message comes over.
func (*Controller) RegisterConversation ¶
func (c *Controller) RegisterConversation(name string, conv *Conversation) error
RegisterConversation registers a new Conversation with the Controller, so it can be used with bot.StartConversation(name)
type ControllerStore ¶
type ControllerStore interface { // Add is supposed to add a new BotID and initialize the ItemStore for the bot. // Ideally returns an error if a bot with same ID is already there, or if ItemStore could not be initialized. Add(BotID) error // Get gets the store for a bot with id BotID, error if no such bot. Get(BotID) (ItemStore, error) // Remove will remove a bot with specified ID, error if no such bot. // Also clears the ItemStore associated with the Bot. Remove(BotID) error }
ControllerStore defines the interface for storing all the bots connected to the app. By default an [in memory implementation](https://godoc.org/suy.io/bots/web#MemoryControllerStore) is used. Implement your own and pass it inside WithControllerStore(https://godoc.org/suy.io/bots/web#WithControllerStore) when initializing a Controller.
type Controls ¶
type Controls struct {
// contains filtered or unexported fields
}
Controls is a data structure passed to conversation handlers to control the current conversational flow, change states, store data, or end the conversation
type Conversation ¶
type Conversation struct {
// contains filtered or unexported fields
}
Conversation stores a set of states and ConversationHandler mappings
func NewConversation ¶
func NewConversation() *Conversation
NewConversation creates a new conversation
func (*Conversation) On ¶
func (s *Conversation) On(state string, handler ConversationHandler) error
On adds a new state to the conversation
type ConversationHandler ¶
ConversationHandler is the callback that is invoked for each state in a conversation
type ConversationRegistry ¶
type ConversationRegistry map[string]*Conversation
ConversationRegistry stores a mapping of string ids and conversations
func NewConversationRegistry ¶
func NewConversationRegistry() ConversationRegistry
NewConversationRegistry creates a new registry
func (ConversationRegistry) Add ¶
func (c ConversationRegistry) Add(name string, conv *Conversation) error
Add adds a new conversation with the specified name
func (ConversationRegistry) Get ¶
func (c ConversationRegistry) Get(name string) (*Conversation, error)
Get gets the conversation with the specified name
type ConversationStore ¶
type ConversationStore interface { Start(bot BotID, id string) error IsActive(bot BotID) bool Active(bot BotID) (id, state string, err error) SetState(bot BotID, state string) error SetData(bot BotID, key, value string) error GetData(bot BotID, key string) (string, error) End(bot BotID) error }
ConversationStore stores current active conversation data for bots, as well as state data.
type Cursor ¶
Cursor objects point to the previous and next item for both messages and threads
func (*Cursor) MarshalJSON ¶
MarshalJSON marshal bytes to json - template
func (*Cursor) MarshalJSONBuf ¶
func (j *Cursor) MarshalJSONBuf(buf fflib.EncodingBuffer) error
MarshalJSONBuf marshal buff to json - template
func (*Cursor) UnmarshalJSON ¶
UnmarshalJSON umarshall json - template of ffjson
func (*Cursor) UnmarshalJSONFFLexer ¶
UnmarshalJSONFFLexer fast json unmarshall - template ffjson
type ErrorHandler ¶
type ErrorHandler func(err error)
ErrorHandler is a function that can be specified to intercept different errors occuring during operation that are not a result of a user action
type ItemSource ¶
type ItemSource string
ItemSource field lets a client know if a message is a bot message or a user message
const ( BotItemSource ItemSource = "bot" UserItemSource ItemSource = "user" )
type ItemStore ¶
type ItemStore interface { // Add a message to a thread, defaults to 0. // Once added, the message should have cursors set. // You can't add a thread with ID zero, that is reserved to // represent messages in global namespace. Add(Item) error // Get gets a specific item in a specific thread Get(ItemID, ItemID) (Item, error) // Update updates an existing item // returns an error if no item with the id was present Update(Item) error }
ItemStore stores data associated with a single bot.
type MemoryControllerStore ¶
type MemoryControllerStore struct {
// contains filtered or unexported fields
}
MemoryControllerStore is an in-memory ControllerStore implementation.
func NewMemoryControllerStore ¶
func NewMemoryControllerStore() *MemoryControllerStore
NewMemoryControllerStore creates a new MemoryControllerStore.
func (*MemoryControllerStore) Add ¶
func (s *MemoryControllerStore) Add(id BotID) error
Add adds a new BotID to the store, and initializes ItemStore for it.
func (*MemoryControllerStore) Get ¶
func (s *MemoryControllerStore) Get(id BotID) (ItemStore, error)
Get gets a new BotID to the store
func (*MemoryControllerStore) Remove ¶
func (s *MemoryControllerStore) Remove(id BotID) error
Remove removes a bot from the store.
type MemoryConversationStore ¶
type MemoryConversationStore struct {
// contains filtered or unexported fields
}
MemoryConversationStore implements an in memory ConversationStore.
func NewMemoryConversationStore ¶
func NewMemoryConversationStore() *MemoryConversationStore
NewMemoryConversationStore creates a new MemoryConversationStore.
func (*MemoryConversationStore) Active ¶
func (s *MemoryConversationStore) Active(bot BotID) (id, state string, err error)
Active returns conversation id and state for the bot with specified ID.
func (*MemoryConversationStore) End ¶
func (s *MemoryConversationStore) End(bot BotID) error
End ends the active conversation for the current bot.
func (*MemoryConversationStore) GetData ¶
func (s *MemoryConversationStore) GetData(bot BotID, key string) (string, error)
GetData gets data with specified key for the current conversation.
func (*MemoryConversationStore) IsActive ¶
func (s *MemoryConversationStore) IsActive(bot BotID) bool
IsActive returns true of the specified has an active conversation.
func (*MemoryConversationStore) SetData ¶
func (s *MemoryConversationStore) SetData(bot BotID, key, value string) error
SetData sets a key-value pair for the current conversation.
type MemoryItemStore ¶
type MemoryItemStore struct {
// contains filtered or unexported fields
}
MemoryItemStore provides a highly inefficient, pretty much incompetent in-memory implementation for an ItemStore.
func NewMemoryItemStore ¶
func NewMemoryItemStore() *MemoryItemStore
NewMemoryItemStore creates a new MemoryItemStore
func (*MemoryItemStore) Add ¶
func (store *MemoryItemStore) Add(item Item) error
Add adds a new item to the current store
func (*MemoryItemStore) All ¶
func (store *MemoryItemStore) All(thread ItemID) ([]Item, error)
All gets all items in a particular thread in this store.
func (*MemoryItemStore) Get ¶
func (store *MemoryItemStore) Get(id, thread ItemID) (Item, error)
Get gets a specific item in a specific thread.
func (*MemoryItemStore) Update ¶
func (store *MemoryItemStore) Update(item Item) error
Update updates an already stored item's data.
type Message ¶
type Message struct { Attachments []Attachment `json:"attachments"` Source ItemSource `json:"source"` Type ItemType `json:"type"` Text string `json:"text"` ThreadID ItemID `json:"threadId"` ReplyID ItemID `json:"replyId"` ID ItemID `json:"id"` Prev *Cursor `json:"prev"` Next *Cursor `json:"next"` }
Message defines the contents of a single message sent by the bot
func TextMessage ¶
TextMessage is a shorthand function that creates a message from the passed text
func (*Message) MarshalJSON ¶
MarshalJSON marshal bytes to json - template
func (*Message) MarshalJSONBuf ¶
func (j *Message) MarshalJSONBuf(buf fflib.EncodingBuffer) error
MarshalJSONBuf marshal buff to json - template
func (*Message) ThreadItemID ¶
ThreadItemID gets the thread ID of the message
func (*Message) UnmarshalJSON ¶
UnmarshalJSON umarshall json - template of ffjson
func (*Message) UnmarshalJSONFFLexer ¶
UnmarshalJSONFFLexer fast json unmarshall - template ffjson
type MessagePair ¶
MessagePair is the payload sent for DirectMessage Event.
ffjson: skip
func (*MessagePair) Reply ¶
func (mp *MessagePair) Reply(msg *Message)
Reply uses the pair's bot to reply with the passed message
func (*MessagePair) ReplyInThread ¶
func (mp *MessagePair) ReplyInThread(msg *Message)
ReplyInThread uses the pair's bot to reply in a new thread
func (*MessagePair) Update ¶
func (mp *MessagePair) Update()
Update uses the pair's bot to update an existing message.
type Thread ¶
type Thread struct { Type ItemType `json:"type"` ThreadID ItemID `json:"threadId"` ID ItemID `json:"id"` Prev *Cursor `json:"prev"` Next *Cursor `json:"next"` }
Thread defines a single messaging thread, which contains messages in itself
func (*Thread) MarshalJSON ¶
MarshalJSON marshal bytes to json - template
func (*Thread) MarshalJSONBuf ¶
func (j *Thread) MarshalJSONBuf(buf fflib.EncodingBuffer) error
MarshalJSONBuf marshal buff to json - template
func (*Thread) ThreadItemID ¶
ThreadItemID returns the id of the parent thread for this thread
func (*Thread) UnmarshalJSON ¶
UnmarshalJSON umarshall json - template of ffjson
func (*Thread) UnmarshalJSONFFLexer ¶
UnmarshalJSONFFLexer fast json unmarshall - template ffjson