Trello APIでカードの期限を一括で設定してみた

## 概要
Trelloで毎日使っているカードの期限をスクリプトで一括設定できるようにしたく、作成しました。

## 準備
### 1-1. APIキーの発行、Tokenの取得
Trello APIを使用するためにAPIキーとTokenを取得する必要があります。
*以下の記事を参考に取得しました。

https://qiita.com/HiguchiTakahiro/items/94f52eee07d257f8f995

### 1-2. 設定
以下の変数をスクリプト内に記載し、環境に合わせて設定してください。

```python
KEY = "APIキー"
TOKEN = "APIトークン"
USER_NAME = "Trelloユーザー名"
TARGET_BOARD_NAME = "対象のボード名"
TARGET_LIST_NAME = "対象のリスト名"
```
### 2-1. 実行
ターミナルからスクリプトを実行します

```bash
python3 update_due_date.py
```

### 3-1. 動作例
スクリプトを実行すると、指定されたリスト内のすべてのカードの期限が一括で設定されます。以下の条件でカードの期限が設定されます。

当日22時より前にスクリプトを実行した場合: カードの期限は「当日22時」に設定されます。
当日22時以降にスクリプトを実行した場合: カードの期限は「翌日22時」に設定されます。

## サンプル
以下はスクリプト全体のコードです。

```python
#!/usr/bin/env python3
from datetime import datetime, timedelta
import sys
import requests


KEY = ""   # 取得したAPIキーを代入
TOKNE = "" # 取得したAPIトークンを代入

USER_NAME = "" # Trelloのユーザー名を代入

TARGET_BOARD_NAME = "" # ボードの名前を代入
TARGET_LIST_NAME = "" # 操作したいリストの名前を代入

# client
class client:
    def __init__(self, key, token):
        self.key = key
        self.token = token

    def send_requests(self, url, data, method):
        try:
            headers = {"Accept": "application/json"}
            query = {'key': self.key,'token': self.token}
            if data:
                response = requests.request(
                method,
                url,
                headers=headers,
                params=query,
                json=data
                )
            else:
                response = requests.request(
                method,
                url,
                headers=headers,
                params=query,
            )
            status_code = response.status_code
        except Exception as e:
            print(f"#### send_requests failed with error: {e}, status_code = {status_code}")
            sys.exit(1)

        return response.json()


    def get_user_information(self, user_name):
        url = f"https://api.trello.com/1/members/{user_name}"
        user_information = self.send_requests(url, None, "GET")

        return user_information


    def get_board_information(self, board_ids):
        board_list = []
        for board_id in board_ids:
            url = f"https://api.trello.com/1/boards/{board_id}"
            board_information = self.send_requests(url, None, "GET")
            board_list.append(board_information)

        board_dict = {board["name"]: board for board in board_list}

        return board_dict

    def get_lists_on_board(self, board_id):
        url = f"https://api.trello.com/1/boards/{board_id}/lists"
        list_on_board = trello_client.send_requests(url, None, "GET")
        list_dict = {board["name"]: board for board in list_on_board}

        return list_dict

    def get_cards(self, list_id):
        url = f"https://api.trello.com/1/lists/{list_id}/cards"
        result = self.send_requests(url, None, "GET")

        return result

    def update_due_date(self, card_id, due_date: datetime):
        due_date = due_date - timedelta(hours=9) # カードに期限を追加する際に+9時間されるので追加
        url = f"https://api.trello.com/1/cards/{card_id}"
        result = self.send_requests(url, {"due": due_date.strftime("%Y-%m-%dT%H:%M:%S.000Z")}, "PUT")

        return result

# card
class card:
    def __init__(self, name: str, detail: dict):
        self.name = name
        self.detail = detail

    def get_due_date(self):
        due = self.detail.get("due", None)
        if not due:
            return

        due_date = datetime.strptime(due, "%Y-%m-%dT%H:%M:%S.000Z")

        return due_date + timedelta(hours=9)

    def settings_new_due_for_habit_card(self):
        day = datetime.now()
        today = datetime(day.year, day.month, day.day, hour=22, minute=0)

        due_date = self.get_due_date()
        if due_date:
            return today if day.hour < 22 else today + timedelta(days=1)

        return


if __name__ == "__main__":
    trello_client = client(KEY, TOKNE)

    user_information = trello_client.get_user_information(USER_NAME)

    board_dict = trello_client.get_board_information(user_information["idBoards"])
    target_board = board_dict[TARGET_BOARD_NAME]

    lists_on_board = trello_client.get_lists_on_board(target_board["id"])

    target_list_information = lists_on_board[TARGET_LIST_NAME]
    cards_on_list = trello_client.get_cards(target_list_information["id"])

    for card_on_list in cards_on_list:
        trello_card = card(card_on_list["name"], card_on_list)
        print(f"card name = {trello_card.name}")

        new_due_date = trello_card.settings_new_due_for_habit_card()
        if new_due_date:
            trello_client.update_due_date(trello_card.detail["id"], new_due_date)
```

## 参考
https://developer.atlassian.com/cloud/trello/rest/api-group-actions/#api-group-actions