Trelloのタスクの移動を検知して、irucaのステータスを変更する

# やりたいこと
今、irucaで勤務ステータスの管理をしていて、PCのログインログアウトで自動打刻している。（誰かが作ってくれたらしい、ありがとう。）
個人的には、trelloのかんばんボードを使って「よし、これから手をつけるぞ！」って思ったタイミングが業務開始の方がしっくりくる。
→かんばんボードで「勤怠報告（出勤）」「勤怠報告（退勤）」を「完了」リストに移動したときに、irucaのステータス更新をしてみることにする。
勤怠システムの打刻、とかでもありだと思う。（実はこれを目指してた）

![スクリーンショット 2021-11-29 20.25.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74969/315edd61-8833-5eeb-06c7-888cf642dd00.png)


# 概要
- Trelloのイベントを取得する仕組みは以下の通り。
![スクリーンショット 2021-11-29 20.36.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74969/828e7263-de48-2250-7714-56ad0b92a1f9.png)


# POSTパラメータからの処理
長いのでリンクで、、、
https://github.com/prettyhappycatty/gas_trello_iruca/blob/main/doPost.gs

- カードのイベントを確認（移動でなければリターン）
- カードのタイトルを確認（「勤怠報告」かどうか）
    - 勤怠報告（出勤）ならirucaの出勤メソッドを呼び、iruca連携済みラベルを追加
    - 勤怠報告（出勤）ならirucaの退勤メソッドを呼び、iruca連携済みラベルを追加
    
# iruca出勤メソッドと退勤メソッド

管理→ルーム設定→外部連携→API連携情報

- ROOM_CODE irucaのルームコード
- MEMBER_ID 変更したいメンバーのメンバーID
 
![スクリーンショット 2021-11-29 20.57.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74969/847a83dd-dc30-d01f-5fd3-203fa7b08233.png)

doPostから呼び出している関数2つ

```javascript:iruca.gs
//出勤用
function sendIrucaEntry(member_id, room_code, dt_str) {
  var requestUrl = "https://iruca.co/api/rooms/"+room_code+"/members/"+member_id

  requestBody = mkIrucaPostData('在席') //在席、退社 
  // POSTオプション
  var options = {
    "method":"PUT",
    'headers': {'ContentType': 'application/json'},
    "payload":requestBody,
    muteHttpExceptions: true
  };
  
  var res = UrlFetchApp.fetch( requestUrl , options );
}

//退勤用
function sendIrucaExit(member_id, room_code, dt_str) {
  var requestUrl = "https://iruca.co/api/rooms/"+room_code+"/members/"+member_id

  requestBody = mkIrucaPostData('退社') //在席、退社 
  // POSTオプション
  var options = {
    "method":"PUT",
    'headers': {'ContentType': 'application/json'},
    "payload":requestBody,
    muteHttpExceptions: true
  };
  
  var res = UrlFetchApp.fetch( requestUrl , options );
}

function mkIrucaPostData(status){

  return {
    "status": status,
  }

}
```
# webhookの登録
Trelloのwebhookを登録する。
[Trello API リファレンス](https://developer.atlassian.com/cloud/trello/rest/api-group-webhooks/#api-webhooks-post)によると、webhookの登録には以下の4つの情報が必要。

- TRELLO_KEY https://trello.com/1/appKey/generate　から確認
- TRELLO_TOKEN　https://trello.com/1/appKey/generate　から作成
- callbackUrl　※あとから作成するURLです
- boardId 自分のボードのID※以下の関数を実行して取得できます

```javascript:trello.gs
function getBoards() {

  let params = {
    'method': 'GET',
    'headers': {'ContentType': 'application/json'},
  };
  let requestUrl = 'https://api.trello.com/1/members/' + TRELLO_USER_ID + '/boards'
          + '?key=' + TRELLO_KEY
          + '&token=' + TRELLO_TOKEN;
  
  let result = UrlFetchApp.fetch(requestUrl, params).getContentText();
  return JSON.parse(result);
}
```

[別記事のGASでWe作るときにハマったメモ](https://qiita.com/meowmeowcats/items/634c6e084d863f303e72)を見つつ、権限に注意してから公開してください。
公開したURLを使って、以下のwebhook登録メソッドを呼びます。

```javascript:trello_webhook.gs

function createWebhook(){
  var requestUrl = 'https://api.trello.com/1/tokens/' + TRELLO_TOKEN + '/webhooks/?key=' + TRELLO_KEY;
  var options = {
    'method' : 'post',
    'headers': {'ContentType': 'application/json'},
    'payload' : {
      'description': 'Webhook of Trello',
      'callbackURL': callbackUrl,
      'idModel': boardId
    },
    'muteHttpExceptions' : true
  }
  Logger.log(UrlFetchApp.fetch(requestUrl, options));
}　
```


# 完成

![スクリーンショット 2021-11-29 21.05.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74969/023e9ddb-951f-da22-b2a1-863750d2161d.png)

ソースコードは以下にあります。ちょっとずつコードの揺れを修正していくかもしれないししないかもしれない。

https://github.com/prettyhappycatty/gas_trello_iruca

# 参照
- https://tech.toreta.in/entry/2019/12/09/210337

# おまけ

gasのWebアプリケーションは、新しいバージョン公開時にURLが変わるという超めんどくさい仕組みなので、旧webhookを消して新しいwebhookを登録できるようメソッドにしています。

```javascript:trello_webhook.gs
/*
 Webページのバージョンを変えるときに、WebhookのURLを塗り替える
 動作要件：公開されているWEBページが、「全員に公開」以外の権限であること
*/
function clearAndCreateWebhook(){
  id = getWebhook()
  if (id){
    deleteWebhook(id)
  }
  createWebhook()
}
```