3 # https://developers.google.com/accounts/docs/OAuth2ForDevices
4 # https://developers.google.com/drive/web/auth/web-server
5 # https://developers.google.com/google-apps/calendar/v3/reference/calendars
6 # https://developers.google.com/picasa-web/
12 import urllib.request, urllib.parse, urllib.error
14 from apiclient.discovery import build
15 from google_auth_oauthlib.flow import InstalledAppFlow
18 logger = logging.getLogger(__file__)
22 def __init__(self, client_secret_file='client_secret.json'):
23 self.credentials = None
24 self.credentials_pickle = './credentials.pickle'
25 if os.path.exists(self.credentials_pickle):
27 f'Refreshing credentials from disk pickle file {self.credentials_pickle}'
29 self.credentials = pickle.load(open(self.credentials_pickle, 'rb'))
32 f'{self.credentials_pickle} does not exist; calling Google.'
34 self.refresh_credentials(client_secret_file)
36 assert self.credentials is not None
38 def refresh_credentials(self, client_secret_file):
40 'https://www.googleapis.com/auth/calendar.events.readonly',
41 'https://www.googleapis.com/auth/calendar.readonly',
42 'https://www.googleapis.com/auth/drive.readonly',
43 'https://www.googleapis.com/auth/drive.photos.readonly',
44 'https://www.googleapis.com/auth/photoslibrary.readonly',
45 # 'https://www.googleapis.com/auth/keep.readonly',
47 flow = InstalledAppFlow.from_client_secrets_file(
48 self.client_secret_file, scopes=scopes
50 self.credentials = flow.run_console()
53 pickle.dump(self.credentials, open(self.credentials_pickle, 'wb'))
55 def calendar_service(self):
56 return build("calendar", "v3", credentials=self.credentials)
58 def keep_service(self):
59 return build('keep', 'v1',
60 discoveryServiceUrl='https://keep.googleapis.com/$discovery/rest?version=v1',
61 credentials=self.credentials)
62 #print(gkeep_service.notes().list().execute())
66 # def __init__(self, client_id: str, client_secret: str) -> None:
67 # print("gdata: initializing oauth token...")
68 # self.client_id = client_id
69 # self.client_secret = client_secret
70 # self.user_code: Optional[str] = None
71 # # print 'Client id: %s' % (client_id)
72 # # print 'Client secret: %s' % (client_secret)
73 # self.token: Optional[Dict] = None
74 # self.device_code = None
75 # self.verfication_url = None
76 # self.token_file = "client_secrets.json"
78 # 'https://www.googleapis.com/auth/calendar.events.readonly',
79 # 'https://www.googleapis.com/auth/calendar.readonly',
80 # 'https://www.googleapis.com/auth/drive.readonly',
81 # 'https://www.googleapis.com/auth/drive.photos.readonly',
82 # 'https://www.googleapis.com/auth/photoslibrary.readonly',
83 # # 'https://www.googleapis.com/auth/keep.readonly',
85 # self.host = "accounts.google.com"
86 # self.reset_connection()
88 # self.last_action = 0.0
89 # self.ssl_ctx: Optional[ssl.SSLContext] = None
91 # # this setup is isolated because it eventually generates a BadStatusLine
92 # # exception, after which we always get httplib.CannotSendRequest errors.
93 # # When this happens, we try re-creating the exception.
94 # def reset_connection(self) -> None:
95 # self.ssl_ctx = ssl.create_default_context() #cafile="/usr/local/etc/ssl/cert.pem")
96 # http.client.HTTPConnection.debuglevel = 2
97 # self.conn = http.client.HTTPSConnection(self.host, context=self.ssl_ctx)
99 # def load_token(self) -> None:
101 # if os.path.isfile(self.token_file):
102 # f = open(self.token_file)
103 # json_token = f.read()
104 # self.token = json.loads(json_token)
107 # def save_token(self) -> None:
108 # f = open(self.token_file, "w")
109 # f.write(json.dumps(self.token))
112 # def has_token(self) -> bool:
113 # if self.token is not None:
114 # print("gdata: we have a token!")
116 # print("gdata: we have no token.")
117 # return self.token is not None
119 # def get_user_code(self) -> Optional[str]:
122 # "/o/oauth2/device/code",
123 # urllib.parse.urlencode(
124 # {"client_id": self.client_id, "scope": " ".join(self.scope)}
126 # {"Content-type": "application/x-www-form-urlencoded"},
128 # response = self.conn.getresponse()
129 # if response.status == 200:
130 # data = json.loads(response.read())
131 # self.device_code = data["device_code"]
132 # self.user_code = data["user_code"]
133 # self.verification_url = data["verification_url"]
134 # self.retry_interval = data["interval"]
136 # self.user_code = None
137 # print(f"gdata: {response.status}")
138 # print(response.read())
140 # return self.user_code
142 # def get_new_token(self) -> None:
143 # # call get_device_code if not already set
144 # if self.user_code is None:
145 # print("gdata: getting user code")
146 # self.get_user_code()
148 # while self.token is None:
152 # urllib.parse.urlencode(
154 # "client_id": self.client_id,
155 # "client_secret": self.client_secret,
156 # "code": self.device_code,
157 # "grant_type": "http://oauth.net/grant_type/device/1.0",
160 # {"Content-type": "application/x-www-form-urlencoded"},
162 # response = self.conn.getresponse()
163 # if response.status == 200:
164 # data = json.loads(response.read())
165 # if "access_token" in data:
169 # time.sleep(self.retry_interval + 2)
171 # print("gdata: failed to get token")
172 # print((response.status))
173 # print((response.read()))
175 # def refresh_token(self) -> bool:
176 # if self.checking_too_often():
177 # print("gdata: not refreshing yet, too soon...")
180 # print("gdata: trying to refresh oauth token...")
181 # self.reset_connection()
182 # if self.token is None:
185 # refresh_token = self.token["refresh_token"]
189 # urllib.parse.urlencode(
191 # "client_id": self.client_id,
192 # "client_secret": self.client_secret,
193 # "refresh_token": refresh_token,
194 # "grant_type": "refresh_token",
197 # {"Content-type": "application/x-www-form-urlencoded"},
200 # response = self.conn.getresponse()
201 # self.last_action = time.time()
202 # if response.status == 200:
203 # data: Dict = json.loads(response.read())
204 # if "access_token" in data:
206 # # in fact we NEVER get a new refresh token at this point
207 # if not "refresh_token" in self.token:
208 # self.token["refresh_token"] = refresh_token
211 # print(("gdata: unexpected response %d to renewal request" % response.status))
212 # print((response.read()))
215 # def checking_too_often(self) -> bool:
217 # return (now - self.last_action) <= 30
219 # # https://developers.google.com/picasa-web/
220 # def photos_service(self):
222 # "Authorization": "%s %s"
223 # % (self.token["token_type"], self.token["access_token"])
225 # client = gdata.photos.service.PhotosService(additional_headers=headers)
228 # # https://developers.google.com/drive/
229 # def docs_service(self):
230 # cred = OAuth2Credentials(
231 # self.token["access_token"],
233 # self.client_secret,
234 # self.token["refresh_token"],
235 # datetime.datetime.now(),
236 # "http://accounts.google.com/o/oauth2/token",
237 # "KitchenKiosk/0.9",
239 # http = httplib2.Http(disable_ssl_certificate_validation=True)
240 # http = cred.authorize(http)
241 # service = build("drive", "v2", http)
244 # # https://developers.google.com/google-apps/calendar/
245 # def calendar_service(self):
246 # cred = OAuth2Credentials(
247 # self.token["access_token"],
249 # self.client_secret,
250 # self.token["refresh_token"],
251 # datetime.datetime.now(),
252 # "http://accounts.google.com/o/oauth2/token",
253 # "KitchenKiosk/0.9",
255 # http = httplib2.Http(disable_ssl_certificate_validation=True)
256 # http = cred.authorize(http)
257 # service = build("calendar", "v3", http)