いつ外出したか思い出すのが辛かったので Google に教えてもらうことにした話

~~結構釣ってる~~

# 背景

会社の交通費申請を出すのに毎回、いつでかけたかとか思い出すのが辛かった。
弊社では外出の予定を Google カレンダーに登録し、自分をアテンドする運用をしている。
↓
Google カレンダーから自分が外出した予定を一覧で出してもらえばええやん。


# 参考にしたサイト

というかまぁここ見れば分かると思う

http://blog.serverworks.co.jp/tech/2017/11/02/google-calendar-bot/

# API の準備

参考サイトを参考に、

- API を有効化
- 認証情報を作成
- credential をダウンロード

して準備完了

# サンプルスクリプトを動かす

[Quick Start](https://developers.google.com/calendar/quickstart/python) のサンプルスクリプトをコピペ

```
"""
Shows basic usage of the Google Calendar API. Creates a Google Calendar API
service object and outputs a list of the next 10 events on the user's calendar.
"""
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
import datetime

# Setup the Calendar API
SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)
service = build('calendar', 'v3', http=creds.authorize(Http()))

# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
print('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now,
                                      maxResults=10, singleEvents=True,
                                      orderBy='startTime').execute()
events = events_result.get('items', [])

if not events:
    print('No upcoming events found.')
for event in events:
    start = event['start'].get('dateTime', event['start'].get('date'))
    print(start, event['summary'])
```

`credentials.json` って名前で書いてあるので、先程ダウンロードした認証情報.json を同名でスクリプトと同じフォルダに mv 

```bash:こんな感じ
$ ls
credentials.json gcal_test.py
```

で、実行（実際の予定は伏せてます）
※ 初回の実行に、OAuth の認証画面がブラウザで開かれるので雑に承認する

```
$ python ./gcal_test.py
Getting the upcoming 10 events
2018-06-01T11:00:00+09:00 hoge
2018-06-01T15:00:00+09:00 hogehoge
2018-06-01T17:00:00+09:00 hoho
2018-06-04T17:00:00+09:00 fufu
2018-06-05T18:30:00+09:00 nya-n
2018-06-07T18:00:00+09:00 読書会
2018-06-08T15:00:00+09:00 ミーティング
2018-06-15T15:00:00+09:00 ミーティング
2018-06-21T18:00:00+09:00 読書会
2018-06-22T15:00:00+09:00 ミーティング
```

ええやん（ここまでゼロプログラミング）

# 自分の欲しい情報を出す

「外出予定カレンダー」から「自分が含まれているもの」を「今月いっぱいを範囲」に探せれば OK とした。

```
"""
Shows basic usage of the Google Calendar API. Creates a Google Calendar API
service object and outputs a list of the next 10 events on the user's calendar.
"""
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
import datetime
from datetime import datetime as dt
from dateutil.relativedelta import relativedelta

# Setup the Calendar API
SCOPES = 'https://www.googleapis.com/auth/calendar.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)
service = build('calendar', 'v3', http=creds.authorize(Http()))

# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
today = dt.today()
first_day = (today.replace(day=1) - datetime.timedelta(days=1)).isoformat() + 'Z'
last_day = ((today + relativedelta(months=1)).replace(day=1) - datetime.timedelta(days=1)).isoformat() + 'Z'

events_result = service.events().list(
        calendarId='ここに対象カレンダーの ID を入れてね',
        timeMin=first_day,
        timeMax=last_day,
        singleEvents=True,
        orderBy='startTime').execute()
events = events_result.get('items', [])
print(events_result["summary"])

if not events:
    print('No upcoming events found.')
for event in events:
    start = event['start'].get('dateTime', event['start'].get('date'))
    if "attendees" in event and len(list(filter(lambda x:x["email"] == "自分のメアド", event["attendees"]))):
        print(start, event['summary'], list(map(lambda x:x["email"], event['attendees'])))

```

まぁ書いたと言っても日付の計算入れて対象カレンダー変えて範囲変えただけ。
書き換え３行くらいか。
UTC-JTC の関係か、当月１日朝 8 時のイベントが抜けたりしてたので、適当に１日バッファをもたせたりした。
この辺は雑すぎるので、気が向いたら直そう。

実行

```
$ python ./gcal_test.py
カレンダーのお名前
2018-05-01T08:00:00+09:00 作業 ['自分のとか人のメアド' ]
2018-05-14T00:00:00+09:00 また作業  ['自分のとか人のメアド' ]
```

やったぜ。
これで ~~自分がカレンダー登録を忘れてない限り~~ 自動でその月の外出予定が出せる。


# 他にやりたいことと感想

雑なところもうちょっと直したらカレンダーとか指定できるように汎用化して、Slack bot にしてしまいたいなぁ。
あとは経路情報もある程度カレンダーに入れておけるし、経路と申請する交通費の自動計算とか？結構 Google API はできること多そう。