読者です 読者をやめる 読者になる 読者になる

手元のPCで動かせる slackbot を作って遊ぶ (2)

前回:手元のPCで動かせる slackbot を作って遊ぶ (1)

前回は,大まかな流れを説明しました. 今回は,token の取得の方法,チャンネルやユーザー情報の取得,やりとりするメッセージの構造なんかを 説明したいと思います.

説明範囲の参考実装は,こちらになります. github.com

token の取得

いま使ってる slack のチーム名が YOURTEAM だとすると, https://[YOURTEAM].slack.com/services/new/bot にアクセスしてください. こんな感じの画面が出ると思います.ここに,これから作る bot の名前を入れます.

f:id:ikawaha:20151005173553p:plain:w300

token が表示されますので,こいつを覚えておいて,save して完了です. f:id:ikawaha:20151005181835p:plain:w300

チャンネルの情報

チャンネルの情報や,参加しているユーザーの情報は,アクセスしたときに折り返すための url と一緒に渡されます. 詳しい説明は, api.slack.com に書いてあるのですが,この説明のところに,お試しで API を叩けるテストがついているので,これを見ながら必要な情報を 拾っていけばいいです.

f:id:ikawaha:20151005174640p:plain:w300

イロイロ細かい情報があるのですが,最初はこんな感じで間に合うと思います.

type connectResponse struct {
    OK       bool                        `json:"ok"`
    Error    string                      `json:"error"`
    URL      string                      `json:"url"`
    Self     struct{ ID string }         `json:"self"`
    Users    []struct{ ID, Name string } `json:"users"`
    Channels []struct {
        ID, Name string
        IsMember bool `json:"is_member"`
    } `json:"channels"`
}

メッセージの構造

slack からの情報は,イベントという形で通知されてきます.

{
    "type": "message",
    "ts": "1358878749.000002",
    "user": "U023BECGF",
    "text": "Hello"
}

このうちの,typemessage のものがチャットでやりとりされるメッセージです. type はメッセージ意外にも沢山あって,誰かが書き込み中のときのイベントとか, チャンネルに誰か追加されたときに発生するイベントとか,いろいろです. イベントの詳細は,https://api.slack.com/rtm にのっています. ここでは,メッセージイベントだけに絞って説明します.

メッセージは,何か書き込まれるたびにリアルタイムに流れてきます. 基本的には,

{
    "type": "message",
    "channel": "C2147483705",
    "user": "U2147483697",
    "text": "Hello world",
    "ts": "1355517523.000005"
}

こんな形をしています.メッセージを編集したときなんかは subtype というのが追加されてきます. なので,普通のメッセージは subtype が空かどうか見れば判定できます.

だれかに Mention 付きで発言した場合には,たとえば @ikawaha こんにちは みたいなときは,

{
    "type": "message",
    "channel": "C2147483705",
    "user": "U2147483697",
    "text": "<@U023BECGF> こんにちは",
    "ts": "1355517523.000005"
}

のように,メッセージの頭に <@・・・> が付与されます.@ 以下にはユーザーのIDが含まれます.ID はチャンネルの情報に含まれるユーザー情報で,接続を確立するときに取得できるので,対応させてやれば,誰に Mention を飛ばしたか分かります.特に,bot に話しかけたときだけ反応したい場合には,この ID が bot の ID と同じ時だけ反応するようにしてやる必要があります.

for {
        msg, err := bot.GetMessage()
        if err != nil {
            log.Printf("receive error, %v", err)
        }
        if bot.ID == msg.MentionID() && msg.Type == "message" && msg.SubType == "" {
            go func(m slackbot.Message) {
                m.Text = m.TextBody()
                bot.PostMessage(m)
            }(msg)
        }
    }

簡単なサンプルをおいておきますので,いろいろ遊んでみてください.

実行例:

$ go get github.com/ikawaha/slackbot/...
$ go run echobot <your_token>

形態素解析 f:id:ikawaha:20151005181232p:plain

dajarebot (awesome https://github.com/kurehajime/dajarep) f:id:ikawaha:20151005181346p:plain

haikubot (awesome https://github.com/mattn/go-haiku) f:id:ikawaha:20151005181628p:plain

単純な bot はこれで全然問題ないんですけど,たとえば,おやつの時間を通知するようにしたいなとか思うと, ちょっとこの作りだと物足りなくなります.次回はその辺を対応するお話 (予定)