22import argparse
33import os
44
5- from oauth2client import client , tools
6- from oauth2client .file import Storage
5+ from google .auth .transport .requests import Request
6+ from google .oauth2 .credentials import Credentials
7+ from google_auth_oauthlib .flow import InstalledAppFlow # type: ignore[import-untyped]
8+
9+ parser = argparse .ArgumentParser (add_help = False )
10+ parser .add_argument (
11+ "--auth_host_name" , default = "localhost" , help = "Hostname when running a local web server."
12+ )
13+ parser .add_argument (
14+ "--noauth_local_webserver" ,
15+ action = "store_true" ,
16+ default = False ,
17+ help = "Do not run a local web server." ,
18+ )
19+ parser .add_argument (
20+ "--auth_host_port" ,
21+ default = [8080 , 8090 ],
22+ type = int ,
23+ nargs = "*" ,
24+ help = "Port web server should listen on." ,
25+ )
26+ flags = parser .parse_args ()
727
8- flags = argparse .ArgumentParser (parents = [tools .argparser ]).parse_args ()
928
1029# If modifying these scopes, delete your previously saved credentials
1130# at zulip/bots/gcal/
1231# NOTE: When adding more scopes, add them after the previous one in the same field, with a space
1332# seperating them.
14- SCOPES = "https://www.googleapis.com/auth/calendar.readonly"
33+ SCOPES = [ "https://www.googleapis.com/auth/calendar.readonly" ]
1534# This file contains the information that google uses to figure out which application is requesting
1635# this client's data.
1736CLIENT_SECRET_FILE = "client_secret.json" # noqa: S105
1837APPLICATION_NAME = "Zulip Calendar Bot"
1938HOME_DIR = os .path .expanduser ("~" )
2039
2140
22- def get_credentials () -> client . Credentials :
41+ def get_credentials () -> Credentials :
2342 """Gets valid user credentials from storage.
2443
2544 If nothing has been stored, or if the stored credentials are invalid,
@@ -28,19 +47,36 @@ def get_credentials() -> client.Credentials:
2847 Returns:
2948 Credentials, the obtained credential.
3049 """
31-
50+ credentials = None
3251 credential_path = os .path .join (HOME_DIR , "google-credentials.json" )
33-
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 )
52+ if os .path .exists (credential_path ):
53+ credentials = Credentials .from_authorized_user_file (credential_path , SCOPES )
54+ if not credentials or not credentials .valid :
55+ if credentials and credentials .expired and credentials .refresh_token :
56+ credentials .refresh (Request ())
57+ else :
58+ flow = InstalledAppFlow .from_client_secrets_file (
59+ os .path .join (HOME_DIR , CLIENT_SECRET_FILE ), SCOPES
60+ )
61+ if not flags .noauth_local_webserver :
62+ credentials = flow .run_local_server (
63+ host = flags .auth_host_name , port = flags .auth_host_port [0 ]
64+ )
65+ # This attempts to open an authorization page in the default web browser, and asks the user
66+ # to grant the bot access to their data. If the user grants permission, the run_flow()
67+ # function returns new credentials.
68+ else :
69+ auth_url , _ = flow .authorization_url (prompt = "consent" )
70+ print (
71+ "Proceed to the following link in your browser:" ,
72+ auth_url ,
73+ )
74+ auth_code = input ("Enter the authorization code: " )
75+ credentials = flow .fetch_token (code = auth_code )
76+ with open (credential_path , "w" ) as token :
77+ token .write (credentials .to_json ())
4378 print ("Storing credentials to " + credential_path )
79+ return credentials
4480
4581
4682get_credentials ()
0 commit comments