Googleスプレッドシートのタスクリストをslackへ通知

この記事は、[Supershipグループ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/supership)の12日目の記事になります。

去年は[Google Calendar APIを利用した便利ツールについての記事を作成しました](https://qiita.com/suzukitheseventh/items/58e29fba080f44630d5a)が今年は、Google Sheets APIを利用した便利ツールの記事にしようと思います。


# 目的
Googleスプレッドシートで作成したタスクリストをslackに通知する方法を記載します。
GASではなくPythonです。
「GASではなくPythonで色々いじりたい」という方向けに参考になれば良いなと思います。



# 前提環境
### 利用したもの
 - Python3
 - Googleスプレッドシート
 - Google Sheets API 
 - Slack Incoming Webhook
 - macのターミナル
 - crontab





# 仕組み概要
1. Googleスプレッドシートで作成したタスクリストを
1. [Sheet API](https://developers.google.com/sheets/api/quickstart/python)を利用して読み込み、選別した結果を組み込んだ通知文章を
1. [slack incoming webhook](https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8)でslackへ送るスクリプトを
1. crontabで定期実行します。


# 仕組み詳細

### タスクリスト作成
Googleスプレッドシートでタスクリストを作成します。

|  タスク名  |  状況  |(→以降自由)|(例)詳細|(例)締め切り|
| ---- | ---- | ---- | ---- | ---- | ---- |
|  AAA  |  完了  ||ドキュメントリンク|yyyymmdd|
|  BBB  |  実施中  ||ドキュメントリンク|yyyymmdd|
|  CCC  |  未着手  ||ドキュメントリンク|yyyymmdd|

(以下は必須ではないですがやっておくとbetterと思われることです。)

 - [データの入力規則の設定](https://support.google.com/docs/answer/186103?hl=ja&co=GENIE.Platform%3DDesktop)で「状況」列を上記3種のステータスのみを選択する設定。
    - 利用者が想定外の値を入力しないようにする目的です。
 - [条件付き書式の設定](https://support.google.com/docs/answer/78413?hl=ja&co=GENIE.Platform%3DDesktop)で「状況」列が「完了」のものはその行の色がグレーになる設定。
    - シートを見たときに見やすくする目的です。


### Google API tokenの準備

公式のマニュアルをご確認いただき、tokenの準備を行ってください。
スクリプト作成当時はtokenがpickleという形式でしたが、2021年12月現在json形式で保存されているなど、今後もGoogle側での更新があることを考慮し詳細は省かせていただきます。

### slackのIncoming Webhook準備
こちらも公式のマニュアルをご確認いただき準備を行ってください。
最初はlegacy tokenと呼ばれる権限強めのものが利用されていたのですが、途中から権限範囲が狭まったものがデフォルトになるなど、slack側での更新があることを考慮し詳細は省かせていただきます。


### スクリプト準備
下記をコピーして、

 - `SAMPLE_SPREADSHEET_ID`
 - `text`内の文章
 - `webhook_url`

あたりを変更した上で.pyファイルで保存してください。


```python
### 公式マニュアル https://developers.google.com/sheets/api/quickstart/python を参考

###library import部分。更新ある可能性があるため該当部分省略。公式マニュアルをご確認ください。
from slack_sdk.webhook import WebhookClient ### slack用のlibraryなのでSheets APIのlibrary群に追加してこちらもimportしてください。

### If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']

### The ID and range of a sample spreadsheet.
SAMPLE_SPREADSHEET_ID = '読みたいスプレッドシートのID(URLの一意の部分。↓のtextの「を参照してます」付近を参考)'
SAMPLE_RANGE_NAME = 'Class Data!A2:E'

def main():
    """Shows basic usage of the Sheets API.
    Prints values from a sample spreadsheet.
    """
 
    ###省略。公式マニュアルをご確認ください。

    if not values:
        print('No data found.')
    else:

### -----以下公式マニュアルから変更加えた部分-----

        list_working = []
        list_not_working = []
        
        for row in values:
            ### Print columns A and E, which correspond to indices 0 and 4.
            if row[1] == '実施中' :
                list_working.append(row[0])
            elif row[1] == '未着手' :
                list_not_working.append(row[0])
            
#     print('実施中は')
#     print(list_working)
#     print('未着手は')
#     print(list_not_working)
    
    str_work = '\n'.join(list_working)
    str_not_work = '\n'.join(list_not_working)
    
    text = """
リマインダー : ' <@membername_a>  (CC <@membername_b>) タスクの進捗はいかがでしょうか？ このスレ
ッドに記載をお願いします:bow: '

実施中のタスクにも関わらず↓にない場合は、スプレッドシートに記載をお願いします。
終了したタスクはスプレッドシートの状況を「完了」に変更お願いします。
「未着手」のうち取りかかれそうなものは実施中へ変更してください。

実施中のタスクは

{list_working}

未着手のタスクは

{list_not_working}

です

タスクリスト
https://docs.google.com/spreadsheets/d/{SAMPLE_SPREADSHEET_ID}/edit#gid=0
を参照してます。

    """.format(list_working=str_work,list_not_working=str_not_work,SAMPLE_SPREADSHEET_ID=SAMPLE_SPREADSHEET_ID)
#    print(text)
    return text


text = main() 


### slackへ通知 公式マニュアル https://slack.dev/python-slack-sdk/webhook/index.html
webhook_url ="取得したIncoming Webhook URL"
webhook = WebhookClient(webhook_url)
response = webhook.send(text=text)
assert response.status_code == 200
assert response.body == "ok"

```

### crontab設定
定期実行の手段は何でも良いと思いますが今回はmacのcrontabで定期実行されるようにしました。

macのターミナルから
`crontab -e`でcronの設定ファイルを呼び出し、(私の環境では)viが開くので「a」or「i」で挿入モードに切り替え、


```vim
59 12 * * 2 cd {スクリプトをおいたディレクトリのパス} ; bash -l -c 'python3 {スクリプトのパス}'
```
と記載して、「esc」して`:wq`で保存して終了します。
この例では毎週火曜日の12:59に通知が飛びます。
PCがスリープ状態だと飛びません(祝日に飛ばないというメリットがあるためこの点は特に対応しておりません)。




# 感想
リファクタリングの余地はあると思います。
「締め切り」列とtodayを比較して締め切りが近いタスクを強調する
や、
「担当者」列を作成し、そのメンバにメンションを飛ばす
など、さらなるカスタマイズの可能性はあると思います。
ぜひ状況に合わせてカスタマイズし、日々の業務を楽にする参考としてください！

「食品と賞味期限をスプレッドシートで管理して賞味期限が近づいたら通知する」しくみにも応用できるかなと思いました(GASのものがすでにあるかもですが)。


# 参考記事
  - Google
    - https://developers.google.com/sheets/api/quickstart/python
    - https://support.google.com/docs/answer/186103?hl=ja&co=GENIE.Platform%3DDesktop
    - https://support.google.com/docs/answer/78413?hl=ja&co=GENIE.Platform%3DDesktop
  - slack
    - https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8
    - https://slack.dev/python-slack-sdk/webhook/index.html
  - crontab
    - https://eng-entrance.com/linux-command-crontab 








# 最後に宣伝
Supershipではプロダクト開発やサービス開発に関わる人を絶賛募集しております。
ご興味がある方は以下リンクよりご確認ください。
 [Supershipグループ 採用サイト](https://supership-hd.jp/recruit/)
是非ともよろしくお願いします。