Trello + Discord 連携メモ

✏️ 編集

公式ドキュメント:

参考記事:

Discord の Webhook URL を取得

普通に用意

image.png (29.3 kB)

Trello の API キー、トークンを取得

  1. Trello にログインしている状態で次のページにアクセス

開発者向け API キー

  1. API キー、トークンを取得する
  • API キー:
    • パーソナルキー の欄にある英数字の羅列
  • トークン:
      1. トークン へアクセス
      1. アプリケーションにアカウントへのアクセスを許可
      1. 発行されたトークンをメモ
  1. 下記コマンドを実行してレスポンスが返ってきていれば OK
1
2
curl --request GET \
  --url 'https://api.trello.com/1/members/me/boards?key={APIKey}&token={APIToken}'

GAS と連携

  1. 通知用チャンネルを作成(権限に Bot を追加しておかないと、Bot から通知できないので注意)
image.png (31.8 kB)
  1. GAS プロジェクトを作成

GAS プロジェクト: trello_notifier_bot

  1. GAS から Discord へ通知を送れるかテスト

Discord の Webhook URL は環境変数的なものなので、プロジェクト設定からスクリプトプロパティへ追加

image.png (18.7 kB)

サンプルコード:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function myFunction() {
  const scriptProps = PropertiesService.getScriptProperties().getProperties();

  const payload = {
    content: "content",
    embeds: [
      {
        title: "title",
        description: "description",
      },
    ],
  };

  const payloads = [
    {
      url: scriptProps.DISCORD_WEBHOOK_URL,
      contentType: "application/json",
      payload: JSON.stringify(payload),
    },
  ];

  UrlFetchApp.fetchAll(payloads);
}

動作結果: image.png (9.1 kB)

Trello に Webhook を登録する

下記 POST を送信する。 callbackURL には GAS プロジェクトをデプロイしたときに発行される URL を入れる。 idModel は変更を検知したいボードの ID を入れる。

1
2
3
4
5
6
7
8
curl -X POST -H "Content-Type: application/json" \
https://api.trello.com/1/tokens/{APIToken}/webhooks/ \
-d '{
  "key": "{APIKey}",
  "callbackURL": "http://www.mywebsite.com/trelloCallback",
  "idModel":"4d5ea62fd76aa1136000000c",
  "description": "My first webhook"
}'

引用: https://developer.atlassian.com/cloud/trello/guides/rest-api/webhooks/#creating-a-webhook

うまくいくと、下記コードの場合、登録したボードに変更を加えると doPost という文字列が Discord へ送信される。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function doPost(e) {
  postToDiscord("doPost");
}

function postToDiscord(content) {
  const payload = {
    content: content,
  };

  const payloads = [
    {
      url: scriptProps.DISCORD_WEBHOOK_URL,
      contentType: "application/json",
      payload: JSON.stringify(payload),
    },
  ];

  UrlFetchApp.fetchAll(payloads);
}

callbackURLURL は全て大文字なので注意(間違えると、 Value isn't a string. というメッセージが返ってくる)

When creating a webhook, the error “Value isn’t a string.” - Trello - The Atlassian Developer Community

次の手順で Webhook の登録を行えるようにした:

  1. 新しいデプロイ > アクセスできるユーザ: 自分のみ にしてデプロイ
  2. createWebhook() を実行
  3. デプロイを管理 > アクセスできるユーザ: 全員 に変更
  4. Trello のボードに変更を加えた時、Discord へ通知が来れば OK

手順 1 で アクセスできるユーザ: 自分のみ する理由は、全体公開にすると 403 エラーが返ってくるかららしい。

参考: GAS を使って trello webhook を受ける時のハマりどころ - Qiita

1 回作成された Webhook を再度作ろうとするとエラーになる。 新しいデプロイ を実施することで暫定的に回避できる。

GAS 変更の反映方法

GAS のコードを変更したら 新しいデプロイ を行わないと反映されない。ただし、 新しいデプロイ をすると Callback URL が変わってしまう。

その場合、 デプロイを管理 から新バージョンとしてデプロイすることで、URL を変更せずに反映できる。

image.png (27.4 kB)

参考:

doPost(e) で受け取る情報

受け取った情報に Action ID があるので、それを使ってアクション詳細を取得するのが良さそう

The Trello REST API

例1)カードのリストを移動した場合:


{
    "id": "63712c0f23c9cc02ffa935ef",
    "idMemberCreator": "5da3f38080e88b1af8e8ff86",
    "data": {
        "card": {
            "idList": "5dd692ca0897377466449231",
            "id": "627bc1e708099f5b7124c099",
            "name": "1曲目の前に名乗り, 挨拶と常套句(余裕があったら)",
            "idShort": 26,
            "shortLink": "cs179j1u"
        },
        "old": {
            "idList": "627bc1c16397f33d596253c0"
        },
        "board": {
            "id": "5dd692c956a9247b4140e18b",
            "name": "2022秋ライブ",
            "shortLink": "szHdDf00"
        },
        "listBefore": {
            "id": "627bc1c16397f33d596253c0",
            "name": "やりたいこと"
        },
        "listAfter": {
            "id": "5dd692ca0897377466449231",
            "name": "やること"
        }
    },
    "appCreator": null,
    "type": "updateCard",
    "date": "2022-11-13T17:40:31.715Z",
    "limits": null,
    "display": {
        "translationKey": "action_move_card_from_list_to_list",
        "entities": {
            "card": {
                "type": "card",
                "idList": "5dd692ca0897377466449231",
                "id": "627bc1e708099f5b7124c099",
                "shortLink": "cs179j1u",
                "text": "1曲目の前に名乗り, 挨拶と常套句(余裕があったら)"
            },
            "listBefore": {
                "type": "list",
                "id": "627bc1c16397f33d596253c0",
                "text": "やりたいこと"
            },
            "listAfter": {
                "type": "list",
                "id": "5dd692ca0897377466449231",
                "text": "やること"
            },
            "memberCreator": {
                "type": "member",
                "id": "5da3f38080e88b1af8e8ff86",
                "username": "user36408094",
                "text": "山本雄太"
            }
        }
    },
    "memberCreator": {
        "id": "5da3f38080e88b1af8e8ff86",
        "activityBlocked": false,
        "avatarHash": "bd843173354efbec0932501d2c787a46",
        "avatarUrl": "https://trello-members.s3.amazonaws.com/5da3f38080e88b1af8e8ff86/bd843173354efbec0932501d2c787a46",
        "fullName": "山本雄太",
        "idMemberReferrer": null,
        "initials": "山本太",
        "nonPublic": {},
        "nonPublicAvailable": true,
        "username": "user36408094"
    }
}

例2)同一リスト内でカードを入れ替えた場合:


{
    "id": "63712d7e1d8da00421bd3234",
    "idMemberCreator": "5da3f38080e88b1af8e8ff86",
    "data": {
        "card": {
            "pos": 229375,
            "id": "627bc2098e68668fe44d5219",
            "name": "背景と照明であわせる",
            "idShort": 28,
            "shortLink": "htmAcLHf"
        },
        "old": {
            "pos": 131071
        },
        "board": {
            "id": "5dd692c956a9247b4140e18b",
            "name": "2022秋ライブ",
            "shortLink": "szHdDf00"
        },
        "list": {
            "id": "627bc1c16397f33d596253c0",
            "name": "やりたいこと"
        }
    },
    "appCreator": null,
    "type": "updateCard",
    "date": "2022-11-13T17:46:38.819Z",
    "limits": null,
    "display": {
        "translationKey": "action_moved_card_higher",
        "entities": {
            "card": {
                "type": "card",
                "pos": 229375,
                "id": "627bc2098e68668fe44d5219",
                "shortLink": "htmAcLHf",
                "text": "背景と照明であわせる"
            },
            "memberCreator": {
                "type": "member",
                "id": "5da3f38080e88b1af8e8ff86",
                "username": "user36408094",
                "text": "山本雄太"
            }
        }
    },
    "memberCreator": {
        "id": "5da3f38080e88b1af8e8ff86",
        "activityBlocked": false,
        "avatarHash": "bd843173354efbec0932501d2c787a46",
        "avatarUrl": "https://trello-members.s3.amazonaws.com/5da3f38080e88b1af8e8ff86/bd843173354efbec0932501d2c787a46",
        "fullName": "山本雄太",
        "idMemberReferrer": null,
        "initials": "山本太",
        "nonPublic": {},
        "nonPublicAvailable": true,
        "username": "user36408094"
    }
}

例3)カードにコメントを追加した場合:


{
    "id": "63712df1630c6c05daf96fd0",
    "idMemberCreator": "5da3f38080e88b1af8e8ff86",
    "data": {
        "text": "aaaaa",
        "textData": {
            "emoji": {}
        },
        "card": {
            "id": "627bc1e708099f5b7124c099",
            "name": "1曲目の前に名乗り, 挨拶と常套句(余裕があったら)",
            "idShort": 26,
            "shortLink": "cs179j1u"
        },
        "board": {
            "id": "5dd692c956a9247b4140e18b",
            "name": "2022秋ライブ",
            "shortLink": "szHdDf00"
        },
        "list": {
            "id": "5dd692ca0897377466449231",
            "name": "やること"
        }
    },
    "appCreator": null,
    "type": "commentCard",
    "date": "2022-11-13T17:48:33.824Z",
    "limits": {
        "reactions": {
            "perAction": {
                "status": "ok",
                "disableAt": 900,
                "warnAt": 720
            },
            "uniquePerAction": {
                "status": "ok",
                "disableAt": 17,
                "warnAt": 14
            }
        }
    },
    "display": {
        "translationKey": "action_comment_on_card",
        "entities": {
            "contextOn": {
                "type": "translatable",
                "translationKey": "action_on",
                "hideIfContext": true,
                "idContext": "627bc1e708099f5b7124c099"
            },
            "card": {
                "type": "card",
                "hideIfContext": true,
                "id": "627bc1e708099f5b7124c099",
                "shortLink": "cs179j1u",
                "text": "1曲目の前に名乗り, 挨拶と常套句(余裕があったら)"
            },
            "comment": {
                "type": "comment",
                "text": "aaaaa"
            },
            "memberCreator": {
                "type": "member",
                "id": "5da3f38080e88b1af8e8ff86",
                "username": "user36408094",
                "text": "山本雄太"
            }
        }
    },
    "memberCreator": {
        "id": "5da3f38080e88b1af8e8ff86",
        "activityBlocked": false,
        "avatarHash": "bd843173354efbec0932501d2c787a46",
        "avatarUrl": "https://trello-members.s3.amazonaws.com/5da3f38080e88b1af8e8ff86/bd843173354efbec0932501d2c787a46",
        "fullName": "山本雄太",
        "idMemberReferrer": null,
        "initials": "山本太",
        "nonPublic": {},
        "nonPublicAvailable": true,
        "username": "user36408094"
    }
}

例4)さらにコメントを追加した場合:


{
    "id": "63712e485c9137001535ed3f",
    "idMemberCreator": "5da3f38080e88b1af8e8ff86",
    "data": {
        "text": "bbbbb",
        "textData": {
            "emoji": {}
        },
        "card": {
            "id": "627bc1e708099f5b7124c099",
            "name": "1曲目の前に名乗り, 挨拶と常套句(余裕があったら)",
            "idShort": 26,
            "shortLink": "cs179j1u"
        },
        "board": {
            "id": "5dd692c956a9247b4140e18b",
            "name": "2022秋ライブ",
            "shortLink": "szHdDf00"
        },
        "list": {
            "id": "5dd692ca0897377466449231",
            "name": "やること"
        }
    },
    "appCreator": null,
    "type": "commentCard",
    "date": "2022-11-13T17:50:00.381Z",
    "limits": {
        "reactions": {
            "perAction": {
                "status": "ok",
                "disableAt": 900,
                "warnAt": 720
            },
            "uniquePerAction": {
                "status": "ok",
                "disableAt": 17,
                "warnAt": 14
            }
        }
    },
    "display": {
        "translationKey": "action_comment_on_card",
        "entities": {
            "contextOn": {
                "type": "translatable",
                "translationKey": "action_on",
                "hideIfContext": true,
                "idContext": "627bc1e708099f5b7124c099"
            },
            "card": {
                "type": "card",
                "hideIfContext": true,
                "id": "627bc1e708099f5b7124c099",
                "shortLink": "cs179j1u",
                "text": "1曲目の前に名乗り, 挨拶と常套句(余裕があったら)"
            },
            "comment": {
                "type": "comment",
                "text": "bbbbb"
            },
            "memberCreator": {
                "type": "member",
                "id": "5da3f38080e88b1af8e8ff86",
                "username": "user36408094",
                "text": "山本雄太"
            }
        }
    },
    "memberCreator": {
        "id": "5da3f38080e88b1af8e8ff86",
        "activityBlocked": false,
        "avatarHash": "bd843173354efbec0932501d2c787a46",
        "avatarUrl": "https://trello-members.s3.amazonaws.com/5da3f38080e88b1af8e8ff86/bd843173354efbec0932501d2c787a46",
        "fullName": "山本雄太",
        "idMemberReferrer": null,
        "initials": "山本太",
        "nonPublic": {},
        "nonPublicAvailable": true,
        "username": "user36408094"
    }
}

Hugo で構築されています。
テーマ StackJimmy によって設計されています。