First Time with Google Calendar API

這份資料會以 Python 搭 Google API 來寫一些東西,此篇文章是在利用 Google Calendar API 時碰到的一些小問題,在文末因為需要解決一些 OAuth 的 URL 沒辦法被 redirect 而用了一些取巧的小方法。

至於 Google Calendar API 的細節我再找時間寫一篇吧(遠望)

建立 Project

先到 Google API console 建立一個專案:

google api console

設定好你的專案名稱,建立之後設定一些資料,這邊設定的名稱會是在向使用者要求權限時顯示的名字。

Set name and other info

建立憑證(credential)

接下來建立憑證,憑證建立後會產生 client_secret.json 檔,有了這個檔案之後就可以寫程式存取 Google 的 API 了。

建立憑證時需要根據使用的 API 來選擇不同的類別,而因為在這個例子當中,我要使用的是 Google Calendar API,因此選擇的是 OAuth

而在眾多選擇當中,這邊使用的是 網路應用程式

在下方的限制設定則是今天的重點:

  • 已授權的 JavaScript 來源
  • 已授權的重新導向 URI

已授權的重新導向 URI

參考資料 - Google OAUTH: The redirect URI in the request did not match a registered redirect URI

如果沒有設定好的話,Google 會和你說你給的 redirect_url 和允許的 List 比較一下就 mismatch 了。

Google Error

所以我給的設定是這樣:

關於 OAuth 認證 URL

1
2
3
4
5
6
7
8
Your browser has been opened to visit:

https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar&client_id=116*****cp4md.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&access_type=offline

If your browser is on a different machine then exit and re-run this
application with the command-line parameter

--noauth_local_webserver

但是我們現在要怎麼取得這個 URL 呢,應該要幫使用者 redirect 過去才對呀?

研究了一陣子之後我想到怎麼做了,但是要透過重新組合這些參數做到。

在這個例子當中使用 Google Calendar API,所以就以 Google Calendar API 的 QuickStart 來說明。

這個是他們的 Sample Code 節錄:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def get_credentials():
"""Gets valid user credentials from storage.

If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.

Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'calendar-python-quickstart.json')

store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials

沒錯,今天我們就是要對這一段程式碼做修改,經過試驗之後,發現 flow 裡面的一些參數經過組合就能變成我們的 URI 了。

1
2
3
4
auth_uri: 'https://accounts.google.com/o/oauth2/auth'
params: {'response_type': 'code', 'access_type': 'offline'}
scope: 'https://www.googleapis.com/auth/calendar'
client_id: '116*****cp4md.apps.googleusercontent.com'

不過還缺少必要的 redirect_uri,所以要再自己補,所以以下小程式是我用來重組出我們需要的 url:

1
2
3
4
5
d = flow.params.copy()
for x in ['scope', 'client_id']:
d[x] = flow.__dict__[x]
d['redirect_uri'] = 'http://aweimeow.tw:5000/export'
url = '%s?%s' % (flow.auth_uri, '&'.join(map(lambda x: '='.join(x), d.items())))

以上,便是我今天耗費好一段時間得出的心得 (´・ω・`)