[初心者向け] GoogleカレンダーにPythonから予定を追加・編集してみた

2023.07.25

業務ではスケジュール管理にGoogleカレンダーを使用しています。 ここに登録されている情報を他にいろいろ使いまわせるようにテキストデータで吸い出したい! また可能ならそこで編集した結果をGoogleカレンダー上に反映させたい! という野望があったので、ChatGPTにやり方を聞きつつやってみました。

とりあえずやりたいことの大枠はできたので、 まずはその方法を記録しておきたいと思います。

概要

流れとしては

  • 認証情報の発行
  • 認証情報を使ってPythonのプログラムを実行

という流れで行っていきます。

やってみた

認証情報の発行

Google Cloudのコンソールにログインします。

新しいプロジェクトを作ります。

名前を適当につけて「作成」

プロジェクトができました。 左のメニューから「APIとサービス」→「ライブラリ」を選択

「calendar」で検索して、 「Google Calendar API」を選びます。

「認証情報を作成」を押して認証情報を作成していきます。

「アクセスするデータの種類」としては「ユーザデータ」の方を選択しました。

「OAuth」同意画面というのが出ますので、 適当なアプリ名と、メールアドレスを入力します。 この画像の下にもう1箇所メールアドレスを入れる箇所がありましたが、 「ユーザーサポートメール」に入力したものと同じアドレスを入れて進めました。

OAuthクライアントIDというところでアプリケーションの種類を選ぶのですが、 今回は「デスクトップアプリ」というのを選択しました。 これで「作成」を押します。

認証情報のクライアントIDが発行されました。

これで完了すると次の画面になりました。 「クライアントシークレット」というものも見えますので、こちらをダウンロードしておきます。

JSONがダウンロードされるので、credentials.jsonという名前で保存しておきます。

PythonからAPIへリクエストを送る

次にPythonのコードを書いていきます。 先ほど保存したcredentials.jsonと同じディレクトリにファイルを作っていく想定です。

パッケージのインストール

必要なPythonパッケージをインストールします。

次のコマンドでパッケージ群をインストールするべしと書かれていました。

pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib dateutil.parser

しかしこれはバージョンの依存関係を満たすことができなかったようで、 次のようなエラーとなって失敗になってしまいました。

$ pip install google-api-python-client google-auth-httplib2 google-auth-oauthlib dateutil.parser
Collecting google-api-python-client
  Using cached google_api_python_client-2.92.0-py2.py3-none-any.whl (11.4 MB)
Collecting google-auth-httplib2
  Using cached google_auth_httplib2-0.1.0-py2.py3-none-any.whl (9.3 kB)
Collecting google-auth-oauthlib
  Using cached google_auth_oauthlib-1.0.0-py2.py3-none-any.whl (18 kB)
ERROR: Could not find a version that satisfies the requirement dateutil.parser (from versions: none)
ERROR: No matching distribution found for dateutil.parser

今回は特に綺麗な依存関係の解決を望むわけではないので、 必要そうなパッケージをそれぞれ個別に入れてみて、できるかどうか試してみました。

具体的には、私の環境では以下の2つを実行したところ、うまくいきました。

$ pip install google-api-python-client
$ pip install google-auth-oauthlib

Pythonコード

ChatGPTが書いてくれたPythonコードをほぼそのまま使っていきます。 このファイル内で参照しているcredentials.jsonは、先程保存したものです。 カレントディレクトリから読む設定になっています。

処理の内容としては、

2023-07-28の0時(UTC-7)から、
サンフランシスコでなんかええ感じのイベントに参加予定

な感じです。

from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
import dateutil.parser

# カレンダーAPIのスコープを設定
SCOPES = ['https://www.googleapis.com/auth/calendar']

# ユーザー認証を行いAPIクライアントを作成
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0)

service = build('calendar', 'v3', credentials=creds)

# イベントデータを作成
event = {
    'summary': 'Google I/O 2019',
    'location': '800 Howard St., San Francisco, CA 94103',
    'description': 'A chance to hear more about Google\'s developer products.',
    'start': {
        'dateTime': '2023-07-28T00:00:00-07:00',
    },
    'end': {
        'dateTime': '2023-07-28T01:00:00-07:00',
    },
}

# イベントを追加
created_event = service.events().insert(calendarId='primary', body=event).execute()

print('Event created: %s' % (created_event.get('htmlLink')))

実行すると、Googleアカウントへのアクセスを許可するか確認されましたので、許可します。 これは実行するたびに許可を求められたので、今のところ毎回許可を行っています。 これを省略する方法は後日調べたいと思います。

これを実行してみると、実際にGoogleカレンダーに上記の内容のスケジュールが、 自分の予定として追加されたことが確認できました!

calendarId='primary'という指定が、自分の予定というのを指定していると考えられます。

既存予定の書き換え

このまま、既存予定の取得と、その書き換えもやってみます。

以下のようなプログラムでできました。 今日を中心として、今週1週間の予定を取得し、 予定の名前の先頭に⭐️をつけたものに変更します。

from datetime import datetime, timedelta

from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build

SCOPES = ["https://www.googleapis.com/auth/calendar"]

flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES)
creds = flow.run_local_server(port=0)

service = build("calendar", "v3", credentials=creds)

# 今週の開始と終了の日時を設定
now = datetime.utcnow()
start_of_week = now - timedelta(days=now.weekday())
end_of_week = start_of_week + timedelta(days=6)

# イベントリストを取得
events_result = (
    service.events()
    .list(
        calendarId="primary",
        timeMin=start_of_week.isoformat() + "Z",
        timeMax=end_of_week.isoformat() + "Z",
        singleEvents=True,
        orderBy="startTime",
    )
    .execute()
)
events = events_result.get("items", [])

for event in events:
    start = event["start"].get("dateTime", event["start"].get("date"))
    print(start, event["summary"])

    event["summary"] = f'⭐️ {event["summary"]}'

    updated_event = (
        service.events()
        .update(calendarId="primary", eventId=event["id"], body=event)
        .execute()
    )

こちらを実行したときも、やはりGoogleへのサインインを毎回求められました。 実際にこれで予定の名前が書き換わることを確認しております。 (実際に試したときは、for文のすべてで確認はしていません。 実際に他の人からも見える予定の名前なので、あまり無闇に変えるのは憚られるので、もうちょっとマイルドに実行しました)

まとめ

Googleカレンダーの予定をを、APIを使って操作することをやってみました。

自分で調べたのでは、なかなか実際に動くところまで行くのは大変だったと思いますが、 ChatGPTのおかげで、かなり簡単に実現することができました。 正直Google Cloudはほとんど何もわからず、あまり適切ではない設定などを行ってしまっている箇所もあるかもしれませんが、 初心者が現実こうなったという記録という意味で共有させて頂ければと思います。

以上、誰かの参考になれば幸いです。