コネヒト開発者ブログ

コネヒト開発者ブログ

Slackにハッシュタグ的な「ゆるく情報をまとめる方法」が欲しかった話

【後日談】

qiita.com

ソースコードを公開しています〜、もしよろしければご一緒にどうぞ!

Slackの話をします

ご無沙汰しております。
コネヒトでPHPを書いている金城 / @o0h_です。

f:id:connehito:20160517000227p:plain:w290

突然ですが、皆様Slack大好きですか。
起床すると真っ先にSlackの赤い丸を消しに行く生活を送っていますか。
コネヒトではSlack大好き従業員・役員が多く、この中で日々色々なやりとりが繰り広げられています。

そんな風にSlackを使っていると、「もっとコレしたい」「アレできないの」が溢れてきます。
先日の島田の記事でも、その一例を紹介いたしました。

Slackの情報が「まとめにくい」問題

非常にフロー型の情報・交流に適したツールだな、と思うわけです。
パッと言える。スッと目に入る。
そうすると、「その場で思いついたアイディア」などを刹那的に投げつけていきたくなります。
・・・が、その速度感をもった利便性ゆえに「後から探しにくい」「どこいったっけ!」といった状況を招きやすく、私は良く悩まされました。

今回は、このフロー/ストック問題に対する1つのアプローチを紹介します。
ハッシュタグ(的な)機能 です。

f:id:connehito:20160516222937g:plain ↑「発言にサインをつけると、1箇所にまとめられる〜」というものを実装したのです

なにをやったの

(TwitterやFacebook、Instagramのような) 「通常のフィードに投稿しつつ、串刺し的に情報をつなげられる」という世界観を実現したいと思いました。*1
エッセンスを自分なりに整理してみて、欲しいのは「特定のサインで発火して」「分類項目ごとに手軽に一覧できる」ものです。

利用方法が簡便であることが必須

前者に関しては、

  1. シンプルであること
  2. 直感的であること(奇抜でないもの、どこかで見たことがあるもの)
  3. 当然ながら、Slackの標準の記法とぶつからないこと

という要件を満たす必要がありました。
例えば、

  • 1に対して言うと「カスタムコマンド(/command)」とすれば発言のパースこそ簡単になりますが、普通の発言操作とは異質すぎてシンプルさに欠けるように思います。
  • 2に対して言うと、エンジニア的には >> とかすると「出力先を変更する」という事で分かりやすいですが、普段Linuxを使っていない人からすれば「見慣れない」ものに思います。
  • 3に対して言うと、 #hashtag が出来ると良いのですが・・・これは既存のチャンネル指定の記法とぶつかるため、扱えません。

諸々を鑑みて、 #_hashtag というサインを決めました。ハッシュ+アンダースコア+キーワード。

アウトプットをどうするか

「手軽に一覧できる」というのをどう実現するか、というのが今回の1番の壁だったように感じます。
が、結論からいうと「チャンネルを柔軟に作成し、そこに発言を放り込んでいく」という手法をとりました。
これに関しては、先駆者がいらっしゃって非常に参考にさせていただいたのです!

Slackにスレッド機能を追加する - Qiita
この記事と巡り会えたのが最大のブレイクスルーだったし、おかげで完全に道が開けた・・・と思っています。

実際の動き

改めて先に貼った画像を挙げて、例として紹介してみます。*2

f:id:connehito:20160516222937g:plain

「会社の近くの夕飯情報」「MySQLに関するキャッチアップすべき情報」「後でやること」とそれぞれの情報が蓄積されていきます。 また、 #_yorumeshi チャンネルを開けば、その発言が(チャンネルのUIで)一覧できるわけです。

より実践的な例で言えば、コネヒトでは「技術的な情報を共有するチャンネル: #article-dev」を設置していますが、 この中で(コネヒトのプロダクトに採用しているWAFである)CakePHP関連の情報を投げる時に #_cakephp と付けておけば関連情報を後から見返すことができます。
また実際にあった例としては、 BIツールのTableauに関する情報は当初 #_tableau としてテンポラリーに運用していたものが、事後的に #article-tableau に「格上げ」されました。

実装の概説

SlackにHubotを住まわせているので、これを拡張する形で組み込みました。
以下の挙動を備えます

STEP 1. /#(_[0-9a-zA-Z\-_]+)/ というパターンで発言を待ち受ける

「ハッシュタグ」を抽出します。以下、抜き出したハッシュタグをそのままチャンネル名として扱います

STEP 2. 対象チャンネルの存在をチェック・設置

#_ハッシュタグ チャンネルが存在しているかをチェックします。
存在チェックは、hubot-slackであれば存在するチャンネル一覧をストレージに保持しているので、channels.list APIを叩く必要はありません。

channels = robot.adapter.client.channels

もし存在していなかったら、チャンネルを作成します。*3 api.slack.com

STEP 3. 発言ユーザーが当該チャンネルにjoinしているかをチェック・招待

チャンネルができたら、そのチャンネルのメンバー一欄を取得して参加状況をチェックします。 api.slack.com 不参加だったら、(チャンネルを作成した権限を持つアカウントで)招待を行います*4api.slack.com

STEP.4 発言のコピーを行う

あとは、キャッチした発言をハッシュタグのチャンネルに再投稿して完了です。 「発言したユーザー名」「発言したユーザーのアイコン」「本文」「元発言のパーマリンク及びチャンネル名」を、
投稿するようにしています。
イメージとしては、次のような処理です。

# channel: STEP 2のチャンネル情報
# msg: 元発言
# user: 元発言のユーザー
# slack: [slack-node](https://www.npmjs.com/package/slack-node)((hubotのSlackアダプターとは別に、直でREST APIを叩くために用意しています))のインスタンス。  
#    (STEP 2で出てきた)チャンネルオーナーとして振る舞わせるアカウント
data =
  channel: channel.id
  text: (msg.message.text.replace "##{msg.match[1]}", '').trim()
  username: user.name
  icon_url: user.slack.profile.image_72
  attachments: JSON.stringify [
    title: "in ##{msg.message.room}"
    title_link: getChatPermalink msg.message
  ]
  slack.api "chat.postMessage", data

これで、次のようにコピーができました。
#kaish-blog-netaチャンネルでの発言
f:id:connehito:20160517000841p:plain

#_yorumeshiチャンネルにアイコン等を模倣して発言が投稿される
f:id:connehito:20160516231914p:plain

やあやあ!「ハッシュタグ機能」の完成です!

おまけ1: 日報を書きやすくする

コネヒトでは職種にかかわらず行動記録を含む日報を毎日提出しています。
個人的には、これまでの経験上「日報はあったほうが良い」と思っているのですが、如何せんこの行動記録は面倒に感じていました。 怠惰。
が!このハッシュタグ機能を用いると、#金城の行動記録 も実現可能だな・・・!と実装しながら気づいたのです。 「ごく短いエイリアスを当てて、自分専用のハッシュタグができればいい」のような。

この行動記録用途には、特殊なサイン #___ を定めました。 これを内部的に #__mylog_{ユーザー名} として扱うエイリアスとしたのです。
実際の利用イメージはこんな感じ。 f:id:connehito:20160516233506g:plain

実装的には、上記STEP 1でチャンネル名を取得していた箇所で

channel_name = "#__mylog_#{msg.user.name}" if msg.match[1] is `___`

という処理を挟んでいるだけです。*5

これさえ付ければSlack上での通常の会話(今から対応します〜的な発言など)を日報に記しておく事もできますし、ChatOps的な運用をしているチームであればdeployのタイミングを記しておく!といった事も可能になります。

おまけ2: 日報を更に書きやすくする

記録を貯めることはできた、これで出力・整形までできれば・・・!ということで、ダンプコマンドも用意しました。 hubot相手に dump mylogと呟くと、直近24H以内の自分の日報チャンネルのログをコンパクトにしてDMしてくれます。

f:id:connehito:20160516234509g:plain

この内容をコピーしてそのまま日報に貼り付け、という使い方をしています。

導入後

実際に帰るのが10分*6早くなった!!!ということで、金城の生活に直接的に恩恵をもたらすプログラムとなりました・・・
社内でもじわじわと利用ユーザーを増やしており、しめしめ😏と思っている毎日です。

個人的にはbotなどを用いた「地味に役立つ」系の改善やアイディアは大好物なので、これからも続けたいなーと思っている日々です!
Slackが公式にスレッド機能を考えている!という情報もありましたし*7、どんどん進化していって欲しいですね・・・!

BotとかSlackとかの話できる人とメッチャ話したい今日このごろ。金城がお送りしました。

*1:最低限の状態を考えると、(当初のTwitterのように)「特定のキーワードや記号を決めて、検索でどうにかする」で充分なのですが、いまいちSlackの検索は使いにくい・・後から見返すにはつらい・・・という欠点があると感じています。

*2:記事中のSlack画像作成には、実際の業務に用いているものを出すのが難しかったので全てダミーのチームを利用しています

*3:通常、Hubotに喰わせる様なトークンですと制限した権限しか付与していないと思うので、別途用意するのが良さそうです

*4:restricted accountは不可、など招待されるアカウト側にも制約有り

*5:やっていることは単純なので、日報以外にも「アイディアメモ」「何かを見ての感想」といったものにも応用できるな、と思っています

*6:10分、という単位で分かりにくければ「1本前の電車」。

*7:http://www.theverge.com/2016/4/13/11418594/slack-threaded-messaging-chat-app-feature