7.28.2013

Reading Event Data on Google Calendar in Python

Python: Google Calendar のイベント情報を読み取るスクリプト

 

ライブラリのインストール

google-api-python-client を利用する。

google-api-python-client - Google APIs Client Library for Python - Google Project Hosting

$ sudo pip install google-api-python-client

 

認証用のファイルを準備

このような画面操作でサンプルを手に入れることができる。それを参考にする。

Installation  Google APIs Client Library for Python  Google Developers

認証は、client_secrets.json というJSON形式のファイルを使うのが推奨されているようだ。
このファイルも手打ちする必要はなく、ダウンロードボタン一発で入手できる。 

Client Secrets - Google APIs Client Library for Python — Google Developers

サンプルをたたくと、初回に client_secrets.json を元にFlow オブジェクトが生成される。

このとき、どのAPIにどのレベルでアクセスするかを指定する。
今回はカレンダーの読み取りだけなので、'https://www.googleapis.com/auth/calendar.readonly' があれば十分。

その内容が Storage オブジェクトとなり、ファイルに保存される。
今回は read_calendar.dat というファイル名にした。 

認証情報(credentials)が完成したら、httplib2、build() 関数を使って Calendar API v3 にアクセスすればよい。 

 

コード

今日一日の予定を出力するコード。
プログラムの第一引数に整数を入れれば、n日後の予定を取得できる。

対象のカレンダーIDは予め調べて、ハードコーディング。

予定の開始時刻、終了時刻、内容、作成者をソートして出力するため、OneDayEvent というクラスを作っている。

タイムゾーンの調整はしていない。(手抜き)
もっとコメント書いた方がいいけどこれも手抜き。

Calendar API のサービスを取得した後、
service.events()list(...).execute() で条件に見合ったイベントのリストを取得している。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import httplib2
import os
import sys
import datetime

from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import flow_from_clientsecrets
from oauth2client.tools import run

# Calendar id for reading.
CALENDAR_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxx@xxxxx.calendar.google.com'

# Path to the credential files.
BASE_DIR = lambda x: os.path.join(os.path.dirname(__file__), x)

CLIENT_SECRETS_PATH = BASE_DIR('client_secrets.json')
STORAGE_PATH = BASE_DIR('read_calendar.dat')

# Set up a Flow object to be used for authentication.
FLOW = flow_from_clientsecrets(CLIENT_SECRETS_PATH, scope=[
    'https://www.googleapis.com/auth/calendar.readonly',
])


def get_calendar_service():
    storage = Storage(STORAGE_PATH)
    credentials = storage.get()

    if credentials is None or credentials.invalid:
        credentials = run(FLOW, storage)

    http = httplib2.Http()
    http = credentials.authorize(http)

    service = build('calendar', 'v3', http=http)
    return service


class OneDayEvent(object):
    def __init__(self, start_time, end_time, summary, creator):
        if start_time is None:
            assert(end_time is None)
        self.start_time = start_time
        self.end_time = end_time
        self.summary = summary
        self.creator = creator

    def __lt__(self, that):
        if self.start_time is None and that.start_time is None:
            return self.summary < that.summary
        if self.start_time is None or that.start_time is None:
            return self.start_time is None
        return (self.start_time, self.end_time, self.summary, self.creator) < (
            that.start_time, that.end_time, that.summary, that.creator)

    def __str__(self):
        if self.start_time is None:
            tm = u'終日'
        else:
            f = lambda x: datetime.datetime.strftime(x, '%H:%M')
            tm = '%s-%s' % (f(self.start_time), f(self.end_time))
        return u'[%s] %s (%s)' % (tm, self.summary, self.creator)


def read_events(date):
    """Returns sorted list of OneDayEvent objects."""

    def format(x):
        return datetime.datetime.strftime(x, '%Y-%m-%dT%H:%M:%SZ')

    time_min = datetime.datetime.combine(date, datetime.time())
    time_max = time_min + datetime.date.resolution

    time_min, time_max = map(format, (time_min, time_max))

    service = get_calendar_service()
    events = service.events().list(
        calendarId=CALENDAR_ID, timeMin=time_min, timeMax=time_max).execute()

    def f(x):
        y = x.get('dateTime')
        if y:
            z = datetime.datetime.strptime(y[:-6], '%Y-%m-%dT%H:%M:%S')
            return datetime.datetime.combine(date, z.time())

    ret = [OneDayEvent(
        f(event['start']), f(event['end']), event['summary'],
        event['creator']['displayName']) for event in events['items']]
    ret.sort()
    return ret


def main(argv):
    offset = int(argv[1]) if len(argv) >= 2 else 0

    for event in read_events(
            datetime.date.today() + datetime.date.resolution * offset):
        print(unicode(event))

if __name__ == '__main__':
    main(sys.argv)

 

 

  • 出力例
    [終日] 有給休暇 (James LaBrie)
    [11:00-12:00] ○○様来社 (John Petrucci)
    [14:00-15:00] [外出] △△訪問 (John Myung)
    [17:30-22:00] □□勉強会 (Jordan Rudess)
    [17:30-23:00] ☆☆飲み会 (Mike Mangini)

 

References

 

0 件のコメント:

コメントを投稿