JS.34 GASでTrelloのタスクを定期的に通知する。

2021-05-14(Fri) | tags: GAS

GASとは

Google Apps Script(GAS, ガス)とは、Googleが提供するサーバーサイド・スクリプト環境です。JavaScript ではありませんが、JavaScript っぽいのでここに記載しています。

なお、どんなことができるかは以前の記事 JS.13 GASでslackにメッセージを送る を参照していただければと思います。

Trello

Trelloは、カードを動かしながらタスクを視覚的に管理できるカンバン方式のツールです。付箋を貼るように直感的にタスクを管理できるのが使いやすく、普段から利用しているのですが、定期的にどのタスクが残っているのかslack等に通知できれば良いと思い、TrelloのAPIを用いてこれを実現しました。

※ APIを使うにあたり、API key と Token が必要になります。Trelloにログインした状態で https://trello.com/app-key にアクセスして取得してください。

なお、ボードIDは Get Memberships of a Boardというメソッドを用いればわかりますが、TrelloのAPIをPythonでWrapしたPython-Charmerspycharmers.api.trello というモジュールを利用すると、以下のように簡単に取得できます。

from pycharmers.api import Trello
trello = Trello(apikey="APIKEY", token="TOKEN")
trello.show_memberships_of_a_board(username="iwasakishuto")
+--------------+---------------------+--------------------------------------+
|     name     |         id          |             url                      |
+==============+=====================+======================================+
|  boardname1  |  id for boardname1  | https://trello.com/b/YYYY/boardname2 |
+--------------+---------------------+--------------------------------------+
|  boardname2  |  id for boardname1  | https://trello.com/b/XXXX/boardname2 |
+--------------+---------------------+--------------------------------------+

作成したもの

Trelloタスク管理

変数定義

セキュリティの観点から、API key や Token はコード内に直書きするのではなく、Propertyに書き、PropertiesService.getScriptProperties() で取得します。

const prop = PropertiesService.getScriptProperties();
const add_trello_params = function(url){
  return url + "?key=" + prop.getProperty("TRELLO_APIKEY") + "&token=" + prop.getProperty("TRELLO_TOKEN")
}
const url_get_lists_on_a_board = add_trello_params("https://api.trello.com/1/boards/" + prop.getProperty("TRELLO_BOARDID") + "/lists");
const url_cards_in_a_list      = add_trello_params("https://api.trello.com/1/boards/" + prop.getProperty("TRELLO_BOARDID") + "/cards");
const private_list_names       = ["Trash"]

getTasks

Trello から予定を取得します。

function getTasks(){
  var boardId2name = {}
  JSON.parse(UrlFetchApp.fetch(url_get_lists_on_a_board).getContentText()).forEach(function(e){
    boardId2name[e["id"]] = e["name"]
  })
  var list2cards = {}
  JSON.parse(UrlFetchApp.fetch(url_cards_in_a_list).getContentText()).forEach(function(e){
    var boardname = boardId2name[e["idList"]];
    if (boardname in list2cards){
      list2cards[boardname].push(e["name"])
    }else{
      list2cards[boardname] = [e["name"]]
    }
  })
  return list2cards
}

arrange_message

取得したタスクを、slackで見やすいように整形します。

function arrange_message(list2cards){
  text = ""
  var num_tasks = 0
  Object.keys(list2cards).forEach(function(l){
    if (!private_list_names.includes(l)){
      cards = list2cards[l]
      text += "\n*【" + l + "】(" + cards.length + ")*"
      num_tasks += cards.length
      cards.forEach(function(c){
        text += "\n\t\t* " + c
      })
    }
  })
  text = "今の <@UTANWKEBU> のタスク *(" + num_tasks + ")*" + text
  return text
}

postSlack

slack にメッセージを送ります。

function postSlack(payload){
  var options = {
    "method" : "POST",
    "payload" : JSON.stringify(payload)
  }
  var url = prop.getProperty("WEBHOOK_URL");
  var response = UrlFetchApp.fetch(url, options);
  var content = response.getContentText("UTF-8");
}

main

以上をまとめた関数です。

function main(){
  var list2cards = getTasks();
  var text = arrange_message(list2cards);
  postSlack({
    "channel"  : "#002_tasks",
    "username" : "文乃【秘書】",
    "text"     : text,
  })
}
other contents
social