これはTECHSCORE Advent Calendar 2015 の 7日目の記事です。
こんにちは、小野寺です。
私が所属しているチームでは、開発のチャットにSlackを使っています。
Slackを使っていると、あれもSlackで通知したい、これもSlackで通知したいという、
なんでもSlackに通知したいという気持ちになってきます。
今回はGo言語の勉強も兼ねてこんな通知を作ってみました。
Slackで通知したいこと
ターミナルでコマンドを実行して、標準出力をSlackにコピペする。
今回はよくやるこれを通知します。できたのが以下です。
1 |
ls -1 | notify -c [Slackのチャンネル] -l [good|warning|danger] |
-c Slackのチャンネルを指定します。
-l メッセージの左側のバーの色を指定します。(デフォルトで#dddddd, good, warning, danger)
結果
GoはビルドしてしまえばOSネイティブ環境で実行可能になるので、こういったツールを作ったときに導入しやすいと思います。
Attachmentsの注意点
SlackへのメッセージはIncoming Webhooksを使用しました。
Attachmentsというフォーマットを使ったのですが、AttachmentsではSlackのチャット上で使用できる pre や code がデフォルトでは使用できないようになっています。
今回は pre を使いたいので以下のような構造体を作成しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
type Slack struct { Username string `json:"username"` IconUrl string `json:"icon_url"` Channel string `json:"channel"` Mrkdwn bool `json:"mrkdwn"` Attachments []Attachment `json:"attachments"` } type Attachment struct { Fallback string `json:"fallback"` Color string `json:"color"` MrkdwnIn []string `json:"mrkdwn_in"` Fields []Field `json:"fields"` } type Field struct { Title string `json:"title"` Value string `json:"value"` Short bool `json:"short"` } |
・SlackのMrkdwnフィールドをtrue
・AttachmentのMrkdwnInフィールドを["pretext","text","fields"]
とそれぞれ指定することでAttachmentsでも pre を使うことができるようになります。
以下、今回使用したコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
package main import ( "bufio" "encoding/json" "flag" "io/ioutil" "log" "net/http" "net/url" "os" ) var IncomingUrl string = "INCOMING_WEBHOOKS_URL" type Slack struct { Username string `json:"username"` IconUrl string `json:"icon_url"` Channel string `json:"channel"` Mrkdwn bool `json:"mrkdwn"` Attachments []Attachment `json:"attachments"` } type Attachment struct { Fallback string `json:"fallback"` Color string `json:"color"` MrkdwnIn []string `json:"mrkdwn_in"` Fields []Field `json:"fields"` } type Field struct { Title string `json:"title"` Value string `json:"value"` Short bool `json:"short"` } func main() { msg := make([]byte, 0, 1024) scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { msg = append(msg, scanner.Text()...) msg = append(msg, "\n"...) } if scanner.Err() != nil { log.Println(scanner.Err()) return } level := flag.String("l", "#dddddd", "notify level good|warging|danger") slackChannel := flag.String("c", "bot", "notify channel default is bot") flag.Parse() field := Field{ "Look this!", "```" + string(msg) + "```", false, } attachment := Attachment{ "Look this!", *level, []string{"fields"}, []Field{field}, } slack := Slack{ "notify", "", "#" + *slackChannel, true, []Attachment{attachment}, } params, err := json.Marshal(slack) if err != nil { log.Println(err) return } res, err := http.PostForm( IncomingUrl, url.Values{"payload": {string(params)}}, ) if err != nil { log.Println(err) return } body, err := ioutil.ReadAll(res.Body) if err != nil { log.Println(err) return } defer res.Body.Close() log.Println(string(body)) } |
まとめ
今回は使用していませんが、Attachmentsでは画像やリンクなどリッチフォーマットでの通知が行えます。
今後もちょっとした業務の効率化・やっている感の向上・習慣化したいことなどを上手に通知していきたいです。