micro bot

micro bot是一只藏在微服务中的小马蝇,有了它,我们可以在Slack、HipChat、XMPP等等聊天程序中与它对话,通过它来操控服务。

我们把消息发送给它,它基于这些消息模仿执行CLI,触发指定的接口功能。

Slack小机器人 - 图1

现在支持的输入方式

  • Slack
  • HipChat

准备上车

安装Micro

安装Micro,已经安装跳过

  1. go get github.com/micro/micro

slack

SLACK_TOKEN需要到Slack上去获取。

  1. micro bot --inputs=slack --slack_token=SLACK_TOKEN

效果见图:

Slack小机器人 - 图2

-

HipChat

  1. micro bot --inputs=hipchat --hipchat_username=XMPP_USER --hipchat_password=XMPP_PASSWORD

效果见图:

Slack小机器人 - 图3

-

如果使用多种机器人,可以使用逗号分隔传入:

  1. micro bot --inputs=hipchat,slack --slack_token=SLACK_TOKEN --hipchat_username=XMPP_USER --hipchat_password=XMPP_PASSWORD

帮助信息

Slack

  1. micro help
  2. deregister service [definition] - Deregisters a service
  3. echo [text] - Returns the [text]
  4. get service [name] - Returns a registered service
  5. health [service] - Returns health of a service
  6. hello - Returns a greeting
  7. list services - Returns a list of registered services
  8. ping - Returns pong
  9. query [service] [method] [request] - Returns the response for a service query
  10. register service [definition] - Registers a service
  11. the three laws - Returns the three laws of robotics
  12. time - Returns the server time

增加命令

小机器人是根据文本消息匹配命令执行指定功能。

编写命令

  1. import "github.com/micro/go-bot/command"
  2. func Ping() command.Command {
  3. usage := "ping"
  4. description := "Returns pong"
  5. return command.NewCommand("ping", usage, desc, func(args ...string) ([]byte, error) {
  6. return []byte("pong"), nil
  7. })
  8. }

注册命令

把命令加到命令映射表中,命令的key可以通过golang/regexp.Match正则匹配。

  1. import "github.com/micro/go-bot/command"
  2. func init() {
  3. command.Commands["^ping$"] = Ping()
  4. }

重构建Micro服务

打包二进制文件

  1. cd github.com/micro/micro
  2. // 本地打包
  3. go build -i -o micro ./main.go
  4. // docker方式打包
  5. CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' -i -o micro ./main.go

增加新的输入源

输入针对通信软件是插件化的,比如Slack、HipChat、XMPP、IRC、SMTP等等。

新的输入源可以通过下列方式增加。

新增输入源

输入源要满足下面的接口。

  1. type Input interface {
  2. // 命令行接口标识
  3. Flags() []cli.Flag
  4. // 使用命令行上下文初始化
  5. Init(*cli.Context) error
  6. // 输入流事件
  7. Stream() (Conn, error)
  8. // 开始输入
  9. Start() error
  10. // 输入终止
  11. Stop() error
  12. // 输入源名
  13. String() string
  14. }

注册输入

把新的输入注册到映射表中

  1. import "github.com/micro/go-bot/input"
  2. func init() {
  3. input.Inputs["name"] = MyInput
  4. }

重构建

二进制打包

  1. cd github.com/micro/micro
  2. // 本地打包
  3. go build -i -o micro ./main.go
  4. // docker打包
  5. CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' -i -o micro ./main.go

命令即服务

小机器人支持创建服务式的命令。

是怎么工作的

小机器人值班时,它会监测它命名空间中注册的服务,默认的命名空间是go.micro.bot。所有在这个命名空间内的服务都会自动加到可执行列表中,当命令执行后,小机器人就会通过方法Command.Exec来调用服务。它也支持使用Command.Help 获取使用信息,当然是注册时要把帮助信息写上。

服务的接口示例如下,也可以在go-bot/proto上找到。

  1. syntax = "proto3";
  2. package go.micro.bot;
  3. service Command {
  4. rpc Help(HelpRequest) returns (HelpResponse) {};
  5. rpc Exec(ExecRequest) returns (ExecResponse) {};
  6. }
  7. message HelpRequest {
  8. }
  9. message HelpResponse {
  10. string usage = 1;
  11. string description = 2;
  12. }
  13. message ExecRequest {
  14. repeated string args = 1;
  15. }
  16. message ExecResponse {
  17. bytes result = 1;
  18. string error = 2;
  19. }

示例

这里有一个示例,以调用微服务来执行打印命令

  1. package main
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/micro/go-micro"
  6. "golang.org/x/net/context"
  7. proto "github.com/micro/go-bot/proto"
  8. )
  9. type Command struct{}
  10. // Help 返回使用帮助信息
  11. func (c *Command) Help(ctx context.Context, req *proto.HelpRequest, rsp *proto.HelpResponse) error {
  12. // Usage 应该要包含命令的名称
  13. rsp.Usage = "echo"
  14. rsp.Description = "This is an example bot command as a micro service which echos the message"
  15. return nil
  16. }
  17. // Exec 指行命令
  18. func (c *Command) Exec(ctx context.Context, req *proto.ExecRequest, rsp *proto.ExecResponse) error {
  19. rsp.Result = []byte(strings.Join(req.Args, " "))
  20. // rsp.Error,如果发生错误,可以设置rsp.Error
  21. // 注意:函数(Exec)返回的错误则只是服务这一级的错误信息,Exec调用方法会收到这个错误,而rsp.Error是返
  22. // 回给命令执行处的错误
  23. return nil
  24. }
  25. func main() {
  26. service := micro.NewService(
  27. micro.Name("go.micro.bot.echo"),
  28. )
  29. service.Init()
  30. proto.RegisterCommandHandler(service.Server(), new(Command))
  31. if err := service.Run(); err != nil {
  32. fmt.Println(err)
  33. }
  34. }