気まぐれ緋夜子

アウトプット力がほしい

黒い画面で三つのslackチームのメセッジーを同時に流れてみた

hiyoko91.hatenablog.jp

前回の続きです。

前に書いたものは一つのslackに対して発言を拾い、特定の発言に反応するbotです。
おまけな感じで、黒い画面のslackアプリができました(ちゃんとパーサーすれば
それを眺める途中で、急に多くのslackチームの発言を同時に拾って流れることができるかなという発想が出ました。

やってみれば簡単にできました。

sub connect {
    my $urls = {};
    my $sockets = {};
    my $ws_clients = {};
    foreach my $token (@tokens) {
        $urls->{$token} = SlackApi::get_rtm_socket($token);
        my ($host) = $urls->{$token} =~ m{wss://(.+)/websocket};
        $sockets->{$token} = IO::Socket::SSL->new(PeerHost => $host, PeerPort => 443);
        $sockets->{$token}->blocking(0);
        $sockets->{$token}->connect;

        $ws_clients->{$token} = Protocol::WebSocket::Client->new(url => $urls->{$token});
        $ws_clients->{$token}->on(read => sub {
            my ($client, $buffer) = @_;
            Hiyobot::parser($buffer, $token); #もらったjsonをどこかに処理する
        });
        $ws_clients->{$token}->on(write => sub {
            my ($client, $buffer) = @_;
            syswrite $sockets->{$token}, $buffer;
        });
        $ws_clients->{$token}->on(connect => sub {
            say 'on_connect';
        });
        $ws_clients->{$token}->on(error => sub {
            my ($client, $error) = @_;
            say 'on_error: ', $error;
        });
        $ws_clients->{$token}->connect;
    }
    say "ready!";

    my $i = 0;
    while (1) {
        foreach my $token (@tokens) {
            my $data = '';
            while (my $line = readline $sockets->{$token}) {
                $data .= $line;
                last if $line eq "\r\n";
            }
            $ws_clients->{$token}->read($data) if $data;
        }
        if ($i++ % 30 == 0) {
            # 定期的にpingしないと接続が切れる
            foreach my $token (@tokens) {
                $ws_clients->{$token}->write('{"type": "ping"}');
            }
        }
        sleep 1;
    }

一つのtokenにつき一つのsocket接続
順番にメセッジーを取るだけです。

たまに再起動のときは最初のresponseがtimeoutで失敗、ちょっと時間を置いて再起動すれば大丈夫です。
あとはあまり多くのslackチームに接続したらすごくtimeoutしやすくなります。

流れるものは前回とほとんど変わってないので略します。