转载

使用Go开发一个 Slack 运维机器人

受湾区日报的自动化机器人启发: 湾区日报的第一个“员工”:Slack/Hubot , 我决定为自己的 side project 写一个自动化的slack运维机器人。

uriDB技术流 是一个搜集高质量技术文章的网站。主要是由爬虫到一些技术站点寻找关注度高的技术文章,以及一些技术聚合站点的高质量的文章,我也会发一些平常自己看到的技术文章。uriDB也允许用户注册发布文章。

因为这是自己的 side project, 我不会将精力全部放在这个项目上。 如果有一个机器人,可以方便的维护这个站点,那么可以极大减少我的工作量。

这个网站后台完全是由 Go 开发的,所以我还是想用Golang实现这个机器人,而没有采用 hubot + hubot-slack 。

目前这个机器人实现了基本的功能:

  • 发表一个文章链接
  • 修改文章的元数据
  • 删除文章
  • 分析一个文章链接

有时间我会将服务器性能监控等功能加上。

关于Slack

Slack创始人是Stewart Butterfield,他在2009年创立游戏制作商Tiny Speck,之后联合创立了图片分享网站Flickr。13年他开始转型做Slack,这款产品13年8月内测,14年2月公测。2014年4月,正式推出不到三个月,Slack就已融资4275万美元。2014年10月,融资1.2亿美元,估值达11.2亿美元,成为了有史以来发展最快的 SaaS 公司。本质上,Slack是一个企业内部沟通协作平台。提供了 Web 端,IOS 端和 Android 端的访问。

我们公司先前用hipchat,被 comcast 收购后开始改用slack。

Slack提供了机器人的功能,而且提供了清晰简单的API接口,这一点在实时通讯工具中值得称赞。人们可以使用各种语言实现各种各样的机器人和插件。你可以查看 Community-built Integrations ,文章中列出了各种语言的插件和SDK。

我使用 nlopes/slack 来实现我的机器人。

第一步,你首先创建一个Team,并且加入到这个Team中。这是使用Slack的第一步。以后你可以直接访问http:// .slack.com登录到你的team中。

第二步,新建一个 bot user integration 。你需要为你的机器人起一个名字,比如我称我的机器人为 mybot。好像不支持中文,本来我想叫她"小冰"的。

可以为它指定头像,slack会为它生成一个 API Token。 这个API Token很重要, 以后访问slack API需要传入这个token。

slack提供乐意个简化的访问API的认证,你可以不使用oauth2的方式获取access token实现认证。而是直接获得api token访问API。

你也可以为你的普通登录用户生成full-access token,网址是: https://api.slack.com/web。

第三步,将你创建的bot加入到一个channel中。 比如我创建一个管理uridb网站的channel,将这个机器人邀请进来:

使用Go开发一个 Slack 运维机器人

现在准备工作完成了。你可以在这个channel聊天了,但是这个机器人无动于衷,因为你还实现它的逻辑。

使用 Go 实现这个机器人

创建一个 Go 项目, 并引入 nlopes/slack :

go get github.com/nlopes/slack

这个库访问slack api超级简单, 如下面访问用户信息的代码:

import( "fmt"  "github.com/nlopes/slack" )  funcmain() {  api := slack.New("YOUR_TOKEN_HERE")  user, err := api.GetUserInfo("U023BECGF") iferr !=nil{  fmt.Printf("%s/n", err) return  }  fmt.Printf("ID: %s, Fullname: %s, Email: %s/n", user.ID, user.Profile.RealName, user.Profile.Email) }

因为我们要机器人实时接受指令,需要访问 Real Time Messaging API , 它是通过websocket实现。

packagemain  import( "fmt"  "github.com/nlopes/slack" )  funcmain() {  api := slack.New("YOUR TOKEN HERE")  api.SetDebug(true)   rtm := api.NewRTM() gortm.ManageConnection()  Loop: for{ select{ casemsg := <-rtm.IncomingEvents:  fmt.Print("Event Received: ") switchev := msg.Data.(type) { case*slack.HelloEvent: // Ignore hello  case*slack.ConnectedEvent:  fmt.Println("Infos:", ev.Info)  fmt.Println("Connection counter:", ev.ConnectionCount) // Replace #general with your Channel ID  rtm.SendMessage(rtm.NewOutgoingMessage("Hello world","#general"))  case*slack.MessageEvent:  fmt.Printf("Message: %v/n", ev)  case*slack.PresenceChangeEvent:  fmt.Printf("Presence Change: %v/n", ev)  case*slack.LatencyReport:  fmt.Printf("Current latency: %v/n", ev.Value)  case*slack.RTMError:  fmt.Printf("Error: %s/n", ev.Error())  case*slack.InvalidAuthEvent:  fmt.Printf("Invalid credentials") breakLoop  default:  // Ignore other events.. // fmt.Printf("Unexpected: %v/n", msg.Data)  }  }  } }

最重要的是 case *slack.MessageEvent: ,这里会接收到实时的消息。 我们可以判断消息是否来自我们定制的channel,以及指令是否是对机器人发出的:

... case*slack.MessageEvent: ifev.Channel == channelID && ev.Team == teamID {  msg := ev.Text    sendToMyBot := checkMessage(msg)  ifsendToMyBot { gohandleCommand(msg)  }   } ...

剩下的逻辑就是你去实现 handleCommand ,你可以实现各种各样的命令,如:

使用Go开发一个 Slack 运维机器人 使用Go开发一个 Slack 运维机器人
正文到此结束
Loading...