Slackの投稿をComment Screenに表示させる

#はじめに
[Comment Screen](https://commentscreen.com/)いいですよね！
ただ、slackの投稿も連携できるともっと便利そうだったので、作ってみました。

#前提条件
- heroku関連
- node.jsがローカルで動かせる

#これからやること
1. 『slackの投稿を受け取って、Comment Screen（のサーバ）に送信するapi』 をherokuに作成する(無料)
2. 『slackの投稿を送信するbot』 を作成する

#herokuでapiを動かす
[Slack の Bolt フレームワークのチュートリアルを Heroku 上で実行する](https://qiita.com/silverskyvicto/items/00102f988c10c267cf55#%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E5%85%88%E3%81%AE-heroku-%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E6%BA%96%E5%82%99)
を参考にしました。（ありがとうございます^ ^）
ほとんど、上サイトの流れと同じなので、異なる部分のみ記載いたします。

apiに必要なパッケージは以下の2つです。

```
npm install @slack/bolt
npm install socket.io-client
```

また、メインのjsファイルは以下のようになっています。

```app.js
const { App } = require('@slack/bolt')
const io = require('socket.io-client')

// CommentScreenのサーバーと接続
let socket = new io.connect('https://commentscreen.com', {
  reconnection: true,
  reconnectionDelay: 1000,
  reconnectionDelayMax: 5000,
  reconnectionAttempts: 100
})

// slack botと接続する
// tokenの設定は以下のように(bot作成後)
//   heroku config:set SLACK_SIGNING_SECRET=xxxxx
const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET
})

// タイムスタンプと部屋名のdic
let timestamp2room = {}

// 全ての投稿を取得
app.message('', ({ message, say }) => {
  let roomName = ''
  let text = message.text
  // 投稿内に[CS]が含まれていたらComment Screenの部屋名を宣言しているとする
  if (~text.indexOf('[CS]')) {
    // スペースはあってもなくてもいいように置換
    roomName = text.replace(/\s+/g, '').split('[CS]')[1]
    if (roomName !== '') {
      // 親メッセージのタイムスタンプは子スレッドのthread_tsと一致するらしい
      if (message.thread_ts === undefined) {
        // タイムラインから宣言した場合
        timestamp2room[message.ts] = roomName
      } else {
        // スレッドから宣言した場合
        timestamp2room[message.thread_ts] = roomName
      }
      sendMessage(roomName, text)
    }
  } else {
    // 部屋名が登録済みなら
    if (timestamp2room[message.thread_ts]) {
      roomName = timestamp2room[message.thread_ts]
      sendMessage(roomName, text)
    }
  }
})
;(async () => {
  // Start your app
  await app.start(process.env.PORT || 3000)
  console.log('⚡️ Bolt app is running!')
})()

function sendMessage(roomName, text) {
  // その都度、所定の部屋に参加する
  socket.emit('join', { room: roomName })
  let array = makeJson(text)
  let jsonStr = JSON.stringify(array)
  // 参加した部屋に投稿を送信する
  // （もしかしたら、joinとmessageの間にsleepとか入れた方がいいのかも）
  socket.emit('message', jsonStr)
}

// 以下、本家サイト(Comment Screen)からコピペ
function makeJson(text) {
  return {
    position: 'opt_ue',
    size: 'opt_small',
    color: '#190707',
    text: text,
    uuid: generateUuid(),
    date: new Date().getTime()
  }
}

function generateUuid() {
  // https://github.com/GoogleChrome/chrome-platform-analytics/blob/master/src/internal/identifier.js
  // const FORMAT: string = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
  let chars = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.split('')
  for (let i = 0, len = chars.length; i < len; i++) {
    switch (chars[i]) {
      case 'x':
        chars[i] = Math.floor(Math.random() * 16).toString(16)
        break
      case 'y':
        chars[i] = (Math.floor(Math.random() * 4) + 8).toString(16)
        break
    }
  }
  return chars.join('')
}

```

#slack botを作る
上と同様に、[Slack の Bolt フレームワークのチュートリアルを Heroku 上で実行する](https://qiita.com/silverskyvicto/items/00102f988c10c267cf55#slack-app-%E3%81%AE%E4%BD%9C%E6%88%90)
を参考にしました。（ありがとうございます^ ^）

必要なのは、
- Botの作成
- `OAuth & Permissions -> Scopes -> Bot Token Scopes`よりchannels:historyをaddする
- `Event Subscriptions` でイベントURLを設定（上サイト参照）。
- さらに、`Subscribe to bot events` よりmessage.channelsをaddする（これにより、必要なOAuth & Permissionsが自動で追加されるので、2行目いらないかも）
- アプリをworkspaceへインストール。

#使い方
1. あらかじめ適用したいチャンネルにアプリを`/invite`する
2. ホストはいつも通りComment Screenを起動して部屋名を決定する
3. slackからComment Screenの部屋を登録する（ex. テストスレ [CS] Testdayo,[CS]Testdayo）
4. スレッド内に投稿することで、Comment Screenにも反映！

本来のComment ScreenのWeb画面にも自動でコメントが反映されるようです。（ラッキー）

<img width="1440" alt="スクリーンショット 2020-06-13 22.42.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/343913/6551c3a5-746d-abb4-eaf5-7e1389a76a37.png">


#メリット
1. ユーザーはslackの画面だけで完結できる
2. ログがslackに残る

#デメリット
1. 匿名性が失われる

#おわりに
筆者は[Comment Screen](https://commentscreen.com/)を応援しています！