flamingo

package module
v0.0.0-...-cbd3e2b Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2016 License: MIT Imports: 5 Imported by: 3

README

godoc reference Build Status codecov License Go Report Card

Flamingo is a very thin and simple platform-agnostic chat bot framework.

Warning: API is still very experimental and it is expected to change in the near future.

You can see a simple example at examples folder.

License

MIT License

Notes

The slack client uses nlopes/slack but right now is using a fork until this pull request is merged.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidMessage occurs when a message can not be broadcasted
	ErrInvalidMessage = errors.New("the message is invalid for broadcasting")
	// ErrSomeMessagesLost occurs when some messages are lost and can't be sent
	ErrSomeMessagesLost = errors.New("some messages could not be delivered")
	// ErrAllMessagesLost occurs when all messages can't be sent
	ErrAllMessagesLost = errors.New("no messages sent")
)

Functions

This section is empty.

Types

type Action

type Action struct {
	// UserAction is the action performed by the user.
	UserAction UserAction
	// User is the user that performed the action.
	User User
	// Channel is the channel in which the action was performed.
	Channel Channel
	// OriginalMessage is the message the action originated from.
	OriginalMessage Message
	// Extra parameters. The contents of this field depend on the
	// specific client you are using. Usually, it is the full
	// data received.
	Extra interface{}
}

Action is a message received by the application to notify the user did something.

type ActionHandler

type ActionHandler func(Bot, Action)

ActionHandler is a function that will handle a certain kind of Action.

type ActionWaitingPolicy

type ActionWaitingPolicy struct {
	// Reply will send a reply every time an action or message arrives and
	// it's not the one we're waiting for.
	Reply bool
	// Message is the text of the reply message. Only necessary if Reply is true.
	Message string
}

ActionWaitingPolicy defines the policy to follow while waiting for actions to arrive.

func IgnorePolicy

func IgnorePolicy() ActionWaitingPolicy

IgnorePolicy returns an ActionWaitingPolicy that ignores all incoming messages and actions but the one we're looking for.

func ReplyPolicy

func ReplyPolicy(msg string) ActionWaitingPolicy

ReplyPolicy returns an ActionWaitingPolicy that replies to every message or action received but the on we're looking for.

type AnswerChecker

type AnswerChecker func(Message) *OutgoingMessage

AnswerChecker is a function that will determine if the provided answer is correct analysing the answer Message. If the function returns nil it is assumed the answer is valid, otherwise it is assumed to be invalid and the question will be repeated with the returned message. Take a look at the AskUntil method of the Bot interface.

type Bot

type Bot interface {
	// ID returns the ID of the bot.
	ID() string

	// Reply replies a Message with an OutgoingMessage and returns the ID of the
	// reply along with an error, if any.
	Reply(Message, OutgoingMessage) (string, error)

	// Ask sends and OutgoingMessage (typically a question) and returns the ID of
	// the question asked, the Message the user replied and an error, if any.
	Ask(OutgoingMessage) (string, Message, error)

	// Conversation asks a series of questions and waits for answers to these
	// questions by the user. Then returns the IDs of all questions, all replies
	// and an error, if any.
	Conversation(Conversation) ([]string, []Message, error)

	// Say writes an OutgoingMessage and returns the ID of that message along with
	// an error, if any.
	Say(OutgoingMessage) (string, error)

	// SayTo sends the given message to the user whose username or id is given. Returns the ID
	// of the message, the channel id, and an error, if any.
	SayTo(string, OutgoingMessage) (string, string, error)

	// Form posts a form and returns the ID of the form and an error, if any.
	Form(Form) (string, error)

	// SendFormTo sends the given form to the user whose username or id is given. Returns the ID
	// of the message, the channel id, and an error, if any.
	SendFormTo(string, Form) (string, string, error)

	// Image posts an Image and returns the ID of the image message and an error,
	// if any.
	Image(Image) (string, error)

	// UpdateMessage updates the message with the given ID with the replacement
	// text and returns the ID of the new message along with an error, if any.
	UpdateMessage(id string, replacement string) (string, error)

	// UpdateForm updates the message with the given ID and replaces it with the
	// given form. Returns the ID of the new form and an error, if any.
	UpdateForm(id string, form Form) (string, error)

	// WaitForMessage will block until a new message arrives.
	WaitForMessage() (Message, error)

	// WaitForAction will block until an action with the given ID comes. Until
	// then, all the incoming messages or actions will be handled according to
	// the given waiting policy.
	WaitForAction(string, ActionWaitingPolicy) (Action, error)

	// WaitForActions will block until an action with any of the given IDs comes.
	// Until then, all the incoming messages or actions will be handled according
	// to the given waiting policy.
	WaitForActions([]string, ActionWaitingPolicy) (Action, error)

	// AskUntil posts a question and checks the received message. If the
	// AnswerChecker considers it is correct, it will return. If not, the message
	// returned by the AnswerChecker will be posted and the process will repeat.
	// It returns the ID of the last question posted, the last user message and
	// an error, if any.
	AskUntil(OutgoingMessage, AnswerChecker) (string, Message, error)

	// InvokeAction dispatches a new action on the current conversation impersonating
	// the given user. A call to InvokeAction does not block, it adds an action to the
	// action queue and it will be processed asynchronously.
	InvokeAction(id string, user User, action UserAction)
}

Bot is the main interface to interact with the user. Either using controllers or action handlers these are all the exposed methods to communicate with the user.

type BroadcastFilter

type BroadcastFilter func(string, Channel) bool

BroadcastFilter returns true if message can be broadcasted to bot and Channel

type Broadcaster

type Broadcaster interface {
	// Broadcast tries to send a message to all running conversations except the ones
	// that are not filtered.
	Broadcast(Sendable, BroadcastFilter) (bots uint64, convs uint64, errCount uint64, err error)
}

Broadcaster defines a client that can send messages to the registered conversations following certain condition

type Button

type Button struct {
	// Text is the visible text of the button.
	Text string
	// Name is the name of the button.
	Name string
	// Value is the value of the button.
	Value string
	// Type is the type of the button.
	Type ButtonType
	// Confirmation defines a confirmation popup to be shown after the button
	// is clicked. This is platform-specific behaviour.
	Confirmation *Confirmation
}

Button is a single button element.

func NewButton

func NewButton(text, value string) Button

NewButton creates a new default button. Value and name will be the same, if that does not work for you, you will need to create a Button by hand.

func NewDangerButton

func NewDangerButton(text, value string) Button

NewDangerButton creates a new danger button. Value and name will be the same, if that does not work for you, you will need to create a Button by hand.

func NewPrimaryButton

func NewPrimaryButton(text, value string) Button

NewPrimaryButton creates a new primary button. Value and name will be the same, if that does not work for you, you will need to create a Button by hand.

type ButtonType

type ButtonType byte

ButtonType is the kind of button. Even though there are several types of buttons this is really very platform-specific.

const (
	// DefaultButton is the default button.
	DefaultButton ButtonType = iota
	// PrimaryButton is a button with an accent color to stand out.
	PrimaryButton
	// DangerButton is a typically red button to indicate a dangerous action.
	DangerButton
)

type Channel

type Channel struct {
	// ID of the channel
	ID string
	// Name if any
	Name string
	// IsDM will be true if is a direct message. That is, between user and bot.
	IsDM bool
	// Users is the list of users in the channel. Some implementations may not
	// provide this.
	Users []User
	// Type is the type of client this channel comes from.
	Type ClientType
	// Extra contains extra data given by the specific client.
	Extra interface{}
}

Channel represents a group, channel, direct message or conversation, all in one, depending on the specific client you are using.

type Client

type Client interface {
	Broadcaster

	// SetLogOutput will write the logs to the given io.Writer.
	SetLogOutput(io.Writer)

	// Use adds one or more middlewares. All middlewares will be executed in the
	// order they were added. Middlewares are only executed for controllers and
	// are executed for all of them.
	Use(...Middleware)

	// AddController adds a new Controller to the Client.
	AddController(Controller)

	// AddActionHandler adds an ActionHandler for the given ID.
	AddActionHandler(string, ActionHandler)

	// AddBot adds a new bot with an ID and a token.
	AddBot(id string, token string, extra interface{})

	// SetIntroHandler sets the IntroHandler for the client.
	SetIntroHandler(IntroHandler)

	// SetErrorHandler sets the error handler of the client. The error handler
	// will receive the result of recover() after a panic has been caught.
	// All running instances of bots are restarted after a panic.
	SetErrorHandler(ErrorHandler)

	// SetStorage sets the storage to be used to store conversations and bots.
	// In this package clients, if the Storage is added *before* calling the
	// Run method bots and conversations will be loaded from there.
	SetStorage(Storage)

	// AddScheduledJob will run the given Job forever after the given
	// duration from the last execution.
	AddScheduledJob(ScheduleTime, Job)

	// Run starts the client.
	Run() error

	// Stop stops the client.
	Stop() error
}

Client is an abstract interface of a platforms-specific client. A client can only run for one platform. If you need to handle more than one platform you will have to start several clients for different platforms.

type ClientType

type ClientType uint

ClientType tells us what type of client is.

const (
	// SlackClient is a client for Slack.
	SlackClient ClientType = 1 << iota
)

type Confirmation

type Confirmation struct {
	// Title of the confirm window.
	Title string
	// Text of the confirm window.
	Text string
	// Ok button text of the confirm window.
	Ok string
	// Dismiss button text of the confirm window.
	Dismiss string
}

Confirmation is a confirmation popup to be shown after a button is clicked. Slack-specific at the moment.

type Controller

type Controller interface {
	// CanHandle tells if the controller can handle the message.
	CanHandle(Message) bool

	// Handle performs the actual work, here an instance of Bot is
	// provided along with the Message to be able to communicate with
	// the user.
	Handle(Bot, Message) error
}

Controller is an object that will handle incoming messages if they can be handled by it.

type Conversation

type Conversation []OutgoingMessage

Conversation is a collection of OutgoingMessages.

type ErrorHandler

type ErrorHandler func(interface{})

ErrorHandler will handle an error after a panic. The parameter it receives is the result of recover()

type Field

type Field interface {
	// contains filtered or unexported methods
}

Field is an element of a FieldGroup.

type FieldGroup

type FieldGroup interface {
	// ID returns the ID of the group (only valid for ButtonGroup)
	ID() string
	// Items returns all the fields in the group.
	Items() []Field
	// Type returns the type of the group.
	Type() FieldGroupType
}

FieldGroup is a collection of Fields of a concrete type.

func NewButtonGroup

func NewButtonGroup(id string, buttons ...Button) FieldGroup

NewButtonGroup creates a FieldGroup with the given buttons.

func NewTextFieldGroup

func NewTextFieldGroup(fields ...TextField) FieldGroup

NewTextFieldGroup creates a FieldGroup with the given text fields.

type FieldGroupType

type FieldGroupType byte

FieldGroupType is the type of elements contained in the group.

const (
	// ButtonGroup is a group of buttons.
	ButtonGroup FieldGroupType = 1 << iota
	// TextFieldGroup is a group of text fields.
	TextFieldGroup
	// ImageGroup is a single image.
	ImageGroup
	// TextGroup is a single text message.
	TextGroup
)

type Form

type Form struct {
	// Title is the title of the form.
	Title string
	// AuthorIconURL sets the icon of the form author to the given one.
	AuthorIconURL string
	// AuthorName sets the name of the form author to the given one.
	AuthorName string
	// Text is the text of the form.
	Text string
	// Combine will force all the form to be in a single message.
	// The behavior of this is actually client-dependant.
	Combine bool
	// Color is the color of the form. This is client-specific.
	Color string
	// Footer is a small text on the footer of the form.
	Footer string
	// Fields is a collection of field groups on the form.
	Fields []FieldGroup
}

Form is the way to post complex structures with the bot. Forms can have title, text, color, footer, several Fields (buttons, text fields, images, ...), etc.

type HandlerFunc

type HandlerFunc func(Bot, Message) error

HandlerFunc is a function that receives a bot and a message and does something with them.

type Image

type Image struct {
	// URL is the URL of the image.
	URL string
	// Text of the image.
	Text string
	// ThumbnailURL is the URL of the thumbnail to be displayed.
	ThumbnailURL string
}

Image is an image to be posted.

func (Image) ID

func (f Image) ID() string

ID always returns an empty string since Images have no ID. This method is just implemented to fulfill the FieldGroup interface.

func (Image) Items

func (f Image) Items() []Field

Items returns a slice with only the image itself, which is both a fieldgroup and a field.

func (Image) Type

func (f Image) Type() FieldGroupType

Type returns the ImageGroup type.

type IntroHandler

type IntroHandler interface {
	// HandleIntro performs the actual work, here an instance of Bot
	// is provided along with the Channel to be able to communicate
	// with the users in the channel.
	HandleIntro(Bot, Channel) error
}

IntroHandler is a handler that is triggered whenever someone starts a new conversation or group with the bot.

type Job

type Job func(Bot, Channel) error

Job is a function that will execute like a cron job after a certain amount of time to perform some kind of task.

type Message

type Message struct {
	// ID of the message.
	ID string
	// Type of client this message comes from.
	Type ClientType
	// User that posted the message.
	User User
	// Channel the message was posted in.
	Channel Channel
	// Time of the message.
	Time time.Time
	// Text of the message.
	Text string
	// Extra contains extra data given by the specific content.
	Extra interface{}
}

Message is the data of a message received.

func (Message) MatchRegex

func (m Message) MatchRegex(regex *regexp.Regexp) bool

MatchRegex reports if the message text matches the given regexp with leading and trailing spaces removed.

func (Message) MatchString

func (m Message) MatchString(str string) bool

MatchString reports if the message text matches the given text lowercased with leading and trailing spaces removed.

func (Message) MatchStringCase

func (m Message) MatchStringCase(str string) bool

MatchStringCase reports if the message text matches the given text with case sensitivity with leading and trailing spaces removed.

type MessageSender

type MessageSender struct {
	// Username is the name of the user.
	Username string
	// IconURL for the message poster picture.
	IconURL string
}

MessageSender define the properties of the sender of a message.

type Middleware

type Middleware func(Bot, Message, HandlerFunc) error

Middleware is a function that receives a bot and a message and the next handler to be called after it.

type OutgoingMessage

type OutgoingMessage struct {
	// ChannelID if is different from the channel in which the current handler
	// or controller is executing.
	ChannelID string
	// Text of the message.
	Text string
	// Sender, if provided, changes the username and icon of the message.
	Sender *MessageSender
}

OutgoingMessage is a message that is going to be sent to the user.

func NewOutgoingMessage

func NewOutgoingMessage(text string) OutgoingMessage

NewOutgoingMessage creates a simple OutgoingMessage with just text.

type ScheduleTime

type ScheduleTime interface {
	// Next time right after the given time a job should be run.
	Next(time.Time) time.Time
}

ScheduleTime gives the next time to run a job.

func NewDayTimeSchedule

func NewDayTimeSchedule(days []time.Weekday, hour, minutes, seconds int) ScheduleTime

NewDayTimeSchedule creates a ScheduleTime that runs once a day at a given hour, minutes and seconds only on the given set of days.

func NewIntervalSchedule

func NewIntervalSchedule(every time.Duration) ScheduleTime

NewIntervalSchedule creates a ScheduleTime that runs in intervals of the given duration.

func NewTimeSchedule

func NewTimeSchedule(hour, minutes, seconds int) ScheduleTime

NewTimeSchedule creates a ScheduleTime that runs once a day at a given hour, minutes and seconds.

type Sendable

type Sendable interface {
	// contains filtered or unexported methods
}

Sendable is the interface that must implements structs that are being sent by a Bot

type Storage

type Storage interface {
	// StoreBot saves the given bot.
	StoreBot(StoredBot) error
	// StoreConversation saves the given conversation.
	StoreConversation(StoredConversation) error
	// LoadBots retrieves all stored bots.
	LoadBots() ([]StoredBot, error)
	// LoadConversations retrieves all stored conversations for a single bot.
	LoadConversations(StoredBot) ([]StoredConversation, error)
	// BotExists checks if the bot is already stored.
	BotExists(StoredBot) (bool, error)
	// ConversationExists checks if the conversation is already stored.
	ConversationExists(StoredConversation) (bool, error)
}

Storage is a service to store and retrieve conversations and bots stored.

type StoredBot

type StoredBot struct {
	// ID is the ID of the bot, an unique identifier.
	ID string
	// Token is the token needed to access the bot API by the client.
	Token string
	// CreatedAt is the time it was first saved.
	CreatedAt time.Time
	// Extra allows clients to store client-specific data needed.
	Extra interface{}
}

StoredBot is the minimal data snapshot to start a previously running bot instance. It is meant to be stored.

type StoredConversation

type StoredConversation struct {
	// ID is the unique identifier of the conversation or channel.
	ID string
	// BotID is the unique identifier of the bot this conversation belongs to.
	BotID string
	// CreatedAt is the time it was first saved.
	CreatedAt time.Time
	// Extra allows clients to store client-specific data needed.
	Extra interface{}
}

StoredConversation is the minimal data snapshot to start a previously running bot conversation instance. It is meant to be stored.

type Text

type Text string

Text is a single free text message to put on a form as a field.

func (Text) ID

func (f Text) ID() string

ID always returns an empty string, because Text don't have IDs. This is only for buttons.

func (Text) Items

func (f Text) Items() []Field

Items returns a slice with only the text itself, which is a field.

func (Text) Type

func (f Text) Type() FieldGroupType

Type returns always the TextGroup type.

type TextField

type TextField struct {
	// Title is the label of the field.
	Title string
	// Value is the text value of the field.
	Value string
	// Short is a platform-specific feature. If available, will be rendered as
	// a short field instead of a wide one.
	Short bool
}

TextField is a field which displays a label with its text value.

func NewShortTextField

func NewShortTextField(title, value string) TextField

NewShortTextField creates a new short text field.

func NewTextField

func NewTextField(title, value string) TextField

NewTextField creates a new textfield.

type User

type User struct {
	// ID of the user.
	ID string
	// Username is the handle of the user.
	Username string
	// Name is the real name, if any.
	Name string
	// Email is the email of the user, if any.
	Email string
	// IsBot will be true if the user is a bot.
	IsBot bool
	// IconURL is the URL of the icon representing that user.
	IconURL string
	// Type is the specific client this user comes from.
	Type ClientType
	// Extra contains extra data given by the specific content.
	Extra interface{}
}

User is the representation of an user.

type UserAction

type UserAction struct {
	// Name of the action performed.
	Name string
	// Value of the action performed.
	Value string
}

UserAction is the kind of action performed by the user.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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