func Animate() command.Command { usage := "animate [text]" desc := "Returns an animation" type Meta struct { Status int `json:"status"` Msg string `json:"msg"` } type Image struct { Url string `json:"url"` } type Images struct { FixedHeight Image `json:"fixed_height"` } type Result struct { Images Images `json:"images"` } type Results struct { Data []Result `json:"data"` Meta Meta `json:"meta"` } return command.NewCommand("animate", usage, desc, func(args ...string) ([]byte, error) { if len(args) < 2 { return []byte("animate what?"), nil } u := url.Values{} u.Set("q", strings.Join(args[1:], " ")) u.Set("limit", "1") u.Set("api_key", key) rsp, err := http.Get("http://api.giphy.com/v1/gifs/search?" + u.Encode()) if err != nil { return nil, err } defer rsp.Body.Close() var res Results if err := json.NewDecoder(rsp.Body).Decode(&res); err != nil { return nil, err } if res.Meta.Status != 200 { return nil, fmt.Errorf("returned status: %d %s", res.Meta.Status, res.Meta.Msg) } if len(res.Data) == 0 { return nil, nil } return []byte(res.Data[0].Images.FixedHeight.Url), nil }) }
func TestBot(t *testing.T) { flagSet := flag.NewFlagSet("test", flag.ExitOnError) app := cli.NewApp() ctx := cli.NewContext(app, flagSet, nil) io := &testInput{ send: make(chan *input.Event), recv: make(chan *input.Event), exit: make(chan bool), } inputs := map[string]input.Input{ "test": io, } commands := map[string]command.Command{ "^echo ": command.NewCommand("echo", "test usage", "test description", func(args ...string) ([]byte, error) { return []byte(strings.Join(args[1:], " ")), nil }), } bot := newBot(ctx, inputs, commands) if err := bot.start(); err != nil { t.Fatal(err) } // send command select { case io.recv <- &input.Event{ Meta: map[string]interface{}{}, Type: input.TextEvent, Data: []byte("echo test"), }: case <-time.After(time.Second): t.Fatal("timed out sending event") } // recv output select { case ev := <-io.send: if string(ev.Data) != "test" { t.Fatal("expected 'test', got: ", string(ev.Data)) } case <-time.After(time.Second): t.Fatal("timed out receiving event") } if err := bot.stop(); err != nil { t.Fatal(err) } }
func Geocode() command.Command { usage := "geocode [address]" desc := "Returns the geocoded address; lat,lng" type Location struct { Lat float64 `json:"lat"` Lng float64 `json:"lng"` } type Geometry struct { Location Location `json:"location"` } type Result struct { Geometry Geometry `json:"geometry"` } type Results struct { Results []Result `json:"results"` Status string `json:"status"` } return command.NewCommand("geocode", usage, desc, func(args ...string) ([]byte, error) { if len(args) < 2 { return []byte("geocode what?"), nil } u := url.Values{} u.Set("address", strings.Join(args[1:], " ")) rsp, err := http.Get("https://maps.googleapis.com/maps/api/geocode/json?" + u.Encode()) if err != nil { return nil, err } defer rsp.Body.Close() var res Results if err := json.NewDecoder(rsp.Body).Decode(&res); err != nil { return nil, err } if res.Status != "OK" { return nil, fmt.Errorf("returned status: %s", res.Status) } lat := res.Results[0].Geometry.Location.Lat lng := res.Results[0].Geometry.Location.Lng val := fmt.Sprintf("%.6f,%.6f", lat, lng) return []byte(val), nil }) }
func WhereAreYou() command.Command { usage := "where are you?" desc := "Returns the location of the bot" getIp := func() string { ifaces, _ := net.Interfaces() for _, i := range ifaces { addrs, _ := i.Addrs() for _, addr := range addrs { if ip, ok := addr.(*net.IPNet); ok && ip.IP.IsLoopback() { continue } switch v := addr.(type) { case *net.IPNet: return v.IP.String() case *net.IPAddr: return v.IP.String() } } } return "127.0.0.1" } return command.NewCommand("whereareyou", usage, desc, func(args ...string) ([]byte, error) { rsp, err := http.Get("http://myexternalip.com/raw") if err != nil { return nil, err } defer rsp.Body.Close() b, err := ioutil.ReadAll(rsp.Body) if err != nil { return nil, err } host, _ := os.Hostname() exIp := string(b) inIp := getIp() val := fmt.Sprintf("hostname: %s\ninternal ip: %s\nexternal ip: %s", host, inIp, exIp) return []byte(val), nil }) }
func help(commands map[string]command.Command) command.Command { usage := "help" desc := "Displays help for all known commands" var cmds []command.Command for _, cmd := range commands { cmds = append(cmds, cmd) } sort.Sort(sortedCommands{cmds}) return command.NewCommand("help", usage, desc, func(args ...string) ([]byte, error) { response := []string{"\n"} for _, cmd := range cmds { response = append(response, fmt.Sprintf("%s - %s", cmd.Usage(), cmd.Description())) } return []byte(strings.Join(response, "\n")), nil }) }