Skip to content

Commit 54340c6

Browse files
committed
google-calendar: Replace deprecated oauth2client library.
Co-authored-by: Vedant Joshi <[email protected]> Co-authored-by: Pransh Gupta <[email protected]> Fixes: zulip#847
1 parent 352a475 commit 54340c6

File tree

4 files changed

+42
-39
lines changed

4 files changed

+42
-39
lines changed

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ module = [
6262
"apiai.*",
6363
"feedparser.*",
6464
"gitlint.*",
65+
"google_auth_oauthlib.*",
6566
"googleapiclient.*",
6667
"irc.*",
6768
"mercurial.*",
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,53 @@
11
#!/usr/bin/env python3
2-
import argparse
32
import os
43

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
97

108
# If modifying these scopes, delete your previously saved credentials
119
# at zulip/bots/gcal/
1210
# NOTE: When adding more scopes, add them after the previous one in the same field, with a space
1311
# seperating them.
14-
SCOPES = "https://www.googleapis.com/auth/calendar.readonly"
12+
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]
1513
# This file contains the information that google uses to figure out which application is requesting
1614
# this client's data.
1715
CLIENT_SECRET_FILE = "client_secret.json" # noqa: S105
18-
APPLICATION_NAME = "Zulip Calendar Bot"
1916
HOME_DIR = os.path.expanduser("~")
2017

2118

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.
2428
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.
2731
28-
Returns:
29-
Credentials, the obtained credential.
32+
The fetched tokens are written to storage in a json file, for reference by other scripts.
3033
"""
3134

35+
creds = None
3236
credential_path = os.path.join(HOME_DIR, "google-credentials.json")
3337

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
4451

4552

4653
get_credentials()

zulip/integrations/google/google-calendar

+8-14
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,20 @@ import time
99
from typing import List, Optional, Set, Tuple
1010

1111
import dateutil.parser
12-
import httplib2
1312
import pytz
14-
from oauth2client import client
15-
from oauth2client.file import Storage
1613

1714
try:
18-
from googleapiclient import discovery
15+
from google.oauth2.credentials import Credentials
16+
from googleapiclient.discovery import build
1917
except ImportError:
20-
logging.exception("Install google-api-python-client")
18+
logging.exception("Install the required python packages from requirements.txt first.")
2119
sys.exit(1)
2220

2321
sys.path.append(os.path.join(os.path.dirname(__file__), "../../"))
2422
import zulip
2523

26-
SCOPES = "https://www.googleapis.com/auth/calendar.readonly"
24+
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]
2725
CLIENT_SECRET_FILE = "client_secret.json" # noqa: S105
28-
APPLICATION_NAME = "Zulip"
2926
HOME_DIR = os.path.expanduser("~")
3027

3128
# Our cached view of the calendar, updated periodically.
@@ -85,7 +82,7 @@ if not options.zulip_email:
8582
zulip_client = zulip.init_from_options(options)
8683

8784

88-
def get_credentials() -> client.Credentials:
85+
def get_credentials() -> Credentials:
8986
"""Gets valid user credentials from storage.
9087
9188
If nothing has been stored, or if the stored credentials are invalid,
@@ -97,10 +94,8 @@ def get_credentials() -> client.Credentials:
9794
"""
9895
try:
9996
credential_path = os.path.join(HOME_DIR, "google-credentials.json")
100-
101-
store = Storage(credential_path)
102-
return store.get()
103-
except client.Error:
97+
return Credentials.from_authorized_user_file(credential_path, SCOPES)
98+
except ValueError:
10499
logging.exception("Error while trying to open the `google-credentials.json` file.")
105100
sys.exit(1)
106101
except OSError:
@@ -110,8 +105,7 @@ def get_credentials() -> client.Credentials:
110105

111106
def populate_events() -> Optional[None]:
112107
credentials = get_credentials()
113-
creds = credentials.authorize(httplib2.Http())
114-
service = discovery.build("calendar", "v3", http=creds)
108+
service = build("calendar", "v3", credentials=credentials)
115109

116110
now = datetime.datetime.now(pytz.utc).isoformat()
117111
feed = (
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
httplib2>=0.22.0
2-
oauth2client>=4.1.3
1+
google-api-python-client>=1.7.9
2+
google-auth-httplib2>=0.0.3
3+
google-auth-oauthlib>=0.4.0
34
python-dateutil
45
pytz

0 commit comments

Comments
 (0)