You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.5 KiB

  1. import datetime
  2. import os
  3. import pickle
  4. from googleapiclient.discovery import build
  5. from google_auth_oauthlib.flow import InstalledAppFlow
  6. from google.auth.transport.requests import Request
  7. import gapi
  8. HOUR = datetime.timedelta(seconds=60 ** 2)
  9. class API:
  10. def __init__(
  11. self,
  12. service,
  13. scopes,
  14. app_name,
  15. client_secret_file=os.path.join(gapi.state_dir, "client_secret.json"),
  16. credentials_dir=gapi.state_dir,
  17. version="v3",
  18. ):
  19. self.service_name = service
  20. self.app_name = app_name
  21. self.client_secret_file = client_secret_file
  22. self.credentials_dir = credentials_dir
  23. self.scopes = scopes
  24. self._service = None
  25. self._service_settime = None
  26. self.version = version
  27. def get_credentials(self):
  28. creds = None
  29. # The file token.pickle stores the user's access and refresh tokens, and is
  30. # created automatically when the authorization flow completes for the first
  31. # time.
  32. credential_path = os.path.join(self.credentials_dir, "token.pickle")
  33. if os.path.exists(credential_path):
  34. with open(credential_path, "rb") as token:
  35. creds = pickle.load(token)
  36. # If there are no (valid) credentials available, let the user log in.
  37. if not creds or not creds.valid:
  38. if creds and creds.expired and creds.refresh_token:
  39. creds.refresh(Request())
  40. else:
  41. flow = InstalledAppFlow.from_client_secrets_file(
  42. self.client_secret_file, self.scopes
  43. )
  44. creds = flow.run_local_server(port=0)
  45. # Save the credentials for the next run
  46. print("Storing credentials to " + credential_path)
  47. with open(credential_path, "wb") as token:
  48. pickle.dump(creds, token)
  49. return creds
  50. def build_service(self):
  51. credentials = self.get_credentials()
  52. service = build(self.service_name, self.version, credentials=credentials)
  53. return service
  54. def _needs_renewal(self):
  55. now = datetime.datetime.today()
  56. if self._service_settime:
  57. return (now - self._service_settime) > HOUR
  58. else:
  59. return True
  60. @property
  61. def service(self):
  62. if self._needs_renewal():
  63. service = self.build_service()
  64. self._service = service
  65. self._service_settime = datetime.datetime.today()
  66. return service
  67. else:
  68. return self._service