Slackでjoinしている全てのチャンネルの発言を1つのウィンドウにまとめてみる

皆様

本日は私の誕生日パーティにようこそお越しくださいました。え?会場ここじゃない?

BPSのSlack事情

はじめまして、今年10月中途入社組のtazuです。初めての転職ということもあり、今までとは違った環境に身をおいて新鮮な気分で仕事をさせてもらっています。

社内の雰囲気を一番感じやすいのはやはりチャットツール・コミュニケーションツールでの交流ですね。
前職ではコミュニケーションツールとしてHipChatを利用していたのですが、BPSではSlackを利用しています。

チャットツールの使い方や雰囲気、どこまで攻めていいかは会社によって違うので、新人としてはいち早くチャット事情を掴むことが重要です。
というわけで早速参加できそうなパブリックチャンネルを探してみました。

はい。多いですね?

ちなみに弊社の社員数は40名前後のようです。なのに何故こんなにチャンネルが多いかというと、プロジェクト毎に分けているのはもちろん、知識の情報共有をするチャンネルも細かくジャンル分けをし、興味ある分野だけ監視できるようにしているからのようです。

しかし今までチャンネル数5程度の世界で活動してきた僕がいきなりこんな数のチャンネルを追えるはずもなく、慣れないショートカットを使ってチャンネルを切り替え発言を追っているだけで思考回路はショート寸前です。Slackの公式クライアントにはすべての未読を表示する機能があるのですが、あまり使い勝手がよくありません。

というわけで自分で作ってみることにしました。

本日作るもの

一つの窓にすべてのジョインしているチャンネルの発言が流れるようなものを作ります。

Slack APIを確認する

まずはSlackの公式APIページを確認してみます。どうやら通常のWeb APIの他に、Real Time Messaging APIというのも用意されており、さらにはNode.jsのSDKもあります。

HipChatのクライアントを作ろうとしたときはWebSocketでつなげられるAPIやSDKがなく、node-xmpp-clientを使ってHipChatの独自拡張XMPPと会話した記憶がありますが、その点Slackは良いですね。

今回はこのSDKを使うことにしました。

フレームワークの選定

今回はNode.jsのSDKを使うということで、GUIはElectronにしました。js部分はどうしようかと思ったのですが、

小さい規模のプログラムだし何か新しいフレームワークを使いたいな

AngularJSは触ったことあるし後継のAngular2触ってみるか!

ふむふむ、Angular2からはTypeScriptで書くのが推奨されているのね

gulp?? grunt?? なんかコンパイルとかのタスク自動化するやつだよね・・・

なんかよくわからないが変換できてる・・・?

Done is better than perfect.

ということでTypeScript + jQueryになったところで力尽きたので今回はこれでいきます。

Slackにつないでみる

Electronの導入は今回のメインではないので省略いたします。早速Slackにつないでみましょう。
GitHub上の example にならって書いてみます。

// 自分のAPI Tokenを入れてください
let token: string = 'please-set-your-api-token' || '';
let slack_sdk_path: string = '@slack/client';
let RtmClient = require(slack_sdk_path).RtmClient;
let RTM_EVENTS = require(slack_sdk_pth).RTM_EVENTS;
let CLIENT_EVENTS = require(slack_sdk_path).CLIENT_EVENTS;
let rtm = new RtmClient(token, {logLevel: 'debug'});
rtm.start();

rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, function (rtmStartData) {
  console.log(
    `Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}, but not yet connected to a channel`
  );
});

// ここでメッセージを取得
rtm.on(RTM_EVENTS.MESSAGE, function (message) {
  console.log(message);
});

テスト用のAPIトークンはここから取れます。

これで無事につながったので、ためしにいろんなチャンネル発言してみると・・・なんと!すでにjoinしているすべてのチャンネルの発言が見えるようになったじゃありませんか。このままDebug Consoleに流れる会話を見て余生を過ごすのも悪くないですね。

機能追加

流石にこれだけでは短いので、いくつか機能を追加してみます。

MarkDownに沿って変換する

SlackといえばMarkDownですよね。早速変換、表示してみましょう。

Node.jsで使えるMarkDownコンバータはいろいろあるようです。今回はmarkedを使ってみました。

let marked = require("marked");

message = marked(message);

・・・動きました。簡単ですね!

注意点: Slackと完全に互換性のあるマークダウンではないので、一部公式クライアントと表示がことなります。

slack-stream

Rubyのコメント’#‘を使って補足的に文章を足しただけなのに超アピールしているように見えてしまいます。平凡な日常に変化をもたらしてくれるのでこれはこれで楽しいと思いますのでこのままいきます。

絵文字を変換する

Slackといえば絵文字ですよね。一番好きな絵文字は:scream:です。一番好きな顔文字は(•̀ᴗ•́)و ̑̑です。

Slackのデフォルトで入っている絵文字を表示してみましょう。Slack APIの中に絵文字を取得するAPIがありますが、これは各チームが追加した絵文字の取得になります。必要であれば取得しましょう。

これまたいろいろと変換方法はあるみたいです。絵文字なので見た目が一番好みなものを選ぶといいかもしれませんね。
今回はemojioneを使ってみます。

let emojione = require("emojione");

function convert_emoji(m: string): string {
  let message = m;
  let emojis = m.match(/:[^:]+:/g);
  if(!!emojis) {
    for (let i = 0; i < emojis.length; i++) {
      if (emojis[i] != emojione.shortnameToImage(emojis[i])) {
        message = message.replace(emojis[i], emojione.shortnameToImage(emojis[i]));
      } else if(!!emoji_list[emojis[i].substr(1, emojis[i].length-2)]) {
        let image_url = emoji_list[emojis[i].substr(1, emojis[i].length-2)];
        let html = '<img class="emojione" src="' + image_url + '" />';
        message = message.replace(emojis[i], html);
      }
    }
  }
  message = convert_emoji_protocol(message);
  return message;
}

function convert_emoji_protocol(m: string): string {
  let message = m;
  let cdn = "//cdn.jsdelivr.net/emojione/assets/png/";
  message = message.replace(new RegExp(cdn, "g"), "https:" + cdn);
  return message;
}

なかなかDIY味あふれるコードです。

今回はいろいろありますね。やっていることは単純に :hogehoge: 形式の部分をhtmlのimgタグへと変換しているだけです。

ただemojioneの変換を利用するとimgのsrcが //cdn.hogehoge という形になってしまいます。Electronではこのような書き方だとhttpsプロトコルとみなされず正しく表示することができません。なのでここでは無理やりemojioneを使ったときだけhttpsを追加しています。replaceするときにhttpsをつければよさそうですがGitHubに今あがっているこの状態を掲載しています。

完成

などなど、いろいろな機能を追加していって今こんな感じです。

秘伝のソースも用意しておきましたので、興味がある方はご覧ください。オートスクロールぐらいは追加したいと思っています。

まとめ

チャットツールといえばbot作りが有名ですが、Slackだとクライアントアプリも簡単に作ることができます。
ちょっとこういうのが欲しいなって思ったときは自分で作ってみると楽しいのではないでしょうか。

関連記事

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

tazu

hi im tazu

tazuの書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ