先週、今のプロジェクトでのメインのコミュニケーションツールをIRCからSlack切り替えました。 それにともないIRCに済んでいたボットたちもお引越しする必要があったので、 ボットとSlackをつなぐためのライブラリを書きました。
Perlとgoのボットが住んでいるのでそれぞれの言語で実装してあります。
AnySan::Provider::Slack
PerlのAnySan用のモジュールです。
use AnySan;
use AnySan::Provider::Slack;
my $slack = slack
token => 'YOUR SLACK API TOKEN',
channels => {
'general' => {},
};
$slack->send_message('slack message', channel => 'C024BE91L');
AnySan->run;
AnySanを使うだけでも便利なんですが、 今のプロジェクトではAnySanを対話形式で使いやすくするようにUnazuSanを使っています。 UnazuSanはIRC前提で書かれていて、AnySan::Provider::Slackをインストールしてもそのままは使えません。
UnazuSanを置き換えるもの面倒なので、イベントの名前を書き換えて投げ直すことで、 SlackのメッセージをIRCに見せかける方法をとっています。 またSlackのOutgoing Webhookで@つきのmentionを捕まえるにもあるように、 Slackのメンションは <@U08DGJVJ7>のような形式になってしまい、UnazuSanは自分へのメッセージとして扱ってくれません。 これをUnazuSanが解釈できる形式に置き換えるのがポイントです。
use 5.010;
use warnings;
use utf8;
use Encode qw/encode_utf8/;
use UnazuSan;
use AnySan;
use AnySan::Provider::Slack;
my $unazu_san = UnazuSan->new(
host => 'example.com',
password => 'xxxxxxxxxxx',
enable_ssl => 1,
join_channels => [qw/arcade/],
respond_all => 1,
);
my $slack = slack(
token => 'YOUR SLACK TOKEN',
channels => {},
as_user => 1,
);
AnySan->register_listener(
slack => {
event => 'message',
cb => sub {
my $receive = shift;
# fake irc privmsg
$receive->{event} = 'privmsg';
$receive->{message} =~ s/<\@xxxxx>:/unazusan:/;
AnySan->broadcast_message($receive);
},
}
);
$unazu_san->on_command(
help => sub {
my ($receive, @args) = @_;
$receive->reply('help '. ($args[0] || ''));
}
);
$unazu_san->run;
ape-slack
apeのSlack対応版です。 SlackRTM APIを使ってイベントを受け取ります。
GoはWebSocketも比較的カンタンに使えるので、実はape-slackを使わなくても以下のようなコードだけでSlackRTM APIを使えてしまいます。
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"golang.org/x/net/websocket"
)
func main() {
resp, _ := http.PostForm("https://slack.com/api/rtm.start", url.Values{"token": {"YOUR SLACK TOKEN"}})
var r struct {
Url string `json:"url"`
}
json.NewDecoder(resp.Body).Decode(&r)
ws := websocket.Dial(r.Url, "", "https://slack.com/")
for {
var data map[string]interface{}
websocket.JSON.Receive(ws, &data)
fmt.Println(data)
}
}
Outgoing Webhookを使うとSlackから呼んでもらえるようセキュリティの設定が必要で面倒ですが、 WebSocketならインターネッツに繋がった環境なら大抵そのままつながります。 Outgoing WebhookならチャンネルにJOINしていなくてもイベントを受け取れたりして便利ですが、 ちょっとしたボットならこちらの方がお手軽ですね。