README
¶
Chatblox
Overview
Chatblox is framework for building chatbots in Go.
This is a work in progress app and not ready for use.
Configuration
Set the following environment variables:
Variable | Type | Required | Notes |
---|---|---|---|
CHATBLOX_ENGINE |
string | y | aws or nethttp |
CHATBLOX_PORT |
integer | n | local port number for net/http |
CHATBLOX_REQUEST_FUZZY_AT_MENTION_MATCH |
boolean | n | Match non-completed at mentions. |
CHATBLOX_RESPONSE_AUTO_AT_MENTION |
boolean | n | |
CHATBLOX_POST_SUFFIX |
string | n | |
GOOGLE_SERVICE_ACCOUNT_JWT |
JSON string | y | |
GOOGLE_SPREADSHEET_ID |
string | y | ID as in URL |
GOOGLE_SHEET_TITLE_RECORDS |
string | y | sheet title for data records, e.g. Records |
GOOGLE_SHEET_TITLE_METADATA |
string | y | sheet title for metadata, e.g. Metadata |
RINGCENTRAL_BOT_ID |
string | y | bot personId in Glip |
RINGCENTRAL_BOT_NAME |
string | y | bot name in Glip for fuzzy at matching |
RINGCENTRAL_SERVER_URL |
string | y | Base API URL, e.g. https://platform.ringcentral.com |
RINGCENTRAL_TOKEN_JSON |
JSON string | y | JSON token as returned by /oauth/token endpoint |
Using the AWS Engine
To use the AWS Lambda engine, you need an AWS account. If you don't hae one, the free trial account includes 1 million free Lambda requests per month forever and 1 million free API Gateway requests per month for the first year.
Installation via AWS Lambda
See the AWS docs for deployment:
https://docs.aws.amazon.com/lambda/latest/dg/lambda-go-how-to-create-deployment-package.html
Using the aws-cli
you can use the following approach:
$ cd ./apps/server
$ GOOS=linux go build main.go
$ zip main.zip ./main
# --handler is the path to the executable inside the .zip
$ aws lambda create-function --region us-east-1 --function-name Databot --memory 128 --role arn:aws:iam::account-id:role/execution_role --runtime go1.x --zip-file fileb://main.zip --handler main
Installation via AWS UI
API Gateway
- "Actions" > "Create Resource"
- Click "Configure as proxy resource"
- Click "Enable API Gateway CORS"
- Click "Create Resource"
- Add "Lambda Function"
- Click "Save"
- Click "Actions" > "Deploy API"
- Add "Stage name", e.g.
prod
,v1
, etc. - Create Webhook URL for
https://myId.execute-api.myRegion.amazonaws.com/v1/webhook
Keepalive
In production, there are are reasons why a RingCentral webhook may fail and become blacklisted. These should be tracked down an eliminated. If there are reasons to reenable the webhook, you can deploy the [rchooks
] RingCentral Lambda keepalive function:
Documentation
¶
Index ¶
- Constants
- func GetAlgoliaAPIClient(botConfig BotConfig) (*algoliasearch.Client, error)
- func GetGoogleAPIClient(botConfig BotConfig) (*http.Client, error)
- func GetRingCentralAPIClient(botConfig BotConfig) (*rc.APIClient, error)
- func GetSheetsMap(googClient *http.Client, spreadsheetID string, sheetTitle string) (sheetsmap.SheetsMap, error)
- func HandleAWSLambda(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
- func ServeAWSLambda(intentRouter IntentRouter)
- func ServeNetHTTP(intentRouter IntentRouter, mux *http.ServeMux)
- type Bot
- func (bot *Bot) HandleAwsLambda(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
- func (bot *Bot) HandleNetHTTP(res http.ResponseWriter, req *http.Request)
- func (bot *Bot) Initialize() (hum.ResponseInfo, error)
- func (bot *Bot) ProcessEvent(reqBodyBytes []byte) (*hum.ResponseInfo, error)
- func (bot *Bot) SendGlipPost(glipPostEventInfo *GlipPostEventInfo, reqBody rc.GlipCreatePost) (*hum.ResponseInfo, error)
- type BotConfig
- type GlipPostEventInfo
- type Intent
- type IntentRouter
- type IntentType
Constants ¶
const ( CharQuoteLeft = "“" CharQuoteRight = "”" )
const ValidationTokenHeader = "Validation-Token"
Variables ¶
This section is empty.
Functions ¶
func GetAlgoliaAPIClient ¶ added in v0.2.0
func GetAlgoliaAPIClient(botConfig BotConfig) (*algoliasearch.Client, error)
func GetGoogleAPIClient ¶ added in v0.2.2
func GetRingCentralAPIClient ¶ added in v0.2.0
func GetSheetsMap ¶
func HandleAWSLambda ¶ added in v0.2.2
func HandleAWSLambda(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
func ServeAWSLambda ¶ added in v0.2.2
func ServeAWSLambda(intentRouter IntentRouter)
func ServeNetHTTP ¶ added in v0.2.2
func ServeNetHTTP(intentRouter IntentRouter, mux *http.ServeMux)
Types ¶
type Bot ¶
type Bot struct { BotConfig BotConfig IntentRouter IntentRouter RingCentralClient *rc.APIClient GoogleClient *http.Client SheetsMap sheetsmap.SheetsMap SheetsMapMeta sheetsmap.SheetsMap }
func (*Bot) HandleAwsLambda ¶
func (bot *Bot) HandleAwsLambda(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error)
func (*Bot) HandleNetHTTP ¶
func (bot *Bot) HandleNetHTTP(res http.ResponseWriter, req *http.Request)
func (*Bot) Initialize ¶
func (bot *Bot) Initialize() (hum.ResponseInfo, error)
func (*Bot) ProcessEvent ¶
func (bot *Bot) ProcessEvent(reqBodyBytes []byte) (*hum.ResponseInfo, error)
func (*Bot) SendGlipPost ¶
func (bot *Bot) SendGlipPost(glipPostEventInfo *GlipPostEventInfo, reqBody rc.GlipCreatePost) (*hum.ResponseInfo, error)
func (bot *Bot) SendGlipPosts(glipPostEventInfo *GlipPostEventInfo, reqBodies []rc.GlipCreatePost) (*hum.ResponseInfo, error) { res := &hum.ResponseInfo{} var err error for _, reqBody := range reqBodies { res, err = bot.SendGlipPost(GlipPostEventInfo, reqBody) if err != nil { return res, err } } return res, err }
type BotConfig ¶
type BotConfig struct { Port int64 `env:"PORT"` BotbloxRequestFuzzyAtMentionMatch bool `env:"CHATBLOX_REQUEST_FUZZY_AT_MENTION_MATCH"` BotbloxResponseAutoAtMention bool `env:"CHATBLOX_RESPONSE_AUTO_AT_MENTION"` BotbloxPostSuffix string `env:"CHATBLOX_POST_SUFFIX"` BotbloxCharQuoteLeft string `env:"CHATBLOX_CHAR_QUOTE_LEFT"` BotbloxCharQuoteRight string `env:"CHATBLOX_CHAR_QUOTE_RIGHT"` RingCentralToken string `env:"RINGCENTRAL_TOKEN"` RingCentralTokenJSON string `env:"RINGCENTRAL_TOKEN_JSON"` RingCentralServerURL string `env:"RINGCENTRAL_SERVER_URL"` RingCentralWebhookDefinitionJSON string `env:"RINGCENTRAL_WEBHOOK_DEFINITION_JSON"` RingCentralBotID string `env:"RINGCENTRAL_BOT_ID"` RingCentralBotName string `env:"RINGCENTRAL_BOT_NAME"` GoogleSvcAccountJWT string `env:"GOOGLE_SERVICE_ACCOUNT_JWT"` GoogleSpreadsheetID string `env:"GOOGLE_SPREADSHEET_ID"` GoogleSheetTitleRecords string `env:"GOOGLE_SHEET_TITLE_RECORDS"` GoogleSheetTitleMetadata string `env:"GOOGLE_SHEET_TITLE_METADATA"` AlgoliaAppCredentialsJSON string `env:"ALGOLIA_APP_CREDENTIALS_JSON"` AlgoliaIndex string `env:"ALGOLIA_INDEX"` }
func (*BotConfig) AppendPostSuffix ¶
type GlipPostEventInfo ¶
type GlipPostEventInfo struct { PostEvent *rc.GlipPostEvent GroupMemberCount int64 CreatorInfo *rc.GlipPersonInfo TryCommandsLc []string }
type Intent ¶
type Intent struct { Type IntentType Strings []string Regexps []*regexp.Regexp HandleIntent func(bot *Bot, matchResults map[string]string, glipPostEventInfo *GlipPostEventInfo) (*hum.ResponseInfo, error) }
type IntentRouter ¶
type IntentRouter struct {
Intents []Intent
}
type EventResponse struct { StatusCode int `json:"statusCode,omitempty"` Headers map[string]string `json:"headers,omitempty"` Message string `json:"message,omitempty"` }
func (er *EventResponse) ToJson() []byte { if len(er.Message) == 0 { er.Message = "" } msgJson, err := json.Marshal(er) if err != nil { return []byte(`{"statusCode":500,"message":"Cannot Marshal to JSON"}`) } return msgJson }
func NewIntentRouter ¶
func NewIntentRouter() IntentRouter
func (*IntentRouter) ProcessRequest ¶
func (ir *IntentRouter) ProcessRequest(bot *Bot, glipPostEventInfo *GlipPostEventInfo) (*hum.ResponseInfo, error)
func (*IntentRouter) ProcessRequestSingle ¶
func (ir *IntentRouter) ProcessRequestSingle(bot *Bot, textNoBotMention string, glipPostEventInfo *GlipPostEventInfo) (*hum.ResponseInfo, error)
type IntentType ¶
type IntentType int
const ( MatchString IntentType = iota MatchStringLowerCase MatchRegexp MatchRegexpCapture MatchAny )