Trelloのラベリング機能を自動化した[PHP7.3, Trello REST API, cron]

新型コロナウイルスの影響でリモート化した大学の講義の管理をTrelloで行っていたのだが、どうしても自動化した方がいいと思う部分があったので、自動化した。

##前までの僕のリモート講義管理方法
① `大学` という名前のボードを作成。
②`月` ~ `金` という名前のリストを作る。
③その内部で、それぞれの曜日にある授業の講義名のカードを作り、
④受けないといけない講義動画が配信されているのが確認されたら、該当カードに赤色のラベルを貼る。
⑤講義を受け、提出物を提出した後、赤ラベルを消す

という管理方法をとっていた。

<img width="1152" alt="スクリーンショット 2020-05-28 18.47.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382190/f1c78c16-eaa5-d2cb-02fd-9faa6134db75.png">


###どこを自動化するか
上記 ④ の、受けないといけない講義動画が配信されているのが確認されたら、該当カードに赤色のラベルを貼る。
という部分は、動画が配信される時間は決まっていたので、該当時間に自動で赤ラベルを貼ってくれるようにできそうだなと思った。

##実装の流れ
①Trello Developer APIのキーとトークンを取得する
②Trello developer公式ドキュメントを参考に実装
③ ② で作成したファイルを該当時間に実行されるようcrontabを設定

###①Trello Developer APIのキーとトークンを取得する
1. まず、ブラウザ上でtrelloをログイン状態にする。

2. ↓のURLに飛ぶと、一番上にKeyが表示される。
https://trello.com/app-key
また、Keyのちょうど下にTokenが取得できるurlリンクがあるのでそこをクリックすると、tokenが発行される。
これらのkeyとtokenをメモ。

![スクリーンショット 2020-05-28 19.17.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382190/41e16cf0-f891-3938-a004-ffc2da02c9e6.png)



###②Trello developer公式ドキュメントを参考に実装
[Trello developer公式ドキュメント](https://developer.atlassian.com/cloud/trello/rest/)に色々載ってるのでこれを参考に実装していく。

####ファイル構成
ファイル構成はこんな感じにした。

```
.
├── exec.php //実行するファイル(バッチファイル)
├── trelloAutomationController.php //処理全般
└── trelloInfoConstant.php //固定情報を置いておくファイル
```

固定情報

```ruby:trelloInfoConstant.php
<?php
class TrelloInfoConstant
{
    public $baseUrl   = 'https://api.trello.com/1';
    #①で取得したkey,token
    public $key       = '';
    public $token     = '';
    #適用させるボード名の指定
    public $boardName = '大学'; #(例)
}
```

処理全般

```ruby:trelloAutomationController.php
<?php
require("/Users/naoki/trello_automation/trelloAutomation/trelloInfoConstant.php");

class trelloAutomation extends TrelloInfoConstant
{
    /**
     * curlの共通実行部分の関数科
     * 
     * @param string $curl
     * @param string $parameter
     * @return string
     */
    public function execCurlProcess($curl, $parameter){
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $parameter);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 証明書の検証を行わない
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);  // curl_execの結果を文字列で返す
        return curl_exec($curl);;
    }

    /**
     * 特定のボードのboardIdの取得
     * 取得できない場合はfalseを返す。
     * 
     * @return string|bool
     */
    public function getBoardIdByBoardName(){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $this->baseUrl. '/members/me/boards?key=' . $this->key . '&token=' . $this->token);
        $response = $this->execCurlProcess($curl, 'GET');
        $boardsInfo   = json_decode($response, true);
        curl_close($curl);
        foreach ($boardsInfo as $board) {
            if ($board['name'] == $this->boardName) {
                return $board['id'];
            }
        }
        return false;
    }

    /**
     * 特定のリストのlistIdの取得
     * 取得できない場合はfalseを返す。
     * 
     * @param string $boardId
     * @param string $dayOfTheWeek
     * @return string|bool
     */
    public function getListIdByBoardId($boardId, $dayOfTheWeek) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $this->baseUrl. '/boards/' . $boardId . '/lists?key=' . $this->key . '&token=' . $this->token);
        $response = $this->execCurlProcess($curl, 'GET');
        $listsInfo   = json_decode($response, true);
        curl_close($curl);

        //特定のリストのid取得
        foreach ($listsInfo as $key => $list) {
            if ($list['name'] ==  $dayOfTheWeek) {
                return $list['id'];
            }
        }
        return false;
    }

    /**
     * 特定のリスト内の全カード情報の取得
     * 取得できない場合はfalseを返す。
     * 
     * @param string $listId
     * @return array|bool
     */
    public function getCardsInfoByListId($listId){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $this->baseUrl. '/lists/' . $listId . '/cards?key=' . $this->key . '&token=' . $this->token);
        $response = $this->execCurlProcess($curl, 'GET');
        curl_close($curl);
        return json_decode($response, true);
    }

    /**
     * 特定のリスト内の全カードへのラベリング実行
     * 
     * @param array $cardInfo
     * @param string $color
     */
    public function execLabelingToCardsInList($cardsInfo, $color) {  
        foreach ($cardsInfo as $card) {
            $cardId  = $card['id'];
            $cardName = $card['name'];
            $color   = $color;
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $this->baseUrl. '/cards/' . $cardId . '/labels?color=' . $color . '&key=' . $this->key . '&token=' . $this->token);
            $response = $this->execCurlProcess($curl, 'POST');
            $result   = json_decode($response, true);
            curl_close($curl);
            if (is_null($result)) {
                echo "already labbeled on " . $cardName . PHP_EOL;
            } else {
                echo "labbeled on " . $cardName . " successfuly" . PHP_EOL;
            }
        }
    }
}
```

実行ファイル (バッチファイル)

```ruby:exec.php
<?php
require("/Users/naoki/trello_automation/trelloAutomation/trelloAutomationController.php");
//引数 1 曜日
//引数 2 ラベルの色

class Exec extends trelloAutomation
{
     /**
     *　該当変数がfalseな場合処理をexit
     * 
     * @param array $variableName
     * @param string $arg
     */
    public function argumentExists($variableName, $arg=false) {
        if (!$arg) {
            echo "could not find " . $variableName;
            exit;
        }
        return true;
    }
}

$dayOfTheWeek = $argv[1];
$labelingColor = $argv[2];

$exec = new Exec;
$boardId = $exec->getBoardIdByBoardName(); //boardId取得
$exec->argumentExists('board_id', $boardId);
$listId = $exec->getListIdByBoardId($boardId, $dayOfTheWeek); //特定のリストId取得
$exec->argumentExists('list_id', $listId);
$cardsInfo = $exec->getCardsInfoByListId($listId); //リスト内のカード情報取得
$exec->argumentExists('cards_info', $cardsInfo);
$exec->execLabelingToCardsInList($cardsInfo, $labelingColor); //ラベリング実行第二引数でラベルの色指定

```

火曜以下省略。

###③ ② で作成したファイルを該当時間に実行されるようcrontabを設定
毎週授業がある曜日の朝9時に特定ファイルが実行されるように設定。

1.crontabを開く

```
$crontab -e
```

以下のように設定する。

```
#0 9 * * 1 php /path/to/exec.php 月 red #mondayExec.phpへの絶対パス（以下同様）
#0 9 * * 3 php /path/to/exec.php 水 red #第一引数に曜日、第二引数にラベルの色を指定
#0 9 * * 4 php /path/to/exec.php 木 red
#0 9 * * 5 php /path/to/exec.php 金 red
```

cronの設定方法に関しての詳細はここでは省略させてもらいますが、
簡単に説明すると、

```
#0 9 * * 1 php /path/to/exec.php 月 red
```

上記の一行は、
`0 9 * * 1` この時刻に、 `php /path/to/exec.php 月 red` これを実行するという意味合いがあります。


`0 9 * * 1`　は　`分 時 日 月 曜`　の順番にならんでおり、　
-> 曜日は `1 2 3 4 5 6 7 0` の順で `月 火 水 木 金 土 日 日` となっています。

つまり上記の一文の場合、毎週9時に、/path/to/mondayExec.phpを実行するということです。

くわしくは[このへん](https://qiita.com/katsukii/items/d5f90a6e4592d1414f99)に載っているのでもっと詳しく知りたい方は見てみてください。

一応これで毎週手動で行っていたラベル付けを自動化することができました。

##最後に
この記事で紹介したものをgithubでも公開しています。
省略している部分も全て記載しているので参考にしてくださるとありがたいです。
https://github.com/Naoki206/trelloAutomation