|
1 | 1 | #!/usr/bin/env python3
|
2 |
| -import argparse |
3 | 2 | import os
|
4 | 3 |
|
5 |
| -from oauth2client import client, tools |
6 |
| -from oauth2client.file import Storage |
7 |
| - |
8 |
| -flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() |
| 4 | +from google.auth.transport.requests import Request |
| 5 | +from google.oauth2.credentials import Credentials |
| 6 | +from google_auth_oauthlib.flow import InstalledAppFlow |
9 | 7 |
|
10 | 8 | # If modifying these scopes, delete your previously saved credentials
|
11 | 9 | # at zulip/bots/gcal/
|
12 | 10 | # NOTE: When adding more scopes, add them after the previous one in the same field, with a space
|
13 | 11 | # seperating them.
|
14 |
| -SCOPES = "https://www.googleapis.com/auth/calendar.readonly" |
| 12 | +SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"] |
15 | 13 | # This file contains the information that google uses to figure out which application is requesting
|
16 | 14 | # this client's data.
|
17 | 15 | CLIENT_SECRET_FILE = "client_secret.json" # noqa: S105
|
18 |
| -APPLICATION_NAME = "Zulip Calendar Bot" |
19 | 16 | HOME_DIR = os.path.expanduser("~")
|
20 | 17 |
|
21 | 18 |
|
22 |
| -def get_credentials() -> client.Credentials: |
23 |
| - """Gets valid user credentials from storage. |
| 19 | +def get_credentials() -> Credentials: |
| 20 | + """ |
| 21 | + Writes google tokens to a json file, using the client secret file (for the OAuth flow), |
| 22 | + and the refresh token. |
| 23 | +
|
| 24 | + If the tokens file exists and is valid, nothing needs to be done. |
| 25 | + If the tokens file exists, but the auth token is expired (expiry duration of auth token |
| 26 | + is 1 hour), the refresh token is used to get a new token. |
| 27 | + If the tokens file does not exist, or is invalid, the OAuth2 flow is triggered. |
24 | 28 |
|
25 |
| - If nothing has been stored, or if the stored credentials are invalid, |
26 |
| - the OAuth2 flow is completed to obtain the new credentials. |
| 29 | + The OAuth2 flow needs the client secret file, and requires the user to grant access to |
| 30 | + the application via a browser authorization page, for the first run. |
27 | 31 |
|
28 |
| - Returns: |
29 |
| - Credentials, the obtained credential. |
| 32 | + The fetched tokens are written to storage in a json file, for reference by other scripts. |
30 | 33 | """
|
31 | 34 |
|
| 35 | + creds = None |
32 | 36 | credential_path = os.path.join(HOME_DIR, "google-credentials.json")
|
33 | 37 |
|
34 |
| - store = Storage(credential_path) |
35 |
| - credentials = store.get() |
36 |
| - if not credentials or credentials.invalid: |
37 |
| - flow = client.flow_from_clientsecrets(os.path.join(HOME_DIR, CLIENT_SECRET_FILE), SCOPES) |
38 |
| - flow.user_agent = APPLICATION_NAME |
39 |
| - # This attempts to open an authorization page in the default web browser, and asks the user |
40 |
| - # to grant the bot access to their data. If the user grants permission, the run_flow() |
41 |
| - # function returns new credentials. |
42 |
| - credentials = tools.run_flow(flow, store, flags) |
43 |
| - print("Storing credentials to " + credential_path) |
| 38 | + if os.path.exists(credential_path): |
| 39 | + creds = Credentials.from_authorized_user_file(credential_path, SCOPES) |
| 40 | + if not creds or not creds.valid: |
| 41 | + if creds and creds.expired and creds.refresh_token: |
| 42 | + creds.refresh(Request()) |
| 43 | + else: |
| 44 | + flow = InstalledAppFlow.from_client_secrets_file( |
| 45 | + os.path.join(HOME_DIR, CLIENT_SECRET_FILE), SCOPES |
| 46 | + ) |
| 47 | + creds = flow.run_local_server(port=0) |
| 48 | + with open(credential_path, "w") as token: |
| 49 | + token.write(creds.to_json()) |
| 50 | + return creds |
44 | 51 |
|
45 | 52 |
|
46 | 53 | get_credentials()
|
0 commit comments