這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
受灣區日報的自動化機器人啟發:灣區日報的第一個“員工”: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億美元,成為了有史以來發展最快的 Saa小型股份有限公司。
本質上,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,將這個機器人邀請進來:
現在準備工作完成了。你可以在這個channel聊天了,但是這個機器人無動於衷,因為你還未實現它的邏輯。
使用 Go 實現這個機器人
建立一個 Go 項目, 並引入nlopes/slack:
1 |
go get github.com/nlopes/slack |
這個庫訪問slack api超級簡單, 如下面訪問使用者資訊的代碼:
123456789101112131415 |
import ( "fmt" "github.com/nlopes/slack")func main() { api := slack.New("YOUR_TOKEN_HERE") user, err := api.GetUserInfo("U023BECGF") if err != 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實現。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
package mainimport ("fmt""github.com/nlopes/slack")func main() {api := slack.New("YOUR TOKEN HERE")api.SetDebug(true)rtm := api.NewRTM()go rtm.ManageConnection()Loop:for {select {case msg := <-rtm.IncomingEvents:fmt.Print("Event Received: ")switch ev := msg.Data.(type) {case *slack.HelloEvent:// Ignore hellocase *slack.ConnectedEvent:fmt.Println("Infos:", ev.Info)fmt.Println("Connection counter:", ev.ConnectionCount)// Replace #general with your Channel IDrtm.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")break Loopdefault:// Ignore other events..// fmt.Printf("Unexpected: %v\n", msg.Data)}}}} |
最重要的是 case *slack.MessageEvent:,這裡會接收到即時的訊息。 我們可以判斷訊息是否來自我們定製的channel,以及指令是否是對機器人發出的:
12345678910111213 |
...case *slack.MessageEvent:if ev.Channel == channelID && ev.Team == teamID {msg := ev.TextsendToMyBot := checkMessage(msg)if sendToMyBot {go handleCommand(msg)}}... |
剩下的邏輯就是你去實現handleCommand,你可以實現各種各樣的命令,如:
BTW:
增加了一個邪惡的功能,可以通過它遠程執行linux命令,這樣就可以運行命令查看伺服器的狀態,但是這個後門有點危險。