README.md
# botopolis Line length[](https://godoc.org/github.com/botopolis/bot) [](https://circleci.com/gh/botopolis/bot) [](https://codeclimate.com/github/botopolis/bot/test_coverage) A hubot clone in Go! botopolis is extendable with plugins and works with differentchat services. ## Usage See [example_test.go](./example_test.go) for usage details. ### Example program Here's an example of a program you can write with `botopolis`. If you've used[Hubot](https://github.com/hubotio/hubot) before, you'll see a familiar API. ```gopackage main import (Hard tabs "github.com/botopolis/bot"Hard tabs "github.com/botopolis/slack") func main() {Hard tabs // Create a bot with a Slack adapterHard tabs robot := bot.New(Hard tabs slack.New(os.Getenv("SLACK_TOKEN")),Hard tabs ) Hard tabs // Create a Listener for messages to the bot with the word "hi"Hard tabs r.Respond(bot.Regexp("hi", func(r bot.Responder) error {Hard tabs // Respond to the sender of the messageHard tabs r.Reply("hello to you too!")Hard tabs }) Hard tabs // Run the botHard tabs r.Run()}``` ### Listeners You have the following listeners at your disposal to interact with incomingmessages: ```go// Listens for any messagerobot.Hear(bot.Matcher, func(bot.Responder) error)// Listens for messages addressed to the botrobot.Respond(bot.Matcher, func(bot.Responder) error)// Listens for topic changesrobot.Topic(func(bot.Responder) error)// Listens for people entering a channelrobot.Enter(func(bot.Responder) error)// Listens for people leaving a channelrobot.Leave(func(bot.Responder) error)``` ### Matchers You'll notice that some listeners take a[`bot.Matcher`](https://godoc.org/github.com/botopolis/bot#Matcher). Matcherswill run before the callback to determine whether the callback should be fired.There are a few matchers provided by `botopolis` and you can write your own aslong as it matches the function signature. ```go// Match the text of the message against a regular expressionbot.Regexp("^hi")// Match a subset of the textbot.Contains("hello")// Match the user of a messagebot.User("jean")// Match the room of a messagebot.Room("general")``` ### Callback and Responder Callbacks are given a[`bot.Responder`](https://godoc.org/github.com/botopolis/bot#Responder<Paste>).The Responder holds a reference to the incoming `bot.Message` and exposes a fewmethods which simplify interacting with the chat service. ```gotype Responder struct {Hard tabs Name stringHard tabs User stringHard tabs Room stringHard tabs Text stringHard tabs // abridged} // Send messagefunc (r Responder) Send(Message) error// DM messagefunc (r Responder) Direct(string) error// Reply to messagefunc (r Responder) Reply(string) error// Change topicfunc (r Responder) Topic(string) error``` ### Brain [`bot.Brain`](https://godoc.org/github.com/botopolis/bot#Brain) is a store withcustomizable backends. By default it will only save things in memory, but youcan add or create your own stores such as[`botopolis/redis`](https://github.com/botopolis/redis) for data persistence. ```gor := bot.New(mock.NewChat())r.Brain.Set("foo", "bar") var out stringr.Brain.Get("foo", &out)fmt.Println(out)// Output: "bar"``` ### HTTP `botopolis` also has an HTTP server built in. One great usecase for this iswebhooks. It exposes [`gorilla/mux`](https://github.com/gorilla/mux) for routingrequests. ```gor := bot.New(mock.NewChat())Line lengthr.Router.HandleFunc("/webhook/name", func(w http.ResponseWriter, r *http.Request) {Hard tabs r.Send(bot.Message{Room: "general", Text: "Webhook incoming!"})Hard tabs w.Write([]byte("OK"))Hard tabs },).Methods("POST")``` ### Plugins `botopolis` allows for injection of plugins via `bot.New(chat, ...bot.Plugin)`.It implements a [`Plugin` interface](https://godoc.org/github.com/botopolis/bot#Plugin)that allows plugin writers to make use of the full `bot.Robot` runtime on load. ```gotype ExamplePlugin struct { PathName string } // Load conforms to Plugin interfacefunc (p ExamplePlugin) Load(r *bot.Robot) {Hard tabs r.Router.HandleFunc(e.PathName, func(w http.ResponseWriter, r *http.Request) {Hard tabs // special sauceHard tabs }).Methods("GET")} // Unload can optionally be implemented for graceful shutdownfunc (p ExamplePlugin) Unload(r *bot.Robot) {Hard tabs // shutting down}``` Here are a couple examples of working plugins: - [https://github.com/botopolis/bot/help](https://github.com/botopolis/bot/tree/master/help)Bare URL used- https://github.com/botopolis/oauth2Bare URL used- https://github.com/botopolis/redis (implements `Unload`) Multiple consecutive blank lines ## Configuration There are very few configuration options in `botopolis` itself, as it relies onthe introduction of plugins. ### Server port You can set the server port with an environment variable `PORT`: ```shPORT=4567 ./botopolis``` ### Custom logging You can set up your own logger as long as it satisfies the[Logger](https://godoc.org/github.com/botopolis/bot#Logger) interface. ```gorobot := bot.New(mychat.Plugin{})robot.Logger = MyCustomLogger{}robot.Run()```