chatworkのメッセージを見逃さないようにSlackに流した件

atma Advent Calendar 2019 12月24日

chatworkのメッセージを見逃さないようにSlackに流した件

atma Advent Calendar 2019 12月24日

この記事はatma Advent Calendar 2019の12月24日の投稿です。

クリスマスイブの日に俺は何をしているんだ….

概要

chatworkの通知に1日以上気づかなかったので猛省してメッセージをslackに転載するツールをGASで作ったので手順・まとめを書きます。

問題

弊社atma株式会社の社内では、コミュニケーションツールにslackをメインとして使っています。ただしクライアントとのコミュニケーションツールとしてMessengerやChatworkを使う場合があります。

(これは僕の設定の問題ですが)MessengerはスマホからもMacのchromeからも通知が来るので4時間ほどで必ず気づきますが、chatworkの場合はchrome通知をオフにしていて(そんな設定があるのをそもそも知らなかった) 1日以上気づかなかったことがあります

問題点としては通知をオフにしていたことが一番ですが、slackに通知を集約することで解決してみました。また、結果的にchatworkで投げられるクライアントからのメッセージをslack内で引用・共有するのが楽になったこともあって、やってよかったです

ついでだからMessengerを転載するバージョンも作りたかったのですが、BotをMessengerのルームに参加させる必要がありそうなので断念しました。

手順

  1. ChatworkのAPIトークンをコピーする※
  2. slackのBotを準備する
  3. GoogleAppScriptでメッセージをfetchするコードを書く
  4. GoogleAppScriptで3を定期的に実行するトリガーを作る

※APIトークンを使う方法よりWebhookの方が用途に沿ってそうですが、WebhookだとRoomIdを都度指定する必要があるのでRoomの追加・削除に合わせてWebhookを管理する必要があります。それはちょっとめんどくさいのであえてAPITokenを使った方法にしています

また、roomIdによって転載するslackのchannelを変えることができるようにもなってます。

1. ChatworkのAPIトークンをコピーする

chatworkにログインした状態で右上のメニューから API Settings を開きます。

API > API Token のメニューを押すとパスワードを求められるのでパスワードを入力します

その後、APITokenが表示されるのでコピーしてください

GASから叩くAPIは以下の2種類です。

2. slackのBotを準備する

slackのBotを持っていない人は適当な記事を読んで作って下さい。

さっさと作りたい人はこちらへどうぞ

準備できた人は、転載したいchannelの数だけIncomingWebhookのURLを作成してください

3. GoogleAppScriptでメッセージをfetchするコードを書く

https://script.google.com/ にアクセスして新しいスクリプトを適当に作ってください。

以下をペタッと貼って、コード上部の値は手順1と手順2の値を使うよう変更してください。

// 以下、送信するwebhook。記載がない場合はXXXXXチャンネルに
// 手順2で取得しているはずです
var defaultChannel = "https://hooks.slack.com/services/xxxxxxxxxxx/xxxxxxxxxxx/xxxxxxxxxxx"
var roomIdToSlackWebhookUrlMap = {
  // roomId=123456789は aaaaaaaaチャンネルに
  "123456789": "https://hooks.slack.com/services/aaaaaaaa/aaaaaaaa/aaaaaaaa",
  // roomId=987654321は bbbbbbbbチャンネルに
  "987654321": "https://hooks.slack.com/services/bbbbbbbb/bbbbbbbb/bbbbbbbb"
}

// 手順1で取得したchatworkのAPIToken
var chatWorkToken = "hogehogehugahuga"

function chatworkToSlack(){
  var rooms = getRoomIds()

  var responseMessageInDefault = []
  var responseMessageMap = {
    "123456789": [],
    "987654321": []
  }
  
  for(var i = 0; i < rooms.length; i++){
    var room = rooms[i]
    
    var midoku = getMidoku(room.room_id)
    if (midoku.length !== 0) {
      for(var j = 0;j<midoku.length;j++) {
        var midokuMessage = midoku[j];
        var midokuMessageFormatted = {
          title: midokuMessage.account.name,
          text: midokuMessage.body
        }
        
        // デフォルト設定があるかどうかチェック
        if (room.room_id in roomIdToSlackWebhookUrlMap) {
          // 指定のwebhookを使う
          responseMessageMap[room.room_id].push(midokuMessageFormatted)
        } else {
          // デフォルトのwebhookを使う
          responseMessageInDefault.push(midokuMessageFormatted)
        }
      }
    }
  }
  
  if (responseMessageInDefault.length !== 0) {
    send({
      text: "通知がありまっせ",
      attachments: responseMessageInDefault
    }, defaultChannel);
  }
  
  Object.keys(responseMessageMap).forEach(function(key) {
    if (responseMessageMap[key].length !== 0) {
      send({
        text: "通知がありまっせ",
        attachments: responseMessageMap[key]
      }, roomIdToSlackWebhookUrlMap[key]);
    }
  })
}

/**
 * 指定のroomIdから未読メッセージを取得
 */ 
function getMidoku(roomId) {
  try {
    
    var response = UrlFetchApp.fetch("https://api.chatwork.com/v2/rooms/" + roomId + "/messages?force=0", {
                                     headers: {'X-chatWorkToken': chatWorkToken}
                                     });
    var responseData = JSON.parse(response.getContentText());
    if(responseData === undefined) return []
    return responseData
  } catch(error) {
    return [] 
  }
}

/**
 * 自身が所属するroomを全て取得
 */ 
function getRoomIds() {
  var response = UrlFetchApp.fetch("https://api.chatwork.com/v2/rooms", {
    headers: {
      'X-chatWorkToken': chatWorkToken
    }
  });
  return JSON.parse(response.getContentText());
}

/**
 * JSONでPOSTする
 */ 
function send(jsonData, url) {
  
  var payload = JSON.stringify(jsonData);
  
  var options =
      {
        "method" : "post",
        "contentType" : "application/json",
        "payload" : payload
      };
  
  UrlFetchApp.fetch(url, options);
}

これを貼って保存すればOKです。試しにchatworkで適当なメッセージを自分宛に投げたあと、このスクリプトの chatworkToSlack を叩いてみてください。

以下のようにslackに投稿されればokです。

4. GoogleAppScriptで手順3を定期的に実行するトリガーを作る

あとはgasのトリガーを使って15分おきとか10分おきとかに叩きましょう。これであなたも15分以内に必ずクライアントのメッセージに気付けるスーパーマンです

まとめ

  • クライアントからのメッセージを1日以上スルーすることがなくなった
  • クライアントからのメッセージをslackで手軽にチームメンバーに共有できるようになった

明日は弊社でインターンをしているスーパー高校生の @nyanko-kota ですー、お楽しみに

参考資料


See also