社内で Chatwork を使用しており、作業報告が毎週定例化してきたので、Chatwork API を使用して作業報告を自動化してみた。

作業報告の内容としては直近1週間で完了したタスクの一覧を出力する形式である。

その場合 Chatwork API ではタスクの完了日を取得することができないため、メッセージからタスク完了時の識別子を正規表現で抜き出すことで完了したタスクの一覧を取得する必要がある。
またメッセージを取得する場合はルームを指定しなければならないため、

Chatwork API のドキュメントには JavaScript のコードがあるが、CORS により JavaScript では取得できないため、レンサバで利用可能であった PHP でコードを記述した。

まず Composer でライブラリをインストールする。

composer require guzzlehttp/guzzle

その後、以下のようなコードを記述する。
※ループ処理がブサイクだが短く書きたかったのでご愛嬌

<?php

require_once( 'vendor/autoload.php' );
getDoneTask( 'ルーム名', ルームID(int型), アカウントID(int型) );

function getDoneTask ( $roomName, $roomID, $accountID ) {
  $client = new \GuzzleHttp\Client();
  $nowDate = new DateTime( date( 'Y/m/d H:i:s' ) );
  $response = $client->request( 'GET', 'https://api.chatwork.com/v2/rooms/' . $roomID . '/messages?force=1', [
    'headers' => [
      'Content-Type' => 'application/json',
      'accept' => 'application/json',
      'x-chatworktoken' => 'トークン',
    ],
  ] );
  $jsonString = $response->getBody()->getContents();
  if ( $statusCode = $response->getStatusCode() === 200 ) {
    $json = json_decode( $jsonString, true, 512, JSON_UNESCAPED_UNICODE );
    $json = array_reverse( $json );
    echo '<h2>' . $roomName . '</h2>';
    $week1 = true;
    $week2 = true;
    foreach ( $json as $obj ) {
      if ( ( strpos( $obj[ 'body' ], '[dtext:task_done]' ) || strpos( $obj[ 'body' ], '作業完了報告' ) ) && $obj[ 'account' ][ 'account_id' ] === $accountID ) {
        $date = date( 'Y/m/d H:i:s', $obj[ 'send_time' ] );
        $url = 'https://www.chatwork.com/#!rid' . $roomID . '-' . $obj[ 'message_id' ];
        $diff = $nowDate->diff( new DateTime( $date ) )->format('%a');
        if ( (int)$diff < 7 ) {
          if ( $week1 ) {
            $week1 = false;
            echo '<details><summary>直近1週間</summary>';
          }
          _insertItem( $date, $url, $obj[ 'body' ] );
        } else if ( (int)$diff < 14 ) {
          if ( $week2 ) {
            $week2 = false;
            echo '</details>';
            echo '<details><summary>直近2週間</summary>';
          }
          _insertItem( $date, $url, $obj[ 'body' ] );
        } else {
          echo '</details>';
        }
      }
    }
  }
}

function _insertItem ( $date, $url, $body ) {
  echo '<div class="item">';
  echo '  <span>' . $date . '</span>';
  echo '  <a href="' . $url . '">' . $url . '</a>';
  echo '  <pre><code>' . htmlspecialchars( preg_replace( '/\[.+?\]/', '', $body ) ) . '</code></pre>';
  echo '</div>';
}

このコードの工夫した点・注意点としては、以下のような感じ。

  • API で取得した JSON では古い順に取得するため、PHP で処理する前に array_reverse を行っていること
  • API では日付を指定してクエリを発行することができないため、DateTime クラスを使用して日付指定していること
  • API では最大 100 件までしかメッセージを取得できないため、100件より前のメッセージで完了したタスクがある場合は取得できないこと
  • がんばればタスクの依頼者を取得できたかもしれないが、あきらめてメッセージ本文のみ出力している
  • メッセージ本文は Unicode エスケープされており、メッセージ送信日はUNIX タイムスタンプが利用されているため、それぞれ変換処理が必要
  • 指定したルーム以外でも完了したタスクがあったり、タスク化されていないものがあったりするので、メッセージ本文に「作業完了報告」の文字を入れたものは出力されるように設定
  • 定期報告会と祝日がかぶった場合に備え、直近2週間も出力